[Spice-commits] 370 commits - CODING_STYLE MAINTAINERS Makefile Makefile.objs Makefile.target QMP/qmp-spec.txt arch_init.c block.c block.h block/blkdebug.c block/cow.c block/curl.c block/qcow.c block/qcow2-cluster.c block/qcow2.c block/qed-check.c block/qed.c block/qed.h block/raw.c block/sheepdog.c block/stream.c block/vdi.c block/vmdk.c block/vpc.c block_int.h blockdev.c bsd-user/main.c check-qdict.c check-qfloat.c check-qint.c check-qjson.c check-qlist.c check-qstring.c configure coroutine-gthread.c cpu-all.h cpu-defs.h cpu-exec.c cpus.c cpus.h def-helper.h dis-asm.h disas.c dma-helpers.c dma.h docs/ccid.txt docs/qapi-code-gen.txt docs/specs elf.h exec-all.h exec.c fpu/softfloat.c fsdev/virtfs-proxy-helper.texi gdbstub.c hmp-commands.hx hmp.c hmp.h hw/a15mpcore.c hw/a9mpcore.c hw/acpi_piix4.c hw/arm11mpcore.c hw/arm_gic.c hw/armv7m_nvic.c hw/blizzard.c hw/eepro100.c hw/exynos4210.c hw/exynos4210.h hw/exynos4210_combiner.c hw/exynos4210_gic.c hw/exynos4210_uart.c hw/exynos4_boards .c hw/ide hw/irq.c hw/irq.h hw/ivshmem.c hw/kvm hw/lsi53c895a.c hw/mc146818rtc.c hw/mc146818rtc.h hw/mc146818rtc_regs.h hw/milkymist-sysctl.c hw/milkymist-vgafb.c hw/ne2000.c hw/omap1.c hw/omap_lcdc.c hw/opencores_eth.c hw/pc.c hw/pc_piix.c hw/pci-hotplug.c hw/pci.c hw/pci.h hw/pci_bridge.c hw/pci_bridge_dev.c hw/pci_host.c hw/pci_regs.h hw/pcie_port.c hw/pcnet.c hw/pcnet.h hw/petalogix_s3adsp1800_mmu.c hw/piix_pci.c hw/pl031.c hw/ppc440_bamboo.c hw/ppc_prep.c hw/ppce500_mpc8544ds.c hw/ps2.c hw/ps2.h hw/pxa2xx.c hw/qdev-monitor.c hw/qdev-properties.c hw/qdev.c hw/qdev.h hw/realview_gic.c hw/rtl8139.c hw/serial.c hw/shpc.c hw/shpc.h hw/slotid_cap.c hw/slotid_cap.h hw/spapr.h hw/spapr_llan.c hw/spapr_pci.c hw/spapr_rtas.c hw/spapr_vio.c hw/spapr_vio.h hw/spapr_vscsi.c hw/spapr_vty.c hw/strongarm.c hw/sun4m.c hw/sun4u.c hw/twl92230.c hw/usb hw/vga.c hw/vhost.c hw/virtio-net.h hw/virtio-pci.c hw/xen.h hw/xen_apic.c hw/xen_backend.c hw/xen_console.c hw/xen_disk.c hw/xen_platform. c include/qemu ioport.c kvm-all.c kvm-stub.c kvm.h libcacard/vcard_emul_nss.c linux-aio.c linux-headers/asm-powerpc linux-headers/asm-s390 linux-headers/linux linux-user/arm linux-user/elfload.c linux-user/ioctls.h linux-user/main.c linux-user/mmap.c linux-user/qemu.h linux-user/syscall.c linux-user/syscall_defs.h linux-user/syscall_types.h lm32-dis.c main-loop.c main-loop.h memory.c migration.c monitor.c nbd.c net.c net.h osdep.h oslib-win32.c pc-bios/optionrom ppc-dis.c qapi-schema-test.json qapi-schema.json qapi/qmp-input-visitor.c qapi/qmp-input-visitor.h qapi/qmp-output-visitor.c qemu-aio.h qemu-char.c qemu-common.h qemu-doc.texi qemu-img.c qemu-io.c qemu-nbd.texi qemu-options.hx qemu-os-win32.h qemu-queue.h qemu-timer.c qemu-timer.h qemu_socket.h qerror.c qerror.h qga/commands-posix.c qmp-commands.hx qom/container.c qom/object.c qtest.c qtest.h rules.mak savevm.c scripts/create_config scripts/gtester-cat scripts/kvm scripts/qapi-commands.py scripts/qapi-types.py script s/qapi-visit.py scripts/qapi.py scripts/qemu-gdb.py scripts/qtest scripts/signrom.py scripts/signrom.sh scripts/texi2pod.pl scripts/tracetool slirp/misc.c slirp/sbuf.c slirp/slirp.h slirp/tcp.h slirp/tcp_subr.c softmmu_header.h softmmu_template.h target-alpha/STATUS target-alpha/cpu-qom.h target-alpha/cpu.c target-alpha/cpu.h target-alpha/fpu_helper.c target-alpha/helper.c target-alpha/helper.h target-alpha/int_helper.c target-alpha/mem_helper.c target-alpha/op_helper.c target-alpha/sys_helper.c target-alpha/translate.c target-arm/cpu-qom.h target-arm/cpu.c target-arm/cpu.h target-arm/helper.c target-arm/op_helper.c target-arm/translate.c target-cris/op_helper.c target-i386/cpu-qom.h target-i386/cpu.c target-i386/cpu.h target-i386/cpuid.c target-i386/helper.c target-i386/op_helper.c target-lm32/cpu-qom.h target-lm32/cpu.c target-lm32/cpu.h target-lm32/helper.c target-lm32/op_helper.c target-m68k/op_helper.c target-microblaze/helper.c target-microblaze/mmu.c target-microblaze /op_helper.c target-microblaze/translate.c target-mips/TODO target-mips/cpu.h target-mips/helper.h target-mips/op_helper.c target-ppc/cpu-qom.h target-ppc/cpu.h target-ppc/helper.c target-ppc/kvm.c target-ppc/kvm_ppc.c target-ppc/kvm_ppc.h target-ppc/machine.c target-ppc/op_helper.c target-ppc/translate.c target-ppc/translate_init.c target-s390x/cpu-qom.h target-s390x/cpu.c target-s390x/cpu.h target-s390x/helper.c target-s390x/op_helper.c target-sh4/op_helper.c target-sparc/cpu-qom.h target-sparc/cpu.c target-sparc/cpu.h target-sparc/cpu_init.c target-sparc/helper.h target-sparc/ldst_helper.c target-sparc/mmu_helper.c target-unicore32/cpu-qom.h target-unicore32/cpu.c target-unicore32/cpu.h target-unicore32/helper.c target-unicore32/helper.h target-unicore32/op_helper.c target-unicore32/translate.c target-xtensa/core-dc232b.c target-xtensa/core-dc233c target-xtensa/core-dc233c.c target-xtensa/core-fsf.c target-xtensa/cpu-qom.h target-xtensa/cpu.c target-xtensa/cpu.h target-xt ensa/helper.c target-xtensa/helper.h target-xtensa/helpers.h target-xtensa/op_helper.c target-xtensa/translate.c tcg/hppa tcg/i386 tcg/ppc64 tcg/sparc tcg/tcg.c tcg/tcg.h tci.c test-coroutine.c test-qmp-commands.c test-qmp-input-visitor.c test-qmp-output-visitor.c test-string-input-visitor.c test-string-output-visitor.c tests/Makefile tests/check-qdict.c tests/check-qfloat.c tests/check-qint.c tests/check-qjson.c tests/check-qlist.c tests/check-qstring.c tests/libqtest.c tests/libqtest.h tests/qemu-iotests tests/rtc-test.c tests/tcg tests/test-coroutine.c tests/test-qmp-commands.c tests/test-qmp-input-strict.c tests/test-qmp-input-visitor.c tests/test-qmp-output-visitor.c tests/test-string-input-visitor.c tests/test-string-output-visitor.c thunk.c thunk.h trace-events translate-all.c ui/cocoa.m ui/spice-display.c user-exec.c vl.c xen-all.c xen-mapcache.c xen-stub.c xtensa-semi.c

Gerd Hoffmann kraxel at kemper.freedesktop.org
Wed Apr 18 03:20:17 PDT 2012


 CODING_STYLE                           |    2 
 MAINTAINERS                            |    5 
 Makefile                               |   12 
 Makefile.objs                          |    7 
 Makefile.target                        |   19 
 QMP/qmp-spec.txt                       |   20 
 arch_init.c                            |    2 
 block.c                                |   88 +
 block.h                                |   21 
 block/blkdebug.c                       |    7 
 block/cow.c                            |    6 
 block/curl.c                           |    2 
 block/qcow.c                           |    6 
 block/qcow2-cluster.c                  |   18 
 block/qcow2.c                          |    6 
 block/qed-check.c                      |    9 
 block/qed.c                            |   33 
 block/qed.h                            |    2 
 block/raw.c                            |    6 
 block/sheepdog.c                       |  144 ++-
 block/stream.c                         |   41 
 block/vdi.c                            |  429 ++-------
 block/vmdk.c                           |    4 
 block/vpc.c                            |    9 
 block_int.h                            |  135 ++
 blockdev.c                             |   12 
 bsd-user/main.c                        |    1 
 check-qdict.c                          |  378 --------
 check-qfloat.c                         |   53 -
 check-qint.c                           |   87 -
 check-qjson.c                          |  728 ---------------
 check-qlist.c                          |  127 --
 check-qstring.c                        |  107 --
 configure                              |   65 +
 coroutine-gthread.c                    |   96 +-
 cpu-all.h                              |   15 
 cpu-defs.h                             |   14 
 cpu-exec.c                             |    5 
 cpus.c                                 |   85 +
 cpus.h                                 |    2 
 def-helper.h                           |    7 
 dis-asm.h                              |    3 
 disas.c                                |   32 
 dma-helpers.c                          |   21 
 dma.h                                  |   13 
 docs/ccid.txt                          |    2 
 docs/qapi-code-gen.txt                 |    4 
 docs/specs/acpi_pci_hotplug.txt        |   18 
 docs/specs/ivshmem_device_spec.txt     |    2 
 elf.h                                  |   37 
 exec-all.h                             |   40 
 exec.c                                 |  112 +-
 fpu/softfloat.c                        |   12 
 fsdev/virtfs-proxy-helper.texi         |    2 
 gdbstub.c                              |   42 
 hmp-commands.hx                        |    3 
 hmp.c                                  |    9 
 hmp.h                                  |    1 
 hw/a15mpcore.c                         |   46 -
 hw/a9mpcore.c                          |   72 -
 hw/acpi_piix4.c                        |  134 +-
 hw/arm11mpcore.c                       |   56 -
 hw/arm_gic.c                           |  157 ++-
 hw/armv7m_nvic.c                       |   24 
 hw/blizzard.c                          |    4 
 hw/eepro100.c                          |   25 
 hw/exynos4210.c                        |   30 
 hw/exynos4210.h                        |    3 
 hw/exynos4210_combiner.c               |   10 
 hw/exynos4210_gic.c                    |   48 -
 hw/exynos4210_uart.c                   |    6 
 hw/exynos4_boards.c                    |    1 
 hw/ide/core.c                          |   60 +
 hw/ide/internal.h                      |    7 
 hw/ide/macio.c                         |    3 
 hw/ide/qdev.c                          |    7 
 hw/irq.c                               |   17 
 hw/irq.h                               |    5 
 hw/ivshmem.c                           |   58 -
 hw/kvm/clock.c                         |   16 
 hw/lsi53c895a.c                        |    1 
 hw/mc146818rtc.c                       |   33 
 hw/mc146818rtc.h                       |    3 
 hw/mc146818rtc_regs.h                  |   62 +
 hw/milkymist-sysctl.c                  |   26 
 hw/milkymist-vgafb.c                   |    5 
 hw/ne2000.c                            |   24 
 hw/omap1.c                             |   10 
 hw/omap_lcdc.c                         |    5 
 hw/opencores_eth.c                     |   25 
 hw/pc.c                                |   10 
 hw/pc_piix.c                           |  318 +-----
 hw/pci-hotplug.c                       |   14 
 hw/pci.c                               |   28 
 hw/pci.h                               |   11 
 hw/pci_bridge.c                        |   22 
 hw/pci_bridge_dev.c                    |  174 +++
 hw/pci_host.c                          |    3 
 hw/pci_regs.h                          |    3 
 hw/pcie_port.c                         |   12 
 hw/pcnet.c                             |   13 
 hw/pcnet.h                             |    1 
 hw/petalogix_s3adsp1800_mmu.c          |    1 
 hw/piix_pci.c                          |    5 
 hw/pl031.c                             |   75 +
 hw/ppc440_bamboo.c                     |    2 
 hw/ppc_prep.c                          |    2 
 hw/ppce500_mpc8544ds.c                 |    2 
 hw/ps2.c                               |    2 
 hw/ps2.h                               |   29 
 hw/pxa2xx.c                            |   28 
 hw/qdev-monitor.c                      |   27 
 hw/qdev-properties.c                   |   46 +
 hw/qdev.c                              |   39 
 hw/qdev.h                              |    8 
 hw/realview_gic.c                      |   46 -
 hw/rtl8139.c                           |   92 +-
 hw/serial.c                            |    5 
 hw/shpc.c                              |  681 ++++++++++++++
 hw/shpc.h                              |   48 +
 hw/slotid_cap.c                        |   44 
 hw/slotid_cap.h                        |   11 
 hw/spapr.h                             |    2 
 hw/spapr_llan.c                        |   26 
 hw/spapr_pci.c                         |  117 +-
 hw/spapr_rtas.c                        |   17 
 hw/spapr_vio.c                         |   62 -
 hw/spapr_vio.h                         |    5 
 hw/spapr_vscsi.c                       |   15 
 hw/spapr_vty.c                         |    4 
 hw/strongarm.c                         |   10 
 hw/sun4m.c                             |   12 
 hw/sun4u.c                             |   36 
 hw/twl92230.c                          |    9 
 hw/usb/dev-storage.c                   |    2 
 hw/vga.c                               |    2 
 hw/vhost.c                             |   10 
 hw/virtio-net.h                        |    1 
 hw/virtio-pci.c                        |    8 
 hw/xen.h                               |    1 
 hw/xen_apic.c                          |   90 +
 hw/xen_backend.c                       |   17 
 hw/xen_console.c                       |    3 
 hw/xen_disk.c                          |   15 
 hw/xen_platform.c                      |    4 
 include/qemu/object.h                  |   24 
 ioport.c                               |    2 
 kvm-all.c                              |   23 
 kvm-stub.c                             |    8 
 kvm.h                                  |    5 
 libcacard/vcard_emul_nss.c             |   36 
 linux-aio.c                            |    1 
 linux-headers/asm-powerpc/kvm.h        |    1 
 linux-headers/asm-s390/kvm.h           |    2 
 linux-headers/linux/kvm.h              |    9 
 linux-user/arm/syscall_nr.h            |    2 
 linux-user/elfload.c                   |   32 
 linux-user/ioctls.h                    |   34 
 linux-user/main.c                      |   51 -
 linux-user/mmap.c                      |   35 
 linux-user/qemu.h                      |    2 
 linux-user/syscall.c                   |  307 ++++++
 linux-user/syscall_defs.h              |   26 
 linux-user/syscall_types.h             |   40 
 lm32-dis.c                             |  361 +++++++
 main-loop.c                            |  149 +--
 main-loop.h                            |    1 
 memory.c                               |   19 
 migration.c                            |    1 
 monitor.c                              |    3 
 nbd.c                                  |    2 
 net.c                                  |   23 
 net.h                                  |    3 
 osdep.h                                |    2 
 oslib-win32.c                          |    3 
 pc-bios/optionrom/Makefile             |    2 
 ppc-dis.c                              |    2 
 qapi-schema-test.json                  |    2 
 qapi-schema.json                       |   20 
 qapi/qmp-input-visitor.c               |  120 +-
 qapi/qmp-input-visitor.h               |    2 
 qapi/qmp-output-visitor.c              |    8 
 qemu-aio.h                             |   21 
 qemu-char.c                            |    1 
 qemu-common.h                          |    2 
 qemu-doc.texi                          |    8 
 qemu-img.c                             |   12 
 qemu-io.c                              |   10 
 qemu-nbd.texi                          |    2 
 qemu-options.hx                        |   33 
 qemu-os-win32.h                        |   35 
 qemu-queue.h                           |    2 
 qemu-timer.c                           |   12 
 qemu-timer.h                           |    1 
 qemu_socket.h                          |    4 
 qerror.c                               |    7 
 qerror.h                               |    4 
 qga/commands-posix.c                   |  111 +-
 qmp-commands.hx                        |    9 
 qom/container.c                        |   23 
 qom/object.c                           |   33 
 qtest.c                                |  444 +++++++++
 qtest.h                                |   35 
 rules.mak                              |    2 
 savevm.c                               |    3 
 scripts/create_config                  |    6 
 scripts/gtester-cat                    |   26 
 scripts/kvm/kvm_flightrecorder         |  126 ++
 scripts/qapi-commands.py               |   16 
 scripts/qapi-types.py                  |    4 
 scripts/qapi-visit.py                  |   24 
 scripts/qapi.py                        |    5 
 scripts/qemu-gdb.py                    |   89 +
 scripts/qtest                          |    5 
 scripts/signrom.py                     |   40 
 scripts/signrom.sh                     |   45 
 scripts/texi2pod.pl                    |    9 
 scripts/tracetool                      |   30 
 slirp/misc.c                           |   46 -
 slirp/sbuf.c                           |    6 
 slirp/slirp.h                          |   14 
 slirp/tcp.h                            |   21 
 slirp/tcp_subr.c                       |    4 
 softmmu_header.h                       |   15 
 softmmu_template.h                     |   42 
 target-alpha/STATUS                    |    2 
 target-alpha/cpu-qom.h                 |   71 +
 target-alpha/cpu.c                     |   58 +
 target-alpha/cpu.h                     |    7 
 target-alpha/fpu_helper.c              |  822 ++++++++++++++++++
 target-alpha/helper.c                  |   60 +
 target-alpha/helper.h                  |  143 +--
 target-alpha/int_helper.c              |  319 +++++++
 target-alpha/mem_helper.c              |  151 +++
 target-alpha/op_helper.c               | 1379 ------------------------------
 target-alpha/sys_helper.c              |   87 +
 target-alpha/translate.c               |  234 ++---
 target-arm/cpu-qom.h                   |   71 +
 target-arm/cpu.c                       |   60 +
 target-arm/cpu.h                       |   35 
 target-arm/helper.c                    |   23 
 target-arm/op_helper.c                 |    8 
 target-arm/translate.c                 |   13 
 target-cris/op_helper.c                |   12 
 target-i386/cpu-qom.h                  |   75 +
 target-i386/cpu.c                      | 1503 +++++++++++++++++++++++++++++++++
 target-i386/cpu.h                      |    3 
 target-i386/cpuid.c                    | 1369 ------------------------------
 target-i386/helper.c                   |  100 --
 target-i386/op_helper.c                |    8 
 target-lm32/cpu-qom.h                  |   71 +
 target-lm32/cpu.c                      |   81 +
 target-lm32/cpu.h                      |    1 
 target-lm32/helper.c                   |   19 
 target-lm32/op_helper.c                |    8 
 target-m68k/op_helper.c                |    8 
 target-microblaze/helper.c             |    1 
 target-microblaze/mmu.c                |    1 
 target-microblaze/op_helper.c          |    9 
 target-microblaze/translate.c          |    1 
 target-mips/TODO                       |    4 
 target-mips/cpu.h                      |    2 
 target-mips/helper.h                   |    4 
 target-mips/op_helper.c                |   21 
 target-ppc/cpu-qom.h                   |   77 +
 target-ppc/cpu.h                       |    9 
 target-ppc/helper.c                    |   75 -
 target-ppc/kvm.c                       |   16 
 target-ppc/kvm_ppc.c                   |    2 
 target-ppc/kvm_ppc.h                   |    5 
 target-ppc/machine.c                   |    8 
 target-ppc/op_helper.c                 |    8 
 target-ppc/translate.c                 |    2 
 target-ppc/translate_init.c            |  176 +++
 target-s390x/cpu-qom.h                 |   71 +
 target-s390x/cpu.c                     |   96 ++
 target-s390x/cpu.h                     |    5 
 target-s390x/helper.c                  |   41 
 target-s390x/op_helper.c               |    8 
 target-sh4/op_helper.c                 |   14 
 target-sparc/cpu-qom.h                 |   75 +
 target-sparc/cpu.c                     |  899 +++++++++++++++++++
 target-sparc/cpu.h                     |    6 
 target-sparc/cpu_init.c                |  849 ------------------
 target-sparc/helper.h                  |    2 
 target-sparc/ldst_helper.c             |   12 
 target-sparc/mmu_helper.c              |   19 
 target-unicore32/cpu-qom.h             |   59 +
 target-unicore32/cpu.c                 |  104 ++
 target-unicore32/cpu.h                 |    4 
 target-unicore32/helper.c              |   65 -
 target-unicore32/helper.h              |    3 
 target-unicore32/op_helper.c           |    3 
 target-unicore32/translate.c           |    3 
 target-xtensa/core-dc232b.c            |   27 
 target-xtensa/core-dc233c.c            |   55 +
 target-xtensa/core-dc233c/core-isa.h   |  474 ++++++++++
 target-xtensa/core-dc233c/gdb-config.c |  145 +++
 target-xtensa/core-fsf.c               |   27 
 target-xtensa/cpu-qom.h                |   80 +
 target-xtensa/cpu.c                    |   88 +
 target-xtensa/cpu.h                    |    2 
 target-xtensa/helper.c                 |   20 
 target-xtensa/helper.h                 |   39 
 target-xtensa/helpers.h                |   39 
 target-xtensa/op_helper.c              |   40 
 target-xtensa/translate.c              |    8 
 tcg/hppa/tcg-target.c                  |  103 +-
 tcg/i386/tcg-target.c                  |  157 +++
 tcg/ppc64/tcg-target.c                 |    1 
 tcg/sparc/tcg-target.c                 |   63 +
 tcg/tcg.c                              |  283 ++++++
 tcg/tcg.h                              |    2 
 tci.c                                  |   35 
 test-coroutine.c                       |  219 ----
 test-qmp-commands.c                    |  142 ---
 test-qmp-input-visitor.c               |  289 ------
 test-qmp-output-visitor.c              |  457 ----------
 test-string-input-visitor.c            |  195 ----
 test-string-output-visitor.c           |  188 ----
 tests/Makefile                         |  164 ++-
 tests/check-qdict.c                    |  378 ++++++++
 tests/check-qfloat.c                   |   53 +
 tests/check-qint.c                     |   87 +
 tests/check-qjson.c                    |  728 +++++++++++++++
 tests/check-qlist.c                    |  127 ++
 tests/check-qstring.c                  |  107 ++
 tests/libqtest.c                       |  387 ++++++++
 tests/libqtest.h                       |  335 +++++++
 tests/qemu-iotests/009                 |    4 
 tests/qemu-iotests/010                 |    6 
 tests/qemu-iotests/011                 |    2 
 tests/qemu-iotests/031                 |   72 +
 tests/qemu-iotests/031.out             |   76 +
 tests/qemu-iotests/common.rc           |    9 
 tests/qemu-iotests/group               |    1 
 tests/qemu-iotests/qcow2.py            |  207 ++++
 tests/rtc-test.c                       |  263 +++++
 tests/tcg/lm32/Makefile                |   13 
 tests/tcg/xtensa/Makefile              |    3 
 tests/tcg/xtensa/macros.inc            |   17 
 tests/tcg/xtensa/test_break.S          |   34 
 tests/tcg/xtensa/test_loop.S           |   50 +
 tests/test-coroutine.c                 |  219 ++++
 tests/test-qmp-commands.c              |  139 +++
 tests/test-qmp-input-strict.c          |  234 +++++
 tests/test-qmp-input-visitor.c         |  308 ++++++
 tests/test-qmp-output-visitor.c        |  477 ++++++++++
 tests/test-string-input-visitor.c      |  195 ++++
 tests/test-string-output-visitor.c     |  188 ++++
 thunk.c                                |   28 
 thunk.h                                |   28 
 trace-events                           |    4 
 translate-all.c                        |    6 
 ui/cocoa.m                             |    2 
 ui/spice-display.c                     |   24 
 user-exec.c                            |    2 
 vl.c                                   |   14 
 xen-all.c                              |   50 -
 xen-mapcache.c                         |   15 
 xen-stub.c                             |    4 
 xtensa-semi.c                          |    2 
 362 files changed, 17570 insertions(+), 9401 deletions(-)

New commits:
commit 158fd3ce98afd21f2e2639600f6414ea703a9121
Author: Peter Portante <peter.portante at redhat.com>
Date:   Thu Apr 5 11:00:45 2012 -0400

    qemu-timer.c: Remove 250us timeouts
    
    Basically, the main wait loop calls qemu_run_all_timers() unconditionally. The
    first thing this routine used to do is to see if a timer had been serviced,
    and then reset the loop timeout to the next deadline.
    
    However, the new deadlines had not been calculated at that point, as
    qemu_run_timers() had not been called yet for each of the clocks. So
    qemu_rearm_alarm_timer() would end up with a negative or zero deadline, and
    default to setting a 250us timeout for the loop.
    
    As qemu_run_timers() is called for each clock, the real deadlines would be put
    in place, but because a loop timeout was already set, the loop timeout would
    not be changed.
    
    Once that 250us timeout fired, the real deadline would be used for the
    subsequent timeout.
    
    For idle VMs, this effectively doubles the number of times through the loop,
    doubling the number of select() system calls, timer calls, etc. putting added
    scheduling pressure on the kernel. And under cgroups, this really causes a big
    problem because the cgroup code does not scale well.
    
    By simply running the timers before trying to rearm the timer, we always rearm
    with a non-zero deadline, effectively halving the number of system calls.
    
    Signed-off-by: Peter Portante <pportant at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-timer.c b/qemu-timer.c
index 80bcc56..17915df 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -472,16 +472,16 @@ void qemu_run_all_timers(void)
 {
     alarm_timer->pending = 0;
 
+    /* vm time timers */
+    qemu_run_timers(vm_clock);
+    qemu_run_timers(rt_clock);
+    qemu_run_timers(host_clock);
+
     /* rearm timer, if not periodic */
     if (alarm_timer->expired) {
         alarm_timer->expired = 0;
         qemu_rearm_alarm_timer(alarm_timer);
     }
-
-    /* vm time timers */
-    qemu_run_timers(vm_clock);
-    qemu_run_timers(rt_clock);
-    qemu_run_timers(host_clock);
 }
 
 #ifdef _WIN32
commit fc34e77bb3dd41a9932ec5830c06bcade1f5a08e
Merge: 52346e8... 9bea6a2...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Apr 16 12:56:28 2012 -0500

    Merge remote-tracking branch 'kiszka/queues/pending' into staging
    
    * kiszka/queues/pending:
      vapic: Disable for pre-1.1 machines
      Kick io-thread on qemu_chr_accept_input
      pcnet: Properly handle TX requests during Link Fail
      pcnet: Clear ERR in CSR0 on stop
      signrom: Rewrite as python script
    
    Conflicts:
    	hw/pc_piix.c
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --cc hw/pc_piix.c
index 5c08245,44995bf..907d723
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@@ -360,21 -359,6 +360,25 @@@ static QEMUMachine pc_machine_v1_1 = 
      .is_default = 1,
  };
  
 +#define PC_COMPAT_1_0 \
 +        {\
 +            .driver   = "pc-sysfw",\
 +            .property = "rom_only",\
 +            .value    = stringify(1),\
 +        }, {\
 +            .driver   = "isa-fdc",\
 +            .property = "check_media_rate",\
 +            .value    = "off",\
 +        }, {\
 +            .driver   = "virtio-balloon-pci",\
 +            .property = "class",\
 +            .value    = stringify(PCI_CLASS_MEMORY_RAM),\
++        },{\
++            .driver   = "apic",\
++            .property = "vapic",\
++            .value    = "off",\
 +        }
 +
  static QEMUMachine pc_machine_v1_0 = {
      .name = "pc-1.0",
      .desc = "Standard PC",
commit 52346e8c75eba1ece4a782565d5a5ce2e23d5117
Merge: 8a6b870... cdde6ff...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Apr 16 12:52:22 2012 -0500

    Merge remote-tracking branch 'mst/tags/for_anthony' into staging
    
    * mst/tags/for_anthony:
      pci: fix corrupted pci conf index register by unaligned write
      acpi: explicitly account for >1 device per slot
      acpi_piix4: Re-define PCI hotplug eject register read
      acpi_piix4: Remove PCI_RMV_BASE write code
      acpi_piix4: Fix PCI hotplug race
      acpi_piix4: Disallow write to up/down PCI hotplug registers
      virtio-pci: change virtio balloon PCI class code
      ivshmem: add missing msix calls
      vhost: readd assert statement
      vhost: Fix size of dirty log sync on resize
      pc: reduce duplication in compat machine types
      piix_pci: fix typo in i400FX chipset init code

commit 8a6b8708e37a4df064aa3b36d7baa786110871f4
Merge: e6f5d0b... fda1f76...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Apr 16 12:50:12 2012 -0500

    Merge remote-tracking branch 'sstabellini/for_anthony' into staging
    
    * sstabellini/for_anthony:
      xen: introduce an event channel for buffered io event notifications
      xen-mapcache: don't unmap locked entry during mapcache invalidation
      Xen, mapcache: Fix the compute of the size of bucket.
      xen: handle backend deletion from xenstore
      Xen: Add xen-apic support and hook it up.
      Xen: basic HVM MSI injection support.

commit 9bea6a2956e5d473b8914b2a5483fbf187b33844
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Thu Mar 29 14:07:46 2012 +0200

    vapic: Disable for pre-1.1 machines
    
    The kvmvapic was not present in older QEMU versions, thus must be
    disabled in compat machines.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>

diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index fadca4c..44995bf 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -373,6 +373,10 @@ static QEMUMachine pc_machine_v1_0 = {
             .driver   = "isa-fdc",
             .property = "check_media_rate",
             .value    = "off",
+        },{
+            .driver   = "apic",
+            .property = "vapic",
+            .value    = "off",
         },
         { /* end of list */ }
     },
@@ -392,6 +396,10 @@ static QEMUMachine pc_machine_v0_15 = {
             .driver   = "isa-fdc",
             .property = "check_media_rate",
             .value    = "off",
+        },{
+            .driver   = "apic",
+            .property = "vapic",
+            .value    = "off",
         },
         { /* end of list */ }
     },
@@ -431,11 +439,14 @@ static QEMUMachine pc_machine_v0_14 = {
             .driver   = "isa-fdc",
             .property = "check_media_rate",
             .value    = "off",
-        },
-        {
+        },{
             .driver   = "pc-sysfw",
             .property = "rom_only",
             .value    = stringify(1),
+        },{
+            .driver   = "apic",
+            .property = "vapic",
+            .value    = "off",
         },
         { /* end of list */ }
     },
@@ -487,11 +498,14 @@ static QEMUMachine pc_machine_v0_13 = {
             .driver   = "isa-fdc",
             .property = "check_media_rate",
             .value    = "off",
-        },
-        {
+        },{
             .driver   = "pc-sysfw",
             .property = "rom_only",
             .value    = stringify(1),
+        },{
+            .driver   = "apic",
+            .property = "vapic",
+            .value    = "off",
         },
         { /* end of list */ }
     },
@@ -547,11 +561,14 @@ static QEMUMachine pc_machine_v0_12 = {
             .driver   = "isa-fdc",
             .property = "check_media_rate",
             .value    = "off",
-        },
-        {
+        },{
             .driver   = "pc-sysfw",
             .property = "rom_only",
             .value    = stringify(1),
+        },{
+            .driver   = "apic",
+            .property = "vapic",
+            .value    = "off",
         },
         { /* end of list */ }
     }
@@ -615,11 +632,14 @@ static QEMUMachine pc_machine_v0_11 = {
             .driver   = "isa-fdc",
             .property = "check_media_rate",
             .value    = "off",
-        },
-        {
+        },{
             .driver   = "pc-sysfw",
             .property = "rom_only",
             .value    = stringify(1),
+        },{
+            .driver   = "apic",
+            .property = "vapic",
+            .value    = "off",
         },
         { /* end of list */ }
     }
@@ -695,11 +715,14 @@ static QEMUMachine pc_machine_v0_10 = {
             .driver   = "isa-fdc",
             .property = "check_media_rate",
             .value    = "off",
-        },
-        {
+        },{
             .driver   = "pc-sysfw",
             .property = "rom_only",
             .value    = stringify(1),
+        },{
+            .driver   = "apic",
+            .property = "vapic",
+            .value    = "off",
         },
         { /* end of list */ }
     },
commit 98c8ee1da81b88252263f9215ca23b2044650696
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Mar 16 13:18:00 2012 +0100

    Kick io-thread on qemu_chr_accept_input
    
    Once a chr frontend is able to receive input again, we need to inform
    the io-thread about this fact. Otherwise, main_loop_wait may continue to
    select without the related backend file descriptor in its set. This can
    cause high input latencies if only low-rate events arrive otherwise.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>

diff --git a/qemu-char.c b/qemu-char.c
index bb9e3f5..74c60e1 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -177,6 +177,7 @@ void qemu_chr_accept_input(CharDriverState *s)
 {
     if (s->chr_accept_input)
         s->chr_accept_input(s);
+    qemu_notify_event();
 }
 
 void qemu_chr_fe_printf(CharDriverState *s, const char *fmt, ...)
commit ef45c9147f534531ef5d8a20315089d43ea4ddef
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Feb 29 15:37:43 2012 +0100

    pcnet: Properly handle TX requests during Link Fail
    
    As long as we have no link and we aren't in internal loopback mode, no
    packet must be sent. Instead, LCAR needs to be set in any active TX
    descriptor and also CERR in CSR0.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>

diff --git a/hw/pcnet.c b/hw/pcnet.c
index 7413409..d769b08 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -77,6 +77,7 @@ struct qemu_ether_header {
 #define CSR_DTX(S)       !!(((S)->csr[15])&0x0002)
 #define CSR_LOOP(S)      !!(((S)->csr[15])&0x0004)
 #define CSR_DXMTFCS(S)   !!(((S)->csr[15])&0x0008)
+#define CSR_INTL(S)      !!(((S)->csr[15])&0x0040)
 #define CSR_DRCVPA(S)    !!(((S)->csr[15])&0x2000)
 #define CSR_DRCVBC(S)    !!(((S)->csr[15])&0x4000)
 #define CSR_PROM(S)      !!(((S)->csr[15])&0x8000)
@@ -1234,6 +1235,15 @@ static void pcnet_transmit(PCNetState *s)
             if (BCR_SWSTYLE(s) != 1)
                 add_crc = GET_FIELD(tmd.status, TMDS, ADDFCS);
         }
+        if (s->lnkst == 0 &&
+            (!CSR_LOOP(s) || (!CSR_INTL(s) && !BCR_TMAULOOP(s)))) {
+            SET_FIELD(&tmd.misc, TMDM, LCAR, 1);
+            SET_FIELD(&tmd.status, TMDS, ERR, 1);
+            SET_FIELD(&tmd.status, TMDS, OWN, 0);
+            s->csr[0] |= 0xa000; /* ERR | CERR */
+            s->xmit_pos = -1;
+            goto txdone;
+        }
         if (!GET_FIELD(tmd.status, TMDS, ENP)) {
             int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
             s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
@@ -1262,6 +1272,7 @@ static void pcnet_transmit(PCNetState *s)
             s->xmit_pos = -1;
         }
 
+    txdone:
         SET_FIELD(&tmd.status, TMDS, OWN, 0);
         TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
         if (!CSR_TOKINTD(s) || (CSR_LTINTEN(s) && GET_FIELD(tmd.status, TMDS, LTINT)))
diff --git a/hw/pcnet.h b/hw/pcnet.h
index edc81c9..803a2cc 100644
--- a/hw/pcnet.h
+++ b/hw/pcnet.h
@@ -20,6 +20,7 @@
 #define BCR_SWS      20
 #define BCR_PLAT     22
 
+#define BCR_TMAULOOP(S)  !!((S)->bcr[BCR_MC  ] & 0x4000)
 #define BCR_APROMWE(S)   !!((S)->bcr[BCR_MC  ] & 0x0100)
 #define BCR_DWIO(S)      !!((S)->bcr[BCR_BSBC] & 0x0080)
 #define BCR_SSIZE32(S)   !!((S)->bcr[BCR_SWS ] & 0x0100)
commit 6655124ddd6442b19a4b43b27e7d5a3846c4e6a8
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Feb 29 15:33:48 2012 +0100

    pcnet: Clear ERR in CSR0 on stop
    
    pcnet_stop already clears any reason (BABL, CERR, MISS, MERR) why ERR
    (bit 15) should be set in CRS0. So we have to clear that bit as well.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>

diff --git a/hw/pcnet.c b/hw/pcnet.c
index c53f06e..7413409 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -884,7 +884,7 @@ static void pcnet_stop(PCNetState *s)
 #ifdef PCNET_DEBUG
     printf("pcnet_stop\n");
 #endif
-    s->csr[0] &= ~0x7feb;
+    s->csr[0] &= ~0xffeb;
     s->csr[0] |= 0x0014;
     s->csr[4] &= ~0x02c2;
     s->csr[5] &= ~0x0011;
commit 0d6b9cc7420dd2d531b48508f0d4083d1c6a632a
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Jan 27 19:44:53 2012 +0100

    signrom: Rewrite as python script
    
    Now that we have a hard dependency on python anyway, we can replace the
    slow shell script to calculate the option ROM checksum with a fast AND
    portable python version. Tested both with python 2.7 and 3.1.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>

diff --git a/pc-bios/optionrom/Makefile b/pc-bios/optionrom/Makefile
index f6b4027..57d8bd0 100644
--- a/pc-bios/optionrom/Makefile
+++ b/pc-bios/optionrom/Makefile
@@ -26,7 +26,7 @@ build-all: multiboot.bin linuxboot.bin kvmvapic.bin
 	$(call quiet-command,$(OBJCOPY) -O binary -j .text $< $@,"  Building $(TARGET_DIR)$@")
 
 %.bin: %.raw
-	$(call quiet-command,$(SHELL) $(SRC_PATH)/scripts/signrom.sh $< $@,"  Signing $(TARGET_DIR)$@")
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/signrom.py $< $@,"  Signing $(TARGET_DIR)$@")
 
 clean:
 	rm -f *.o *.d *.raw *.img *.bin *~
diff --git a/scripts/signrom.py b/scripts/signrom.py
new file mode 100644
index 0000000..f9c35cc
--- /dev/null
+++ b/scripts/signrom.py
@@ -0,0 +1,40 @@
+#
+# Option ROM signing utility
+#
+# Authors:
+#  Jan Kiszka <jan.kiszka at siemens.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later.
+# See the COPYING file in the top-level directory.
+
+import sys
+import struct
+
+if len(sys.argv) < 3:
+    print('usage: signrom.py input output')
+    sys.exit(1)
+
+fin = open(sys.argv[1], 'rb')
+fout = open(sys.argv[2], 'wb')
+
+fin.seek(2)
+size = ord(fin.read(1)) * 512 - 1
+
+fin.seek(0)
+data = fin.read(size)
+fout.write(data)
+
+checksum = 0
+for b in data:
+    # catch Python 2 vs. 3 differences
+    if isinstance(b, int):
+        checksum += b
+    else:
+        checksum += ord(b)
+checksum = (256 - checksum) % 256
+
+# Python 3 no longer allows chr(checksum)
+fout.write(struct.pack('B', checksum))
+
+fin.close()
+fout.close()
diff --git a/scripts/signrom.sh b/scripts/signrom.sh
deleted file mode 100755
index 9dc5c63..0000000
--- a/scripts/signrom.sh
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/bin/sh
-
-# Option ROM Signing utility
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, see <http://www.gnu.org/licenses/>.
-#
-# Copyright Novell Inc, 2009
-#   Authors: Alexander Graf <agraf at suse.de>
-#
-# Syntax: signrom.sh <input> <output>
-
-# did we get proper arguments?
-test "$1" -a "$2" || exit 1
-
-sum=0
-
-# find out the file size
-x=`dd if="$1" bs=1 count=1 skip=2 2>/dev/null | od -t u1 -A n`
-#size=`expr $x \* 512 - 1`
-size=$(( $x * 512 - 1 ))
-
-# now get the checksum
-nums=`od -A n -t u1 -v -N $size "$1"`
-for i in ${nums}; do
-    # add each byte's value to sum
-    sum=`expr \( $sum + $i \) % 256`
-done
-
-sum=$(( (256 - $sum) % 256 ))
-sum_octal=$( printf "%o" $sum )
-
-# and write the output file
-cp "$1" "$2"
-printf "\\$sum_octal" | dd of="$2" bs=1 count=1 seek=$size conv=notrunc 2>/dev/null
commit e6f5d0be730a41bacb10edba19d1369ec2949486
Merge: 9444006... 55dd9ff...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Apr 15 19:56:06 2012 +0000

    Merge branch 'w64' of git://qemu.weilnetz.de/qemu
    
    * 'w64' of git://qemu.weilnetz.de/qemu:
      w64: Fix time conversion for some versions of MinGW-w64
      nbd: Fix compiler warning (w64)
      disas: Replace 'unsigned long' by 'uintptr_t'
      cpu-exec: Remove non-portable type cast and fix format string
      target-mips: Fix type cast for w64 (uintptr_t)
      w64: Fix type cast in os_host_main_loop_wait
      w64: Fix data types in softmmu*.h
      w64: Use uintptr_t in exec.c
      softmmu: Use uintptr_t for physaddr and rename it
      w64: Fix struct CPUTLBEntry
      w64: Fix definition of setjmp
      w32: Move defines for socket specific errors to qemu-os-win32.h
      w64: Use larger alignment for section with generated code
      w64: Fix data types in cpu-all.h, exec.c
      w64: Fix type casts used in some macros in cpu-all.h
      tcg/i386: Add support for w64 ABI
      tcg/i386: Use GDB JIT debugging interface only for hosts with ELF

commit 9444006fa6ba1d5e4079ee534a7236124b66ea77
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Apr 7 01:19:45 2012 +0200

    target-alpha: QOM'ify CPU init
    
    Move code from cpu_alpha_init() into a CPU initializer.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-alpha/cpu.c b/target-alpha/cpu.c
index 315b0c1..62d2a66 100644
--- a/target-alpha/cpu.c
+++ b/target-alpha/cpu.c
@@ -1,6 +1,7 @@
 /*
  * QEMU Alpha CPU
  *
+ * Copyright (c) 2007 Jocelyn Mayer
  * Copyright (c) 2012 SUSE LINUX Products GmbH
  *
  * This library is free software; you can redistribute it and/or
@@ -22,10 +23,29 @@
 #include "qemu-common.h"
 
 
+static void alpha_cpu_initfn(Object *obj)
+{
+    AlphaCPU *cpu = ALPHA_CPU(obj);
+    CPUAlphaState *env = &cpu->env;
+
+    cpu_exec_init(env);
+    tlb_flush(env, 1);
+
+#if defined(CONFIG_USER_ONLY)
+    env->ps = PS_USER_MODE;
+    cpu_alpha_store_fpcr(env, (FPCR_INVD | FPCR_DZED | FPCR_OVFD
+                               | FPCR_UNFD | FPCR_INED | FPCR_DNOD
+                               | FPCR_DYN_NORMAL));
+#endif
+    env->lock_addr = -1;
+    env->fen = 1;
+}
+
 static const TypeInfo alpha_cpu_type_info = {
     .name = TYPE_ALPHA_CPU,
     .parent = TYPE_CPU,
     .instance_size = sizeof(AlphaCPU),
+    .instance_init = alpha_cpu_initfn,
     .abstract = false,
     .class_size = sizeof(AlphaCPUClass),
 };
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index f773e6c..12de6a3 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3531,9 +3531,8 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
 
     cpu = ALPHA_CPU(object_new(TYPE_ALPHA_CPU));
     env = &cpu->env;
-    cpu_exec_init(env);
+
     alpha_translate_init();
-    tlb_flush(env, 1);
 
     /* Default to ev67; no reason not to emulate insns by default.  */
     implver = IMPLVER_21264;
@@ -3551,15 +3550,6 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
     env->implver = implver;
     env->amask = amask;
 
-#if defined (CONFIG_USER_ONLY)
-    env->ps = PS_USER_MODE;
-    cpu_alpha_store_fpcr(env, (FPCR_INVD | FPCR_DZED | FPCR_OVFD
-                               | FPCR_UNFD | FPCR_INED | FPCR_DNOD
-                               | FPCR_DYN_NORMAL));
-#endif
-    env->lock_addr = -1;
-    env->fen = 1;
-
     qemu_init_vcpu(env);
     return env;
 }
commit 25ebd80f1d0e4b8863968d56ccfe634ea577d365
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri Apr 6 19:46:48 2012 +0200

    target-alpha: QOM'ify CPU
    
    Embed CPUAlphaState as first member of AlphaCPU.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Richard Henderson <rth at twiddle.net>

diff --git a/Makefile.target b/Makefile.target
index 3ab791a..61dfe3b 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -104,6 +104,7 @@ libobj-$(TARGET_SPARC64) += int64_helper.o
 libobj-$(TARGET_UNICORE32) += cpu.o
 libobj-$(TARGET_XTENSA) += cpu.o
 libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o sys_helper.o mem_helper.o
+libobj-$(TARGET_ALPHA) += cpu.o
 
 libobj-y += disas.o
 libobj-$(CONFIG_TCI_DIS) += tci-dis.o
diff --git a/target-alpha/cpu-qom.h b/target-alpha/cpu-qom.h
new file mode 100644
index 0000000..6b4ca6d
--- /dev/null
+++ b/target-alpha/cpu-qom.h
@@ -0,0 +1,71 @@
+/*
+ * QEMU Alpha CPU
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * 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.1 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/lgpl-2.1.html>
+ */
+#ifndef QEMU_ALPHA_CPU_QOM_H
+#define QEMU_ALPHA_CPU_QOM_H
+
+#include "qemu/cpu.h"
+#include "cpu.h"
+
+#define TYPE_ALPHA_CPU "alpha-cpu"
+
+#define ALPHA_CPU_CLASS(klass) \
+    OBJECT_CLASS_CHECK(AlphaCPUClass, (klass), TYPE_ALPHA_CPU)
+#define ALPHA_CPU(obj) \
+    OBJECT_CHECK(AlphaCPU, (obj), TYPE_ALPHA_CPU)
+#define ALPHA_CPU_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(AlphaCPUClass, (obj), TYPE_ALPHA_CPU)
+
+/**
+ * AlphaCPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * An Alpha CPU model.
+ */
+typedef struct AlphaCPUClass {
+    /*< private >*/
+    CPUClass parent_class;
+    /*< public >*/
+
+    void (*parent_reset)(CPUState *cpu);
+} AlphaCPUClass;
+
+/**
+ * AlphaCPU:
+ * @env: #CPUAlphaState
+ *
+ * An Alpha CPU.
+ */
+typedef struct AlphaCPU {
+    /*< private >*/
+    CPUState parent_obj;
+    /*< public >*/
+
+    CPUAlphaState env;
+} AlphaCPU;
+
+static inline AlphaCPU *alpha_env_get_cpu(CPUAlphaState *env)
+{
+    return ALPHA_CPU(container_of(env, AlphaCPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(alpha_env_get_cpu(e))
+
+
+#endif
diff --git a/target-alpha/cpu.c b/target-alpha/cpu.c
new file mode 100644
index 0000000..315b0c1
--- /dev/null
+++ b/target-alpha/cpu.c
@@ -0,0 +1,38 @@
+/*
+ * QEMU Alpha CPU
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * 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.1 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/lgpl-2.1.html>
+ */
+
+#include "cpu-qom.h"
+#include "qemu-common.h"
+
+
+static const TypeInfo alpha_cpu_type_info = {
+    .name = TYPE_ALPHA_CPU,
+    .parent = TYPE_CPU,
+    .instance_size = sizeof(AlphaCPU),
+    .abstract = false,
+    .class_size = sizeof(AlphaCPUClass),
+};
+
+static void alpha_cpu_register_types(void)
+{
+    type_register_static(&alpha_cpu_type_info);
+}
+
+type_init(alpha_cpu_register_types)
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index fd578ce..99f9ee1 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -292,6 +292,7 @@ struct CPUAlphaState {
 #define cpu_signal_handler cpu_alpha_signal_handler
 
 #include "cpu-all.h"
+#include "cpu-qom.h"
 
 enum {
     FEATURE_ASN    = 0x00000001,
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 1f4565d..f773e6c 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3525,10 +3525,12 @@ static const struct cpu_def_t cpu_defs[] = {
 
 CPUAlphaState * cpu_alpha_init (const char *cpu_model)
 {
+    AlphaCPU *cpu;
     CPUAlphaState *env;
     int implver, amask, i, max;
 
-    env = g_malloc0(sizeof(CPUAlphaState));
+    cpu = ALPHA_CPU(object_new(TYPE_ALPHA_CPU));
+    env = &cpu->env;
     cpu_exec_init(env);
     alpha_translate_init();
     tlb_flush(env, 1);
commit 55dd9ffa70eb44f461b12c248c3df106ba8deca9
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Apr 12 22:33:12 2012 +0200

    w64: Fix time conversion for some versions of MinGW-w64
    
    tb.time is a time value, but not necessarily of the same size as time_t:
    while time_t is 64 bit for w64, tb.time still is 32 bit only.
    
    Therefore we need en explicit conversion.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/savevm.c b/savevm.c
index 12fb209..2d18bab 100644
--- a/savevm.c
+++ b/savevm.c
@@ -2106,7 +2106,8 @@ void do_savevm(Monitor *mon, const QDict *qdict)
         }
     } else {
 #ifdef _WIN32
-        ptm = localtime(&tb.time);
+        time_t t = tb.time;
+        ptm = localtime(&t);
         strftime(sn->name, sizeof(sn->name), "vm-%Y%m%d%H%M%S", ptm);
 #else
         /* cast below needed for OpenBSD where tv_sec is still 'long' */
commit 0fee8f342884e96b29d7df28475d0c485a317d54
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Apr 12 22:30:16 2012 +0200

    nbd: Fix compiler warning (w64)
    
    Portable printing of dev_offset (data type off_t) needs a type cast.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/nbd.c b/nbd.c
index 567e94e..406e555 100644
--- a/nbd.c
+++ b/nbd.c
@@ -813,7 +813,7 @@ static void nbd_trip(void *opaque)
             LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64
             ", Offset: %" PRIu64 "\n",
                     request.from, request.len,
-                    (uint64_t)exp->size, exp->dev_offset);
+                    (uint64_t)exp->size, (uint64_t)exp->dev_offset);
         LOG("requested operation past EOF--bad client?");
         goto invalid_request;
     }
commit b0b0f1c964bb7643a6d4469ffd8157de84741d1f
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Apr 12 15:44:35 2012 +0200

    disas: Replace 'unsigned long' by 'uintptr_t'
    
    This is needed for w64. It changes nothing for other hosts.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/disas.c b/disas.c
index 4f2c4e4..27071c3 100644
--- a/disas.c
+++ b/disas.c
@@ -268,7 +268,7 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
 /* Disassemble this for me please... (debugging). */
 void disas(FILE *out, void *code, unsigned long size)
 {
-    unsigned long pc;
+    uintptr_t pc;
     int count;
     struct disassemble_info disasm_info;
     int (*print_insn)(bfd_vma pc, disassemble_info *info);
@@ -276,7 +276,7 @@ void disas(FILE *out, void *code, unsigned long size)
     INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf);
 
     disasm_info.buffer = code;
-    disasm_info.buffer_vma = (unsigned long)code;
+    disasm_info.buffer_vma = (uintptr_t)code;
     disasm_info.buffer_length = size;
 
 #ifdef HOST_WORDS_BIGENDIAN
@@ -320,8 +320,8 @@ void disas(FILE *out, void *code, unsigned long size)
 	    (long) code);
     return;
 #endif
-    for (pc = (unsigned long)code; size > 0; pc += count, size -= count) {
-	fprintf(out, "0x%08lx:  ", pc);
+    for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) {
+        fprintf(out, "0x%08" PRIxPTR ":  ", pc);
 	count = print_insn(pc, &disasm_info);
 	fprintf(out, "\n");
 	if (count < 0)
commit 3ba19255450666869ecfe764774c2371f989e68b
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Apr 12 15:44:24 2012 +0200

    cpu-exec: Remove non-portable type cast and fix format string
    
    This change is needed for w64, but also changes the code for other hosts.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/cpu-exec.c b/cpu-exec.c
index d153f97..0344cd5 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -541,8 +541,8 @@ int cpu_exec(CPUArchState *env)
                     tb_invalidated_flag = 0;
                 }
 #ifdef CONFIG_DEBUG_EXEC
-                qemu_log_mask(CPU_LOG_EXEC, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
-                             (long)tb->tc_ptr, tb->pc,
+                qemu_log_mask(CPU_LOG_EXEC, "Trace %p [" TARGET_FMT_lx "] %s\n",
+                             tb->tc_ptr, tb->pc,
                              lookup_symbol(tb->pc));
 #endif
                 /* see if we can patch the calling TB. When the TB
commit b69e48a84d83162efd4782472572783e99840cf5
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Apr 12 15:43:09 2012 +0200

    target-mips: Fix type cast for w64 (uintptr_t)
    
    This changes nothing for other hosts.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index bca1d70..5627447 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -2275,7 +2275,7 @@ void helper_pmon (int function)
         break;
     case 158:
         {
-            unsigned char *fmt = (void *)(unsigned long)env->active_tc.gpr[4];
+            unsigned char *fmt = (void *)(uintptr_t)env->active_tc.gpr[4];
             printf("%s", fmt);
         }
         break;
commit 58b9630d7e2252d077b632c3a26d1aa334cf5fe6
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Apr 12 20:42:34 2012 +0200

    w64: Fix type cast in os_host_main_loop_wait
    
    Casting a pointer to an integer must use (DWORD_PTR) instead of (DWORD).
    This also matches the definition of 'fd' (gint for w32, gint64 for w64).
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/main-loop.c b/main-loop.c
index 1ebdc4b..4887c73 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -430,7 +430,7 @@ static int os_host_main_loop_wait(int timeout)
     g_assert(n_poll_fds <= ARRAY_SIZE(poll_fds));
 
     for (i = 0; i < w->num; i++) {
-        poll_fds[n_poll_fds + i].fd = (DWORD) w->events[i];
+        poll_fds[n_poll_fds + i].fd = (DWORD_PTR)w->events[i];
         poll_fds[n_poll_fds + i].events = G_IO_IN;
     }
 
commit b065927a02cbbaca032ed20d3039baca0914165c
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Apr 12 14:14:51 2012 +0200

    w64: Fix data types in softmmu*.h
    
    w64 requires uintptr_t.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/softmmu_header.h b/softmmu_header.h
index 289dae2..cf1aa38 100644
--- a/softmmu_header.h
+++ b/softmmu_header.h
@@ -111,7 +111,7 @@ glue(glue(glue(CPU_PREFIX, ld), USUFFIX), MEMSUFFIX)(ENV_PARAM
                                                                      mmu_idx);
     } else {
         uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
-        res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)hostaddr);
+        res = glue(glue(ld, USUFFIX), _raw)(hostaddr);
     }
     return res;
 }
@@ -134,7 +134,7 @@ glue(glue(glue(CPU_PREFIX, lds), SUFFIX), MEMSUFFIX)(ENV_PARAM
                                MMUSUFFIX)(ENV_VAR addr, mmu_idx);
     } else {
         uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
-        res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)hostaddr);
+        res = glue(glue(lds, SUFFIX), _raw)(hostaddr);
     }
     return res;
 }
@@ -161,7 +161,7 @@ glue(glue(glue(CPU_PREFIX, st), SUFFIX), MEMSUFFIX)(ENV_PARAM target_ulong ptr,
                                                                mmu_idx);
     } else {
         uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
-        glue(glue(st, SUFFIX), _raw)((uint8_t *)hostaddr, v);
+        glue(glue(st, SUFFIX), _raw)(hostaddr, v);
     }
 }
 
diff --git a/softmmu_template.h b/softmmu_template.h
index b285d78..b8bd700 100644
--- a/softmmu_template.h
+++ b/softmmu_template.h
@@ -112,7 +112,6 @@ glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_PARAM
     int index;
     target_ulong tlb_addr;
     target_phys_addr_t ioaddr;
-    unsigned long addend;
     uintptr_t retaddr;
 
     /* test if there is match for unaligned or IO access */
@@ -139,6 +138,7 @@ glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_PARAM
                                                          mmu_idx, retaddr);
         } else {
             /* unaligned/aligned access in the same page */
+            uintptr_t addend;
 #ifdef ALIGNED_ONLY
             if ((addr & (DATA_SIZE - 1)) != 0) {
                 retaddr = GETPC();
@@ -146,7 +146,8 @@ glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_PARAM
             }
 #endif
             addend = env->tlb_table[mmu_idx][index].addend;
-            res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(long)(addr+addend));
+            res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(intptr_t)
+                                                (addr + addend));
         }
     } else {
         /* the page is not in the TLB : fill it */
@@ -171,7 +172,6 @@ glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_PARAM
     DATA_TYPE res, res1, res2;
     int index, shift;
     target_phys_addr_t ioaddr;
-    unsigned long addend;
     target_ulong tlb_addr, addr1, addr2;
 
     index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
@@ -202,8 +202,9 @@ glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_PARAM
             res = (DATA_TYPE)res;
         } else {
             /* unaligned/aligned access in the same page */
-            addend = env->tlb_table[mmu_idx][index].addend;
-            res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(long)(addr+addend));
+            uintptr_t addend = env->tlb_table[mmu_idx][index].addend;
+            res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(intptr_t)
+                                                (addr + addend));
         }
     } else {
         /* the page is not in the TLB : fill it */
@@ -258,7 +259,6 @@ void glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_PARAM
                                                             int mmu_idx)
 {
     target_phys_addr_t ioaddr;
-    unsigned long addend;
     target_ulong tlb_addr;
     uintptr_t retaddr;
     int index;
@@ -284,6 +284,7 @@ void glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_PARAM
                                                    mmu_idx, retaddr);
         } else {
             /* aligned/unaligned access in the same page */
+            uintptr_t addend;
 #ifdef ALIGNED_ONLY
             if ((addr & (DATA_SIZE - 1)) != 0) {
                 retaddr = GETPC();
@@ -291,7 +292,8 @@ void glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_PARAM
             }
 #endif
             addend = env->tlb_table[mmu_idx][index].addend;
-            glue(glue(st, SUFFIX), _raw)((uint8_t *)(long)(addr+addend), val);
+            glue(glue(st, SUFFIX), _raw)((uint8_t *)(intptr_t)
+                                         (addr + addend), val);
         }
     } else {
         /* the page is not in the TLB : fill it */
@@ -313,7 +315,6 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_PARAM
                                                    uintptr_t retaddr)
 {
     target_phys_addr_t ioaddr;
-    unsigned long addend;
     target_ulong tlb_addr;
     int index, i;
 
@@ -345,8 +346,9 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_PARAM
             }
         } else {
             /* aligned/unaligned access in the same page */
-            addend = env->tlb_table[mmu_idx][index].addend;
-            glue(glue(st, SUFFIX), _raw)((uint8_t *)(long)(addr+addend), val);
+            uintptr_t addend = env->tlb_table[mmu_idx][index].addend;
+            glue(glue(st, SUFFIX), _raw)((uint8_t *)(intptr_t)
+                                         (addr + addend), val);
         }
     } else {
         /* the page is not in the TLB : fill it */
commit 8efe0ca83eb9c5f996acc7a37d522da5c542ec79
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Apr 12 15:42:19 2012 +0200

    w64: Use uintptr_t in exec.c
    
    Replace all type casts to 'long' or 'unsigned long' by 'intptr_t' or 'uintptr_t'.
    
    For type casts which are only used to extract the lower bits of an address
    or to modify those bits, signedness does not matter. There I always use 'uintptr_t'.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/exec.c b/exec.c
index 6d10595..77d6866 100644
--- a/exec.c
+++ b/exec.c
@@ -887,8 +887,8 @@ static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb)
 
     for(;;) {
         tb1 = *ptb;
-        n1 = (long)tb1 & 3;
-        tb1 = (TranslationBlock *)((long)tb1 & ~3);
+        n1 = (uintptr_t)tb1 & 3;
+        tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3);
         if (tb1 == tb) {
             *ptb = tb1->page_next[n1];
             break;
@@ -908,8 +908,8 @@ static inline void tb_jmp_remove(TranslationBlock *tb, int n)
         /* find tb(n) in circular list */
         for(;;) {
             tb1 = *ptb;
-            n1 = (long)tb1 & 3;
-            tb1 = (TranslationBlock *)((long)tb1 & ~3);
+            n1 = (uintptr_t)tb1 & 3;
+            tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3);
             if (n1 == n && tb1 == tb)
                 break;
             if (n1 == 2) {
@@ -929,7 +929,7 @@ static inline void tb_jmp_remove(TranslationBlock *tb, int n)
    another TB */
 static inline void tb_reset_jump(TranslationBlock *tb, int n)
 {
-    tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
+    tb_set_jmp_target(tb, n, (uintptr_t)(tb->tc_ptr + tb->tb_next_offset[n]));
 }
 
 void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
@@ -974,16 +974,16 @@ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
     /* suppress any remaining jumps to this TB */
     tb1 = tb->jmp_first;
     for(;;) {
-        n1 = (long)tb1 & 3;
+        n1 = (uintptr_t)tb1 & 3;
         if (n1 == 2)
             break;
-        tb1 = (TranslationBlock *)((long)tb1 & ~3);
+        tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3);
         tb2 = tb1->jmp_next[n1];
         tb_reset_jump(tb1, n1);
         tb1->jmp_next[n1] = NULL;
         tb1 = tb2;
     }
-    tb->jmp_first = (TranslationBlock *)((long)tb | 2); /* fail safe */
+    tb->jmp_first = (TranslationBlock *)((uintptr_t)tb | 2); /* fail safe */
 
     tb_phys_invalidate_count++;
 }
@@ -1024,8 +1024,8 @@ static void build_page_bitmap(PageDesc *p)
 
     tb = p->first_tb;
     while (tb != NULL) {
-        n = (long)tb & 3;
-        tb = (TranslationBlock *)((long)tb & ~3);
+        n = (uintptr_t)tb & 3;
+        tb = (TranslationBlock *)((uintptr_t)tb & ~3);
         /* NOTE: this is subtle as a TB may span two physical pages */
         if (n == 0) {
             /* NOTE: tb_end may be after the end of the page, but
@@ -1069,7 +1069,8 @@ TranslationBlock *tb_gen_code(CPUArchState *env,
     tb->flags = flags;
     tb->cflags = cflags;
     cpu_gen_code(env, tb, &code_gen_size);
-    code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
+    code_gen_ptr = (void *)(((uintptr_t)code_gen_ptr + code_gen_size +
+                             CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
 
     /* check next page if needed */
     virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
@@ -1117,8 +1118,8 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
     /* XXX: see if in some cases it could be faster to invalidate all the code */
     tb = p->first_tb;
     while (tb != NULL) {
-        n = (long)tb & 3;
-        tb = (TranslationBlock *)((long)tb & ~3);
+        n = (uintptr_t)tb & 3;
+        tb = (TranslationBlock *)((uintptr_t)tb & ~3);
         tb_next = tb->page_next[n];
         /* NOTE: this is subtle as a TB may span two physical pages */
         if (n == 0) {
@@ -1201,7 +1202,8 @@ static inline void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len)
         qemu_log("modifying code at 0x%x size=%d EIP=%x PC=%08x\n",
                   cpu_single_env->mem_io_vaddr, len,
                   cpu_single_env->eip,
-                  cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
+                  cpu_single_env->eip +
+                  (intptr_t)cpu_single_env->segs[R_CS].base);
     }
 #endif
     p = page_find(start >> TARGET_PAGE_BITS);
@@ -1245,8 +1247,8 @@ static void tb_invalidate_phys_page(tb_page_addr_t addr,
     }
 #endif
     while (tb != NULL) {
-        n = (long)tb & 3;
-        tb = (TranslationBlock *)((long)tb & ~3);
+        n = (uintptr_t)tb & 3;
+        tb = (TranslationBlock *)((uintptr_t)tb & ~3);
 #ifdef TARGET_HAS_PRECISE_SMC
         if (current_tb == tb &&
             (current_tb->cflags & CF_COUNT_MASK) != 1) {
@@ -1294,7 +1296,7 @@ static inline void tb_alloc_page(TranslationBlock *tb,
 #ifndef CONFIG_USER_ONLY
     page_already_protected = p->first_tb != NULL;
 #endif
-    p->first_tb = (TranslationBlock *)((long)tb | n);
+    p->first_tb = (TranslationBlock *)((uintptr_t)tb | n);
     invalidate_page_bitmap(p);
 
 #if defined(TARGET_HAS_SMC) || 1
@@ -1361,7 +1363,7 @@ void tb_link_page(TranslationBlock *tb,
     else
         tb->page_addr[1] = -1;
 
-    tb->jmp_first = (TranslationBlock *)((long)tb | 2);
+    tb->jmp_first = (TranslationBlock *)((uintptr_t)tb | 2);
     tb->jmp_next[0] = NULL;
     tb->jmp_next[1] = NULL;
 
@@ -1382,21 +1384,22 @@ void tb_link_page(TranslationBlock *tb,
 TranslationBlock *tb_find_pc(uintptr_t tc_ptr)
 {
     int m_min, m_max, m;
-    unsigned long v;
+    uintptr_t v;
     TranslationBlock *tb;
 
     if (nb_tbs <= 0)
         return NULL;
-    if (tc_ptr < (unsigned long)code_gen_buffer ||
-        tc_ptr >= (unsigned long)code_gen_ptr)
+    if (tc_ptr < (uintptr_t)code_gen_buffer ||
+        tc_ptr >= (uintptr_t)code_gen_ptr) {
         return NULL;
+    }
     /* binary search (cf Knuth) */
     m_min = 0;
     m_max = nb_tbs - 1;
     while (m_min <= m_max) {
         m = (m_min + m_max) >> 1;
         tb = &tbs[m];
-        v = (unsigned long)tb->tc_ptr;
+        v = (uintptr_t)tb->tc_ptr;
         if (v == tc_ptr)
             return tb;
         else if (tc_ptr < v) {
@@ -1419,8 +1422,8 @@ static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
     if (tb1 != NULL) {
         /* find head of list */
         for(;;) {
-            n1 = (long)tb1 & 3;
-            tb1 = (TranslationBlock *)((long)tb1 & ~3);
+            n1 = (uintptr_t)tb1 & 3;
+            tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3);
             if (n1 == 2)
                 break;
             tb1 = tb1->jmp_next[n1];
@@ -1432,8 +1435,8 @@ static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
         ptb = &tb_next->jmp_first;
         for(;;) {
             tb1 = *ptb;
-            n1 = (long)tb1 & 3;
-            tb1 = (TranslationBlock *)((long)tb1 & ~3);
+            n1 = (uintptr_t)tb1 & 3;
+            tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3);
             if (n1 == n && tb1 == tb)
                 break;
             ptb = &tb1->jmp_next[n1];
@@ -2040,9 +2043,9 @@ static bool tlb_is_dirty_ram(CPUTLBEntry *tlbe)
 }
 
 static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
-                                         unsigned long start, unsigned long length)
+                                         uintptr_t start, uintptr_t length)
 {
-    unsigned long addr;
+    uintptr_t addr;
     if (tlb_is_dirty_ram(tlb_entry)) {
         addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
         if ((addr - start) < length) {
@@ -2056,7 +2059,7 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
                                      int dirty_flags)
 {
     CPUArchState *env;
-    unsigned long length, start1;
+    uintptr_t length, start1;
     int i;
 
     start &= TARGET_PAGE_MASK;
@@ -2069,10 +2072,10 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
 
     /* we modify the TLB cache so that the dirty bit will be set again
        when accessing the range */
-    start1 = (unsigned long)qemu_safe_ram_ptr(start);
+    start1 = (uintptr_t)qemu_safe_ram_ptr(start);
     /* Check that we don't span multiple blocks - this breaks the
        address comparisons below.  */
-    if ((unsigned long)qemu_safe_ram_ptr(end - 1) - start1
+    if ((uintptr_t)qemu_safe_ram_ptr(end - 1) - start1
             != (end - 1) - start) {
         abort();
     }
@@ -2100,7 +2103,7 @@ static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
     void *p;
 
     if (tlb_is_dirty_ram(tlb_entry)) {
-        p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
+        p = (void *)(uintptr_t)((tlb_entry->addr_write & TARGET_PAGE_MASK)
             + tlb_entry->addend);
         ram_addr = qemu_ram_addr_from_host_nofail(p);
         if (!cpu_physical_memory_is_dirty(ram_addr)) {
@@ -2190,7 +2193,7 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr,
     unsigned int index;
     target_ulong address;
     target_ulong code_address;
-    unsigned long addend;
+    uintptr_t addend;
     CPUTLBEntry *te;
     CPUWatchpoint *wp;
     target_phys_addr_t iotlb;
@@ -2212,7 +2215,7 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr,
         address |= TLB_MMIO;
     }
     if (is_ram_rom_romd(section)) {
-        addend = (unsigned long)memory_region_get_ram_ptr(section->mr)
+        addend = (uintptr_t)memory_region_get_ram_ptr(section->mr)
                                  + section_addr(section, paddr);
     } else {
         addend = 0;
@@ -2302,7 +2305,7 @@ struct walk_memory_regions_data
 {
     walk_memory_regions_fn fn;
     void *priv;
-    unsigned long start;
+    uintptr_t start;
     int prot;
 };
 
@@ -2363,7 +2366,7 @@ static int walk_memory_regions_1(struct walk_memory_regions_data *data,
 int walk_memory_regions(void *priv, walk_memory_regions_fn fn)
 {
     struct walk_memory_regions_data data;
-    unsigned long i;
+    uintptr_t i;
 
     data.fn = fn;
     data.priv = priv;
@@ -2551,7 +2554,7 @@ int page_unprotect(target_ulong address, uintptr_t pc, void *puc)
 }
 
 static inline void tlb_set_dirty(CPUArchState *env,
-                                 unsigned long addr, target_ulong vaddr)
+                                 uintptr_t addr, target_ulong vaddr)
 {
 }
 #endif /* defined(CONFIG_USER_ONLY) */
commit 23ddbf08bfe3cf3e9d6993bd7918b6c4339ba2bb
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sun Apr 15 21:02:09 2012 +0200

    softmmu: Use uintptr_t for physaddr and rename it
    
    Variable physaddr is a host address which should be represented by
    data type 'uintptr_t'.
    
    This is needed for w64 and changes nothing for other hosts.
    
    v2:
    Rename physaddr -> hostaddr (suggested by Blue Swirl).
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/softmmu_header.h b/softmmu_header.h
index 6b72093..289dae2 100644
--- a/softmmu_header.h
+++ b/softmmu_header.h
@@ -99,7 +99,6 @@ glue(glue(glue(CPU_PREFIX, ld), USUFFIX), MEMSUFFIX)(ENV_PARAM
     int page_index;
     RES_TYPE res;
     target_ulong addr;
-    unsigned long physaddr;
     int mmu_idx;
 
     addr = ptr;
@@ -111,8 +110,8 @@ glue(glue(glue(CPU_PREFIX, ld), USUFFIX), MEMSUFFIX)(ENV_PARAM
                                                                      addr,
                                                                      mmu_idx);
     } else {
-        physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
-        res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr);
+        uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
+        res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)hostaddr);
     }
     return res;
 }
@@ -124,7 +123,6 @@ glue(glue(glue(CPU_PREFIX, lds), SUFFIX), MEMSUFFIX)(ENV_PARAM
 {
     int res, page_index;
     target_ulong addr;
-    unsigned long physaddr;
     int mmu_idx;
 
     addr = ptr;
@@ -135,8 +133,8 @@ glue(glue(glue(CPU_PREFIX, lds), SUFFIX), MEMSUFFIX)(ENV_PARAM
         res = (DATA_STYPE)glue(glue(glue(HELPER_PREFIX, ld), SUFFIX),
                                MMUSUFFIX)(ENV_VAR addr, mmu_idx);
     } else {
-        physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
-        res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr);
+        uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
+        res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)hostaddr);
     }
     return res;
 }
@@ -152,7 +150,6 @@ glue(glue(glue(CPU_PREFIX, st), SUFFIX), MEMSUFFIX)(ENV_PARAM target_ulong ptr,
 {
     int page_index;
     target_ulong addr;
-    unsigned long physaddr;
     int mmu_idx;
 
     addr = ptr;
@@ -163,8 +160,8 @@ glue(glue(glue(CPU_PREFIX, st), SUFFIX), MEMSUFFIX)(ENV_PARAM target_ulong ptr,
         glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_VAR addr, v,
                                                                mmu_idx);
     } else {
-        physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
-        glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v);
+        uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
+        glue(glue(st, SUFFIX), _raw)((uint8_t *)hostaddr, v);
     }
 }
 
commit 3b2992e42f8945f4bc6b9151f83dbf2bb5bcd538
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Apr 12 20:29:36 2012 +0200

    w64: Fix struct CPUTLBEntry
    
    For w64, some entries need 'uintptr_t' instead of 'unsigned long'.
    
    For other host systems, both data types are identical, so nothing changes.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/cpu-defs.h b/cpu-defs.h
index 88d8093..f49e950 100644
--- a/cpu-defs.h
+++ b/cpu-defs.h
@@ -98,12 +98,12 @@ typedef struct CPUTLBEntry {
     target_ulong addr_code;
     /* Addend to virtual address to get host address.  IO accesses
        use the corresponding iotlb value.  */
-    unsigned long addend;
+    uintptr_t addend;
     /* padding to get a power of two size */
-    uint8_t dummy[(1 << CPU_TLB_ENTRY_BITS) - 
-                  (sizeof(target_ulong) * 3 + 
-                   ((-sizeof(target_ulong) * 3) & (sizeof(unsigned long) - 1)) + 
-                   sizeof(unsigned long))];
+    uint8_t dummy[(1 << CPU_TLB_ENTRY_BITS) -
+                  (sizeof(target_ulong) * 3 +
+                   ((-sizeof(target_ulong) * 3) & (sizeof(uintptr_t) - 1)) +
+                   sizeof(uintptr_t))];
 } CPUTLBEntry;
 
 extern int CPUTLBEntry_wrong_size[sizeof(CPUTLBEntry) == (1 << CPU_TLB_ENTRY_BITS) ? 1 : -1];
commit 5cf6dd51abb252d25cb77d3b7a95a744bed1a69c
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Apr 12 21:13:28 2012 +0200

    w64: Fix definition of setjmp
    
    The default definition of setjmp which is implemented in MinGW-w64
    cannot be used with programs like QEMU which call longjmp from
    code without structured exception handling (SEH).
    
    This code therefore disables stack unwinding.
    
    We could also implement SEH for QEMU's generated JIT code, but
    that is much more difficult. Stack unwinding would also cost
    execution time.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index b6533c0..753679b 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -56,6 +56,15 @@
 # define EWOULDBLOCK  WSAEWOULDBLOCK
 #endif
 
+#if defined(_WIN64)
+/* On w64, setjmp is implemented by _setjmp which needs a second parameter.
+ * If this parameter is NULL, longjump does no stack unwinding.
+ * That is what we need for QEMU. Passing the value of register rsp (default)
+ * lets longjmp try a stack unwinding which will crash with generated code. */
+# undef setjmp
+# define setjmp(env) _setjmp(env, NULL)
+#endif
+
 /* Declaration of ffs() is missing in MinGW's strings.h. */
 int ffs(int i);
 
commit acf126ba58425f11e74fbb9c1095224cb142fffa
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Apr 12 21:13:15 2012 +0200

    w32: Move defines for socket specific errors to qemu-os-win32.h
    
    As those defines are only used for w32,
    they should be in the header file for w32.
    
    All files which include slirp.h or qemu_socket.h also
    include qemu-os-win32.h.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index 8eda4bd..b6533c0 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -30,6 +30,32 @@
 #include <winsock2.h>
 #include "main-loop.h"
 
+/* Workaround for older versions of MinGW. */
+#ifndef ECONNREFUSED
+# define ECONNREFUSED WSAECONNREFUSED
+#endif
+#ifndef EINPROGRESS
+# define EINPROGRESS  WSAEINPROGRESS
+#endif
+#ifndef EHOSTUNREACH
+# define EHOSTUNREACH WSAEHOSTUNREACH
+#endif
+#ifndef EINTR
+# define EINTR        WSAEINTR
+#endif
+#ifndef EINPROGRESS
+# define EINPROGRESS  WSAEINPROGRESS
+#endif
+#ifndef ENETUNREACH
+# define ENETUNREACH  WSAENETUNREACH
+#endif
+#ifndef ENOTCONN
+# define ENOTCONN     WSAENOTCONN
+#endif
+#ifndef EWOULDBLOCK
+# define EWOULDBLOCK  WSAEWOULDBLOCK
+#endif
+
 /* Declaration of ffs() is missing in MinGW's strings.h. */
 int ffs(int i);
 
diff --git a/qemu_socket.h b/qemu_socket.h
index 51ad210..a5d0a84 100644
--- a/qemu_socket.h
+++ b/qemu_socket.h
@@ -8,12 +8,6 @@
 #include <ws2tcpip.h>
 
 #define socket_error() WSAGetLastError()
-#undef EWOULDBLOCK
-#undef EINTR
-#undef EINPROGRESS
-#define EWOULDBLOCK WSAEWOULDBLOCK
-#define EINTR       WSAEINTR
-#define EINPROGRESS WSAEINPROGRESS
 
 int inet_aton(const char *cp, struct in_addr *ia);
 
diff --git a/slirp/slirp.h b/slirp/slirp.h
index 46bfe46..f2c5eca 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -15,18 +15,6 @@ typedef char *caddr_t;
 # include <sys/timeb.h>
 # include <iphlpapi.h>
 
-# undef EWOULDBLOCK
-# undef EINPROGRESS
-# undef ENOTCONN
-# undef EHOSTUNREACH
-# undef ENETUNREACH
-# undef ECONNREFUSED
-# define EWOULDBLOCK WSAEWOULDBLOCK
-# define EINPROGRESS WSAEINPROGRESS
-# define ENOTCONN WSAENOTCONN
-# define EHOSTUNREACH WSAEHOSTUNREACH
-# define ENETUNREACH WSAENETUNREACH
-# define ECONNREFUSED WSAECONNREFUSED
 #else
 # define ioctlsocket ioctl
 # define closesocket(s) close(s)
commit 6840981dfb76a1a1d2401efdb237ed5ddac8bf2f
Author: Stefan Weil <sw at weilnetz.de>
Date:   Wed Apr 4 07:45:21 2012 +0200

    w64: Use larger alignment for section with generated code
    
    The MinGW-w64 compiler allows __attribute__((aligned (32)).
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/exec.c b/exec.c
index 3dda2ca..6d10595 100644
--- a/exec.c
+++ b/exec.c
@@ -93,8 +93,7 @@ spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
 #define code_gen_section                                \
     __attribute__((__section__(".gen_code")))           \
     __attribute__((aligned (32)))
-#elif defined(_WIN32)
-/* Maximum alignment for Win32 is 16. */
+#elif defined(_WIN32) && !defined(_WIN64)
 #define code_gen_section                                \
     __attribute__((aligned (16)))
 #else
commit c6d506742fd997a29b611fda11f67c53d60dd5ef
Author: Stefan Weil <sw at weilnetz.de>
Date:   Fri Mar 16 20:23:49 2012 +0100

    w64: Fix data types in cpu-all.h, exec.c
    
    w64 needs uintptr_t instead of unsigned long.
    For other hosts, nothing changes.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/cpu-all.h b/cpu-all.h
index 58420be..f7d6867 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -299,10 +299,10 @@ extern unsigned long reserved_va;
 #define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1)
 #define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK)
 
-/* ??? These should be the larger of unsigned long and target_ulong.  */
-extern unsigned long qemu_real_host_page_size;
-extern unsigned long qemu_host_page_size;
-extern unsigned long qemu_host_page_mask;
+/* ??? These should be the larger of uintptr_t and target_ulong.  */
+extern uintptr_t qemu_real_host_page_size;
+extern uintptr_t qemu_host_page_size;
+extern uintptr_t qemu_host_page_mask;
 
 #define HOST_PAGE_ALIGN(addr) (((addr) + qemu_host_page_size - 1) & qemu_host_page_mask)
 
diff --git a/exec.c b/exec.c
index 68b8a6a..3dda2ca 100644
--- a/exec.c
+++ b/exec.c
@@ -177,9 +177,9 @@ typedef struct PageDesc {
 
 #define V_L1_SHIFT (L1_MAP_ADDR_SPACE_BITS - TARGET_PAGE_BITS - V_L1_BITS)
 
-unsigned long qemu_real_host_page_size;
-unsigned long qemu_host_page_size;
-unsigned long qemu_host_page_mask;
+uintptr_t qemu_real_host_page_size;
+uintptr_t qemu_host_page_size;
+uintptr_t qemu_host_page_mask;
 
 /* This is a multi-level map on the virtual address space.
    The bottom level has pointers to PageDesc.  */
commit 27b0dc16b4e50b59aeefff2bfa73cf2eb8c7a70d
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sun Apr 15 15:18:29 2012 +0200

    w64: Fix type casts used in some macros in cpu-all.h
    
    Instead of type casts to long, w64 needs type casts to intptr_t.
    For other hosts, this changes nothing.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/cpu-all.h b/cpu-all.h
index 4512518..58420be 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -222,8 +222,8 @@ extern unsigned long reserved_va;
 #else /* !CONFIG_USER_ONLY */
 /* NOTE: we use double casts if pointers and target_ulong have
    different sizes */
-#define saddr(x) (uint8_t *)(long)(x)
-#define laddr(x) (uint8_t *)(long)(x)
+#define saddr(x) (uint8_t *)(intptr_t)(x)
+#define laddr(x) (uint8_t *)(intptr_t)(x)
 #endif
 
 #define ldub_raw(p) ldub_p(laddr((p)))
commit 8d918718edcd6753aa12be96b71d1bd4fb6ed7cd
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Apr 12 20:46:32 2012 +0200

    tcg/i386: Add support for w64 ABI
    
    w64 uses the registers rcx, rdx, r8 and r9 for function arguments,
    so it needs a different declaration of tcg_target_call_iarg_regs.
    
    rax, rcx, rdx, r8, r9, r10 and r11 may be changed by function calls.
    
    rbx, rbp, rdi, rsi, r12, r13, r14 and r15 remain unchanged by function calls.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 79545e3..da17bba 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -63,10 +63,15 @@ static const int tcg_target_reg_alloc_order[] = {
 
 static const int tcg_target_call_iarg_regs[] = {
 #if TCG_TARGET_REG_BITS == 64
+#if defined(_WIN64)
+    TCG_REG_RCX,
+    TCG_REG_RDX,
+#else
     TCG_REG_RDI,
     TCG_REG_RSI,
     TCG_REG_RDX,
     TCG_REG_RCX,
+#endif
     TCG_REG_R8,
     TCG_REG_R9,
 #else
@@ -176,10 +181,10 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
         ct->ct |= TCG_CT_REG;
         if (TCG_TARGET_REG_BITS == 64) {
             tcg_regset_set32(ct->u.regs, 0, 0xffff);
-            tcg_regset_reset_reg(ct->u.regs, TCG_REG_RSI);
-            tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDI);
+            tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[0]);
+            tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[1]);
 #ifdef CONFIG_TCG_PASS_AREG0
-            tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDX);
+            tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[2]);
 #endif
         } else {
             tcg_regset_set32(ct->u.regs, 0, 0xff);
@@ -1300,9 +1305,12 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
                use the ADDR32 prefix.  For now, do nothing.  */
 
             if (offset != GUEST_BASE) {
-                tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_RDI, GUEST_BASE);
-                tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_RDI, base);
-                base = TCG_REG_RDI, offset = 0;
+                tcg_out_movi(s, TCG_TYPE_I64,
+                             tcg_target_call_iarg_regs[0], GUEST_BASE);
+                tgen_arithr(s, ARITH_ADD + P_REXW,
+                            tcg_target_call_iarg_regs[0], base);
+                base = tcg_target_call_iarg_regs[0];
+                offset = 0;
             }
         }
 
@@ -1434,8 +1442,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
 #endif
 #else
     tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32),
-                TCG_REG_RSI, data_reg);
-    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index);
+                tcg_target_call_iarg_regs[1], data_reg);
+    tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2], mem_index);
     stack_adjust = 0;
 #ifdef CONFIG_TCG_PASS_AREG0
     /* XXX/FIXME: suboptimal */
@@ -1474,9 +1482,12 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
                use the ADDR32 prefix.  For now, do nothing.  */
 
             if (offset != GUEST_BASE) {
-                tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_RDI, GUEST_BASE);
-                tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_RDI, base);
-                base = TCG_REG_RDI, offset = 0;
+                tcg_out_movi(s, TCG_TYPE_I64,
+                             tcg_target_call_iarg_regs[0], GUEST_BASE);
+                tgen_arithr(s, ARITH_ADD + P_REXW,
+                            tcg_target_call_iarg_regs[0], base);
+                base = tcg_target_call_iarg_regs[0];
+                offset = 0;
             }
         }
 
@@ -1977,6 +1988,10 @@ static int tcg_target_callee_save_regs[] = {
 #if TCG_TARGET_REG_BITS == 64
     TCG_REG_RBP,
     TCG_REG_RBX,
+#if defined(_WIN64)
+    TCG_REG_RDI,
+    TCG_REG_RSI,
+#endif
     TCG_REG_R12,
     TCG_REG_R13,
     TCG_REG_R14, /* Currently used for the global env. */
@@ -2064,8 +2079,10 @@ static void tcg_target_init(TCGContext *s)
     tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EDX);
     tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_ECX);
     if (TCG_TARGET_REG_BITS == 64) {
+#if !defined(_WIN64)
         tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RDI);
         tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RSI);
+#endif
         tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R8);
         tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R9);
         tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R10);
commit c170cb66490aa20bfc8d2c2421481dd9195dbb8b
Author: Stefan Weil <sw at weilnetz.de>
Date:   Fri Apr 6 08:06:41 2012 +0200

    tcg/i386: Use GDB JIT debugging interface only for hosts with ELF
    
    Not all i386 / x86_64 hosts use ELF.
    Ask the compiler whether ELF is used.
    
    On w64, gdb crashes when ELF_HOST_MACHINE is defined.
    
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Acked-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 871a7e7..79545e3 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -2102,7 +2102,9 @@ typedef struct {
     DebugFrameFDE fde;
 } DebugFrame;
 
-#if TCG_TARGET_REG_BITS == 64
+#if !defined(__ELF__)
+    /* Host machine without ELF. */
+#elif TCG_TARGET_REG_BITS == 64
 #define ELF_HOST_MACHINE EM_X86_64
 static DebugFrame debug_frame = {
     .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
@@ -2156,6 +2158,7 @@ static DebugFrame debug_frame = {
 };
 #endif
 
+#if defined(ELF_HOST_MACHINE)
 void tcg_register_jit(void *buf, size_t buf_size)
 {
     /* We're expecting a 2 byte uleb128 encoded value.  */
@@ -2166,3 +2169,4 @@ void tcg_register_jit(void *buf, size_t buf_size)
 
     tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
 }
+#endif
commit 4d0365165dd831b9f5d305a1480447dd83810a55
Merge: b79b38e... c17491b...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Apr 15 18:39:55 2012 +0000

    Merge branch 'ppc-for-upstream' of git://repo.or.cz/qemu/agraf
    
    * 'ppc-for-upstream' of git://repo.or.cz/qemu/agraf:
      pseries: Fix reset of VIO network device
      pseries: Reset vscsi properly
      pseries: Correctly use the device model reset hooks
      pseries: Remove old hcalls hook stub
      pseries: Remove old debug leftovers from spapr_vscsi
      pseries: Fix RTAS based config access
      target-ppc/machine.c: Drop unnecessary ifdefs
      target-ppc: Init dcache and icache size for e500 user mode
      target-ppc: Fix type casts for w64 (uintptr_t)
      target-ppc: QOM'ify CPU reset
      target-ppc: Start QOM'ifying CPU init
      target-ppc: QOM'ify CPU
      target-ppc: Add hooks for handling tcg and kvm limitations
      target-ppc: Drop cpu_ppc_close()
      pseries: Consolidate hack for RTAS display-character usage
      pseries: Remove unused fields from VIOsPAPRBus structure
      pseries: Implement RTAS system-reboot call
      pseries: Fix bug with reset of VIO CRQs
      pseries: Clean up hcall_dprintf() debugging messages
      PPC: Fix TLB invalidation bug within the PPC interrupt handler.

commit c17491b63e198ac48d533f8a9d301d11c5880a36
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Thu Apr 12 12:44:15 2012 +1000

    pseries: Fix reset of VIO network device
    
    Currently, the PAPR VIO network device does not have a reset handler.  This
    means that after a hard reset, H_REGISTER_LOGICAL_LAN will return an error
    when the new guest boot attempts to initialize the device.
    
    This patch corrects this, adding a suitable reset hook.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/spapr_llan.c b/hw/spapr_llan.c
index 32dce17..e18d2eb 100644
--- a/hw/spapr_llan.c
+++ b/hw/spapr_llan.c
@@ -182,6 +182,15 @@ static NetClientInfo net_spapr_vlan_info = {
     .receive = spapr_vlan_receive,
 };
 
+static void spapr_vlan_reset(VIOsPAPRDevice *sdev)
+{
+    VIOsPAPRVLANDevice *dev = DO_UPCAST(VIOsPAPRVLANDevice, sdev, sdev);
+
+    dev->buf_list = 0;
+    dev->rx_bufs = 0;
+    dev->isopen = 0;
+}
+
 static int spapr_vlan_init(VIOsPAPRDevice *sdev)
 {
     VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev;
@@ -335,9 +344,7 @@ static target_ulong h_free_logical_lan(CPUPPCState *env, sPAPREnvironment *spapr
         return H_RESOURCE;
     }
 
-    dev->buf_list = 0;
-    dev->rx_bufs = 0;
-    dev->isopen = 0;
+    spapr_vlan_reset(sdev);
     return H_SUCCESS;
 }
 
@@ -484,6 +491,7 @@ static void spapr_vlan_class_init(ObjectClass *klass, void *data)
     VIOsPAPRDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
 
     k->init = spapr_vlan_init;
+    k->reset = spapr_vlan_reset;
     k->devnode = spapr_vlan_devnode;
     k->dt_name = "l-lan";
     k->dt_type = "network";
commit 3cabba609de07e06b3dacf4f30403f6e9e293f2c
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Thu Apr 12 12:44:14 2012 +1000

    pseries: Reset vscsi properly
    
    Currently the PAPR vscsi implementation does not properly clear its table
    of request tags when the system is reset.  This patch adds a reset hook
    to do so.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c
index 3530a38..538e0b7 100644
--- a/hw/spapr_vscsi.c
+++ b/hw/spapr_vscsi.c
@@ -893,16 +893,20 @@ static const struct SCSIBusInfo vscsi_scsi_info = {
     .cancel = vscsi_request_cancelled
 };
 
-static int spapr_vscsi_init(VIOsPAPRDevice *dev)
+static void spapr_vscsi_reset(VIOsPAPRDevice *dev)
 {
     VSCSIState *s = DO_UPCAST(VSCSIState, vdev, dev);
     int i;
 
-    /* Initialize qemu request tags */
     memset(s->reqs, 0, sizeof(s->reqs));
     for (i = 0; i < VSCSI_REQ_LIMIT; i++) {
         s->reqs[i].qtag = i;
     }
+}
+
+static int spapr_vscsi_init(VIOsPAPRDevice *dev)
+{
+    VSCSIState *s = DO_UPCAST(VSCSIState, vdev, dev);
 
     dev->crq.SendFunc = vscsi_do_crq;
 
@@ -952,6 +956,7 @@ static void spapr_vscsi_class_init(ObjectClass *klass, void *data)
     VIOsPAPRDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
 
     k->init = spapr_vscsi_init;
+    k->reset = spapr_vscsi_reset;
     k->devnode = spapr_vscsi_devnode;
     k->dt_name = "v-scsi";
     k->dt_type = "vscsi";
commit b1c7f725a3bc5fec87912e907066edd6b80b878c
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Thu Apr 12 12:44:13 2012 +1000

    pseries: Correctly use the device model reset hooks
    
    Recently we added code to properly clean away VIO CRQs on reset  However,
    this directly uses qemu_register, rather than the existing device model
    reset callbacks.  This patch cleans this up by adding proper use of the
    reset hook to the VIO bus model.  The existing CRQ reset code is converted
    to the new method.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index 0bf2c31..fccf48b 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -648,13 +648,18 @@ static int spapr_vio_check_reg(VIOsPAPRDevice *sdev)
     return 0;
 }
 
-static void spapr_vio_busdev_reset(void *opaque)
+static void spapr_vio_busdev_reset(DeviceState *qdev)
 {
-    VIOsPAPRDevice *dev = (VIOsPAPRDevice *)opaque;
+    VIOsPAPRDevice *dev = DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
+    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
 
     if (dev->crq.qsize) {
         free_crq(dev);
     }
+
+    if (pc->reset) {
+        pc->reset(dev);
+    }
 }
 
 static int spapr_vio_busdev_init(DeviceState *qdev)
@@ -685,8 +690,6 @@ static int spapr_vio_busdev_init(DeviceState *qdev)
 
     rtce_init(dev);
 
-    qemu_register_reset(spapr_vio_busdev_reset, dev);
-
     return pc->init(dev);
 }
 
@@ -776,6 +779,7 @@ static void vio_spapr_device_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *k = DEVICE_CLASS(klass);
     k->init = spapr_vio_busdev_init;
+    k->reset = spapr_vio_busdev_reset;
     k->bus_info = &spapr_vio_bus_info;
 }
 
diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h
index 626d04f..10ab359 100644
--- a/hw/spapr_vio.h
+++ b/hw/spapr_vio.h
@@ -64,6 +64,7 @@ typedef struct VIOsPAPRDeviceClass {
     const char *dt_name, *dt_type, *dt_compatible;
     target_ulong signal_mask;
     int (*init)(VIOsPAPRDevice *dev);
+    void (*reset)(VIOsPAPRDevice *dev);
     int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off);
 } VIOsPAPRDeviceClass;
 
commit 91067bf8689ad4a4489a5080812619a9eb932716
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Thu Apr 12 12:44:12 2012 +1000

    pseries: Remove old hcalls hook stub
    
    Some time ago we removed all use of the 'hcalls' callback in the pseries
    VIO code, which was used to workaround an ordering problem which has since
    been solved properly.  However, the function pointer for the hook remains.
    This patch cleans it away.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h
index fd29c5e..626d04f 100644
--- a/hw/spapr_vio.h
+++ b/hw/spapr_vio.h
@@ -64,7 +64,6 @@ typedef struct VIOsPAPRDeviceClass {
     const char *dt_name, *dt_type, *dt_compatible;
     target_ulong signal_mask;
     int (*init)(VIOsPAPRDevice *dev);
-    void (*hcalls)(VIOsPAPRBus *bus);
     int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off);
 } VIOsPAPRDeviceClass;
 
commit e2d9154dfab73c36ead3cd368e7bc702dfb2ab68
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Thu Apr 12 12:44:11 2012 +1000

    pseries: Remove old debug leftovers from spapr_vscsi
    
    The PAPR VSCSI emulation contains a few lines of code which were once used
    for debug but now do nothing at all.  This patch removes them.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c
index 2167017..3530a38 100644
--- a/hw/spapr_vscsi.c
+++ b/hw/spapr_vscsi.c
@@ -99,10 +99,6 @@ typedef struct {
     vscsi_req reqs[VSCSI_REQ_LIMIT];
 } VSCSIState;
 
-/* XXX Debug only */
-static VSCSIState *dbg_vscsi_state;
-
-
 static struct vscsi_req *vscsi_get_req(VSCSIState *s)
 {
     vscsi_req *req;
@@ -902,8 +898,6 @@ static int spapr_vscsi_init(VIOsPAPRDevice *dev)
     VSCSIState *s = DO_UPCAST(VSCSIState, vdev, dev);
     int i;
 
-    dbg_vscsi_state = s;
-
     /* Initialize qemu request tags */
     memset(s->reqs, 0, sizeof(s->reqs));
     for (i = 0; i < VSCSI_REQ_LIMIT; i++) {
commit 92615a5ab96cd2b4981e2aaef40bece6cd7553b6
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Mon Apr 2 14:17:35 2012 +1000

    pseries: Fix RTAS based config access
    
    On the pseries platform, access to PCI config space is via RTAS calls(
    which go to the hypervisor) rather than MMIO.  This means we don't use
    the same code path as nearly everyone else which goes through pci_host.c
    and we're missing some of the parameter checking along the way.
    
    We do have some parameter checking in the RTAS calls, but it's not enough.
    It checks for overruns, but does not check for unaligned accesses,
    oversized accesses (which means the guest could trigger an assertion
    failure from pci_host_config_{read,write}_common().  Worse it doesn't do
    the basic checking for the number of RTAS arguments and results before
    accessing them.
    
    This patch fixes these bugs.
    
    Cc: Michael S. Tsirkin <mst at redhat.com>
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    [AF: Fix typos spotted by mst]
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index e7ef551..a564c00 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -57,26 +57,38 @@ static PCIDevice *find_dev(sPAPREnvironment *spapr,
 
 static uint32_t rtas_pci_cfgaddr(uint32_t arg)
 {
+    /* This handles the encoding of extended config space addresses */
     return ((arg >> 20) & 0xf00) | (arg & 0xff);
 }
 
-static uint32_t rtas_read_pci_config_do(PCIDevice *pci_dev, uint32_t addr,
-                                        uint32_t limit, uint32_t len)
+static void finish_read_pci_config(sPAPREnvironment *spapr, uint64_t buid,
+                                   uint32_t addr, uint32_t size,
+                                   target_ulong rets)
 {
-    if ((addr + len) <= limit) {
-        return pci_host_config_read_common(pci_dev, addr, limit, len);
-    } else {
-        return ~0x0;
+    PCIDevice *pci_dev;
+    uint32_t val;
+
+    if ((size != 1) && (size != 2) && (size != 4)) {
+        /* access must be 1, 2 or 4 bytes */
+        rtas_st(rets, 0, -1);
+        return;
     }
-}
 
-static void rtas_write_pci_config_do(PCIDevice *pci_dev, uint32_t addr,
-                                     uint32_t limit, uint32_t val,
-                                     uint32_t len)
-{
-    if ((addr + len) <= limit) {
-        pci_host_config_write_common(pci_dev, addr, limit, val, len);
+    pci_dev = find_dev(spapr, buid, addr);
+    addr = rtas_pci_cfgaddr(addr);
+
+    if (!pci_dev || (addr % size) || (addr >= pci_config_size(pci_dev))) {
+        /* Access must be to a valid device, within bounds and
+         * naturally aligned */
+        rtas_st(rets, 0, -1);
+        return;
     }
+
+    val = pci_host_config_read_common(pci_dev, addr,
+                                      pci_config_size(pci_dev), size);
+
+    rtas_st(rets, 0, 0);
+    rtas_st(rets, 1, val);
 }
 
 static void rtas_ibm_read_pci_config(sPAPREnvironment *spapr,
@@ -84,19 +96,19 @@ static void rtas_ibm_read_pci_config(sPAPREnvironment *spapr,
                                      target_ulong args,
                                      uint32_t nret, target_ulong rets)
 {
-    uint32_t val, size, addr;
-    uint64_t buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
-    PCIDevice *dev = find_dev(spapr, buid, rtas_ld(args, 0));
+    uint64_t buid;
+    uint32_t size, addr;
 
-    if (!dev) {
+    if ((nargs != 4) || (nret != 2)) {
         rtas_st(rets, 0, -1);
         return;
     }
+
+    buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
     size = rtas_ld(args, 3);
-    addr = rtas_pci_cfgaddr(rtas_ld(args, 0));
-    val = rtas_read_pci_config_do(dev, addr, pci_config_size(dev), size);
-    rtas_st(rets, 0, 0);
-    rtas_st(rets, 1, val);
+    addr = rtas_ld(args, 0);
+
+    finish_read_pci_config(spapr, buid, addr, size, rets);
 }
 
 static void rtas_read_pci_config(sPAPREnvironment *spapr,
@@ -104,18 +116,45 @@ static void rtas_read_pci_config(sPAPREnvironment *spapr,
                                  target_ulong args,
                                  uint32_t nret, target_ulong rets)
 {
-    uint32_t val, size, addr;
-    PCIDevice *dev = find_dev(spapr, 0, rtas_ld(args, 0));
+    uint32_t size, addr;
 
-    if (!dev) {
+    if ((nargs != 2) || (nret != 2)) {
         rtas_st(rets, 0, -1);
         return;
     }
+
     size = rtas_ld(args, 1);
-    addr = rtas_pci_cfgaddr(rtas_ld(args, 0));
-    val = rtas_read_pci_config_do(dev, addr, pci_config_size(dev), size);
+    addr = rtas_ld(args, 0);
+
+    finish_read_pci_config(spapr, 0, addr, size, rets);
+}
+
+static void finish_write_pci_config(sPAPREnvironment *spapr, uint64_t buid,
+                                    uint32_t addr, uint32_t size,
+                                    uint32_t val, target_ulong rets)
+{
+    PCIDevice *pci_dev;
+
+    if ((size != 1) && (size != 2) && (size != 4)) {
+        /* access must be 1, 2 or 4 bytes */
+        rtas_st(rets, 0, -1);
+        return;
+    }
+
+    pci_dev = find_dev(spapr, buid, addr);
+    addr = rtas_pci_cfgaddr(addr);
+
+    if (!pci_dev || (addr % size) || (addr >= pci_config_size(pci_dev))) {
+        /* Access must be to a valid device, within bounds and
+         * naturally aligned */
+        rtas_st(rets, 0, -1);
+        return;
+    }
+
+    pci_host_config_write_common(pci_dev, addr, pci_config_size(pci_dev),
+                                 val, size);
+
     rtas_st(rets, 0, 0);
-    rtas_st(rets, 1, val);
 }
 
 static void rtas_ibm_write_pci_config(sPAPREnvironment *spapr,
@@ -123,19 +162,20 @@ static void rtas_ibm_write_pci_config(sPAPREnvironment *spapr,
                                       target_ulong args,
                                       uint32_t nret, target_ulong rets)
 {
+    uint64_t buid;
     uint32_t val, size, addr;
-    uint64_t buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
-    PCIDevice *dev = find_dev(spapr, buid, rtas_ld(args, 0));
 
-    if (!dev) {
+    if ((nargs != 5) || (nret != 1)) {
         rtas_st(rets, 0, -1);
         return;
     }
+
+    buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
     val = rtas_ld(args, 4);
     size = rtas_ld(args, 3);
-    addr = rtas_pci_cfgaddr(rtas_ld(args, 0));
-    rtas_write_pci_config_do(dev, addr, pci_config_size(dev), val, size);
-    rtas_st(rets, 0, 0);
+    addr = rtas_ld(args, 0);
+
+    finish_write_pci_config(spapr, buid, addr, size, val, rets);
 }
 
 static void rtas_write_pci_config(sPAPREnvironment *spapr,
@@ -144,17 +184,18 @@ static void rtas_write_pci_config(sPAPREnvironment *spapr,
                                   uint32_t nret, target_ulong rets)
 {
     uint32_t val, size, addr;
-    PCIDevice *dev = find_dev(spapr, 0, rtas_ld(args, 0));
 
-    if (!dev) {
+    if ((nargs != 3) || (nret != 1)) {
         rtas_st(rets, 0, -1);
         return;
     }
+
+
     val = rtas_ld(args, 2);
     size = rtas_ld(args, 1);
-    addr = rtas_pci_cfgaddr(rtas_ld(args, 0));
-    rtas_write_pci_config_do(dev, addr, pci_config_size(dev), val, size);
-    rtas_st(rets, 0, 0);
+    addr = rtas_ld(args, 0);
+
+    finish_write_pci_config(spapr, 0, addr, size, val, rets);
 }
 
 static int pci_spapr_map_irq(PCIDevice *pci_dev, int irq_num)
commit b79b38e4b3199984a6ad0ead5be2431c8e804eaa
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun Apr 15 19:12:18 2012 +0400

    target-xtensa: add license to core-fsf.c
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-xtensa/core-fsf.c b/target-xtensa/core-fsf.c
index c11d970..e36b0de 100644
--- a/target-xtensa/core-fsf.c
+++ b/target-xtensa/core-fsf.c
@@ -1,3 +1,30 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
 #include "cpu.h"
 #include "exec-all.h"
 #include "gdbstub.h"
commit fbaa9fb5cbfad74e7df1230acf4b7f5cb4a9f089
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun Apr 15 19:12:17 2012 +0400

    target-xtensa: add license to core-dc232b.c
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-xtensa/core-dc232b.c b/target-xtensa/core-dc232b.c
index 7c03835..804fdef 100644
--- a/target-xtensa/core-dc232b.c
+++ b/target-xtensa/core-dc232b.c
@@ -1,3 +1,30 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
 #include "cpu.h"
 #include "exec-all.h"
 #include "gdbstub.h"
commit 176ac95ed19f7728985d3d904671732a54eb42e7
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun Apr 15 19:12:16 2012 +0400

    target-xtensa: add dc233c core
    
    This is Diamond 233L Standard Core Rev.C (LE), implemented through
    linux/gdb overlay.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 65fb8f0..3ab791a 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -416,6 +416,7 @@ obj-xtensa-y += xtensa_sim.o
 obj-xtensa-y += xtensa_lx60.o
 obj-xtensa-y += xtensa-semi.o
 obj-xtensa-y += core-dc232b.o
+obj-xtensa-y += core-dc233c.o
 obj-xtensa-y += core-fsf.o
 
 main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
diff --git a/target-xtensa/core-dc233c.c b/target-xtensa/core-dc233c.c
new file mode 100644
index 0000000..d643f41
--- /dev/null
+++ b/target-xtensa/core-dc233c.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "cpu.h"
+#include "exec-all.h"
+#include "gdbstub.h"
+#include "qemu-common.h"
+#include "host-utils.h"
+
+#include "core-dc233c/core-isa.h"
+#include "overlay_tool.h"
+
+static const XtensaConfig dc233c = {
+    .name = "dc233c",
+    .options = XTENSA_OPTIONS,
+    .gdb_regmap = {
+        .num_regs = 121,
+        .num_core_regs = 52,
+        .reg = {
+#include "core-dc233c/gdb-config.c"
+        }
+    },
+    .nareg = XCHAL_NUM_AREGS,
+    .ndepc = 1,
+    EXCEPTIONS_SECTION,
+    INTERRUPTS_SECTION,
+    TLB_SECTION,
+    .clock_freq_khz = 10000,
+};
+
+REGISTER_CORE(dc233c)
diff --git a/target-xtensa/core-dc233c/core-isa.h b/target-xtensa/core-dc233c/core-isa.h
new file mode 100644
index 0000000..e82c3cb
--- /dev/null
+++ b/target-xtensa/core-dc233c/core-isa.h
@@ -0,0 +1,474 @@
+/*
+ * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa
+ *                              processor CORE configuration
+ *
+ *  See <xtensa/config/core.h>, which includes this file, for more details.
+ */
+
+/* Xtensa processor core configuration information.
+
+   Copyright (c) 1999-2010 Tensilica Inc.
+
+   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 _XTENSA_CORE_CONFIGURATION_H
+#define _XTENSA_CORE_CONFIGURATION_H
+
+
+/****************************************************************************
+            Parameters Useful for Any Code, USER or PRIVILEGED
+ ****************************************************************************/
+
+/*
+ *  Note:  Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is
+ *  configured, and a value of 0 otherwise.  These macros are always defined.
+ */
+
+
+/*----------------------------------------------------------------------
+                                ISA
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_BE                   0       /* big-endian byte ordering */
+#define XCHAL_HAVE_WINDOWED             1       /* windowed registers option */
+#define XCHAL_NUM_AREGS                 32      /* num of physical addr regs */
+#define XCHAL_NUM_AREGS_LOG2            5       /* log2(XCHAL_NUM_AREGS) */
+#define XCHAL_MAX_INSTRUCTION_SIZE      3       /* max instr bytes (3..8) */
+#define XCHAL_HAVE_DEBUG                1       /* debug option */
+#define XCHAL_HAVE_DENSITY              1       /* 16-bit instructions */
+#define XCHAL_HAVE_LOOPS                1       /* zero-overhead loops */
+#define XCHAL_HAVE_NSA                  1       /* NSA/NSAU instructions */
+#define XCHAL_HAVE_MINMAX               1       /* MIN/MAX instructions */
+#define XCHAL_HAVE_SEXT                 1       /* SEXT instruction */
+#define XCHAL_HAVE_CLAMPS               1       /* CLAMPS instruction */
+#define XCHAL_HAVE_MUL16                1       /* MUL16S/MUL16U instructions */
+#define XCHAL_HAVE_MUL32                1       /* MULL instruction */
+#define XCHAL_HAVE_MUL32_HIGH           0       /* MULUH/MULSH instructions */
+#define XCHAL_HAVE_DIV32                1       /* QUOS/QUOU/REMS/REMU instructions */
+#define XCHAL_HAVE_L32R                 1       /* L32R instruction */
+#define XCHAL_HAVE_ABSOLUTE_LITERALS    1       /* non-PC-rel (extended) L32R */
+#define XCHAL_HAVE_CONST16              0       /* CONST16 instruction */
+#define XCHAL_HAVE_ADDX                 1       /* ADDX#/SUBX# instructions */
+#define XCHAL_HAVE_WIDE_BRANCHES        0       /* B*.W18 or B*.W15 instr's */
+#define XCHAL_HAVE_PREDICTED_BRANCHES   0       /* B[EQ/EQZ/NE/NEZ]T instr's */
+#define XCHAL_HAVE_CALL4AND12           1       /* (obsolete option) */
+#define XCHAL_HAVE_ABS                  1       /* ABS instruction */
+/*#define XCHAL_HAVE_POPC               0*/     /* POPC instruction */
+/*#define XCHAL_HAVE_CRC                0*/     /* CRC instruction */
+#define XCHAL_HAVE_RELEASE_SYNC         1       /* L32AI/S32RI instructions */
+#define XCHAL_HAVE_S32C1I               1       /* S32C1I instruction */
+#define XCHAL_HAVE_SPECULATION          0       /* speculation */
+#define XCHAL_HAVE_FULL_RESET           1       /* all regs/state reset */
+#define XCHAL_NUM_CONTEXTS              1       /* */
+#define XCHAL_NUM_MISC_REGS             2       /* num of scratch regs (0..4) */
+#define XCHAL_HAVE_TAP_MASTER           0       /* JTAG TAP control instr's */
+#define XCHAL_HAVE_PRID                 1       /* processor ID register */
+#define XCHAL_HAVE_EXTERN_REGS          1       /* WER/RER instructions */
+#define XCHAL_HAVE_MP_INTERRUPTS        0       /* interrupt distributor port */
+#define XCHAL_HAVE_MP_RUNSTALL          0       /* core RunStall control port */
+#define XCHAL_HAVE_THREADPTR            1       /* THREADPTR register */
+#define XCHAL_HAVE_BOOLEANS             0       /* boolean registers */
+#define XCHAL_HAVE_CP                   1       /* CPENABLE reg (coprocessor) */
+#define XCHAL_CP_MAXCFG                 8       /* max allowed cp id plus one */
+#define XCHAL_HAVE_MAC16                1       /* MAC16 package */
+#define XCHAL_HAVE_VECTORFPU2005        0       /* vector floating-point pkg */
+#define XCHAL_HAVE_FP                   0       /* floating point pkg */
+#define XCHAL_HAVE_DFP                  0       /* double precision FP pkg */
+#define XCHAL_HAVE_DFP_accel            0       /* double precision FP acceleration pkg */
+#define XCHAL_HAVE_VECTRA1              0       /* Vectra I  pkg */
+#define XCHAL_HAVE_VECTRALX             0       /* Vectra LX pkg */
+#define XCHAL_HAVE_HIFIPRO              0       /* HiFiPro Audio Engine pkg */
+#define XCHAL_HAVE_HIFI2                0       /* HiFi2 Audio Engine pkg */
+#define XCHAL_HAVE_HIFI2EP      0       /* HiFi2EP */
+#define XCHAL_HAVE_CONNXD2              0       /* ConnX D2 pkg */
+#define XCHAL_HAVE_BBE16                0       /* ConnX BBE16 pkg */
+#define XCHAL_HAVE_BBE16_RSQRT          0       /* BBE16 & vector recip sqrt */
+#define XCHAL_HAVE_BBE16_VECDIV         0       /* BBE16 & vector divide */
+#define XCHAL_HAVE_BBE16_DESPREAD       0       /* BBE16 & despread */
+#define XCHAL_HAVE_BSP3                 0       /* ConnX BSP3 pkg */
+#define XCHAL_HAVE_SSP16                0       /* ConnX SSP16 pkg */
+#define XCHAL_HAVE_SSP16_VITERBI        0       /* SSP16 & viterbi */
+#define XCHAL_HAVE_TURBO16              0       /* ConnX Turbo16 pkg */
+#define XCHAL_HAVE_BBP16                0       /* ConnX BBP16 pkg */
+
+
+/*----------------------------------------------------------------------
+                                MISC
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_NUM_WRITEBUFFER_ENTRIES   8       /* size of write buffer */
+#define XCHAL_INST_FETCH_WIDTH          4       /* instr-fetch width in bytes */
+#define XCHAL_DATA_WIDTH                4       /* data width in bytes */
+/*  In T1050, applies to selected core load and store instructions (see ISA): */
+#define XCHAL_UNALIGNED_LOAD_EXCEPTION  1       /* unaligned loads cause exc. */
+#define XCHAL_UNALIGNED_STORE_EXCEPTION 1       /* unaligned stores cause exc.*/
+#define XCHAL_UNALIGNED_LOAD_HW         0       /* unaligned loads work in hw */
+#define XCHAL_UNALIGNED_STORE_HW        0       /* unaligned stores work in hw*/
+
+#define XCHAL_SW_VERSION                900001  /* sw version of this header */
+
+#define XCHAL_CORE_ID                   "dc233c"        /* alphanum core name
+(CoreID) set in the Xtensa
+Processor Generator */
+
+#define XCHAL_CORE_DESCRIPTION          "dc233c"
+#define XCHAL_BUILD_UNIQUE_ID           0x00004B21      /* 22-bit sw build ID */
+
+/*
+ *  These definitions describe the hardware targeted by this software.
+ */
+#define XCHAL_HW_CONFIGID0              0xC56707FE      /* ConfigID hi 32 bits*/
+#define XCHAL_HW_CONFIGID1              0x14404B21      /* ConfigID lo 32 bits*/
+#define XCHAL_HW_VERSION_NAME           "LX4.0.1"       /* full version name */
+#define XCHAL_HW_VERSION_MAJOR          2400    /* major ver# of targeted hw */
+#define XCHAL_HW_VERSION_MINOR          1       /* minor ver# of targeted hw */
+#define XCHAL_HW_VERSION                240001  /* major*100+minor */
+#define XCHAL_HW_REL_LX4                1
+#define XCHAL_HW_REL_LX4_0              1
+#define XCHAL_HW_REL_LX4_0_1            1
+#define XCHAL_HW_CONFIGID_RELIABLE      1
+/*  If software targets a *range* of hardware versions, these are the bounds: */
+#define XCHAL_HW_MIN_VERSION_MAJOR      2400    /* major v of earliest tgt hw */
+#define XCHAL_HW_MIN_VERSION_MINOR      1       /* minor v of earliest tgt hw */
+#define XCHAL_HW_MIN_VERSION            240001  /* earliest targeted hw */
+#define XCHAL_HW_MAX_VERSION_MAJOR      2400    /* major v of latest tgt hw */
+#define XCHAL_HW_MAX_VERSION_MINOR      1       /* minor v of latest tgt hw */
+#define XCHAL_HW_MAX_VERSION            240001  /* latest targeted hw */
+
+
+/*----------------------------------------------------------------------
+                                CACHE
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_ICACHE_LINESIZE           32      /* I-cache line size in bytes */
+#define XCHAL_DCACHE_LINESIZE           32      /* D-cache line size in bytes */
+#define XCHAL_ICACHE_LINEWIDTH          5       /* log2(I line size in bytes) */
+#define XCHAL_DCACHE_LINEWIDTH          5       /* log2(D line size in bytes) */
+
+#define XCHAL_ICACHE_SIZE               16384   /* I-cache size in bytes or 0 */
+#define XCHAL_DCACHE_SIZE               16384   /* D-cache size in bytes or 0 */
+
+#define XCHAL_DCACHE_IS_WRITEBACK       1       /* writeback feature */
+#define XCHAL_DCACHE_IS_COHERENT        0       /* MP coherence feature */
+
+#define XCHAL_HAVE_PREFETCH             0       /* PREFCTL register */
+
+
+
+
+/****************************************************************************
+    Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code
+ ****************************************************************************/
+
+
+#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY
+
+/*----------------------------------------------------------------------
+                                CACHE
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_PIF                  1       /* any outbound PIF present */
+
+/*  If present, cache size in bytes == (ways * 2^(linewidth + setwidth)).  */
+
+/*  Number of cache sets in log2(lines per way):  */
+#define XCHAL_ICACHE_SETWIDTH           7
+#define XCHAL_DCACHE_SETWIDTH           7
+
+/*  Cache set associativity (number of ways):  */
+#define XCHAL_ICACHE_WAYS               4
+#define XCHAL_DCACHE_WAYS               4
+
+/*  Cache features:  */
+#define XCHAL_ICACHE_LINE_LOCKABLE      1
+#define XCHAL_DCACHE_LINE_LOCKABLE      1
+#define XCHAL_ICACHE_ECC_PARITY         0
+#define XCHAL_DCACHE_ECC_PARITY         0
+
+/*  Cache access size in bytes (affects operation of SICW instruction):  */
+#define XCHAL_ICACHE_ACCESS_SIZE        4
+#define XCHAL_DCACHE_ACCESS_SIZE        4
+
+/*  Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits):  */
+#define XCHAL_CA_BITS                   4
+
+
+/*----------------------------------------------------------------------
+                        INTERNAL I/D RAM/ROMs and XLMI
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_NUM_INSTROM               0       /* number of core instr. ROMs */
+#define XCHAL_NUM_INSTRAM               0       /* number of core instr. RAMs */
+#define XCHAL_NUM_DATAROM               0       /* number of core data ROMs */
+#define XCHAL_NUM_DATARAM               0       /* number of core data RAMs */
+#define XCHAL_NUM_URAM                  0       /* number of core unified RAMs*/
+#define XCHAL_NUM_XLMI                  0       /* number of core XLMI ports */
+
+#define XCHAL_HAVE_IMEM_LOADSTORE       1       /* can load/store to IROM/IRAM*/
+
+
+/*----------------------------------------------------------------------
+                        INTERRUPTS and TIMERS
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_INTERRUPTS           1       /* interrupt option */
+#define XCHAL_HAVE_HIGHPRI_INTERRUPTS   1       /* med/high-pri. interrupts */
+#define XCHAL_HAVE_NMI                  1       /* non-maskable interrupt */
+#define XCHAL_HAVE_CCOUNT               1       /* CCOUNT reg. (timer option) */
+#define XCHAL_NUM_TIMERS                3       /* number of CCOMPAREn regs */
+#define XCHAL_NUM_INTERRUPTS            22      /* number of interrupts */
+#define XCHAL_NUM_INTERRUPTS_LOG2       5       /* ceil(log2(NUM_INTERRUPTS)) */
+#define XCHAL_NUM_EXTINTERRUPTS         17      /* num of external interrupts */
+#define XCHAL_NUM_INTLEVELS             6       /* number of interrupt levels
+(not including level zero) */
+#define XCHAL_EXCM_LEVEL                3       /* level masked by PS.EXCM */
+/* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */
+
+/*  Masks of interrupts at each interrupt level:  */
+#define XCHAL_INTLEVEL1_MASK            0x001F80FF
+#define XCHAL_INTLEVEL2_MASK            0x00000100
+#define XCHAL_INTLEVEL3_MASK            0x00200E00
+#define XCHAL_INTLEVEL4_MASK            0x00001000
+#define XCHAL_INTLEVEL5_MASK            0x00002000
+#define XCHAL_INTLEVEL6_MASK            0x00000000
+#define XCHAL_INTLEVEL7_MASK            0x00004000
+
+/*  Masks of interrupts at each range 1..n of interrupt levels:  */
+#define XCHAL_INTLEVEL1_ANDBELOW_MASK   0x001F80FF
+#define XCHAL_INTLEVEL2_ANDBELOW_MASK   0x001F81FF
+#define XCHAL_INTLEVEL3_ANDBELOW_MASK   0x003F8FFF
+#define XCHAL_INTLEVEL4_ANDBELOW_MASK   0x003F9FFF
+#define XCHAL_INTLEVEL5_ANDBELOW_MASK   0x003FBFFF
+#define XCHAL_INTLEVEL6_ANDBELOW_MASK   0x003FBFFF
+#define XCHAL_INTLEVEL7_ANDBELOW_MASK   0x003FFFFF
+
+/*  Level of each interrupt:  */
+#define XCHAL_INT0_LEVEL                1
+#define XCHAL_INT1_LEVEL                1
+#define XCHAL_INT2_LEVEL                1
+#define XCHAL_INT3_LEVEL                1
+#define XCHAL_INT4_LEVEL                1
+#define XCHAL_INT5_LEVEL                1
+#define XCHAL_INT6_LEVEL                1
+#define XCHAL_INT7_LEVEL                1
+#define XCHAL_INT8_LEVEL                2
+#define XCHAL_INT9_LEVEL                3
+#define XCHAL_INT10_LEVEL               3
+#define XCHAL_INT11_LEVEL               3
+#define XCHAL_INT12_LEVEL               4
+#define XCHAL_INT13_LEVEL               5
+#define XCHAL_INT14_LEVEL               7
+#define XCHAL_INT15_LEVEL               1
+#define XCHAL_INT16_LEVEL               1
+#define XCHAL_INT17_LEVEL               1
+#define XCHAL_INT18_LEVEL               1
+#define XCHAL_INT19_LEVEL               1
+#define XCHAL_INT20_LEVEL               1
+#define XCHAL_INT21_LEVEL               3
+#define XCHAL_DEBUGLEVEL                6       /* debug interrupt level */
+#define XCHAL_HAVE_DEBUG_EXTERN_INT     1       /* OCD external db interrupt */
+#define XCHAL_NMILEVEL                  7       /* NMI "level" (for use with
+EXCSAVE/EPS/EPC_n, RFI n) */
+
+/*  Type of each interrupt:  */
+#define XCHAL_INT0_TYPE         XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT1_TYPE         XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT2_TYPE         XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT3_TYPE         XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT4_TYPE         XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT5_TYPE         XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT6_TYPE         XTHAL_INTTYPE_TIMER
+#define XCHAL_INT7_TYPE         XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT8_TYPE         XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT9_TYPE         XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT10_TYPE        XTHAL_INTTYPE_TIMER
+#define XCHAL_INT11_TYPE        XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT12_TYPE        XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT13_TYPE        XTHAL_INTTYPE_TIMER
+#define XCHAL_INT14_TYPE        XTHAL_INTTYPE_NMI
+#define XCHAL_INT15_TYPE        XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT16_TYPE        XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT17_TYPE        XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT18_TYPE        XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT19_TYPE        XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT20_TYPE        XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT21_TYPE        XTHAL_INTTYPE_EXTERN_EDGE
+
+/*  Masks of interrupts for each type of interrupt:  */
+#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFFC00000
+#define XCHAL_INTTYPE_MASK_SOFTWARE     0x00000880
+#define XCHAL_INTTYPE_MASK_EXTERN_EDGE  0x003F8000
+#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x0000133F
+#define XCHAL_INTTYPE_MASK_TIMER        0x00002440
+#define XCHAL_INTTYPE_MASK_NMI          0x00004000
+#define XCHAL_INTTYPE_MASK_WRITE_ERROR  0x00000000
+
+/*  Interrupt numbers assigned to specific interrupt sources:  */
+#define XCHAL_TIMER0_INTERRUPT          6       /* CCOMPARE0 */
+#define XCHAL_TIMER1_INTERRUPT          10      /* CCOMPARE1 */
+#define XCHAL_TIMER2_INTERRUPT          13      /* CCOMPARE2 */
+#define XCHAL_TIMER3_INTERRUPT          XTHAL_TIMER_UNCONFIGURED
+#define XCHAL_NMI_INTERRUPT             14      /* non-maskable interrupt */
+
+/*  Interrupt numbers for levels at which only one interrupt is configured:  */
+#define XCHAL_INTLEVEL2_NUM             8
+#define XCHAL_INTLEVEL4_NUM             12
+#define XCHAL_INTLEVEL5_NUM             13
+#define XCHAL_INTLEVEL7_NUM             14
+/*  (There are many interrupts each at level(s) 1, 3.)  */
+
+
+/*
+ *  External interrupt vectors/levels.
+ *  These macros describe how Xtensa processor interrupt numbers
+ *  (as numbered internally, eg. in INTERRUPT and INTENABLE registers)
+ *  map to external BInterrupt<n> pins, for those interrupts
+ *  configured as external (level-triggered, edge-triggered, or NMI).
+ *  See the Xtensa processor databook for more details.
+ */
+
+/*  Core interrupt numbers mapped to each EXTERNAL interrupt number:  */
+#define XCHAL_EXTINT0_NUM               0       /* (intlevel 1) */
+#define XCHAL_EXTINT1_NUM               1       /* (intlevel 1) */
+#define XCHAL_EXTINT2_NUM               2       /* (intlevel 1) */
+#define XCHAL_EXTINT3_NUM               3       /* (intlevel 1) */
+#define XCHAL_EXTINT4_NUM               4       /* (intlevel 1) */
+#define XCHAL_EXTINT5_NUM               5       /* (intlevel 1) */
+#define XCHAL_EXTINT6_NUM               8       /* (intlevel 2) */
+#define XCHAL_EXTINT7_NUM               9       /* (intlevel 3) */
+#define XCHAL_EXTINT8_NUM               12      /* (intlevel 4) */
+#define XCHAL_EXTINT9_NUM               14      /* (intlevel 7) */
+#define XCHAL_EXTINT10_NUM              15      /* (intlevel 1) */
+#define XCHAL_EXTINT11_NUM              16      /* (intlevel 1) */
+#define XCHAL_EXTINT12_NUM              17      /* (intlevel 1) */
+#define XCHAL_EXTINT13_NUM              18      /* (intlevel 1) */
+#define XCHAL_EXTINT14_NUM              19      /* (intlevel 1) */
+#define XCHAL_EXTINT15_NUM              20      /* (intlevel 1) */
+#define XCHAL_EXTINT16_NUM              21      /* (intlevel 3) */
+
+
+/*----------------------------------------------------------------------
+                        EXCEPTIONS and VECTORS
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_XEA_VERSION               2       /* Xtensa Exception Architecture
+number: 1 == XEA1 (old)
+2 == XEA2 (new)
+0 == XEAX (extern) or TX */
+#define XCHAL_HAVE_XEA1                 0       /* Exception Architecture 1 */
+#define XCHAL_HAVE_XEA2                 1       /* Exception Architecture 2 */
+#define XCHAL_HAVE_XEAX                 0       /* External Exception Arch. */
+#define XCHAL_HAVE_EXCEPTIONS           1       /* exception option */
+#define XCHAL_HAVE_HALT                 0       /* halt architecture option */
+#define XCHAL_HAVE_BOOTLOADER           0       /* boot loader (for TX) */
+#define XCHAL_HAVE_MEM_ECC_PARITY       0       /* local memory ECC/parity */
+#define XCHAL_HAVE_VECTOR_SELECT        1       /* relocatable vectors */
+#define XCHAL_HAVE_VECBASE              1       /* relocatable vectors */
+#define XCHAL_VECBASE_RESET_VADDR       0x00002000  /* VECBASE reset value */
+#define XCHAL_VECBASE_RESET_PADDR       0x00002000
+#define XCHAL_RESET_VECBASE_OVERLAP     0
+
+#define XCHAL_RESET_VECTOR0_VADDR       0xFE000000
+#define XCHAL_RESET_VECTOR0_PADDR       0xFE000000
+#define XCHAL_RESET_VECTOR1_VADDR       0x00001000
+#define XCHAL_RESET_VECTOR1_PADDR       0x00001000
+#define XCHAL_RESET_VECTOR_VADDR        0xFE000000
+#define XCHAL_RESET_VECTOR_PADDR        0xFE000000
+#define XCHAL_USER_VECOFS               0x00000340
+#define XCHAL_USER_VECTOR_VADDR         0x00002340
+#define XCHAL_USER_VECTOR_PADDR         0x00002340
+#define XCHAL_KERNEL_VECOFS             0x00000300
+#define XCHAL_KERNEL_VECTOR_VADDR       0x00002300
+#define XCHAL_KERNEL_VECTOR_PADDR       0x00002300
+#define XCHAL_DOUBLEEXC_VECOFS          0x000003C0
+#define XCHAL_DOUBLEEXC_VECTOR_VADDR    0x000023C0
+#define XCHAL_DOUBLEEXC_VECTOR_PADDR    0x000023C0
+#define XCHAL_WINDOW_OF4_VECOFS         0x00000000
+#define XCHAL_WINDOW_UF4_VECOFS         0x00000040
+#define XCHAL_WINDOW_OF8_VECOFS         0x00000080
+#define XCHAL_WINDOW_UF8_VECOFS         0x000000C0
+#define XCHAL_WINDOW_OF12_VECOFS        0x00000100
+#define XCHAL_WINDOW_UF12_VECOFS        0x00000140
+#define XCHAL_WINDOW_VECTORS_VADDR      0x00002000
+#define XCHAL_WINDOW_VECTORS_PADDR      0x00002000
+#define XCHAL_INTLEVEL2_VECOFS          0x00000180
+#define XCHAL_INTLEVEL2_VECTOR_VADDR    0x00002180
+#define XCHAL_INTLEVEL2_VECTOR_PADDR    0x00002180
+#define XCHAL_INTLEVEL3_VECOFS          0x000001C0
+#define XCHAL_INTLEVEL3_VECTOR_VADDR    0x000021C0
+#define XCHAL_INTLEVEL3_VECTOR_PADDR    0x000021C0
+#define XCHAL_INTLEVEL4_VECOFS          0x00000200
+#define XCHAL_INTLEVEL4_VECTOR_VADDR    0x00002200
+#define XCHAL_INTLEVEL4_VECTOR_PADDR    0x00002200
+#define XCHAL_INTLEVEL5_VECOFS          0x00000240
+#define XCHAL_INTLEVEL5_VECTOR_VADDR    0x00002240
+#define XCHAL_INTLEVEL5_VECTOR_PADDR    0x00002240
+#define XCHAL_INTLEVEL6_VECOFS          0x00000280
+#define XCHAL_INTLEVEL6_VECTOR_VADDR    0x00002280
+#define XCHAL_INTLEVEL6_VECTOR_PADDR    0x00002280
+#define XCHAL_DEBUG_VECOFS              XCHAL_INTLEVEL6_VECOFS
+#define XCHAL_DEBUG_VECTOR_VADDR        XCHAL_INTLEVEL6_VECTOR_VADDR
+#define XCHAL_DEBUG_VECTOR_PADDR        XCHAL_INTLEVEL6_VECTOR_PADDR
+#define XCHAL_NMI_VECOFS                0x000002C0
+#define XCHAL_NMI_VECTOR_VADDR          0x000022C0
+#define XCHAL_NMI_VECTOR_PADDR          0x000022C0
+#define XCHAL_INTLEVEL7_VECOFS          XCHAL_NMI_VECOFS
+#define XCHAL_INTLEVEL7_VECTOR_VADDR    XCHAL_NMI_VECTOR_VADDR
+#define XCHAL_INTLEVEL7_VECTOR_PADDR    XCHAL_NMI_VECTOR_PADDR
+
+
+/*----------------------------------------------------------------------
+                                DEBUG
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_OCD                  1       /* OnChipDebug option */
+#define XCHAL_NUM_IBREAK                2       /* number of IBREAKn regs */
+#define XCHAL_NUM_DBREAK                2       /* number of DBREAKn regs */
+#define XCHAL_HAVE_OCD_DIR_ARRAY        1       /* faster OCD option */
+
+
+/*----------------------------------------------------------------------
+                                MMU
+  ----------------------------------------------------------------------*/
+
+/*  See core-matmap.h header file for more details.  */
+
+#define XCHAL_HAVE_TLBS                 1       /* inverse of HAVE_CACHEATTR */
+#define XCHAL_HAVE_SPANNING_WAY         1       /* one way maps I+D 4GB vaddr */
+#define XCHAL_SPANNING_WAY              6       /* TLB spanning way number */
+#define XCHAL_HAVE_IDENTITY_MAP         0       /* vaddr == paddr always */
+#define XCHAL_HAVE_CACHEATTR            0       /* CACHEATTR register present */
+#define XCHAL_HAVE_MIMIC_CACHEATTR      0       /* region protection */
+#define XCHAL_HAVE_XLT_CACHEATTR        0       /* region prot. w/translation */
+#define XCHAL_HAVE_PTP_MMU              1       /* full MMU (with page table
+[autorefill] and protection)
+usable for an MMU-based OS */
+/*  If none of the above last 4 are set, it's a custom TLB configuration.  */
+#define XCHAL_ITLB_ARF_ENTRIES_LOG2     2       /* log2(autorefill way size) */
+#define XCHAL_DTLB_ARF_ENTRIES_LOG2     2       /* log2(autorefill way size) */
+
+#define XCHAL_MMU_ASID_BITS             8       /* number of bits in ASIDs */
+#define XCHAL_MMU_RINGS                 4       /* number of rings (1..4) */
+#define XCHAL_MMU_RING_BITS             2       /* num of bits in RING field */
+
+#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */
+
+
+#endif /* _XTENSA_CORE_CONFIGURATION_H */
diff --git a/target-xtensa/core-dc233c/gdb-config.c b/target-xtensa/core-dc233c/gdb-config.c
new file mode 100644
index 0000000..b632341
--- /dev/null
+++ b/target-xtensa/core-dc233c/gdb-config.c
@@ -0,0 +1,145 @@
+/* Configuration for the Xtensa architecture for GDB, the GNU debugger.
+
+   Copyright (c) 2003-2010 Tensilica Inc.
+
+   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.  */
+
+/*    idx ofs bi sz al targno  flags cp typ group name  */
+XTREG(0,  0, 32, 4, 4, 0x0020, 0x0006, -2, 9, 0x0100, pc,          0, 0, 0, 0, 0, 0)
+XTREG(1,  4, 32, 4, 4, 0x0100, 0x0006, -2, 1, 0x0002, ar0,         0, 0, 0, 0, 0, 0)
+XTREG(2,  8, 32, 4, 4, 0x0101, 0x0006, -2, 1, 0x0002, ar1,         0, 0, 0, 0, 0, 0)
+XTREG(3, 12, 32, 4, 4, 0x0102, 0x0006, -2, 1, 0x0002, ar2,         0, 0, 0, 0, 0, 0)
+XTREG(4, 16, 32, 4, 4, 0x0103, 0x0006, -2, 1, 0x0002, ar3,         0, 0, 0, 0, 0, 0)
+XTREG(5, 20, 32, 4, 4, 0x0104, 0x0006, -2, 1, 0x0002, ar4,         0, 0, 0, 0, 0, 0)
+XTREG(6, 24, 32, 4, 4, 0x0105, 0x0006, -2, 1, 0x0002, ar5,         0, 0, 0, 0, 0, 0)
+XTREG(7, 28, 32, 4, 4, 0x0106, 0x0006, -2, 1, 0x0002, ar6,         0, 0, 0, 0, 0, 0)
+XTREG(8, 32, 32, 4, 4, 0x0107, 0x0006, -2, 1, 0x0002, ar7,         0, 0, 0, 0, 0, 0)
+XTREG(9, 36, 32, 4, 4, 0x0108, 0x0006, -2, 1, 0x0002, ar8,         0, 0, 0, 0, 0, 0)
+XTREG(10, 40, 32, 4, 4, 0x0109, 0x0006, -2, 1, 0x0002, ar9,         0, 0, 0, 0, 0, 0)
+XTREG(11, 44, 32, 4, 4, 0x010a, 0x0006, -2, 1, 0x0002, ar10,        0, 0, 0, 0, 0, 0)
+XTREG(12, 48, 32, 4, 4, 0x010b, 0x0006, -2, 1, 0x0002, ar11,        0, 0, 0, 0, 0, 0)
+XTREG(13, 52, 32, 4, 4, 0x010c, 0x0006, -2, 1, 0x0002, ar12,        0, 0, 0, 0, 0, 0)
+XTREG(14, 56, 32, 4, 4, 0x010d, 0x0006, -2, 1, 0x0002, ar13,        0, 0, 0, 0, 0, 0)
+XTREG(15, 60, 32, 4, 4, 0x010e, 0x0006, -2, 1, 0x0002, ar14,        0, 0, 0, 0, 0, 0)
+XTREG(16, 64, 32, 4, 4, 0x010f, 0x0006, -2, 1, 0x0002, ar15,        0, 0, 0, 0, 0, 0)
+XTREG(17, 68, 32, 4, 4, 0x0110, 0x0006, -2, 1, 0x0002, ar16,        0, 0, 0, 0, 0, 0)
+XTREG(18, 72, 32, 4, 4, 0x0111, 0x0006, -2, 1, 0x0002, ar17,        0, 0, 0, 0, 0, 0)
+XTREG(19, 76, 32, 4, 4, 0x0112, 0x0006, -2, 1, 0x0002, ar18,        0, 0, 0, 0, 0, 0)
+XTREG(20, 80, 32, 4, 4, 0x0113, 0x0006, -2, 1, 0x0002, ar19,        0, 0, 0, 0, 0, 0)
+XTREG(21, 84, 32, 4, 4, 0x0114, 0x0006, -2, 1, 0x0002, ar20,        0, 0, 0, 0, 0, 0)
+XTREG(22, 88, 32, 4, 4, 0x0115, 0x0006, -2, 1, 0x0002, ar21,        0, 0, 0, 0, 0, 0)
+XTREG(23, 92, 32, 4, 4, 0x0116, 0x0006, -2, 1, 0x0002, ar22,        0, 0, 0, 0, 0, 0)
+XTREG(24, 96, 32, 4, 4, 0x0117, 0x0006, -2, 1, 0x0002, ar23,        0, 0, 0, 0, 0, 0)
+XTREG(25, 100, 32, 4, 4, 0x0118, 0x0006, -2, 1, 0x0002, ar24,        0, 0, 0, 0, 0, 0)
+XTREG(26, 104, 32, 4, 4, 0x0119, 0x0006, -2, 1, 0x0002, ar25,        0, 0, 0, 0, 0, 0)
+XTREG(27, 108, 32, 4, 4, 0x011a, 0x0006, -2, 1, 0x0002, ar26,        0, 0, 0, 0, 0, 0)
+XTREG(28, 112, 32, 4, 4, 0x011b, 0x0006, -2, 1, 0x0002, ar27,        0, 0, 0, 0, 0, 0)
+XTREG(29, 116, 32, 4, 4, 0x011c, 0x0006, -2, 1, 0x0002, ar28,        0, 0, 0, 0, 0, 0)
+XTREG(30, 120, 32, 4, 4, 0x011d, 0x0006, -2, 1, 0x0002, ar29,        0, 0, 0, 0, 0, 0)
+XTREG(31, 124, 32, 4, 4, 0x011e, 0x0006, -2, 1, 0x0002, ar30,        0, 0, 0, 0, 0, 0)
+XTREG(32, 128, 32, 4, 4, 0x011f, 0x0006, -2, 1, 0x0002, ar31,        0, 0, 0, 0, 0, 0)
+XTREG(33, 132, 32, 4, 4, 0x0200, 0x0006, -2, 2, 0x1100, lbeg,        0, 0, 0, 0, 0, 0)
+XTREG(34, 136, 32, 4, 4, 0x0201, 0x0006, -2, 2, 0x1100, lend,        0, 0, 0, 0, 0, 0)
+XTREG(35, 140, 32, 4, 4, 0x0202, 0x0006, -2, 2, 0x1100, lcount,      0, 0, 0, 0, 0, 0)
+XTREG(36, 144, 6, 4, 4, 0x0203, 0x0006, -2, 2, 0x1100, sar,         0, 0, 0, 0, 0, 0)
+XTREG(37, 148, 32, 4, 4, 0x0205, 0x0006, -2, 2, 0x1100, litbase,     0, 0, 0, 0, 0, 0)
+XTREG(38, 152, 3, 4, 4, 0x0248, 0x0006, -2, 2, 0x1002, windowbase,  0, 0, 0, 0, 0, 0)
+XTREG(39, 156, 8, 4, 4, 0x0249, 0x0006, -2, 2, 0x1002, windowstart, 0, 0, 0, 0, 0, 0)
+XTREG(40, 160, 32, 4, 4, 0x02b0, 0x0002, -2, 2, 0x1000, sr176,       0, 0, 0, 0, 0, 0)
+XTREG(41, 164, 32, 4, 4, 0x02d0, 0x0002, -2, 2, 0x1000, sr208,       0, 0, 0, 0, 0, 0)
+XTREG(42, 168, 19, 4, 4, 0x02e6, 0x0006, -2, 2, 0x1100, ps,          0, 0, 0, 0, 0, 0)
+XTREG(43, 172, 32, 4, 4, 0x03e7, 0x0006, -2, 3, 0x0110, threadptr,   0, 0, 0, 0, 0, 0)
+XTREG(44, 176, 32, 4, 4, 0x020c, 0x0006, -1, 2, 0x1100, scompare1,   0, 0, 0, 0, 0, 0)
+XTREG(45, 180, 32, 4, 4, 0x0210, 0x0006, -1, 2, 0x1100, acclo,       0, 0, 0, 0, 0, 0)
+XTREG(46, 184, 8, 4, 4, 0x0211, 0x0006, -1, 2, 0x1100, acchi,       0, 0, 0, 0, 0, 0)
+XTREG(47, 188, 32, 4, 4, 0x0220, 0x0006, -1, 2, 0x1100, m0,          0, 0, 0, 0, 0, 0)
+XTREG(48, 192, 32, 4, 4, 0x0221, 0x0006, -1, 2, 0x1100, m1,          0, 0, 0, 0, 0, 0)
+XTREG(49, 196, 32, 4, 4, 0x0222, 0x0006, -1, 2, 0x1100, m2,          0, 0, 0, 0, 0, 0)
+XTREG(50, 200, 32, 4, 4, 0x0223, 0x0006, -1, 2, 0x1100, m3,          0, 0, 0, 0, 0, 0)
+XTREG(51, 204, 32, 4, 4, 0x03e6, 0x000e, -1, 3, 0x0110, expstate,    0, 0, 0, 0, 0, 0)
+XTREG(52, 208, 32, 4, 4, 0x0253, 0x0007, -2, 2, 0x1000, ptevaddr,    0, 0, 0, 0, 0, 0)
+XTREG(53, 212, 32, 4, 4, 0x0259, 0x000d, -2, 2, 0x1000, mmid,        0, 0, 0, 0, 0, 0)
+XTREG(54, 216, 32, 4, 4, 0x025a, 0x0007, -2, 2, 0x1000, rasid,       0, 0, 0, 0, 0, 0)
+XTREG(55, 220, 25, 4, 4, 0x025b, 0x0007, -2, 2, 0x1000, itlbcfg,     0, 0, 0, 0, 0, 0)
+XTREG(56, 224, 25, 4, 4, 0x025c, 0x0007, -2, 2, 0x1000, dtlbcfg,     0, 0, 0, 0, 0, 0)
+XTREG(57, 228, 2, 4, 4, 0x0260, 0x0007, -2, 2, 0x1000, ibreakenable, 0, 0, 0, 0, 0, 0)
+XTREG(58, 232, 6, 4, 4, 0x0263, 0x0007, -2, 2, 0x1000, atomctl,     0, 0, 0, 0, 0, 0)
+XTREG(59, 236, 32, 4, 4, 0x0268, 0x0007, -2, 2, 0x1000, ddr,         0, 0, 0, 0, 0, 0)
+XTREG(60, 240, 32, 4, 4, 0x0280, 0x0007, -2, 2, 0x1000, ibreaka0,    0, 0, 0, 0, 0, 0)
+XTREG(61, 244, 32, 4, 4, 0x0281, 0x0007, -2, 2, 0x1000, ibreaka1,    0, 0, 0, 0, 0, 0)
+XTREG(62, 248, 32, 4, 4, 0x0290, 0x0007, -2, 2, 0x1000, dbreaka0,    0, 0, 0, 0, 0, 0)
+XTREG(63, 252, 32, 4, 4, 0x0291, 0x0007, -2, 2, 0x1000, dbreaka1,    0, 0, 0, 0, 0, 0)
+XTREG(64, 256, 32, 4, 4, 0x02a0, 0x0007, -2, 2, 0x1000, dbreakc0,    0, 0, 0, 0, 0, 0)
+XTREG(65, 260, 32, 4, 4, 0x02a1, 0x0007, -2, 2, 0x1000, dbreakc1,    0, 0, 0, 0, 0, 0)
+XTREG(66, 264, 32, 4, 4, 0x02b1, 0x0007, -2, 2, 0x1000, epc1,        0, 0, 0, 0, 0, 0)
+XTREG(67, 268, 32, 4, 4, 0x02b2, 0x0007, -2, 2, 0x1000, epc2,        0, 0, 0, 0, 0, 0)
+XTREG(68, 272, 32, 4, 4, 0x02b3, 0x0007, -2, 2, 0x1000, epc3,        0, 0, 0, 0, 0, 0)
+XTREG(69, 276, 32, 4, 4, 0x02b4, 0x0007, -2, 2, 0x1000, epc4,        0, 0, 0, 0, 0, 0)
+XTREG(70, 280, 32, 4, 4, 0x02b5, 0x0007, -2, 2, 0x1000, epc5,        0, 0, 0, 0, 0, 0)
+XTREG(71, 284, 32, 4, 4, 0x02b6, 0x0007, -2, 2, 0x1000, epc6,        0, 0, 0, 0, 0, 0)
+XTREG(72, 288, 32, 4, 4, 0x02b7, 0x0007, -2, 2, 0x1000, epc7,        0, 0, 0, 0, 0, 0)
+XTREG(73, 292, 32, 4, 4, 0x02c0, 0x0007, -2, 2, 0x1000, depc,        0, 0, 0, 0, 0, 0)
+XTREG(74, 296, 19, 4, 4, 0x02c2, 0x0007, -2, 2, 0x1000, eps2,        0, 0, 0, 0, 0, 0)
+XTREG(75, 300, 19, 4, 4, 0x02c3, 0x0007, -2, 2, 0x1000, eps3,        0, 0, 0, 0, 0, 0)
+XTREG(76, 304, 19, 4, 4, 0x02c4, 0x0007, -2, 2, 0x1000, eps4,        0, 0, 0, 0, 0, 0)
+XTREG(77, 308, 19, 4, 4, 0x02c5, 0x0007, -2, 2, 0x1000, eps5,        0, 0, 0, 0, 0, 0)
+XTREG(78, 312, 19, 4, 4, 0x02c6, 0x0007, -2, 2, 0x1000, eps6,        0, 0, 0, 0, 0, 0)
+XTREG(79, 316, 19, 4, 4, 0x02c7, 0x0007, -2, 2, 0x1000, eps7,        0, 0, 0, 0, 0, 0)
+XTREG(80, 320, 32, 4, 4, 0x02d1, 0x0007, -2, 2, 0x1000, excsave1,    0, 0, 0, 0, 0, 0)
+XTREG(81, 324, 32, 4, 4, 0x02d2, 0x0007, -2, 2, 0x1000, excsave2,    0, 0, 0, 0, 0, 0)
+XTREG(82, 328, 32, 4, 4, 0x02d3, 0x0007, -2, 2, 0x1000, excsave3,    0, 0, 0, 0, 0, 0)
+XTREG(83, 332, 32, 4, 4, 0x02d4, 0x0007, -2, 2, 0x1000, excsave4,    0, 0, 0, 0, 0, 0)
+XTREG(84, 336, 32, 4, 4, 0x02d5, 0x0007, -2, 2, 0x1000, excsave5,    0, 0, 0, 0, 0, 0)
+XTREG(85, 340, 32, 4, 4, 0x02d6, 0x0007, -2, 2, 0x1000, excsave6,    0, 0, 0, 0, 0, 0)
+XTREG(86, 344, 32, 4, 4, 0x02d7, 0x0007, -2, 2, 0x1000, excsave7,    0, 0, 0, 0, 0, 0)
+XTREG(87, 348, 8, 4, 4, 0x02e0, 0x0007, -2, 2, 0x1000, cpenable,    0, 0, 0, 0, 0, 0)
+XTREG(88, 352, 22, 4, 4, 0x02e2, 0x000b, -2, 2, 0x1000, interrupt,   0, 0, 0, 0, 0, 0)
+XTREG(89, 356, 22, 4, 4, 0x02e2, 0x000d, -2, 2, 0x1000, intset,      0, 0, 0, 0, 0, 0)
+XTREG(90, 360, 22, 4, 4, 0x02e3, 0x000d, -2, 2, 0x1000, intclear,    0, 0, 0, 0, 0, 0)
+XTREG(91, 364, 22, 4, 4, 0x02e4, 0x0007, -2, 2, 0x1000, intenable,   0, 0, 0, 0, 0, 0)
+XTREG(92, 368, 32, 4, 4, 0x02e7, 0x0007, -2, 2, 0x1000, vecbase,     0, 0, 0, 0, 0, 0)
+XTREG(93, 372, 6, 4, 4, 0x02e8, 0x0007, -2, 2, 0x1000, exccause,    0, 0, 0, 0, 0, 0)
+XTREG(94, 376, 12, 4, 4, 0x02e9, 0x0003, -2, 2, 0x1000, debugcause,  0, 0, 0, 0, 0, 0)
+XTREG(95, 380, 32, 4, 4, 0x02ea, 0x000f, -2, 2, 0x1000, ccount,      0, 0, 0, 0, 0, 0)
+XTREG(96, 384, 32, 4, 4, 0x02eb, 0x0003, -2, 2, 0x1000, prid,        0, 0, 0, 0, 0, 0)
+XTREG(97, 388, 32, 4, 4, 0x02ec, 0x000f, -2, 2, 0x1000, icount,      0, 0, 0, 0, 0, 0)
+XTREG(98, 392, 4, 4, 4, 0x02ed, 0x0007, -2, 2, 0x1000, icountlevel, 0, 0, 0, 0, 0, 0)
+XTREG(99, 396, 32, 4, 4, 0x02ee, 0x0007, -2, 2, 0x1000, excvaddr,    0, 0, 0, 0, 0, 0)
+XTREG(100, 400, 32, 4, 4, 0x02f0, 0x000f, -2, 2, 0x1000, ccompare0,   0, 0, 0, 0, 0, 0)
+XTREG(101, 404, 32, 4, 4, 0x02f1, 0x000f, -2, 2, 0x1000, ccompare1,   0, 0, 0, 0, 0, 0)
+XTREG(102, 408, 32, 4, 4, 0x02f2, 0x000f, -2, 2, 0x1000, ccompare2,   0, 0, 0, 0, 0, 0)
+XTREG(103, 412, 32, 4, 4, 0x02f4, 0x0007, -2, 2, 0x1000, misc0,       0, 0, 0, 0, 0, 0)
+XTREG(104, 416, 32, 4, 4, 0x02f5, 0x0007, -2, 2, 0x1000, misc1,       0, 0, 0, 0, 0, 0)
+XTREG(105, 420, 32, 4, 4, 0x0000, 0x0006, -2, 8, 0x0100, a0,          0, 0, 0, 0, 0, 0)
+XTREG(106, 424, 32, 4, 4, 0x0001, 0x0006, -2, 8, 0x0100, a1,          0, 0, 0, 0, 0, 0)
+XTREG(107, 428, 32, 4, 4, 0x0002, 0x0006, -2, 8, 0x0100, a2,          0, 0, 0, 0, 0, 0)
+XTREG(108, 432, 32, 4, 4, 0x0003, 0x0006, -2, 8, 0x0100, a3,          0, 0, 0, 0, 0, 0)
+XTREG(109, 436, 32, 4, 4, 0x0004, 0x0006, -2, 8, 0x0100, a4,          0, 0, 0, 0, 0, 0)
+XTREG(110, 440, 32, 4, 4, 0x0005, 0x0006, -2, 8, 0x0100, a5,          0, 0, 0, 0, 0, 0)
+XTREG(111, 444, 32, 4, 4, 0x0006, 0x0006, -2, 8, 0x0100, a6,          0, 0, 0, 0, 0, 0)
+XTREG(112, 448, 32, 4, 4, 0x0007, 0x0006, -2, 8, 0x0100, a7,          0, 0, 0, 0, 0, 0)
+XTREG(113, 452, 32, 4, 4, 0x0008, 0x0006, -2, 8, 0x0100, a8,          0, 0, 0, 0, 0, 0)
+XTREG(114, 456, 32, 4, 4, 0x0009, 0x0006, -2, 8, 0x0100, a9,          0, 0, 0, 0, 0, 0)
+XTREG(115, 460, 32, 4, 4, 0x000a, 0x0006, -2, 8, 0x0100, a10,         0, 0, 0, 0, 0, 0)
+XTREG(116, 464, 32, 4, 4, 0x000b, 0x0006, -2, 8, 0x0100, a11,         0, 0, 0, 0, 0, 0)
+XTREG(117, 468, 32, 4, 4, 0x000c, 0x0006, -2, 8, 0x0100, a12,         0, 0, 0, 0, 0, 0)
+XTREG(118, 472, 32, 4, 4, 0x000d, 0x0006, -2, 8, 0x0100, a13,         0, 0, 0, 0, 0, 0)
+XTREG(119, 476, 32, 4, 4, 0x000e, 0x0006, -2, 8, 0x0100, a14,         0, 0, 0, 0, 0, 0)
+XTREG(120, 480, 32, 4, 4, 0x000f, 0x0006, -2, 8, 0x0100, a15,         0, 0, 0, 0, 0, 0)
commit 11ea40905259f29e448af816ff00d9d9f0951818
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Apr 15 18:51:01 2012 +0200

    linux-user: Fix exit syscall with QOM CPU
    
    For QOM'ified CPUs we cannot g_free() CPUArchState, we must
    object_delete() the object it is embedded into.
    
    Fixes LP#982321 (invalid free() while executing pacman with qemu-arm).
    
    Reported-by: Serge Schneider <serge at xecdesign.com>
    Reported-by: Russell Keith Davis <russell at russelldavis.org>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Serge Schneider <serge at xecdesign.com>
    Tested-by: Russell Keith Davis <russell at russelldavis.org>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 8a92162..7128618 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5045,7 +5045,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                         NULL, NULL, 0);
           }
           thread_env = NULL;
+#ifdef ENV_GET_CPU
+          object_delete(OBJECT(ENV_GET_CPU(cpu_env)));
+#else
           g_free(cpu_env);
+#endif
           g_free(ts);
           pthread_exit(NULL);
       }
commit 45e45ed2d61fb287adf03e49c74c152bfd2c975a
Author: Juan Quintela <quintela at redhat.com>
Date:   Mon Mar 19 23:57:36 2012 +0100

    target-ppc/machine.c: Drop unnecessary ifdefs
    
    machine.c is only compiled for softmmu targets, so checks for
    !defined(CONFIG_USER_ONLY) are unnecessary and can be dropped.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    [AF: Use more verbose commit message suggested by PMM]
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-ppc/machine.c b/target-ppc/machine.c
index 70e2582..d6c2ee4 100644
--- a/target-ppc/machine.c
+++ b/target-ppc/machine.c
@@ -32,7 +32,6 @@ void cpu_save(QEMUFile *f, void *opaque)
     }
     qemu_put_be32s(f, &env->fpscr);
     qemu_put_sbe32s(f, &env->access_type);
-#if !defined(CONFIG_USER_ONLY)
 #if defined(TARGET_PPC64)
     qemu_put_betls(f, &env->asr);
     qemu_put_sbe32s(f, &env->slb_nr);
@@ -62,7 +61,6 @@ void cpu_save(QEMUFile *f, void *opaque)
     }
     for (i = 0; i < 4; i++)
         qemu_put_betls(f, &env->pb[i]);
-#endif
     for (i = 0; i < 1024; i++)
         qemu_put_betls(f, &env->spr[i]);
     qemu_put_be32s(f, &env->vscr);
@@ -72,7 +70,6 @@ void cpu_save(QEMUFile *f, void *opaque)
     qemu_put_be32s(f, &env->flags);
     qemu_put_sbe32s(f, &env->error_code);
     qemu_put_be32s(f, &env->pending_interrupts);
-#if !defined(CONFIG_USER_ONLY)
     qemu_put_be32s(f, &env->irq_input_state);
     for (i = 0; i < POWERPC_EXCP_NB; i++)
         qemu_put_betls(f, &env->excp_vectors[i]);
@@ -81,7 +78,6 @@ void cpu_save(QEMUFile *f, void *opaque)
     qemu_put_betls(f, &env->ivor_mask);
     qemu_put_betls(f, &env->ivpr_mask);
     qemu_put_betls(f, &env->hreset_vector);
-#endif
     qemu_put_betls(f, &env->nip);
     qemu_put_betls(f, &env->hflags);
     qemu_put_betls(f, &env->hflags_nmsr);
@@ -120,7 +116,6 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     }
     qemu_get_be32s(f, &env->fpscr);
     qemu_get_sbe32s(f, &env->access_type);
-#if !defined(CONFIG_USER_ONLY)
 #if defined(TARGET_PPC64)
     qemu_get_betls(f, &env->asr);
     qemu_get_sbe32s(f, &env->slb_nr);
@@ -150,7 +145,6 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     }
     for (i = 0; i < 4; i++)
         qemu_get_betls(f, &env->pb[i]);
-#endif
     for (i = 0; i < 1024; i++)
         qemu_get_betls(f, &env->spr[i]);
     ppc_store_sdr1(env, sdr1);
@@ -161,7 +155,6 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     qemu_get_be32s(f, &env->flags);
     qemu_get_sbe32s(f, &env->error_code);
     qemu_get_be32s(f, &env->pending_interrupts);
-#if !defined(CONFIG_USER_ONLY)
     qemu_get_be32s(f, &env->irq_input_state);
     for (i = 0; i < POWERPC_EXCP_NB; i++)
         qemu_get_betls(f, &env->excp_vectors[i]);
@@ -170,7 +163,6 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     qemu_get_betls(f, &env->ivor_mask);
     qemu_get_betls(f, &env->ivpr_mask);
     qemu_get_betls(f, &env->hreset_vector);
-#endif
     qemu_get_betls(f, &env->nip);
     qemu_get_betls(f, &env->hflags);
     qemu_get_betls(f, &env->hflags_nmsr);
commit a5cabbda760c798bb551d53a697058de28fce51c
Author: Meador Inge <meadori at codesourcery.com>
Date:   Tue Apr 10 15:04:23 2012 -0500

    target-ppc: Init dcache and icache size for e500 user mode
    
    commit f7aa558396dd0f6b7a2b22c05cb503c655854102 pulled the dcache and icache
    line size initialization inside of a '#if !defined(CONFIG_USER_ONLY)' block.
    This is not correct because instructions like 'dcbz' need the dcache size
    initialized even for user mode.
    
    Signed-off-by: Meador Inge <meadori at codesourcery.com>
    Cc: Varun Sethi <Varun.Sethi at freescale.com>
    [AF: Simplify #ifdefs by using cache line size 32 for *-user as before]
    Suggested-by: Scott Wood <scottwood at freescale.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index fdc0a5f..ba4b84d 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -4462,7 +4462,10 @@ static void init_proc_e500 (CPUPPCState *env, int version)
                  &spr_read_spefscr, &spr_write_spefscr,
                  0x00000000);
     /* Memory management */
-#if !defined(CONFIG_USER_ONLY)
+#if defined(CONFIG_USER_ONLY)
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+#else /* !defined(CONFIG_USER_ONLY) */
     env->nb_pids = 3;
     env->nb_ways = 2;
     env->id_tlbs = 0;
commit 5724753e6576fc26ff4a563a6c2ccb8ce3b02cb8
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sun Apr 15 16:13:48 2012 +0200

    target-ppc: Fix type casts for w64 (uintptr_t)
    
    This changes nothing for other hosts.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 025122d..fdc0a5f 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -9504,12 +9504,12 @@ enum {
 
 static inline int is_indirect_opcode (void *handler)
 {
-    return ((unsigned long)handler & 0x03) == PPC_INDIRECT;
+    return ((uintptr_t)handler & 0x03) == PPC_INDIRECT;
 }
 
 static inline opc_handler_t **ind_table(void *handler)
 {
-    return (opc_handler_t **)((unsigned long)handler & ~3);
+    return (opc_handler_t **)((uintptr_t)handler & ~3);
 }
 
 /* Instruction table creation */
@@ -9528,7 +9528,7 @@ static int create_new_table (opc_handler_t **table, unsigned char idx)
 
     tmp = malloc(0x20 * sizeof(opc_handler_t));
     fill_new_table(tmp, 0x20);
-    table[idx] = (opc_handler_t *)((unsigned long)tmp | PPC_INDIRECT);
+    table[idx] = (opc_handler_t *)((uintptr_t)tmp | PPC_INDIRECT);
 
     return 0;
 }
commit a13895420561da4f8eae03f4d423a7c2fdb83f65
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri Apr 6 15:35:34 2012 +0200

    target-ppc: QOM'ify CPU reset
    
    Move code from cpu_state_reset() into ppc_cpu_reset().
    Reorder #include of helper_regs.h to use it in translate_init.c.
    
    Adjust whitespace and add braces.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: David Gibson <david at gibson.dropbear.id.au>

diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index c5de0ea..c610ce3 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -3138,50 +3138,7 @@ void cpu_dump_rfi (target_ulong RA, target_ulong msr)
 
 void cpu_state_reset(CPUPPCState *env)
 {
-    target_ulong msr;
-
-    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
-        log_cpu_state(env, 0);
-    }
-
-    msr = (target_ulong)0;
-    if (0) {
-        /* XXX: find a suitable condition to enable the hypervisor mode */
-        msr |= (target_ulong)MSR_HVB;
-    }
-    msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
-    msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
-    msr |= (target_ulong)1 << MSR_EP;
-#if defined (DO_SINGLE_STEP) && 0
-    /* Single step trace mode */
-    msr |= (target_ulong)1 << MSR_SE;
-    msr |= (target_ulong)1 << MSR_BE;
-#endif
-#if defined(CONFIG_USER_ONLY)
-    msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
-    msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
-    msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
-    msr |= (target_ulong)1 << MSR_PR;
-#else
-    env->excp_prefix = env->hreset_excp_prefix;
-    env->nip = env->hreset_vector | env->excp_prefix;
-    if (env->mmu_model != POWERPC_MMU_REAL)
-        ppc_tlb_invalidate_all(env);
-#endif
-    env->msr = msr & env->msr_mask;
-#if defined(TARGET_PPC64)
-    if (env->mmu_model & POWERPC_MMU_64)
-        env->msr |= (1ULL << MSR_SF);
-#endif
-    hreg_compute_hflags(env);
-    env->reserve_addr = (target_ulong)-1ULL;
-    /* Be sure no exception or interrupt is pending */
-    env->pending_interrupts = 0;
-    env->exception_index = POWERPC_EXCP_NONE;
-    env->error_code = 0;
-    /* Flush all TLBs */
-    tlb_flush(env, 1);
+    cpu_reset(ENV_GET_CPU(env));
 }
 
 CPUPPCState *cpu_ppc_init (const char *cpu_model)
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index c9a503a..cf59765 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -9306,8 +9306,8 @@ GEN_SPEOP_LDST(evstwwe, 0x1C, 2),
 GEN_SPEOP_LDST(evstwwo, 0x1E, 2),
 };
 
-#include "translate_init.c"
 #include "helper_regs.h"
+#include "translate_init.c"
 
 /*****************************************************************************/
 /* Misc PowerPC helpers */
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 5a7ac77..025122d 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -10211,10 +10211,54 @@ static void ppc_cpu_reset(CPUState *s)
     PowerPCCPU *cpu = POWERPC_CPU(s);
     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
     CPUPPCState *env = &cpu->env;
+    target_ulong msr;
+
+    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+        log_cpu_state(env, 0);
+    }
 
     pcc->parent_reset(s);
 
-    cpu_state_reset(env);
+    msr = (target_ulong)0;
+    if (0) {
+        /* XXX: find a suitable condition to enable the hypervisor mode */
+        msr |= (target_ulong)MSR_HVB;
+    }
+    msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
+    msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
+    msr |= (target_ulong)1 << MSR_EP;
+#if defined(DO_SINGLE_STEP) && 0
+    /* Single step trace mode */
+    msr |= (target_ulong)1 << MSR_SE;
+    msr |= (target_ulong)1 << MSR_BE;
+#endif
+#if defined(CONFIG_USER_ONLY)
+    msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
+    msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
+    msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
+    msr |= (target_ulong)1 << MSR_PR;
+#else
+    env->excp_prefix = env->hreset_excp_prefix;
+    env->nip = env->hreset_vector | env->excp_prefix;
+    if (env->mmu_model != POWERPC_MMU_REAL) {
+        ppc_tlb_invalidate_all(env);
+    }
+#endif
+    env->msr = msr & env->msr_mask;
+#if defined(TARGET_PPC64)
+    if (env->mmu_model & POWERPC_MMU_64) {
+        env->msr |= (1ULL << MSR_SF);
+    }
+#endif
+    hreg_compute_hflags(env);
+    env->reserve_addr = (target_ulong)-1ULL;
+    /* Be sure no exception or interrupt is pending */
+    env->pending_interrupts = 0;
+    env->exception_index = POWERPC_EXCP_NONE;
+    env->error_code = 0;
+    /* Flush all TLBs */
+    tlb_flush(env, 1);
 }
 
 static void ppc_cpu_initfn(Object *obj)
commit 6cca7ad686de0270fe30ae303e31c6a27b53d7a9
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri Apr 6 15:09:01 2012 +0200

    target-ppc: Start QOM'ifying CPU init
    
    Move code not dependent on ppc_def_t from cpu_ppc_init() into an initfn.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: David Gibson <david at gibson.dropbear.id.au>

diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 0d904dd..c5de0ea 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -3196,10 +3196,11 @@ CPUPPCState *cpu_ppc_init (const char *cpu_model)
 
     cpu = POWERPC_CPU(object_new(TYPE_POWERPC_CPU));
     env = &cpu->env;
-    cpu_exec_init(env);
+
     if (tcg_enabled()) {
         ppc_translate_init();
     }
+
     env->cpu_model_str = cpu_model;
     cpu_ppc_register_internal(env, def);
 
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index e4d15a5..5a7ac77 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -10217,6 +10217,14 @@ static void ppc_cpu_reset(CPUState *s)
     cpu_state_reset(env);
 }
 
+static void ppc_cpu_initfn(Object *obj)
+{
+    PowerPCCPU *cpu = POWERPC_CPU(obj);
+    CPUPPCState *env = &cpu->env;
+
+    cpu_exec_init(env);
+}
+
 static void ppc_cpu_class_init(ObjectClass *oc, void *data)
 {
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
@@ -10230,6 +10238,7 @@ static const TypeInfo ppc_cpu_type_info = {
     .name = TYPE_POWERPC_CPU,
     .parent = TYPE_CPU,
     .instance_size = sizeof(PowerPCCPU),
+    .instance_init = ppc_cpu_initfn,
     .abstract = false,
     .class_size = sizeof(PowerPCCPUClass),
     .class_init = ppc_cpu_class_init,
commit 1d0cb67da9eff798420d0f6479fec6026c4dc41f
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri Apr 6 14:39:03 2012 +0200

    target-ppc: QOM'ify CPU
    
    Embed CPUPPCState as first member of PowerPCCPU.
    Distinguish between "powerpc-cpu", "powerpc64-cpu" and
    "embedded-powerpc-cpu".
    
    Let CPUClass::reset() call cpu_state_reset() for now.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: David Gibson <david at gibson.dropbear.id.au>

diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
new file mode 100644
index 0000000..fef6f95
--- /dev/null
+++ b/target-ppc/cpu-qom.h
@@ -0,0 +1,77 @@
+/*
+ * QEMU PowerPC CPU
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * 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.1 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/lgpl-2.1.html>
+ */
+#ifndef QEMU_PPC_CPU_QOM_H
+#define QEMU_PPC_CPU_QOM_H
+
+#include "qemu/cpu.h"
+#include "cpu.h"
+
+#ifdef TARGET_PPC64
+#define TYPE_POWERPC_CPU "powerpc64-cpu"
+#elif defined(TARGET_PPCEMB)
+#define TYPE_POWERPC_CPU "embedded-powerpc-cpu"
+#else
+#define TYPE_POWERPC_CPU "powerpc-cpu"
+#endif
+
+#define POWERPC_CPU_CLASS(klass) \
+    OBJECT_CLASS_CHECK(PowerPCCPUClass, (klass), TYPE_POWERPC_CPU)
+#define POWERPC_CPU(obj) \
+    OBJECT_CHECK(PowerPCCPU, (obj), TYPE_POWERPC_CPU)
+#define POWERPC_CPU_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(PowerPCCPUClass, (obj), TYPE_POWERPC_CPU)
+
+/**
+ * PowerPCCPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * A PowerPC CPU model.
+ */
+typedef struct PowerPCCPUClass {
+    /*< private >*/
+    CPUClass parent_class;
+    /*< public >*/
+
+    void (*parent_reset)(CPUState *cpu);
+} PowerPCCPUClass;
+
+/**
+ * PowerPCCPU:
+ * @env: #CPUPPCState
+ *
+ * A PowerPC CPU.
+ */
+typedef struct PowerPCCPU {
+    /*< private >*/
+    CPUState parent_obj;
+    /*< public >*/
+
+    CPUPPCState env;
+} PowerPCCPU;
+
+static inline PowerPCCPU *ppc_env_get_cpu(CPUPPCState *env)
+{
+    return POWERPC_CPU(container_of(env, PowerPCCPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(ppc_env_get_cpu(e))
+
+
+#endif
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 1d5c602..84c9674 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1096,6 +1096,8 @@ struct mmu_ctx_t {
 };
 #endif
 
+#include "cpu-qom.h"
+
 /*****************************************************************************/
 CPUPPCState *cpu_ppc_init (const char *cpu_model);
 void ppc_translate_init(void);
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index b34dcbe..0d904dd 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -3186,6 +3186,7 @@ void cpu_state_reset(CPUPPCState *env)
 
 CPUPPCState *cpu_ppc_init (const char *cpu_model)
 {
+    PowerPCCPU *cpu;
     CPUPPCState *env;
     const ppc_def_t *def;
 
@@ -3193,7 +3194,8 @@ CPUPPCState *cpu_ppc_init (const char *cpu_model)
     if (!def)
         return NULL;
 
-    env = g_malloc0(sizeof(CPUPPCState));
+    cpu = POWERPC_CPU(object_new(TYPE_POWERPC_CPU));
+    env = &cpu->env;
     cpu_exec_init(env);
     if (tcg_enabled()) {
         ppc_translate_init();
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 067e07e..e4d15a5 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -10204,3 +10204,40 @@ void ppc_cpu_list (FILE *f, fprintf_function cpu_fprintf)
                        ppc_defs[i].name, ppc_defs[i].pvr);
     }
 }
+
+/* CPUClass::reset() */
+static void ppc_cpu_reset(CPUState *s)
+{
+    PowerPCCPU *cpu = POWERPC_CPU(s);
+    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+    CPUPPCState *env = &cpu->env;
+
+    pcc->parent_reset(s);
+
+    cpu_state_reset(env);
+}
+
+static void ppc_cpu_class_init(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+    CPUClass *cc = CPU_CLASS(oc);
+
+    pcc->parent_reset = cc->reset;
+    cc->reset = ppc_cpu_reset;
+}
+
+static const TypeInfo ppc_cpu_type_info = {
+    .name = TYPE_POWERPC_CPU,
+    .parent = TYPE_CPU,
+    .instance_size = sizeof(PowerPCCPU),
+    .abstract = false,
+    .class_size = sizeof(PowerPCCPUClass),
+    .class_init = ppc_cpu_class_init,
+};
+
+static void ppc_cpu_register_types(void)
+{
+    type_register_static(&ppc_cpu_type_info);
+}
+
+type_init(ppc_cpu_register_types)
commit 12b1143b2807a5b760e477fac0e1028a9760b6c6
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Wed Apr 4 15:02:05 2012 +1000

    target-ppc: Add hooks for handling tcg and kvm limitations
    
    On target-ppc, our table of CPU types and features encodes the features as
    found on the hardware, regardless of whether these features are actually
    usable under TCG or KVM.  We already have cases where the information from
    the cpu table must be fixed up to account for limitations in the emulation
    method we're using.  e.g. TCG does not support the DFP and VSX instructions
    and KVM needs different numbering of the CPUs in order to tell it the
    correct thread to core mappings.
    
    This patch cleans up these hacks to handle emulation limitations by
    consolidating them into a pair of functions specifically for the purpose.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    [AF: Style and typo fixes, rename new functions and drop ppc_def_t arg]
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index f61b8b2..b34dcbe 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -3198,15 +3198,6 @@ CPUPPCState *cpu_ppc_init (const char *cpu_model)
     if (tcg_enabled()) {
         ppc_translate_init();
     }
-    /* Adjust cpu index for SMT */
-#if !defined(CONFIG_USER_ONLY)
-    if (kvm_enabled()) {
-        int smt = kvmppc_smt_threads();
-
-        env->cpu_index = (env->cpu_index / smp_threads)*smt
-            + (env->cpu_index % smp_threads);
-    }
-#endif /* !CONFIG_USER_ONLY */
     env->cpu_model_str = cpu_model;
     cpu_ppc_register_internal(env, def);
 
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index d929213..c09cc39 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -27,6 +27,7 @@
 #include "kvm.h"
 #include "kvm_ppc.h"
 #include "cpu.h"
+#include "cpus.h"
 #include "device_tree.h"
 #include "hw/sysbus.h"
 #include "hw/spapr.h"
@@ -938,6 +939,19 @@ const ppc_def_t *kvmppc_host_cpu_def(void)
     return spec;
 }
 
+int kvmppc_fixup_cpu(CPUPPCState *env)
+{
+    int smt;
+
+    /* Adjust cpu index for SMT */
+    smt = kvmppc_smt_threads();
+    env->cpu_index = (env->cpu_index / smp_threads) * smt
+        + (env->cpu_index % smp_threads);
+
+    return 0;
+}
+
+
 bool kvm_arch_stop_on_emulation_error(CPUPPCState *env)
 {
     return true;
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index 8f1267c..34ecad3 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -29,6 +29,7 @@ void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd);
 int kvmppc_remove_spapr_tce(void *table, int pfd, uint32_t window_size);
 #endif /* !CONFIG_USER_ONLY */
 const ppc_def_t *kvmppc_host_cpu_def(void);
+int kvmppc_fixup_cpu(CPUPPCState *env);
 
 #else
 
@@ -95,6 +96,10 @@ static inline const ppc_def_t *kvmppc_host_cpu_def(void)
     return NULL;
 }
 
+static inline int kvmppc_fixup_cpu(CPUPPCState *env)
+{
+    return -1;
+}
 #endif
 
 #ifndef CONFIG_KVM
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index b1f8785..067e07e 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -9889,6 +9889,28 @@ static int gdb_set_spe_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
+static int ppc_fixup_cpu(CPUPPCState *env)
+{
+    /* TCG doesn't (yet) emulate some groups of instructions that
+     * are implemented on some otherwise supported CPUs (e.g. VSX
+     * and decimal floating point instructions on POWER7).  We
+     * remove unsupported instruction groups from the cpu state's
+     * instruction masks and hope the guest can cope.  For at
+     * least the pseries machine, the unavailability of these
+     * instructions can be advertised to the guest via the device
+     * tree. */
+    if ((env->insns_flags & ~PPC_TCG_INSNS)
+        || (env->insns_flags2 & ~PPC_TCG_INSNS2)) {
+        fprintf(stderr, "Warning: Disabling some instructions which are not "
+                "emulated by TCG (0x%" PRIx64 ", 0x%" PRIx64 ")\n",
+                env->insns_flags & ~PPC_TCG_INSNS,
+                env->insns_flags2 & ~PPC_TCG_INSNS2);
+    }
+    env->insns_flags &= PPC_TCG_INSNS;
+    env->insns_flags2 &= PPC_TCG_INSNS2;
+    return 0;
+}
+
 int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
 {
     env->msr_mask = def->msr_mask;
@@ -9897,25 +9919,22 @@ int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
     env->bus_model = def->bus_model;
     env->insns_flags = def->insns_flags;
     env->insns_flags2 = def->insns_flags2;
-    if (!kvm_enabled()) {
-        /* TCG doesn't (yet) emulate some groups of instructions that
-         * are implemented on some otherwise supported CPUs (e.g. VSX
-         * and decimal floating point instructions on POWER7).  We
-         * remove unsupported instruction groups from the cpu state's
-         * instruction masks and hope the guest can cope.  For at
-         * least the pseries machine, the unavailability of these
-         * instructions can be advertise to the guest via the device
-         * tree.
-         *
-         * FIXME: we should have a similar masking for CPU features
-         * not accessible under KVM, but so far, there aren't any of
-         * those. */
-        env->insns_flags &= PPC_TCG_INSNS;
-        env->insns_flags2 &= PPC_TCG_INSNS2;
-    }
     env->flags = def->flags;
     env->bfd_mach = def->bfd_mach;
     env->check_pow = def->check_pow;
+
+    if (kvm_enabled()) {
+        if (kvmppc_fixup_cpu(env) != 0) {
+            fprintf(stderr, "Unable to virtualize selected CPU with KVM\n");
+            exit(1);
+        }
+    } else {
+        if (ppc_fixup_cpu(env) != 0) {
+            fprintf(stderr, "Unable to emulate selected CPU with TCG\n");
+            exit(1);
+        }
+    }
+
     if (create_ppc_opcodes(env, def) < 0)
         return -1;
     init_ppc_proc(env, def);
commit e2fbb432fc4ec64d0a53c41588ede31450b6c6a8
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri Apr 6 14:42:59 2012 +0200

    target-ppc: Drop cpu_ppc_close()
    
    It is unused, so avoid QOM'ifying it unneededly.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: David Gibson <david at gibson.dropbear.id.au>

diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index e7fb364..1d5c602 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1100,7 +1100,6 @@ struct mmu_ctx_t {
 CPUPPCState *cpu_ppc_init (const char *cpu_model);
 void ppc_translate_init(void);
 int cpu_ppc_exec (CPUPPCState *s);
-void cpu_ppc_close (CPUPPCState *s);
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
    is returned if the signal was handled by the virtual CPU.  */
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index f0ea1c3..f61b8b2 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -3214,9 +3214,3 @@ CPUPPCState *cpu_ppc_init (const char *cpu_model)
 
     return env;
 }
-
-void cpu_ppc_close (CPUPPCState *env)
-{
-    /* Should also remove all opcode tables... */
-    g_free(env);
-}
commit 5f2e2ba2625d6fa4ecbc2af86e076c20ab84c171
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Wed Apr 4 15:02:07 2012 +1000

    pseries: Consolidate hack for RTAS display-character usage
    
    Currently the pseries machine contains not one but two somewhat ugly hacks
    to allow printing of early debug messages before the guest has properly
    read the device tree.
    
    First, we special case H_PUT_TERM_CHAR so that a vtermno of 0 (usually
    invalid) will look for a suitable vty and use that.  This supports Linux's
    early debug code which will use H_PUT_TERM_CHAR with vtermno==0 before
    reading the device tree.  Second, we support the RTAS display-character call.
    This takes no vtermno so we assume the address of the default first VTY.
    
    This patch makes things more consistent by folding the second hack into the
    first.  Now, display-character uses the existing vty_lookup() function to
    do the same search for a suitable VTY.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c
index 480a4ae..ae18595 100644
--- a/hw/spapr_rtas.c
+++ b/hw/spapr_rtas.c
@@ -44,8 +44,7 @@ static void rtas_display_character(sPAPREnvironment *spapr,
                                    uint32_t nret, target_ulong rets)
 {
     uint8_t c = rtas_ld(args, 0);
-    VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus,
-                                                 SPAPR_VTY_BASE_ADDRESS);
+    VIOsPAPRDevice *sdev = vty_lookup(spapr, 0);
 
     if (!sdev) {
         rtas_st(rets, 0, -1);
diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h
index ae3283c..fd29c5e 100644
--- a/hw/spapr_vio.h
+++ b/hw/spapr_vio.h
@@ -117,6 +117,7 @@ uint64_t ldq_tce(VIOsPAPRDevice *dev, uint64_t taddr);
 
 int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq);
 
+VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg);
 void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len);
 void spapr_vty_create(VIOsPAPRBus *bus, uint32_t reg, CharDriverState *chardev);
 void spapr_vlan_create(VIOsPAPRBus *bus, uint32_t reg, NICInfo *nd);
diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c
index 60e22b1..a30c040 100644
--- a/hw/spapr_vty.c
+++ b/hw/spapr_vty.c
@@ -70,8 +70,6 @@ static int spapr_vty_init(VIOsPAPRDevice *sdev)
 }
 
 /* Forward declaration */
-static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg);
-
 static target_ulong h_put_term_char(CPUPPCState *env, sPAPREnvironment *spapr,
                                     target_ulong opcode, target_ulong *args)
 {
@@ -195,7 +193,7 @@ VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus)
     return selected;
 }
 
-static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg)
+VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg)
 {
     VIOsPAPRDevice *sdev;
 
commit 3b768df95a877577a9b8d7ea98166240b017ca84
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Wed Apr 4 15:02:06 2012 +1000

    pseries: Remove unused fields from VIOsPAPRBus structure
    
    The VIOsPAPRBus structure, used on the pseries machine contains some old
    fields which are no longer used anywhere.  This patch removes them.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h
index d8527be..ae3283c 100644
--- a/hw/spapr_vio.h
+++ b/hw/spapr_vio.h
@@ -89,8 +89,6 @@ struct VIOsPAPRDevice {
 
 struct VIOsPAPRBus {
     BusState bus;
-    const char *dt_name, *dt_type, *dt_compatible;
-    target_ulong signal_mask;
     int (*init)(VIOsPAPRDevice *dev);
     int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off);
 };
commit c821a43c60e55fdfb8bc9c64696238e409d96192
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Thu Mar 29 08:39:47 2012 +1100

    pseries: Implement RTAS system-reboot call
    
    This patch adds the PAPR defined RTAS system-reboot call to the pseries
    machine emulation, providing the guest with a way to trigger a reboot.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c
index 0946585..480a4ae 100644
--- a/hw/spapr_rtas.c
+++ b/hw/spapr_rtas.c
@@ -112,6 +112,19 @@ static void rtas_power_off(sPAPREnvironment *spapr,
     rtas_st(rets, 0, 0);
 }
 
+static void rtas_system_reboot(sPAPREnvironment *spapr,
+                               uint32_t token, uint32_t nargs,
+                               target_ulong args,
+                               uint32_t nret, target_ulong rets)
+{
+    if (nargs != 0 || nret != 1) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+    qemu_system_reset_request();
+    rtas_st(rets, 0, 0);
+}
+
 static void rtas_query_cpu_stopped_state(sPAPREnvironment *spapr,
                                          uint32_t token, uint32_t nargs,
                                          target_ulong args,
@@ -294,6 +307,7 @@ static void core_rtas_register_types(void)
     spapr_rtas_register("get-time-of-day", rtas_get_time_of_day);
     spapr_rtas_register("set-time-of-day", rtas_set_time_of_day);
     spapr_rtas_register("power-off", rtas_power_off);
+    spapr_rtas_register("system-reboot", rtas_system_reboot);
     spapr_rtas_register("query-cpu-stopped-state",
                         rtas_query_cpu_stopped_state);
     spapr_rtas_register("start-cpu", rtas_start_cpu);
commit 8e01f355db4c7e54b0877a6d9508e83d0afbc4b6
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Thu Mar 29 08:39:46 2012 +1100

    pseries: Fix bug with reset of VIO CRQs
    
    PAPR specifies a Command Response Queue (CRQ) mechanism used for virtual
    IO, which we implement.  However, we don't correctly clean up registered
    CRQs when we reset the system.
    
    This patch adds a reset handler to fix this bug.  While we're at it, add
    in some of the extra debug messages that were used to track the problem
    down.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    [AF: Updated hcall_dprintf()s to not duplicate the function name]
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index 1f67e64..0bf2c31 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -431,12 +431,13 @@ static target_ulong h_reg_crq(CPUPPCState *env, sPAPREnvironment *spapr,
 
     /* Check if device supports CRQs */
     if (!dev->crq.SendFunc) {
+        hcall_dprintf("Device does not support CRQ\n");
         return H_NOT_FOUND;
     }
 
-
     /* Already a queue ? */
     if (dev->crq.qsize) {
+        hcall_dprintf("CRQ already registered\n");
         return H_RESOURCE;
     }
     dev->crq.qladdr = queue_addr;
@@ -449,6 +450,17 @@ static target_ulong h_reg_crq(CPUPPCState *env, sPAPREnvironment *spapr,
     return H_SUCCESS;
 }
 
+static target_ulong free_crq(VIOsPAPRDevice *dev)
+{
+    dev->crq.qladdr = 0;
+    dev->crq.qsize = 0;
+    dev->crq.qnext = 0;
+
+    dprintf("CRQ for dev 0x%" PRIx32 " freed\n", dev->reg);
+
+    return H_SUCCESS;
+}
+
 static target_ulong h_free_crq(CPUPPCState *env, sPAPREnvironment *spapr,
                                target_ulong opcode, target_ulong *args)
 {
@@ -460,13 +472,7 @@ static target_ulong h_free_crq(CPUPPCState *env, sPAPREnvironment *spapr,
         return H_PARAMETER;
     }
 
-    dev->crq.qladdr = 0;
-    dev->crq.qsize = 0;
-    dev->crq.qnext = 0;
-
-    dprintf("CRQ for dev 0x" TARGET_FMT_lx " freed\n", reg);
-
-    return H_SUCCESS;
+    return free_crq(dev);
 }
 
 static target_ulong h_send_crq(CPUPPCState *env, sPAPREnvironment *spapr,
@@ -642,6 +648,15 @@ static int spapr_vio_check_reg(VIOsPAPRDevice *sdev)
     return 0;
 }
 
+static void spapr_vio_busdev_reset(void *opaque)
+{
+    VIOsPAPRDevice *dev = (VIOsPAPRDevice *)opaque;
+
+    if (dev->crq.qsize) {
+        free_crq(dev);
+    }
+}
+
 static int spapr_vio_busdev_init(DeviceState *qdev)
 {
     VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
@@ -670,6 +685,8 @@ static int spapr_vio_busdev_init(DeviceState *qdev)
 
     rtce_init(dev);
 
+    qemu_register_reset(spapr_vio_busdev_reset, dev);
+
     return pc->init(dev);
 }
 
commit d9599c9205089805cd6ef55985beeb06aef0c819
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Thu Mar 29 08:39:45 2012 +1100

    pseries: Clean up hcall_dprintf() debugging messages
    
    The pseries machine code has a number of debug messages for debugging PAPR
    hypercalls, dependent on DEBUG_SPAPR_HCALLS.  This patch cleans these
    messages up a bit, by adding __func__ to the hcall_dprintf() macro and
    simplifying up a number of the individual messages accordingly.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/spapr.h b/hw/spapr.h
index 11160b0..654a7a8 100644
--- a/hw/spapr.h
+++ b/hw/spapr.h
@@ -272,7 +272,7 @@ extern sPAPREnvironment *spapr;
 
 #ifdef DEBUG_SPAPR_HCALLS
 #define hcall_dprintf(fmt, ...) \
-    do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
+    do { fprintf(stderr, "%s: " fmt, __func__, ## __VA_ARGS__); } while (0)
 #else
 #define hcall_dprintf(fmt, ...) \
     do { } while (0)
diff --git a/hw/spapr_llan.c b/hw/spapr_llan.c
index cfc7778..32dce17 100644
--- a/hw/spapr_llan.c
+++ b/hw/spapr_llan.c
@@ -279,21 +279,19 @@ static target_ulong h_register_logical_lan(CPUPPCState *env,
 
     if (check_bd(dev, VLAN_VALID_BD(buf_list, SPAPR_VIO_TCE_PAGE_SIZE),
                  SPAPR_VIO_TCE_PAGE_SIZE) < 0) {
-        hcall_dprintf("Bad buf_list 0x" TARGET_FMT_lx " for "
-                      "H_REGISTER_LOGICAL_LAN\n", buf_list);
+        hcall_dprintf("Bad buf_list 0x" TARGET_FMT_lx "\n", buf_list);
         return H_PARAMETER;
     }
 
     filter_list_bd = VLAN_VALID_BD(filter_list, SPAPR_VIO_TCE_PAGE_SIZE);
     if (check_bd(dev, filter_list_bd, SPAPR_VIO_TCE_PAGE_SIZE) < 0) {
-        hcall_dprintf("Bad filter_list 0x" TARGET_FMT_lx " for "
-                      "H_REGISTER_LOGICAL_LAN\n", filter_list);
+        hcall_dprintf("Bad filter_list 0x" TARGET_FMT_lx "\n", filter_list);
         return H_PARAMETER;
     }
 
     if (!(rec_queue & VLAN_BD_VALID)
         || (check_bd(dev, rec_queue, VLAN_RQ_ALIGNMENT) < 0)) {
-        hcall_dprintf("Bad receive queue for H_REGISTER_LOGICAL_LAN\n");
+        hcall_dprintf("Bad receive queue\n");
         return H_PARAMETER;
     }
 
@@ -358,13 +356,13 @@ static target_ulong h_add_logical_lan_buffer(CPUPPCState *env,
             ", 0x" TARGET_FMT_lx ")\n", reg, buf);
 
     if (!sdev) {
-        hcall_dprintf("Wrong device in h_add_logical_lan_buffer\n");
+        hcall_dprintf("Bad device\n");
         return H_PARAMETER;
     }
 
     if ((check_bd(dev, buf, 4) < 0)
         || (VLAN_BD_LEN(buf) < 16)) {
-        hcall_dprintf("Bad buffer enqueued in h_add_logical_lan_buffer\n");
+        hcall_dprintf("Bad buffer enqueued\n");
         return H_PARAMETER;
     }
 
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index dbf5a90..1f67e64 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -204,8 +204,7 @@ static target_ulong h_put_tce(CPUPPCState *env, sPAPREnvironment *spapr,
     VIOsPAPR_RTCE *rtce;
 
     if (!dev) {
-        hcall_dprintf("spapr_vio_put_tce on non-existent LIOBN "
-                      TARGET_FMT_lx "\n", liobn);
+        hcall_dprintf("LIOBN 0x" TARGET_FMT_lx " does not exist\n", liobn);
         return H_PARAMETER;
     }
 
@@ -217,8 +216,7 @@ static target_ulong h_put_tce(CPUPPCState *env, sPAPREnvironment *spapr,
 #endif
 
     if (ioba >= dev->rtce_window_size) {
-        hcall_dprintf("spapr_vio_put_tce on out-of-boards IOBA 0x"
-                      TARGET_FMT_lx "\n", ioba);
+        hcall_dprintf("Out-of-bounds IOBA 0x" TARGET_FMT_lx "\n", ioba);
         return H_PARAMETER;
     }
 
@@ -414,22 +412,20 @@ static target_ulong h_reg_crq(CPUPPCState *env, sPAPREnvironment *spapr,
     VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
 
     if (!dev) {
-        hcall_dprintf("h_reg_crq on non-existent unit 0x"
-                      TARGET_FMT_lx "\n", reg);
+        hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
         return H_PARAMETER;
     }
 
     /* We can't grok a queue size bigger than 256M for now */
     if (queue_len < 0x1000 || queue_len > 0x10000000) {
-        hcall_dprintf("h_reg_crq, queue size too small or too big (0x%llx)\n",
-                      (unsigned long long)queue_len);
+        hcall_dprintf("Queue size too small or too big (0x" TARGET_FMT_lx
+                      ")\n", queue_len);
         return H_PARAMETER;
     }
 
     /* Check queue alignment */
     if (queue_addr & 0xfff) {
-        hcall_dprintf("h_reg_crq, queue not aligned (0x%llx)\n",
-                      (unsigned long long)queue_addr);
+        hcall_dprintf("Queue not aligned (0x" TARGET_FMT_lx ")\n", queue_addr);
         return H_PARAMETER;
     }
 
@@ -460,8 +456,7 @@ static target_ulong h_free_crq(CPUPPCState *env, sPAPREnvironment *spapr,
     VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
 
     if (!dev) {
-        hcall_dprintf("h_free_crq on non-existent unit 0x"
-                      TARGET_FMT_lx "\n", reg);
+        hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
         return H_PARAMETER;
     }
 
@@ -484,8 +479,7 @@ static target_ulong h_send_crq(CPUPPCState *env, sPAPREnvironment *spapr,
     uint64_t crq_mangle[2];
 
     if (!dev) {
-        hcall_dprintf("h_send_crq on non-existent unit 0x"
-                      TARGET_FMT_lx "\n", reg);
+        hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
         return H_PARAMETER;
     }
     crq_mangle[0] = cpu_to_be64(msg_hi);
@@ -505,8 +499,7 @@ static target_ulong h_enable_crq(CPUPPCState *env, sPAPREnvironment *spapr,
     VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
 
     if (!dev) {
-        hcall_dprintf("h_enable_crq on non-existent unit 0x"
-                      TARGET_FMT_lx "\n", reg);
+        hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
         return H_PARAMETER;
     }
 
commit 52d631dcc70144b6ce8293db78cd6de635331c83
Author: Mark Cave-Ayland <mark.cave-ayland at ilande.co.uk>
Date:   Tue Mar 27 16:41:55 2012 +0100

    PPC: Fix TLB invalidation bug within the PPC interrupt handler.
    
    Commit 41557447d30eeb944e42069513df13585f5e6c7f also introduced a subtle TLB
    flush bug. By applying a mask to the interrupt MSR which cleared the IR/DR
    bits at the start of the interrupt handler, the logic towards the end of the
    handler to force a TLB flush if either one of these bits were set would never
    be triggered.
    
    This patch simply changes the IR/DR bit check in the TLB flush logic to use
    the original MSR value (albeit with some interrupt-specific bits cleared) so
    that the IR/DR bits are preserved at the point where the check takes place.
    
    Signed-off-by: Mark Cave-Ayland <mark.cave-ayland at ilande.co.uk>
    Acked-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index e13b749..f0ea1c3 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -2960,7 +2960,7 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp)
     if (asrr1 != -1)
         env->spr[asrr1] = env->spr[srr1];
     /* If we disactivated any translation, flush TLBs */
-    if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
+    if (msr & ((1 << MSR_IR) | (1 << MSR_DR)))
         tlb_flush(env, 1);
 
     if (msr_ile) {
commit cdde6ffc27517bdf069734fbc5693ce2b14edc75
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Jan 4 16:28:42 2012 +0200

    pci: fix corrupted pci conf index register by unaligned write
    
    Commit d0ed8076cbdc261 converted the PCI config access to the memory
    API, but also inadvertantly changed it to accept unaligned writes,
    and corrupt the index register in the process.  This causes a regression
    booting NetBSD.
    
    Fix by ignoring unaligned or non-dword writes.
    
    https://bugs.launchpad.net/qemu/+bug/897771
    
    Reported-by: Andreas Gustafsson <gson at gson.org>
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci_host.c b/hw/pci_host.c
index 44c6c20..8041778 100644
--- a/hw/pci_host.c
+++ b/hw/pci_host.c
@@ -101,6 +101,9 @@ static void pci_host_config_write(void *opaque, target_phys_addr_t addr,
 
     PCI_DPRINTF("%s addr " TARGET_FMT_plx " len %d val %"PRIx64"\n",
                 __func__, addr, len, val);
+    if (addr != 0 || len != 4) {
+        return;
+    }
     s->config_reg = val;
 }
 
commit 54bfa546a0b5af335128ef5c477f8af9834df498
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Sun Apr 15 12:00:52 2012 +0300

    acpi: explicitly account for >1 device per slot
    
    Slot present bit is cleared apparently for each device. Hotplug and non
    hotplug devices should not mix normally, and we only set the bit when we
    add a device so it should all work out, but it's more robust to
    explicitly account for more than one device per slot.
    
    Acked-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 11c1f85..585da4e 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -287,6 +287,7 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
     DeviceState *qdev, *next;
     BusState *bus = qdev_get_parent_bus(&s->dev.qdev);
     int slot = ffs(slots) - 1;
+    bool slot_free = true;
 
     /* Mark request as complete */
     s->pci0_status.down &= ~(1U << slot);
@@ -294,11 +295,17 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
     QTAILQ_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
         PCIDevice *dev = PCI_DEVICE(qdev);
         PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
-        if (PCI_SLOT(dev->devfn) == slot && !pc->no_hotplug) {
-            s->pci0_slot_device_present &= ~(1U << slot);
-            qdev_free(qdev);
+        if (PCI_SLOT(dev->devfn) == slot) {
+            if (pc->no_hotplug) {
+                slot_free = false;
+            } else {
+                qdev_free(qdev);
+            }
         }
     }
+    if (slot_free) {
+        s->pci0_slot_device_present &= ~(1U << slot);
+    }
 }
 
 static void piix4_update_hotplug(PIIX4PMState *s)
commit 9290f364c1f0c0a5a2ee8e03607f4804455c0d0e
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Apr 5 11:07:28 2012 -0600

    acpi_piix4: Re-define PCI hotplug eject register read
    
    The PCI hotplug eject register has always returned 0, so let's redefine
    it as a hotplug feature register.  The existing model of using separate
    up & down read-only registers and an eject via write to this register
    becomes the base implementation.  As we make use of new interfaces we'll
    set bits here to allow the BIOS and AML implementation to optimize for
    the platform implementation.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/docs/specs/acpi_pci_hotplug.txt b/docs/specs/acpi_pci_hotplug.txt
index 1883d63..a839434 100644
--- a/docs/specs/acpi_pci_hotplug.txt
+++ b/docs/specs/acpi_pci_hotplug.txt
@@ -27,8 +27,16 @@ events.  Read-only.
 PCI device eject (IO port 0xae08-0xae0b, 4-byte access):
 ----------------------------------------
 
-Used by ACPI BIOS _EJ0 method to request device removal. One bit per slot.
-Reads return 0.
+Write: Used by ACPI BIOS _EJ0 method to request device removal.
+One bit per slot.
+
+Read: Hotplug features register.  Used by platform to identify features
+available.  Current base feature set (no bits set):
+ - Read-only "up" register @0xae00, 4-byte access, bit per slot
+ - Read-only "down" register @0xae04, 4-byte access, bit per slot
+ - Read/write "eject" register @0xae08, 4-byte access,
+   write: bit per slot eject, read: hotplug feature set
+ - Read-only hotplug capable register @0xae0c, 4-byte access, bit per slot
 
 PCI removability status (IO port 0xae0c-0xae0f, 4-byte access):
 -----------------------------------------------
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 5d3b0ba..11c1f85 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -511,9 +511,10 @@ static uint32_t pci_down_read(void *opaque, uint32_t addr)
     return val;
 }
 
-static uint32_t pciej_read(void *opaque, uint32_t addr)
+static uint32_t pci_features_read(void *opaque, uint32_t addr)
 {
-    PIIX4_DPRINTF("pciej read %x\n", addr);
+    /* No feature defined yet */
+    PIIX4_DPRINTF("pci_features_read %x\n", 0);
     return 0;
 }
 
@@ -545,7 +546,7 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
     register_ioport_read(PCI_DOWN_BASE, 4, 4, pci_down_read, s);
 
     register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, s);
-    register_ioport_read(PCI_EJ_BASE, 4, 4,  pciej_read, s);
+    register_ioport_read(PCI_EJ_BASE, 4, 4,  pci_features_read, s);
 
     register_ioport_read(PCI_RMV_BASE, 4, 4,  pcirmv_read, s);
 
commit 31745aabcd6dce5583dbd0e5ddee93ff9fdfe3e6
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Apr 5 11:07:21 2012 -0600

    acpi_piix4: Remove PCI_RMV_BASE write code
    
    Clarify this register as read-only and remove write code.  No
    change in existing behavior.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/docs/specs/acpi_pci_hotplug.txt b/docs/specs/acpi_pci_hotplug.txt
index 1e2c8a2..1883d63 100644
--- a/docs/specs/acpi_pci_hotplug.txt
+++ b/docs/specs/acpi_pci_hotplug.txt
@@ -34,4 +34,4 @@ PCI removability status (IO port 0xae0c-0xae0f, 4-byte access):
 -----------------------------------------------
 
 Used by ACPI BIOS _RMV method to indicate removability status to OS. One
-bit per slot.
+bit per slot.  Read-only
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 0e7af51..5d3b0ba 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -531,11 +531,6 @@ static uint32_t pcirmv_read(void *opaque, uint32_t addr)
     return s->pci0_hotplug_enable;
 }
 
-static void pcirmv_write(void *opaque, uint32_t addr, uint32_t val)
-{
-    return;
-}
-
 static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
                                 PCIHotplugState state);
 
@@ -552,7 +547,6 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
     register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, s);
     register_ioport_read(PCI_EJ_BASE, 4, 4,  pciej_read, s);
 
-    register_ioport_write(PCI_RMV_BASE, 4, 4, pcirmv_write, s);
     register_ioport_read(PCI_RMV_BASE, 4, 4,  pcirmv_read, s);
 
     pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev);
commit 7faa8075d898ae56d2c533c530569bb25ab86eaf
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Apr 5 11:07:15 2012 -0600

    acpi_piix4: Fix PCI hotplug race
    
    As Michael Tsirkin demonstrated, current PCI hotplug is vulnerable
    to a few races.  The first is a race with other hotplug operations
    because we clear the up & down registers at each event.  If a new
    event comes before the last is processed, up/down is cleared and
    the event is lost.
    
    To fix this for the down register, we create a life cycle for
    the event request that starts with the hot unplug request in
    piix4_device_hotplug() and ends when the device is ejected.
    This allows us to mask and clear individual bits, preserving them
    against races.  For the up register, we have no clear end point
    for when the event is finished.  We could modify the BIOS to
    acknowledge the bit and clear it, but this creates BIOS compatibiliy
    issues without offering a complete solution.  Instead we note that
    gratuitous ACPI device checks are not harmful, which allows us to
    issue a device check for every slot.  We know which slots are present
    and we know which slots are hotpluggable, so we can easily reduce
    this to a more manageable set for the guest.
    
    The other race Michael noted was that an unplug request followed
    by reset may also lose the eject notification, which may also
    result in the eject request being lost which a subsequent add
    or remove.  Once we're in reset, the device is unused and we can
    flush the queue of device removals ourselves.  Previously if a
    device_del was issued to a guest without ACPI PCI hotplug support,
    it was necessary to shutdown the guest to recover the device.
    With this, a guest reboot is sufficient.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 5e8b261..0e7af51 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -48,7 +48,7 @@
 #define PIIX4_PCI_HOTPLUG_STATUS 2
 
 struct pci_status {
-    uint32_t up;
+    uint32_t up; /* deprecated, maintained for migration compatibility */
     uint32_t down;
 };
 
@@ -70,6 +70,7 @@ typedef struct PIIX4PMState {
     /* for pci hotplug */
     struct pci_status pci0_status;
     uint32_t pci0_hotplug_enable;
+    uint32_t pci0_slot_device_present;
 } PIIX4PMState;
 
 static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s);
@@ -205,6 +206,17 @@ static void pm_write_config(PCIDevice *d,
         pm_io_space_update((PIIX4PMState *)d);
 }
 
+static void vmstate_pci_status_pre_save(void *opaque)
+{
+    struct pci_status *pci0_status = opaque;
+    PIIX4PMState *s = container_of(pci0_status, PIIX4PMState, pci0_status);
+
+    /* We no longer track up, so build a safe value for migrating
+     * to a version that still does... of course these might get lost
+     * by an old buggy implementation, but we try. */
+    pci0_status->up = s->pci0_slot_device_present & s->pci0_hotplug_enable;
+}
+
 static int vmstate_acpi_post_load(void *opaque, int version_id)
 {
     PIIX4PMState *s = opaque;
@@ -241,6 +253,7 @@ static const VMStateDescription vmstate_pci_status = {
     .version_id = 1,
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
+    .pre_save = vmstate_pci_status_pre_save,
     .fields      = (VMStateField []) {
         VMSTATE_UINT32(up, struct pci_status),
         VMSTATE_UINT32(down, struct pci_status),
@@ -269,13 +282,38 @@ static const VMStateDescription vmstate_acpi = {
     }
 };
 
+static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
+{
+    DeviceState *qdev, *next;
+    BusState *bus = qdev_get_parent_bus(&s->dev.qdev);
+    int slot = ffs(slots) - 1;
+
+    /* Mark request as complete */
+    s->pci0_status.down &= ~(1U << slot);
+
+    QTAILQ_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
+        PCIDevice *dev = PCI_DEVICE(qdev);
+        PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
+        if (PCI_SLOT(dev->devfn) == slot && !pc->no_hotplug) {
+            s->pci0_slot_device_present &= ~(1U << slot);
+            qdev_free(qdev);
+        }
+    }
+}
+
 static void piix4_update_hotplug(PIIX4PMState *s)
 {
     PCIDevice *dev = &s->dev;
     BusState *bus = qdev_get_parent_bus(&dev->qdev);
     DeviceState *qdev, *next;
 
+    /* Execute any pending removes during reset */
+    while (s->pci0_status.down) {
+        acpi_piix_eject_slot(s, s->pci0_status.down);
+    }
+
     s->pci0_hotplug_enable = ~0;
+    s->pci0_slot_device_present = 0;
 
     QTAILQ_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
         PCIDevice *pdev = PCI_DEVICE(qdev);
@@ -283,8 +321,10 @@ static void piix4_update_hotplug(PIIX4PMState *s)
         int slot = PCI_SLOT(pdev->devfn);
 
         if (pc->no_hotplug) {
-            s->pci0_hotplug_enable &= ~(1 << slot);
+            s->pci0_hotplug_enable &= ~(1U << slot);
         }
+
+        s->pci0_slot_device_present |= (1U << slot);
     }
 }
 
@@ -452,7 +492,11 @@ static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val)
 static uint32_t pci_up_read(void *opaque, uint32_t addr)
 {
     PIIX4PMState *s = opaque;
-    uint32_t val = s->pci0_status.up;
+    uint32_t val;
+
+    /* Manufacture an "up" value to cause a device check on any hotplug
+     * slot with a device.  Extra device checks are harmless. */
+    val = s->pci0_slot_device_present & s->pci0_hotplug_enable;
 
     PIIX4_DPRINTF("pci_up_read %x\n", val);
     return val;
@@ -475,18 +519,7 @@ static uint32_t pciej_read(void *opaque, uint32_t addr)
 
 static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
 {
-    BusState *bus = opaque;
-    DeviceState *qdev, *next;
-    int slot = ffs(val) - 1;
-
-    QTAILQ_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
-        PCIDevice *dev = PCI_DEVICE(qdev);
-        PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
-        if (PCI_SLOT(dev->devfn) == slot && !pc->no_hotplug) {
-            qdev_free(qdev);
-        }
-    }
-
+    acpi_piix_eject_slot(opaque, val);
 
     PIIX4_DPRINTF("pciej write %x <== %d\n", addr, val);
 }
@@ -516,8 +549,8 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
     register_ioport_read(PCI_UP_BASE, 4, 4, pci_up_read, s);
     register_ioport_read(PCI_DOWN_BASE, 4, 4, pci_down_read, s);
 
-    register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, bus);
-    register_ioport_read(PCI_EJ_BASE, 4, 4,  pciej_read, bus);
+    register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, s);
+    register_ioport_read(PCI_EJ_BASE, 4, 4,  pciej_read, s);
 
     register_ioport_write(PCI_RMV_BASE, 4, 4, pcirmv_write, s);
     register_ioport_read(PCI_RMV_BASE, 4, 4,  pcirmv_read, s);
@@ -528,13 +561,13 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
 static void enable_device(PIIX4PMState *s, int slot)
 {
     s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
-    s->pci0_status.up |= (1 << slot);
+    s->pci0_slot_device_present |= (1U << slot);
 }
 
 static void disable_device(PIIX4PMState *s, int slot)
 {
     s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
-    s->pci0_status.down |= (1 << slot);
+    s->pci0_status.down |= (1U << slot);
 }
 
 static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
@@ -548,11 +581,10 @@ static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
      * it is present on boot, no hotplug event is necessary. We do send an
      * event when the device is disabled later. */
     if (state == PCI_COLDPLUG_ENABLED) {
+        s->pci0_slot_device_present |= (1U << slot);
         return 0;
     }
 
-    s->pci0_status.up = 0;
-    s->pci0_status.down = 0;
     if (state == PCI_HOTPLUG_ENABLED) {
         enable_device(s, slot);
     } else {
commit ba737541edddf9d0026460eb7b1d1c599b4c8ae9
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Apr 5 11:07:08 2012 -0600

    acpi_piix4: Disallow write to up/down PCI hotplug registers
    
    The write side of these registers is never used and actually can't be
    used as defined because any read/modify/write sequence from the guest
    potentially races with qemu.  Drop the write support and define these
    as read-only registers.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/docs/specs/acpi_pci_hotplug.txt b/docs/specs/acpi_pci_hotplug.txt
index f0f74a7..1e2c8a2 100644
--- a/docs/specs/acpi_pci_hotplug.txt
+++ b/docs/specs/acpi_pci_hotplug.txt
@@ -15,14 +15,14 @@ PCI slot injection notification pending (IO port 0xae00-0xae03, 4-byte access):
 Slot injection notification pending. One bit per slot.
 
 Read by ACPI BIOS GPE.1 handler to notify OS of injection
-events.
+events.  Read-only.
 
 PCI slot removal notification (IO port 0xae04-0xae07, 4-byte access):
 -----------------------------------------------------
 Slot removal notification pending. One bit per slot.
 
 Read by ACPI BIOS GPE.1 handler to notify OS of removal
-events.
+events.  Read-only.
 
 PCI device eject (IO port 0xae08-0xae0b, 4-byte access):
 ----------------------------------------
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 797ed24..5e8b261 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -40,7 +40,8 @@
 
 #define GPE_BASE 0xafe0
 #define GPE_LEN 4
-#define PCI_BASE 0xae00
+#define PCI_UP_BASE 0xae00
+#define PCI_DOWN_BASE 0xae04
 #define PCI_EJ_BASE 0xae08
 #define PCI_RMV_BASE 0xae0c
 
@@ -448,38 +449,22 @@ static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val)
     PIIX4_DPRINTF("gpe write %x <== %d\n", addr, val);
 }
 
-static uint32_t pcihotplug_read(void *opaque, uint32_t addr)
+static uint32_t pci_up_read(void *opaque, uint32_t addr)
 {
-    uint32_t val = 0;
-    struct pci_status *g = opaque;
-    switch (addr) {
-        case PCI_BASE:
-            val = g->up;
-            break;
-        case PCI_BASE + 4:
-            val = g->down;
-            break;
-        default:
-            break;
-    }
+    PIIX4PMState *s = opaque;
+    uint32_t val = s->pci0_status.up;
 
-    PIIX4_DPRINTF("pcihotplug read %x == %x\n", addr, val);
+    PIIX4_DPRINTF("pci_up_read %x\n", val);
     return val;
 }
 
-static void pcihotplug_write(void *opaque, uint32_t addr, uint32_t val)
+static uint32_t pci_down_read(void *opaque, uint32_t addr)
 {
-    struct pci_status *g = opaque;
-    switch (addr) {
-        case PCI_BASE:
-            g->up = val;
-            break;
-        case PCI_BASE + 4:
-            g->down = val;
-            break;
-   }
-
-    PIIX4_DPRINTF("pcihotplug write %x <== %d\n", addr, val);
+    PIIX4PMState *s = opaque;
+    uint32_t val = s->pci0_status.down;
+
+    PIIX4_DPRINTF("pci_down_read %x\n", val);
+    return val;
 }
 
 static uint32_t pciej_read(void *opaque, uint32_t addr)
@@ -523,14 +508,13 @@ static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
 
 static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
 {
-    struct pci_status *pci0_status = &s->pci0_status;
 
     register_ioport_write(GPE_BASE, GPE_LEN, 1, gpe_writeb, s);
     register_ioport_read(GPE_BASE, GPE_LEN, 1,  gpe_readb, s);
     acpi_gpe_blk(&s->ar, GPE_BASE);
 
-    register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, pci0_status);
-    register_ioport_read(PCI_BASE, 8, 4,  pcihotplug_read, pci0_status);
+    register_ioport_read(PCI_UP_BASE, 4, 4, pci_up_read, s);
+    register_ioport_read(PCI_DOWN_BASE, 4, 4, pci_down_read, s);
 
     register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, bus);
     register_ioport_read(PCI_EJ_BASE, 4, 4,  pciej_read, bus);
commit da12872a0973718997c00f1c1e8e5b91ee4c713a
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Sat Apr 14 22:51:33 2012 +0200

    pcspk: initialize PC speaker if compiled in
    
    PC speaker has been moved to target-independant code in 71093711589dafcb920dc3bc9bb811eaf8b14101,
    so do not depend of target to include it or not.
    
    Cc: malc <av1474 at comtv.ru>
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Herv? Poussineau <hpoussin at reactos.org>
    Signed-off-by: malc <av1474 at comtv.ru>

diff --git a/arch_init.c b/arch_init.c
index 595badf..9a35aee 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -475,7 +475,7 @@ struct soundhw {
 
 static struct soundhw soundhw[] = {
 #ifdef HAS_AUDIO_CHOICE
-#if defined(TARGET_I386) || defined(TARGET_MIPS)
+#ifdef CONFIG_PCSPK
     {
         "pcspk",
         "PC speaker",
commit 2ad596079ecc9b379bcd253157bd0c911058e0e1
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Mar 31 12:50:21 2012 +0200

    tests: remove .SECONDARY special target
    
    The special target should not be needed anymore, and caused (perhaps
    due to a Make bug) a failure with "make -j2".  In any case, the
    main makefile is a better place for such special targets rather
    than an included makefile.
    
    Reported-by: Luiz Capitulino <lcapitulino at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Tested-by: Luiz Capitulino <lcapitulino at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tests/Makefile b/tests/Makefile
index a98a848..baf1d70 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -92,8 +92,6 @@ check-help:
 	@echo "Default options are -k and (for make V=1) --verbose; they can be"
 	@echo "changed with variable GTESTER_OPTIONS."
 
-.SECONDARY:
-
 SPEED = quick
 GTESTER_OPTIONS = -k $(if $(V),--verbose,-q)
 
commit ad4ccc9370339e4f311a9e1d2c7cae77a9d45639
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Tue Apr 10 02:48:20 2012 +0400

    target-xtensa: add test for IBREAK invalidation
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tests/tcg/xtensa/test_break.S b/tests/tcg/xtensa/test_break.S
index 8a8db80..7574cbe 100644
--- a/tests/tcg/xtensa/test_break.S
+++ b/tests/tcg/xtensa/test_break.S
@@ -91,6 +91,40 @@ test ibreak
     assert  eq, a2, a3
 test_end
 
+test ibreak_remove
+    set_vector debug_vector, 3f
+    rsil    a2, debug_level - 1
+    movi    a2, 2f
+    wsr     a2, ibreaka0
+    movi    a3, 1
+1:
+    wsr     a3, ibreakenable
+    isync
+2:
+    beqz    a3, 4f
+    test_fail
+3:
+    assert  eqi, a3, 1
+    rsr     a2, ps
+    movi    a3, 0x1f
+    and     a2, a2, a3
+    movi    a3, 0x10 | debug_level
+    assert  eq, a2, a3
+    rsr     a2, epc6
+    movi    a3, 2b
+    assert  eq, a2, a3
+    rsr     a2, debugcause
+    movi    a3, 0x2
+    assert  eq, a2, a3
+
+    movi    a2, 0x40000
+    wsr     a2, ps
+    isync
+    movi    a3, 0
+    j       1b
+4:
+test_end
+
 test ibreak_priority
     set_vector debug_vector, 2f
     rsil    a2, debug_level - 1
commit ec9fe93efe3a1211caa182771725833bbca733e0
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Tue Apr 10 02:48:19 2012 +0400

    target-xtensa: add tests for LBEG/LEND invalidation
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tests/tcg/xtensa/test_loop.S b/tests/tcg/xtensa/test_loop.S
index a5ea933..5cead47 100644
--- a/tests/tcg/xtensa/test_loop.S
+++ b/tests/tcg/xtensa/test_loop.S
@@ -74,4 +74,54 @@ test loop_excm
     assert  eqi, a2, 1
 test_end
 
+test lbeg_invalidation
+    movi    a2, 0
+    movi    a3, 1
+    movi    a4, 1f
+    movi    a5, 3f
+    wsr     a3, lcount
+    wsr     a4, lbeg
+    wsr     a5, lend
+    isync
+    j       1f
+.align 4
+1:
+    addi    a2, a2, 1
+    j       2f
+.align 4
+2:
+    addi    a2, a2, 2
+    movi    a3, 2b
+    wsr     a3, lbeg
+    isync
+    nop
+3:
+    assert  eqi, a2, 5
+test_end
+
+test lend_invalidation
+    movi    a2, 0
+    movi    a3, 5
+    movi    a4, 1f
+    movi    a5, 2f
+    wsr     a3, lcount
+    wsr     a4, lbeg
+    wsr     a5, lend
+    isync
+    j       1f
+.align 4
+1:
+    addi    a2, a2, 1
+2:
+    beqi    a3, 3, 1f
+    assert  eqi, a2, 6
+    movi    a3, 3
+    wsr     a3, lcount
+    wsr     a4, lend
+    isync
+    j       1b
+1:
+    assert  eqi, a2, 7
+test_end
+
 test_suite_end
commit 3d0be8a5c135dadcfbd68ed354007a8cece98849
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Tue Apr 10 02:48:18 2012 +0400

    target-xtensa: fix tb invalidation for IBREAK and LOOP
    
    Instruction breakpoint/zero overhead loop handling code is built into
    TBs pointed to by IBREAKA/LEND SRs. When these or related SRs get
    changed TBs at virtual addresses corresponding to their old and their
    new values must be invalidated.
    
    Virtual address range is passed to the tb_invalidate_phys_page_range,
    which is incorrect in system emulation mode.
    
    To fix it use guest TLB/MMU to translate virtual address to physical
    address.
    
    However the guest may not have virtual-to-physical mapping at the moment
    of IBREAKA/LEND change, thus this fix is not 100% accurate.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index a6dd72d..364dc19 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -98,6 +98,18 @@ void tlb_fill(CPUXtensaState *env1, target_ulong vaddr, int is_write, int mmu_id
     env = saved_env;
 }
 
+static void tb_invalidate_virtual_addr(CPUXtensaState *env, uint32_t vaddr)
+{
+    uint32_t paddr;
+    uint32_t page_size;
+    unsigned access;
+    int ret = xtensa_get_physical_addr(env, vaddr, 2, 0,
+            &paddr, &page_size, &access);
+    if (ret == 0) {
+        tb_invalidate_phys_addr(paddr);
+    }
+}
+
 void HELPER(exception)(uint32_t excp)
 {
     env->exception_index = excp;
@@ -357,8 +369,7 @@ void HELPER(movsp)(uint32_t pc)
 void HELPER(wsr_lbeg)(uint32_t v)
 {
     if (env->sregs[LBEG] != v) {
-        tb_invalidate_phys_page_range(
-                env->sregs[LEND] - 1, env->sregs[LEND], 0);
+        tb_invalidate_virtual_addr(env, env->sregs[LEND] - 1);
         env->sregs[LBEG] = v;
     }
 }
@@ -366,11 +377,9 @@ void HELPER(wsr_lbeg)(uint32_t v)
 void HELPER(wsr_lend)(uint32_t v)
 {
     if (env->sregs[LEND] != v) {
-        tb_invalidate_phys_page_range(
-                env->sregs[LEND] - 1, env->sregs[LEND], 0);
+        tb_invalidate_virtual_addr(env, env->sregs[LEND] - 1);
         env->sregs[LEND] = v;
-        tb_invalidate_phys_page_range(
-                env->sregs[LEND] - 1, env->sregs[LEND], 0);
+        tb_invalidate_virtual_addr(env, env->sregs[LEND] - 1);
     }
 }
 
@@ -691,8 +700,7 @@ void HELPER(wsr_ibreakenable)(uint32_t v)
 
     for (i = 0; i < env->config->nibreak; ++i) {
         if (change & (1 << i)) {
-            tb_invalidate_phys_page_range(
-                    env->sregs[IBREAKA + i], env->sregs[IBREAKA + i] + 1, 0);
+            tb_invalidate_virtual_addr(env, env->sregs[IBREAKA + i]);
         }
     }
     env->sregs[IBREAKENABLE] = v & ((1 << env->config->nibreak) - 1);
@@ -701,9 +709,8 @@ void HELPER(wsr_ibreakenable)(uint32_t v)
 void HELPER(wsr_ibreaka)(uint32_t i, uint32_t v)
 {
     if (env->sregs[IBREAKENABLE] & (1 << i) && env->sregs[IBREAKA + i] != v) {
-        tb_invalidate_phys_page_range(
-                env->sregs[IBREAKA + i], env->sregs[IBREAKA + i] + 1, 0);
-        tb_invalidate_phys_page_range(v, v + 1, 0);
+        tb_invalidate_virtual_addr(env, env->sregs[IBREAKA + i]);
+        tb_invalidate_virtual_addr(env, v);
     }
     env->sregs[IBREAKA + i] = v;
 }
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 492dbcc..6900123 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -459,11 +459,13 @@ static void gen_rsr(DisasContext *dc, TCGv_i32 d, uint32_t sr)
 static void gen_wsr_lbeg(DisasContext *dc, uint32_t sr, TCGv_i32 s)
 {
     gen_helper_wsr_lbeg(s);
+    gen_jumpi_check_loop_end(dc, 0);
 }
 
 static void gen_wsr_lend(DisasContext *dc, uint32_t sr, TCGv_i32 s)
 {
     gen_helper_wsr_lend(s);
+    gen_jumpi_check_loop_end(dc, 0);
 }
 
 static void gen_wsr_sar(DisasContext *dc, uint32_t sr, TCGv_i32 s)
commit 1e7855a558085d6acd0aba4e3278b594d05df1ec
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Tue Apr 10 02:48:17 2012 +0400

    exec: provide tb_invalidate_phys_addr function
    
    Allow TB invalidation by its physical address, extract implementation
    from the breakpoint_invalidate function.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/exec-all.h b/exec-all.h
index fccce88..6bcc075 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -102,6 +102,7 @@ void tlb_flush(CPUArchState *env, int flush_global);
 void tlb_set_page(CPUArchState *env, target_ulong vaddr,
                   target_phys_addr_t paddr, int prot,
                   int mmu_idx, target_ulong size);
+void tb_invalidate_phys_addr(target_phys_addr_t addr);
 #endif
 
 #define CODE_GEN_ALIGN           16 /* must be >= of the size of a icache line */
diff --git a/exec.c b/exec.c
index 63a0d2f..68b8a6a 100644
--- a/exec.c
+++ b/exec.c
@@ -1463,13 +1463,11 @@ static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
     tb_invalidate_phys_page_range(pc, pc + 1, 0);
 }
 #else
-static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
+void tb_invalidate_phys_addr(target_phys_addr_t addr)
 {
-    target_phys_addr_t addr;
     ram_addr_t ram_addr;
     MemoryRegionSection *section;
 
-    addr = cpu_get_phys_page_debug(env, pc);
     section = phys_page_find(addr >> TARGET_PAGE_BITS);
     if (!(memory_region_is_ram(section->mr)
           || (section->mr->rom_device && section->mr->readable))) {
@@ -1479,6 +1477,11 @@ static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
         + section_addr(section, addr);
     tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
 }
+
+static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
+{
+    tb_invalidate_phys_addr(cpu_get_phys_page_debug(env, pc));
+}
 #endif
 #endif /* TARGET_HAS_ICE */
 
commit 2050396801ca0c8359364d61eaadece951006057
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Mon Apr 9 14:20:20 2012 +0000

    Use uintptr_t for various op related functions
    
    Use uintptr_t instead of void * or unsigned long in
    several op related functions, env->mem_io_pc and
    GETPC() macro.
    
    Reviewed-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpu-defs.h b/cpu-defs.h
index 3268968..88d8093 100644
--- a/cpu-defs.h
+++ b/cpu-defs.h
@@ -166,8 +166,8 @@ typedef struct CPUWatchpoint {
     /* in order to avoid passing too many arguments to the MMIO         \
        helpers, we store some rarely used information in the CPU        \
        context) */                                                      \
-    unsigned long mem_io_pc; /* host pc at which the memory was         \
-                                accessed */                             \
+    uintptr_t mem_io_pc; /* host pc at which the memory was             \
+                            accessed */                                 \
     target_ulong mem_io_vaddr; /* target virtual addr at which the      \
                                      memory was accessed */             \
     uint32_t halted; /* Nonzero if the CPU is in suspend state */       \
diff --git a/exec-all.h b/exec-all.h
index fa7bdfe..fccce88 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -87,7 +87,7 @@ int cpu_gen_code(CPUArchState *env, struct TranslationBlock *tb,
 int cpu_restore_state(struct TranslationBlock *tb,
                       CPUArchState *env, uintptr_t searched_pc);
 void QEMU_NORETURN cpu_resume_from_signal(CPUArchState *env1, void *puc);
-void QEMU_NORETURN cpu_io_recompile(CPUArchState *env, void *retaddr);
+void QEMU_NORETURN cpu_io_recompile(CPUArchState *env, uintptr_t retaddr);
 TranslationBlock *tb_gen_code(CPUArchState *env, 
                               target_ulong pc, target_ulong cs_base, int flags,
                               int cflags);
@@ -287,13 +287,13 @@ extern void *tci_tb_ptr;
 # endif
 #elif defined(__s390__) && !defined(__s390x__)
 # define GETPC() \
-    ((void *)(((uintptr_t)__builtin_return_address(0) & 0x7fffffffUL) - 1))
+    (((uintptr_t)__builtin_return_address(0) & 0x7fffffffUL) - 1)
 #elif defined(__arm__)
 /* Thumb return addresses have the low bit set, so we need to subtract two.
    This is still safe in ARM mode because instructions are 4 bytes.  */
-# define GETPC() ((void *)((uintptr_t)__builtin_return_address(0) - 2))
+# define GETPC() ((uintptr_t)__builtin_return_address(0) - 2)
 #else
-# define GETPC() ((void *)((uintptr_t)__builtin_return_address(0) - 1))
+# define GETPC() ((uintptr_t)__builtin_return_address(0) - 1)
 #endif
 
 #if !defined(CONFIG_USER_ONLY)
@@ -305,7 +305,7 @@ void io_mem_write(struct MemoryRegion *mr, target_phys_addr_t addr,
                   uint64_t value, unsigned size);
 
 void tlb_fill(CPUArchState *env1, target_ulong addr, int is_write, int mmu_idx,
-              void *retaddr);
+              uintptr_t retaddr);
 
 #include "softmmu_defs.h"
 
diff --git a/exec.c b/exec.c
index 03d3a6b..63a0d2f 100644
--- a/exec.c
+++ b/exec.c
@@ -1221,7 +1221,7 @@ static inline void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len)
 
 #if !defined(CONFIG_SOFTMMU)
 static void tb_invalidate_phys_page(tb_page_addr_t addr,
-                                    unsigned long pc, void *puc)
+                                    uintptr_t pc, void *puc)
 {
     TranslationBlock *tb;
     PageDesc *p;
@@ -4477,20 +4477,20 @@ int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr,
 
 /* in deterministic execution mode, instructions doing device I/Os
    must be at the end of the TB */
-void cpu_io_recompile(CPUArchState *env, void *retaddr)
+void cpu_io_recompile(CPUArchState *env, uintptr_t retaddr)
 {
     TranslationBlock *tb;
     uint32_t n, cflags;
     target_ulong pc, cs_base;
     uint64_t flags;
 
-    tb = tb_find_pc((uintptr_t)retaddr);
+    tb = tb_find_pc(retaddr);
     if (!tb) {
         cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p", 
-                  retaddr);
+                  (void *)retaddr);
     }
     n = env->icount_decr.u16.low + tb->icount;
-    cpu_restore_state(tb, env, (unsigned long)retaddr);
+    cpu_restore_state(tb, env, retaddr);
     /* Calculate how many instructions had been executed before the fault
        occurred.  */
     n = n - env->icount_decr.u16.low;
@@ -4638,7 +4638,7 @@ bool virtio_is_big_endian(void)
 
 #define MMUSUFFIX _cmmu
 #undef GETPC
-#define GETPC() NULL
+#define GETPC() ((uintptr_t)0)
 #define env cpu_single_env
 #define SOFTMMU_CODE_ACCESS
 
diff --git a/softmmu_template.h b/softmmu_template.h
index afcab1e..b285d78 100644
--- a/softmmu_template.h
+++ b/softmmu_template.h
@@ -69,17 +69,17 @@
 static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_PARAM
                                                         target_ulong addr,
                                                         int mmu_idx,
-                                                        void *retaddr);
+                                                        uintptr_t retaddr);
 static inline DATA_TYPE glue(io_read, SUFFIX)(ENV_PARAM
                                               target_phys_addr_t physaddr,
                                               target_ulong addr,
-                                              void *retaddr)
+                                              uintptr_t retaddr)
 {
     DATA_TYPE res;
     MemoryRegion *mr = iotlb_to_region(physaddr);
 
     physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
-    env->mem_io_pc = (unsigned long)retaddr;
+    env->mem_io_pc = retaddr;
     if (mr != &io_mem_ram && mr != &io_mem_rom
         && mr != &io_mem_unassigned
         && mr != &io_mem_notdirty
@@ -113,7 +113,7 @@ glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_PARAM
     target_ulong tlb_addr;
     target_phys_addr_t ioaddr;
     unsigned long addend;
-    void *retaddr;
+    uintptr_t retaddr;
 
     /* test if there is match for unaligned or IO access */
     /* XXX: could done more in memory macro in a non portable way */
@@ -166,7 +166,7 @@ static DATA_TYPE
 glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_PARAM
                                        target_ulong addr,
                                        int mmu_idx,
-                                       void *retaddr)
+                                       uintptr_t retaddr)
 {
     DATA_TYPE res, res1, res2;
     int index, shift;
@@ -219,13 +219,13 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_PARAM
                                                    target_ulong addr,
                                                    DATA_TYPE val,
                                                    int mmu_idx,
-                                                   void *retaddr);
+                                                   uintptr_t retaddr);
 
 static inline void glue(io_write, SUFFIX)(ENV_PARAM
                                           target_phys_addr_t physaddr,
                                           DATA_TYPE val,
                                           target_ulong addr,
-                                          void *retaddr)
+                                          uintptr_t retaddr)
 {
     MemoryRegion *mr = iotlb_to_region(physaddr);
 
@@ -238,7 +238,7 @@ static inline void glue(io_write, SUFFIX)(ENV_PARAM
     }
 
     env->mem_io_vaddr = addr;
-    env->mem_io_pc = (unsigned long)retaddr;
+    env->mem_io_pc = retaddr;
 #if SHIFT <= 2
     io_mem_write(mr, physaddr, val, 1 << SHIFT);
 #else
@@ -260,7 +260,7 @@ void glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_PARAM
     target_phys_addr_t ioaddr;
     unsigned long addend;
     target_ulong tlb_addr;
-    void *retaddr;
+    uintptr_t retaddr;
     int index;
 
     index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
@@ -310,7 +310,7 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_PARAM
                                                    target_ulong addr,
                                                    DATA_TYPE val,
                                                    int mmu_idx,
-                                                   void *retaddr)
+                                                   uintptr_t retaddr)
 {
     target_phys_addr_t ioaddr;
     unsigned long addend;
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 74bf7f7..fd578ce 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -433,9 +433,9 @@ int cpu_alpha_handle_mmu_fault (CPUAlphaState *env, uint64_t address, int rw,
                                 int mmu_idx);
 #define cpu_handle_mmu_fault cpu_alpha_handle_mmu_fault
 void do_interrupt (CPUAlphaState *env);
-void do_restore_state(CPUAlphaState *, void *retaddr);
-void QEMU_NORETURN dynamic_excp(CPUAlphaState *, void *, int, int);
-void QEMU_NORETURN arith_excp(CPUAlphaState *, void *, int, uint64_t);
+void do_restore_state(CPUAlphaState *, uintptr_t retaddr);
+void QEMU_NORETURN dynamic_excp(CPUAlphaState *, uintptr_t, int, int);
+void QEMU_NORETURN arith_excp(CPUAlphaState *, uintptr_t, int, uint64_t);
 
 uint64_t cpu_alpha_load_fpcr (CPUAlphaState *env);
 void cpu_alpha_store_fpcr (CPUAlphaState *env, uint64_t val);
diff --git a/target-alpha/fpu_helper.c b/target-alpha/fpu_helper.c
index dda1103..fe988ec 100644
--- a/target-alpha/fpu_helper.c
+++ b/target-alpha/fpu_helper.c
@@ -44,7 +44,7 @@ uint32_t helper_fp_exc_get(CPUAlphaState *env)
     return get_float_exception_flags(&FP_STATUS);
 }
 
-static inline void inline_fp_exc_raise(CPUAlphaState *env, void *retaddr,
+static inline void inline_fp_exc_raise(CPUAlphaState *env, uintptr_t retaddr,
                                        uint32_t exc, uint32_t regno)
 {
     if (exc) {
@@ -160,7 +160,7 @@ static uint64_t float32_to_f(float32 fa)
     return r;
 }
 
-static float32 f_to_float32(CPUAlphaState *env, void *retaddr, uint64_t a)
+static float32 f_to_float32(CPUAlphaState *env, uintptr_t retaddr, uint64_t a)
 {
     uint32_t exp, mant_sig;
     CPU_FloatU r;
@@ -291,7 +291,7 @@ static uint64_t float64_to_g(float64 fa)
     return r;
 }
 
-static float64 g_to_float64(CPUAlphaState *env, void *retaddr, uint64_t a)
+static float64 g_to_float64(CPUAlphaState *env, uintptr_t retaddr, uint64_t a)
 {
     uint64_t exp, mant_sig;
     CPU_DoubleU r;
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 765e650..81d4763 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -494,13 +494,12 @@ void cpu_dump_state (CPUAlphaState *env, FILE *f, fprintf_function cpu_fprintf,
     cpu_fprintf(f, "\n");
 }
 
-void do_restore_state(CPUAlphaState *env, void *retaddr)
+void do_restore_state(CPUAlphaState *env, uintptr_t retaddr)
 {
-    uintptr_t pc = (uintptr_t)retaddr;
-    if (pc) {
-        TranslationBlock *tb = tb_find_pc(pc);
+    if (retaddr) {
+        TranslationBlock *tb = tb_find_pc(retaddr);
         if (tb) {
-            cpu_restore_state(tb, env, pc);
+            cpu_restore_state(tb, env, retaddr);
         }
     }
 }
@@ -515,7 +514,7 @@ void QEMU_NORETURN helper_excp(CPUAlphaState *env, int excp, int error)
 }
 
 /* This may be called from any of the helpers to set up EXCEPTION_INDEX.  */
-void QEMU_NORETURN dynamic_excp(CPUAlphaState *env, void *retaddr,
+void QEMU_NORETURN dynamic_excp(CPUAlphaState *env, uintptr_t retaddr,
                                 int excp, int error)
 {
     env->exception_index = excp;
@@ -524,7 +523,7 @@ void QEMU_NORETURN dynamic_excp(CPUAlphaState *env, void *retaddr,
     cpu_loop_exit(env);
 }
 
-void QEMU_NORETURN arith_excp(CPUAlphaState *env, void *retaddr,
+void QEMU_NORETURN arith_excp(CPUAlphaState *env, uintptr_t retaddr,
                               int exc, uint64_t mask)
 {
     env->trap_arg0 = exc;
diff --git a/target-alpha/mem_helper.c b/target-alpha/mem_helper.c
index dd5ca49..87cada4 100644
--- a/target-alpha/mem_helper.c
+++ b/target-alpha/mem_helper.c
@@ -89,7 +89,7 @@ uint64_t helper_stq_c_phys(CPUAlphaState *env, uint64_t p, uint64_t v)
 }
 
 static void do_unaligned_access(CPUAlphaState *env, target_ulong addr,
-                                int is_write, int is_user, void *retaddr)
+                                int is_write, int is_user, uintptr_t retaddr)
 {
     uint64_t pc;
     uint32_t insn;
@@ -112,7 +112,7 @@ void cpu_unassigned_access(CPUAlphaState *env, target_phys_addr_t addr,
 {
     env->trap_arg0 = addr;
     env->trap_arg1 = is_write;
-    dynamic_excp(env, NULL, EXCP_MCHK, 0);
+    dynamic_excp(env, 0, EXCP_MCHK, 0);
 }
 
 #include "softmmu_exec.h"
@@ -137,7 +137,7 @@ void cpu_unassigned_access(CPUAlphaState *env, target_phys_addr_t addr,
    from generated code or from helper.c) */
 /* XXX: fix it to restore all registers */
 void tlb_fill(CPUAlphaState *env, target_ulong addr, int is_write,
-              int mmu_idx, void *retaddr)
+              int mmu_idx, uintptr_t retaddr)
 {
     int ret;
 
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index c728432..b53369d 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -76,11 +76,10 @@ uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def,
    from generated code or from helper.c) */
 /* XXX: fix it to restore all registers */
 void tlb_fill(CPUARMState *env1, target_ulong addr, int is_write, int mmu_idx,
-              void *retaddr)
+              uintptr_t retaddr)
 {
     TranslationBlock *tb;
     CPUARMState *saved_env;
-    unsigned long pc;
     int ret;
 
     saved_env = env;
@@ -89,12 +88,11 @@ void tlb_fill(CPUARMState *env1, target_ulong addr, int is_write, int mmu_idx,
     if (unlikely(ret)) {
         if (retaddr) {
             /* now we have a real cpu fault */
-            pc = (unsigned long)retaddr;
-            tb = tb_find_pc(pc);
+            tb = tb_find_pc(retaddr);
             if (tb) {
                 /* the PC is inside the translated code. It means that we have
                    a virtual CPU fault */
-                cpu_restore_state(tb, env, pc);
+                cpu_restore_state(tb, env, retaddr);
             }
         }
         raise_exception(env->exception_index);
diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c
index c568e2b..b92c106 100644
--- a/target-cris/op_helper.c
+++ b/target-cris/op_helper.c
@@ -57,28 +57,26 @@
    from generated code or from helper.c) */
 /* XXX: fix it to restore all registers */
 void tlb_fill(CPUCRISState *env1, target_ulong addr, int is_write, int mmu_idx,
-              void *retaddr)
+              uintptr_t retaddr)
 {
     TranslationBlock *tb;
     CPUCRISState *saved_env;
-    unsigned long pc;
     int ret;
 
     saved_env = env;
     env = env1;
 
-    D_LOG("%s pc=%x tpc=%x ra=%x\n", __func__, 
-	     env->pc, env->debug1, retaddr);
+    D_LOG("%s pc=%x tpc=%x ra=%p\n", __func__,
+          env->pc, env->debug1, (void *)retaddr);
     ret = cpu_cris_handle_mmu_fault(env, addr, is_write, mmu_idx);
     if (unlikely(ret)) {
         if (retaddr) {
             /* now we have a real cpu fault */
-            pc = (unsigned long)retaddr;
-            tb = tb_find_pc(pc);
+            tb = tb_find_pc(retaddr);
             if (tb) {
                 /* the PC is inside the translated code. It means that we have
                    a virtual CPU fault */
-                cpu_restore_state(tb, env, pc);
+                cpu_restore_state(tb, env, retaddr);
 
 		/* Evaluate flags after retranslation.  */
                 helper_top_evaluate_flags();
diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index c04ae44..bc3b94e 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -5003,11 +5003,10 @@ void helper_boundl(target_ulong a0, int v)
    from generated code or from helper.c) */
 /* XXX: fix it to restore all registers */
 void tlb_fill(CPUX86State *env1, target_ulong addr, int is_write, int mmu_idx,
-              void *retaddr)
+              uintptr_t retaddr)
 {
     TranslationBlock *tb;
     int ret;
-    unsigned long pc;
     CPUX86State *saved_env;
 
     saved_env = env;
@@ -5017,12 +5016,11 @@ void tlb_fill(CPUX86State *env1, target_ulong addr, int is_write, int mmu_idx,
     if (ret) {
         if (retaddr) {
             /* now we have a real cpu fault */
-            pc = (unsigned long)retaddr;
-            tb = tb_find_pc(pc);
+            tb = tb_find_pc(retaddr);
             if (tb) {
                 /* the PC is inside the translated code. It means that we have
                    a virtual CPU fault */
-                cpu_restore_state(tb, env, pc);
+                cpu_restore_state(tb, env, retaddr);
             }
         }
         raise_exception_err(env->exception_index, env->error_code);
diff --git a/target-lm32/op_helper.c b/target-lm32/op_helper.c
index e9c9638..51edc1a 100644
--- a/target-lm32/op_helper.c
+++ b/target-lm32/op_helper.c
@@ -76,11 +76,10 @@ uint32_t helper_rcsr_jrx(void)
    from generated code or from helper.c) */
 /* XXX: fix it to restore all registers */
 void tlb_fill(CPULM32State *env1, target_ulong addr, int is_write, int mmu_idx,
-              void *retaddr)
+              uintptr_t retaddr)
 {
     TranslationBlock *tb;
     CPULM32State *saved_env;
-    unsigned long pc;
     int ret;
 
     saved_env = env;
@@ -90,12 +89,11 @@ void tlb_fill(CPULM32State *env1, target_ulong addr, int is_write, int mmu_idx,
     if (unlikely(ret)) {
         if (retaddr) {
             /* now we have a real cpu fault */
-            pc = (unsigned long)retaddr;
-            tb = tb_find_pc(pc);
+            tb = tb_find_pc(retaddr);
             if (tb) {
                 /* the PC is inside the translated code. It means that we have
                    a virtual CPU fault */
-                cpu_restore_state(tb, env, pc);
+                cpu_restore_state(tb, env, retaddr);
             }
         }
         cpu_loop_exit(env);
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index bc8c1f0..1971a57 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -56,11 +56,10 @@ extern int semihosting_enabled;
    from generated code or from helper.c) */
 /* XXX: fix it to restore all registers */
 void tlb_fill(CPUM68KState *env1, target_ulong addr, int is_write, int mmu_idx,
-              void *retaddr)
+              uintptr_t retaddr)
 {
     TranslationBlock *tb;
     CPUM68KState *saved_env;
-    unsigned long pc;
     int ret;
 
     saved_env = env;
@@ -69,12 +68,11 @@ void tlb_fill(CPUM68KState *env1, target_ulong addr, int is_write, int mmu_idx,
     if (unlikely(ret)) {
         if (retaddr) {
             /* now we have a real cpu fault */
-            pc = (unsigned long)retaddr;
-            tb = tb_find_pc(pc);
+            tb = tb_find_pc(retaddr);
             if (tb) {
                 /* the PC is inside the translated code. It means that we have
                    a virtual CPU fault */
-                cpu_restore_state(tb, env, pc);
+                cpu_restore_state(tb, env, retaddr);
             }
         }
         cpu_loop_exit(env);
diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index a83da8d..3b1f072 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -44,11 +44,10 @@
    from generated code or from helper.c) */
 /* XXX: fix it to restore all registers */
 void tlb_fill(CPUMBState *env1, target_ulong addr, int is_write, int mmu_idx,
-              void *retaddr)
+              uintptr_t retaddr)
 {
     TranslationBlock *tb;
     CPUMBState *saved_env;
-    unsigned long pc;
     int ret;
 
     saved_env = env;
@@ -58,12 +57,11 @@ void tlb_fill(CPUMBState *env1, target_ulong addr, int is_write, int mmu_idx,
     if (unlikely(ret)) {
         if (retaddr) {
             /* now we have a real cpu fault */
-            pc = (unsigned long)retaddr;
-            tb = tb_find_pc(pc);
+            tb = tb_find_pc(retaddr);
             if (tb) {
                 /* the PC is inside the translated code. It means that we have
                    a virtual CPU fault */
-                cpu_restore_state(tb, env, pc);
+                cpu_restore_state(tb, env, retaddr);
             }
         }
         cpu_loop_exit(env);
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index ce01225..bca1d70 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -101,11 +101,10 @@ void helper_raise_exception (uint32_t exception)
 }
 
 #if !defined(CONFIG_USER_ONLY)
-static void do_restore_state (void *pc_ptr)
+static void do_restore_state(uintptr_t pc)
 {
     TranslationBlock *tb;
-    unsigned long pc = (unsigned long) pc_ptr;
-    
+
     tb = tb_find_pc (pc);
     if (tb) {
         cpu_restore_state(tb, env, pc);
@@ -2293,7 +2292,7 @@ void helper_wait (void)
 #if !defined(CONFIG_USER_ONLY)
 
 static void QEMU_NORETURN do_unaligned_access(target_ulong addr, int is_write,
-                                              int is_user, void *retaddr);
+                                              int is_user, uintptr_t retaddr);
 
 #define MMUSUFFIX _mmu
 #define ALIGNED_ONLY
@@ -2310,7 +2309,8 @@ static void QEMU_NORETURN do_unaligned_access(target_ulong addr, int is_write,
 #define SHIFT 3
 #include "softmmu_template.h"
 
-static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr)
+static void do_unaligned_access(target_ulong addr, int is_write,
+                                int is_user, uintptr_t retaddr)
 {
     env->CP0_BadVAddr = addr;
     do_restore_state (retaddr);
@@ -2318,11 +2318,10 @@ static void do_unaligned_access (target_ulong addr, int is_write, int is_user, v
 }
 
 void tlb_fill(CPUMIPSState *env1, target_ulong addr, int is_write, int mmu_idx,
-              void *retaddr)
+              uintptr_t retaddr)
 {
     TranslationBlock *tb;
     CPUMIPSState *saved_env;
-    unsigned long pc;
     int ret;
 
     saved_env = env;
@@ -2331,12 +2330,11 @@ void tlb_fill(CPUMIPSState *env1, target_ulong addr, int is_write, int mmu_idx,
     if (ret) {
         if (retaddr) {
             /* now we have a real cpu fault */
-            pc = (unsigned long)retaddr;
-            tb = tb_find_pc(pc);
+            tb = tb_find_pc(retaddr);
             if (tb) {
                 /* the PC is inside the translated code. It means that we have
                    a virtual CPU fault */
-                cpu_restore_state(tb, env, pc);
+                cpu_restore_state(tb, env, retaddr);
             }
         }
         helper_raise_exception_err(env->exception_index, env->error_code);
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 40927b6..4ef2332 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -3715,11 +3715,10 @@ uint32_t helper_efdcmpeq (uint64_t op1, uint64_t op2)
    from generated code or from helper.c) */
 /* XXX: fix it to restore all registers */
 void tlb_fill(CPUPPCState *env1, target_ulong addr, int is_write, int mmu_idx,
-              void *retaddr)
+              uintptr_t retaddr)
 {
     TranslationBlock *tb;
     CPUPPCState *saved_env;
-    unsigned long pc;
     int ret;
 
     saved_env = env;
@@ -3728,12 +3727,11 @@ void tlb_fill(CPUPPCState *env1, target_ulong addr, int is_write, int mmu_idx,
     if (unlikely(ret != 0)) {
         if (likely(retaddr)) {
             /* now we have a real cpu fault */
-            pc = (unsigned long)retaddr;
-            tb = tb_find_pc(pc);
+            tb = tb_find_pc(retaddr);
             if (likely(tb)) {
                 /* the PC is inside the translated code. It means that we have
                    a virtual CPU fault */
-                cpu_restore_state(tb, env, pc);
+                cpu_restore_state(tb, env, retaddr);
             }
         }
         helper_raise_exception_err(env->exception_index, env->error_code);
diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index 18fdbb2..7b72473 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -57,11 +57,10 @@
    from generated code or from helper.c) */
 /* XXX: fix it to restore all registers */
 void tlb_fill(CPUS390XState *env1, target_ulong addr, int is_write, int mmu_idx,
-              void *retaddr)
+              uintptr_t retaddr)
 {
     TranslationBlock *tb;
     CPUS390XState *saved_env;
-    unsigned long pc;
     int ret;
 
     saved_env = env;
@@ -70,12 +69,11 @@ void tlb_fill(CPUS390XState *env1, target_ulong addr, int is_write, int mmu_idx,
     if (unlikely(ret != 0)) {
         if (likely(retaddr)) {
             /* now we have a real cpu fault */
-            pc = (unsigned long)retaddr;
-            tb = tb_find_pc(pc);
+            tb = tb_find_pc(retaddr);
             if (likely(tb)) {
                 /* the PC is inside the translated code. It means that we have
                    a virtual CPU fault */
-                cpu_restore_state(tb, env, pc);
+                cpu_restore_state(tb, env, retaddr);
             }
         }
         cpu_loop_exit(env);
diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c
index 30f762f..4054791 100644
--- a/target-sh4/op_helper.c
+++ b/target-sh4/op_helper.c
@@ -22,18 +22,16 @@
 #include "dyngen-exec.h"
 #include "helper.h"
 
-static void cpu_restore_state_from_retaddr(void *retaddr)
+static void cpu_restore_state_from_retaddr(uintptr_t retaddr)
 {
     TranslationBlock *tb;
-    unsigned long pc;
 
     if (retaddr) {
-        pc = (unsigned long) retaddr;
-        tb = tb_find_pc(pc);
+        tb = tb_find_pc(retaddr);
         if (tb) {
             /* the PC is inside the translated code. It means that we have
                a virtual CPU fault */
-            cpu_restore_state(tb, env, pc);
+            cpu_restore_state(tb, env, retaddr);
         }
     }
 }
@@ -56,7 +54,7 @@ static void cpu_restore_state_from_retaddr(void *retaddr)
 #include "softmmu_template.h"
 
 void tlb_fill(CPUSH4State *env1, target_ulong addr, int is_write, int mmu_idx,
-              void *retaddr)
+              uintptr_t retaddr)
 {
     CPUSH4State *saved_env;
     int ret;
@@ -84,7 +82,7 @@ void helper_ldtlb(void)
 #endif
 }
 
-static inline void raise_exception(int index, void *retaddr)
+static inline void raise_exception(int index, uintptr_t retaddr)
 {
     env->exception_index = index;
     cpu_restore_state_from_retaddr(retaddr);
@@ -447,7 +445,7 @@ void helper_ld_fpscr(uint32_t val)
     set_flush_to_zero((val & FPSCR_DN) != 0, &env->fp_status);
 }
 
-static void update_fpscr(void *retaddr)
+static void update_fpscr(uintptr_t retaddr)
 {
     int xcpt, cause, enable;
 
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 865288c..29c63c7 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -702,7 +702,7 @@ trap_state* cpu_tsptr(CPUSPARCState* env);
 #endif
 void QEMU_NORETURN do_unaligned_access(CPUSPARCState *env, target_ulong addr,
                                        int is_write, int is_user,
-                                       void *retaddr);
+                                       uintptr_t retaddr);
 
 #define TB_FLAG_FPU_ENABLED (1 << 4)
 #define TB_FLAG_AM_ENABLED (1 << 5)
diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
index 1418205..04ffddf 100644
--- a/target-sparc/ldst_helper.c
+++ b/target-sparc/ldst_helper.c
@@ -2376,25 +2376,23 @@ void cpu_unassigned_access(CPUSPARCState *env, target_phys_addr_t addr,
 
 #if !defined(CONFIG_USER_ONLY)
 /* XXX: make it generic ? */
-static void cpu_restore_state2(CPUSPARCState *env, void *retaddr)
+static void cpu_restore_state2(CPUSPARCState *env, uintptr_t retaddr)
 {
     TranslationBlock *tb;
-    unsigned long pc;
 
     if (retaddr) {
         /* now we have a real cpu fault */
-        pc = (unsigned long)retaddr;
-        tb = tb_find_pc(pc);
+        tb = tb_find_pc(retaddr);
         if (tb) {
             /* the PC is inside the translated code. It means that we have
                a virtual CPU fault */
-            cpu_restore_state(tb, env, pc);
+            cpu_restore_state(tb, env, retaddr);
         }
     }
 }
 
 void do_unaligned_access(CPUSPARCState *env, target_ulong addr, int is_write,
-                         int is_user, void *retaddr)
+                         int is_user, uintptr_t retaddr)
 {
 #ifdef DEBUG_UNALIGNED
     printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
@@ -2409,7 +2407,7 @@ void do_unaligned_access(CPUSPARCState *env, target_ulong addr, int is_write,
    from generated code or from helper.c) */
 /* XXX: fix it to restore all registers */
 void tlb_fill(CPUSPARCState *env, target_ulong addr, int is_write, int mmu_idx,
-              void *retaddr)
+              uintptr_t retaddr)
 {
     int ret;
 
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index 806384f..a6dd72d 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -31,7 +31,7 @@
 #include "host-utils.h"
 
 static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
-        void *retaddr);
+                                uintptr_t retaddr);
 
 #define ALIGNED_ONLY
 #define MMUSUFFIX _mmu
@@ -48,10 +48,9 @@ static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
 #define SHIFT 3
 #include "softmmu_template.h"
 
-static void do_restore_state(void *pc_ptr)
+static void do_restore_state(uintptr_t pc)
 {
     TranslationBlock *tb;
-    uint32_t pc = (uint32_t)(intptr_t)pc_ptr;
 
     tb = tb_find_pc(pc);
     if (tb) {
@@ -60,7 +59,7 @@ static void do_restore_state(void *pc_ptr)
 }
 
 static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
-        void *retaddr)
+                                uintptr_t retaddr)
 {
     if (xtensa_option_enabled(env->config, XTENSA_OPTION_UNALIGNED_EXCEPTION) &&
             !xtensa_option_enabled(env->config, XTENSA_OPTION_HW_ALIGNMENT)) {
@@ -71,7 +70,7 @@ static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
 }
 
 void tlb_fill(CPUXtensaState *env1, target_ulong vaddr, int is_write, int mmu_idx,
-              void *retaddr)
+              uintptr_t retaddr)
 {
     CPUXtensaState *saved_env = env;
 
diff --git a/user-exec.c b/user-exec.c
index cd905ff..be6bc4f 100644
--- a/user-exec.c
+++ b/user-exec.c
@@ -82,7 +82,7 @@ void cpu_resume_from_signal(CPUArchState *env1, void *puc)
    the effective address of the memory exception. 'is_write' is 1 if a
    write caused the exception and otherwise 0'. 'old_set' is the
    signal set which should be restored */
-static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
+static inline int handle_cpu_signal(uintptr_t pc, unsigned long address,
                                     int is_write, sigset_t *old_set,
                                     void *puc)
 {
commit d1b719e98ce8b506d122a845d405f941a7a497c1
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sat Mar 3 04:52:56 2012 +0000

    coroutine-gthread.c: Avoid threading APIs deprecated in GLib 2.31
    
    The GLib threading APIs were revamped in GLib 2.31 and a number
    of the old interfaces were deprecated, which means they provoke
    compilation warnings (errors if -Werror) now. Add support for the
    new interfaces while retaining the old ones so we can still compile
    on older versions of GLib too.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/coroutine-gthread.c b/coroutine-gthread.c
index 662801b..30c24c9 100644
--- a/coroutine-gthread.c
+++ b/coroutine-gthread.c
@@ -26,13 +26,93 @@ typedef struct {
     Coroutine base;
     GThread *thread;
     bool runnable;
+    bool free_on_thread_exit;
     CoroutineAction action;
 } CoroutineGThread;
 
-static GCond *coroutine_cond;
 static GStaticMutex coroutine_lock = G_STATIC_MUTEX_INIT;
+
+/* GLib 2.31 and beyond deprecated various parts of the thread API,
+ * but the new interfaces are not available in older GLib versions
+ * so we have to cope with both.
+ */
+#if GLIB_CHECK_VERSION(2, 31, 0)
+/* Default zero-initialisation is sufficient for 2.31+ GCond */
+static GCond the_coroutine_cond;
+static GCond *coroutine_cond = &the_coroutine_cond;
+static inline void init_coroutine_cond(void)
+{
+}
+
+/* Awkwardly, the GPrivate API doesn't provide a way to update the
+ * GDestroyNotify handler for the coroutine key dynamically. So instead
+ * we track whether or not the CoroutineGThread should be freed on
+ * thread exit / coroutine key update using the free_on_thread_exit
+ * field.
+ */
+static void coroutine_destroy_notify(gpointer data)
+{
+    CoroutineGThread *co = data;
+    if (co && co->free_on_thread_exit) {
+        g_free(co);
+    }
+}
+
+static GPrivate coroutine_key = G_PRIVATE_INIT(coroutine_destroy_notify);
+
+static inline CoroutineGThread *get_coroutine_key(void)
+{
+    return g_private_get(&coroutine_key);
+}
+
+static inline void set_coroutine_key(CoroutineGThread *co,
+                                     bool free_on_thread_exit)
+{
+    /* Unlike g_static_private_set() this does not call the GDestroyNotify
+     * if the previous value of the key was NULL. Fortunately we only need
+     * the GDestroyNotify in the non-NULL key case.
+     */
+    co->free_on_thread_exit = free_on_thread_exit;
+    g_private_replace(&coroutine_key, co);
+}
+
+static inline GThread *create_thread(GThreadFunc func, gpointer data)
+{
+    return g_thread_new("coroutine", func, data);
+}
+
+#else
+
+/* Handle older GLib versions */
+static GCond *coroutine_cond;
+static inline void init_coroutine_cond(void)
+{
+    coroutine_cond = g_cond_new();
+}
+
 static GStaticPrivate coroutine_key = G_STATIC_PRIVATE_INIT;
 
+static inline CoroutineGThread *get_coroutine_key(void)
+{
+    return g_static_private_get(&coroutine_key);
+}
+
+static inline void set_coroutine_key(CoroutineGThread *co,
+                                     bool free_on_thread_exit)
+{
+    g_static_private_set(&coroutine_key, co,
+                         free_on_thread_exit ? (GDestroyNotify)g_free : NULL);
+}
+
+static inline GThread *create_thread(GThreadFunc func, gpointer data)
+{
+    return g_thread_create_full(func, data, 0, TRUE, TRUE,
+                                G_THREAD_PRIORITY_NORMAL, NULL);
+}
+
+#endif
+
+
 static void __attribute__((constructor)) coroutine_init(void)
 {
     if (!g_thread_supported()) {
@@ -44,7 +124,7 @@ static void __attribute__((constructor)) coroutine_init(void)
 #endif
     }
 
-    coroutine_cond = g_cond_new();
+    init_coroutine_cond();
 }
 
 static void coroutine_wait_runnable_locked(CoroutineGThread *co)
@@ -65,7 +145,7 @@ static gpointer coroutine_thread(gpointer opaque)
 {
     CoroutineGThread *co = opaque;
 
-    g_static_private_set(&coroutine_key, co, NULL);
+    set_coroutine_key(co, false);
     coroutine_wait_runnable(co);
     co->base.entry(co->base.entry_arg);
     qemu_coroutine_switch(&co->base, co->base.caller, COROUTINE_TERMINATE);
@@ -77,8 +157,7 @@ Coroutine *qemu_coroutine_new(void)
     CoroutineGThread *co;
 
     co = g_malloc0(sizeof(*co));
-    co->thread = g_thread_create_full(coroutine_thread, co, 0, TRUE, TRUE,
-                                      G_THREAD_PRIORITY_NORMAL, NULL);
+    co->thread = create_thread(coroutine_thread, co);
     if (!co->thread) {
         g_free(co);
         return NULL;
@@ -117,12 +196,11 @@ CoroutineAction qemu_coroutine_switch(Coroutine *from_,
 
 Coroutine *qemu_coroutine_self(void)
 {
-    CoroutineGThread *co = g_static_private_get(&coroutine_key);
-
+    CoroutineGThread *co = get_coroutine_key();
     if (!co) {
         co = g_malloc0(sizeof(*co));
         co->runnable = true;
-        g_static_private_set(&coroutine_key, co, (GDestroyNotify)g_free);
+        set_coroutine_key(co, true);
     }
 
     return &co->base;
@@ -130,7 +208,7 @@ Coroutine *qemu_coroutine_self(void)
 
 bool qemu_in_coroutine(void)
 {
-    CoroutineGThread *co = g_static_private_get(&coroutine_key);
+    CoroutineGThread *co = get_coroutine_key();
 
     return co && co->base.caller;
 }
commit 044c62aaf223b3b5a8eae4f5f79b210a65501e23
Merge: e92861c... e554bbc...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Apr 14 10:56:04 2012 +0000

    Merge branch 'xtensa' of git://jcmvbkbc.spb.ru/dumb/qemu-xtensa
    
    * 'xtensa' of git://jcmvbkbc.spb.ru/dumb/qemu-xtensa:
      target-xtensa: Start QOM'ifying CPU init
      target-xtensa: QOM'ify CPU reset
      target-xtensa: QOM'ify CPU
      target-xtensa: improve unit tests debugging
      target-xtensa: Move helpers.h to helper.h

commit e92861ccb166883b0672b1ddfebce4f5de85e23d
Merge: 7672725... c79981c...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Apr 14 10:55:00 2012 +0000

    Merge branch 'arm-devs.for-upstream' of git://git.linaro.org/people/pmaydell/qemu-arm
    
    * 'arm-devs.for-upstream' of git://git.linaro.org/people/pmaydell/qemu-arm:
      hw/arm_gic: Remove stray hardcoded tab
      hw/arm_gic: gic_set_pending_private() is NVIC only
      hw/arm_gic: Use NVIC instead of LEGACY_INCLUDED_GIC define
      hw/arm_gic: Make gic_reset a sysbus reset function
      hw/arm11mpcore: Convert to using sysbus GIC device
      hw/exynos4210_gic: Convert to using sysbus GIC
      hw/realview_gic: switch to sysbus GIC
      hw/a9mpcore: Switch to using sysbus GIC
      hw/a15mpcore: switch to using sysbus GIC
      hw/arm_gic: Make the GIC its own sysbus device
      hw/arm_gic: Expose PPI inputs as gpio inputs
      hw/arm_gic: Move gic_get_current_cpu into arm_gic.c
      hw/arm_gic: Move NCPU definition to arm_gic.c
      hw/exynos4210_combiner.c: Drop excessive read/write access check.
      ARM: Exynos4210: Drop gic_cpu_write() after initialization.
      Fix bit test in Exynos4210 UART emulation to use & instead of &&

commit e554bbc6892394e506f5995ff4e0ca21cfe04a25
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Apr 11 18:24:50 2012 +0200

    target-xtensa: Start QOM'ifying CPU init
    
    Move XtensaConfig-independent code from cpu_xtensa_init() into a
    QOM initfn, as a start.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/target-xtensa/cpu.c b/target-xtensa/cpu.c
index 55d2dea..97deacb 100644
--- a/target-xtensa/cpu.c
+++ b/target-xtensa/cpu.c
@@ -53,6 +53,14 @@ static void xtensa_cpu_reset(CPUState *s)
     reset_mmu(env);
 }
 
+static void xtensa_cpu_initfn(Object *obj)
+{
+    XtensaCPU *cpu = XTENSA_CPU(obj);
+    CPUXtensaState *env = &cpu->env;
+
+    cpu_exec_init(env);
+}
+
 static void xtensa_cpu_class_init(ObjectClass *oc, void *data)
 {
     CPUClass *cc = CPU_CLASS(oc);
@@ -66,6 +74,7 @@ static const TypeInfo xtensa_cpu_type_info = {
     .name = TYPE_XTENSA_CPU,
     .parent = TYPE_CPU,
     .instance_size = sizeof(XtensaCPU),
+    .instance_init = xtensa_cpu_initfn,
     .abstract = false,
     .class_size = sizeof(XtensaCPUClass),
     .class_init = xtensa_cpu_class_init,
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index 000f965..2094227 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -102,7 +102,6 @@ CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
     cpu = XTENSA_CPU(object_new(TYPE_XTENSA_CPU));
     env = &cpu->env;
     env->config = config;
-    cpu_exec_init(env);
 
     if (!tcg_inited) {
         tcg_inited = 1;
commit 5087a72cb3e94f48c1d447babd67e33bfd9dda12
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Apr 11 18:24:49 2012 +0200

    target-xtensa: QOM'ify CPU reset
    
    Move code from cpu_state_reset() into QOM xtensa_cpu_reset().
    To avoid moving reset_mmu() and dependencies, make it non-static.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/target-xtensa/cpu.c b/target-xtensa/cpu.c
index d68be22..55d2dea 100644
--- a/target-xtensa/cpu.c
+++ b/target-xtensa/cpu.c
@@ -1,6 +1,7 @@
 /*
  * QEMU Xtensa CPU
  *
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
  * Copyright (c) 2012 SUSE LINUX Products GmbH
  * All rights reserved.
  *
@@ -40,7 +41,16 @@ static void xtensa_cpu_reset(CPUState *s)
 
     xcc->parent_reset(s);
 
-    cpu_state_reset(env);
+    env->exception_taken = 0;
+    env->pc = env->config->exception_vector[EXC_RESET];
+    env->sregs[LITBASE] &= ~1;
+    env->sregs[PS] = xtensa_option_enabled(env->config,
+            XTENSA_OPTION_INTERRUPT) ? 0x1f : 0x10;
+    env->sregs[VECBASE] = env->config->vecbase;
+    env->sregs[IBREAKENABLE] = 0;
+
+    env->pending_irq_level = 0;
+    reset_mmu(env);
 }
 
 static void xtensa_cpu_class_init(ObjectClass *oc, void *data)
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 2de5144..6d0ea7c 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -375,6 +375,7 @@ void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb,
 int xtensa_get_physical_addr(CPUXtensaState *env,
         uint32_t vaddr, int is_write, int mmu_idx,
         uint32_t *paddr, uint32_t *page_size, unsigned *access);
+void reset_mmu(CPUXtensaState *env);
 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUXtensaState *env);
 void debug_exception_env(CPUXtensaState *new_env, uint32_t cause);
 
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index 20338e6..000f965 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -33,20 +33,9 @@
 #include "hw/loader.h"
 #endif
 
-static void reset_mmu(CPUXtensaState *env);
-
 void cpu_state_reset(CPUXtensaState *env)
 {
-    env->exception_taken = 0;
-    env->pc = env->config->exception_vector[EXC_RESET];
-    env->sregs[LITBASE] &= ~1;
-    env->sregs[PS] = xtensa_option_enabled(env->config,
-            XTENSA_OPTION_INTERRUPT) ? 0x1f : 0x10;
-    env->sregs[VECBASE] = env->config->vecbase;
-    env->sregs[IBREAKENABLE] = 0;
-
-    env->pending_irq_level = 0;
-    reset_mmu(env);
+    cpu_reset(ENV_GET_CPU(env));
 }
 
 static struct XtensaConfigList *xtensa_cores;
@@ -336,7 +325,7 @@ static void reset_tlb_region_way0(CPUXtensaState *env,
     }
 }
 
-static void reset_mmu(CPUXtensaState *env)
+void reset_mmu(CPUXtensaState *env)
 {
     if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
         env->sregs[RASID] = 0x04030201;
commit a4633e16d77bd1cf0c25e500d15943499b94f2f9
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Apr 11 18:24:48 2012 +0200

    target-xtensa: QOM'ify CPU
    
    Embed CPUXtensaState as first member of XtensaCPU.
    Let CPUClass::reset() call cpu_state_reset() for now.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index e88b896..75b97ae 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -102,6 +102,7 @@ endif
 libobj-$(TARGET_SPARC) += int32_helper.o
 libobj-$(TARGET_SPARC64) += int64_helper.o
 libobj-$(TARGET_UNICORE32) += cpu.o
+libobj-$(TARGET_XTENSA) += cpu.o
 libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o sys_helper.o mem_helper.o
 
 libobj-y += disas.o
diff --git a/target-xtensa/cpu-qom.h b/target-xtensa/cpu-qom.h
new file mode 100644
index 0000000..1fd2f27
--- /dev/null
+++ b/target-xtensa/cpu-qom.h
@@ -0,0 +1,80 @@
+/*
+ * QEMU Xtensa CPU
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef QEMU_XTENSA_CPU_QOM_H
+#define QEMU_XTENSA_CPU_QOM_H
+
+#include "qemu/cpu.h"
+#include "cpu.h"
+
+#define TYPE_XTENSA_CPU "xtensa-cpu"
+
+#define XTENSA_CPU_CLASS(class) \
+    OBJECT_CLASS_CHECK(XtensaCPUClass, (class), TYPE_XTENSA_CPU)
+#define XTENSA_CPU(obj) \
+    OBJECT_CHECK(XtensaCPU, (obj), TYPE_XTENSA_CPU)
+#define XTENSA_CPU_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(XtensaCPUClass, (obj), TYPE_XTENSA_CPU)
+
+/**
+ * XtensaCPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * An Xtensa CPU model.
+ */
+typedef struct XtensaCPUClass {
+    /*< private >*/
+    CPUClass parent_class;
+    /*< public >*/
+
+    void (*parent_reset)(CPUState *cpu);
+} XtensaCPUClass;
+
+/**
+ * XtensaCPU:
+ * @env: #CPUXtensaState
+ *
+ * An Xtensa CPU.
+ */
+typedef struct XtensaCPU {
+    /*< private >*/
+    CPUState parent_obj;
+    /*< public >*/
+
+    CPUXtensaState env;
+} XtensaCPU;
+
+static inline XtensaCPU *xtensa_env_get_cpu(const CPUXtensaState *env)
+{
+    return XTENSA_CPU(container_of(env, XtensaCPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(xtensa_env_get_cpu(e))
+
+
+#endif
diff --git a/target-xtensa/cpu.c b/target-xtensa/cpu.c
new file mode 100644
index 0000000..d68be22
--- /dev/null
+++ b/target-xtensa/cpu.c
@@ -0,0 +1,69 @@
+/*
+ * QEMU Xtensa CPU
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "cpu-qom.h"
+#include "qemu-common.h"
+
+
+/* CPUClass::reset() */
+static void xtensa_cpu_reset(CPUState *s)
+{
+    XtensaCPU *cpu = XTENSA_CPU(s);
+    XtensaCPUClass *xcc = XTENSA_CPU_GET_CLASS(cpu);
+    CPUXtensaState *env = &cpu->env;
+
+    xcc->parent_reset(s);
+
+    cpu_state_reset(env);
+}
+
+static void xtensa_cpu_class_init(ObjectClass *oc, void *data)
+{
+    CPUClass *cc = CPU_CLASS(oc);
+    XtensaCPUClass *xcc = XTENSA_CPU_CLASS(cc);
+
+    xcc->parent_reset = cc->reset;
+    cc->reset = xtensa_cpu_reset;
+}
+
+static const TypeInfo xtensa_cpu_type_info = {
+    .name = TYPE_XTENSA_CPU,
+    .parent = TYPE_CPU,
+    .instance_size = sizeof(XtensaCPU),
+    .abstract = false,
+    .class_size = sizeof(XtensaCPUClass),
+    .class_init = xtensa_cpu_class_init,
+};
+
+static void xtensa_cpu_register_types(void)
+{
+    type_register_static(&xtensa_cpu_type_info);
+}
+
+type_init(xtensa_cpu_register_types)
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index a7bcf52..2de5144 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -470,6 +470,7 @@ static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc,
 }
 
 #include "cpu-all.h"
+#include "cpu-qom.h"
 #include "exec-all.h"
 
 static inline int cpu_has_work(CPUXtensaState *env)
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index dab135c..20338e6 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -95,6 +95,7 @@ CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
 {
     static int tcg_inited;
     static int debug_handler_inited;
+    XtensaCPU *cpu;
     CPUXtensaState *env;
     const XtensaConfig *config = NULL;
     XtensaConfigList *core = xtensa_cores;
@@ -109,7 +110,8 @@ CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
         return NULL;
     }
 
-    env = g_malloc0(sizeof(*env));
+    cpu = XTENSA_CPU(object_new(TYPE_XTENSA_CPU));
+    env = &cpu->env;
     env->config = config;
     cpu_exec_init(env);
 
commit 7d6b9f0a3838632b4c553e0a387af0bbdf4297c0
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Fri Mar 16 01:24:57 2012 +0400

    target-xtensa: improve unit tests debugging
    
    - add testcase announcement;
    - add global symbols for individual tests;
    - add host-debug-* makefile target.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/tests/tcg/xtensa/Makefile b/tests/tcg/xtensa/Makefile
index 7e1e619..0ff0ccf 100644
--- a/tests/tcg/xtensa/Makefile
+++ b/tests/tcg/xtensa/Makefile
@@ -72,5 +72,8 @@ run-test_fail.tst: test_fail.tst
 debug-%.tst: %.tst
 	$(SIM) $(SIMDEBUG) $(SIMFLAGS) ./$<
 
+host-debug-%.tst: %.tst
+	gdb --args $(SIM) $(SIMFLAGS) ./$<
+
 clean:
 	$(RM) -fr $(TESTCASES) $(CRT)
diff --git a/tests/tcg/xtensa/macros.inc b/tests/tcg/xtensa/macros.inc
index 2d4515e..23bf3e9 100644
--- a/tests/tcg/xtensa/macros.inc
+++ b/tests/tcg/xtensa/macros.inc
@@ -29,7 +29,24 @@ main:
     exit
 .endm
 
+.macro print text
+.data
+97: .ascii "\text\n"
+98:
+    .align 4
+.text
+    movi    a2, 4
+    movi    a3, 2
+    movi    a4, 97b
+    movi    a5, 98b
+    sub     a5, a5, a4
+    simcall
+.endm
+
 .macro test name
+    //print test_\name
+test_\name:
+.global test_\name
 .endm
 
 .macro test_end
commit 16c1deae215d4aac5b9b4fc090844b92852a0c5b
Author: Lluís Vilanova <vilanova at ac.upc.edu>
Date:   Mon Feb 13 16:33:58 2012 +0100

    target-xtensa: Move helpers.h to helper.h
    
    Provides a file naming scheme consistent with other targets.
    
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/target-xtensa/helper.h b/target-xtensa/helper.h
new file mode 100644
index 0000000..48a741e
--- /dev/null
+++ b/target-xtensa/helper.h
@@ -0,0 +1,39 @@
+#include "def-helper.h"
+
+DEF_HELPER_1(exception, void, i32)
+DEF_HELPER_2(exception_cause, void, i32, i32)
+DEF_HELPER_3(exception_cause_vaddr, void, i32, i32, i32)
+DEF_HELPER_2(debug_exception, void, i32, i32)
+
+DEF_HELPER_1(nsa, i32, i32)
+DEF_HELPER_1(nsau, i32, i32)
+DEF_HELPER_1(wsr_windowbase, void, i32)
+DEF_HELPER_3(entry, void, i32, i32, i32)
+DEF_HELPER_1(retw, i32, i32)
+DEF_HELPER_1(rotw, void, i32)
+DEF_HELPER_2(window_check, void, i32, i32)
+DEF_HELPER_0(restore_owb, void)
+DEF_HELPER_1(movsp, void, i32)
+DEF_HELPER_1(wsr_lbeg, void, i32)
+DEF_HELPER_1(wsr_lend, void, i32)
+DEF_HELPER_1(simcall, void, env)
+DEF_HELPER_0(dump_state, void)
+
+DEF_HELPER_2(waiti, void, i32, i32)
+DEF_HELPER_2(timer_irq, void, i32, i32)
+DEF_HELPER_1(advance_ccount, void, i32)
+DEF_HELPER_1(check_interrupts, void, env)
+
+DEF_HELPER_1(wsr_rasid, void, i32)
+DEF_HELPER_2(rtlb0, i32, i32, i32)
+DEF_HELPER_2(rtlb1, i32, i32, i32)
+DEF_HELPER_2(itlb, void, i32, i32)
+DEF_HELPER_2(ptlb, i32, i32, i32)
+DEF_HELPER_3(wtlb, void, i32, i32, i32)
+
+DEF_HELPER_1(wsr_ibreakenable, void, i32)
+DEF_HELPER_2(wsr_ibreaka, void, i32, i32)
+DEF_HELPER_2(wsr_dbreaka, void, i32, i32)
+DEF_HELPER_2(wsr_dbreakc, void, i32, i32)
+
+#include "def-helper.h"
diff --git a/target-xtensa/helpers.h b/target-xtensa/helpers.h
deleted file mode 100644
index 48a741e..0000000
--- a/target-xtensa/helpers.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#include "def-helper.h"
-
-DEF_HELPER_1(exception, void, i32)
-DEF_HELPER_2(exception_cause, void, i32, i32)
-DEF_HELPER_3(exception_cause_vaddr, void, i32, i32, i32)
-DEF_HELPER_2(debug_exception, void, i32, i32)
-
-DEF_HELPER_1(nsa, i32, i32)
-DEF_HELPER_1(nsau, i32, i32)
-DEF_HELPER_1(wsr_windowbase, void, i32)
-DEF_HELPER_3(entry, void, i32, i32, i32)
-DEF_HELPER_1(retw, i32, i32)
-DEF_HELPER_1(rotw, void, i32)
-DEF_HELPER_2(window_check, void, i32, i32)
-DEF_HELPER_0(restore_owb, void)
-DEF_HELPER_1(movsp, void, i32)
-DEF_HELPER_1(wsr_lbeg, void, i32)
-DEF_HELPER_1(wsr_lend, void, i32)
-DEF_HELPER_1(simcall, void, env)
-DEF_HELPER_0(dump_state, void)
-
-DEF_HELPER_2(waiti, void, i32, i32)
-DEF_HELPER_2(timer_irq, void, i32, i32)
-DEF_HELPER_1(advance_ccount, void, i32)
-DEF_HELPER_1(check_interrupts, void, env)
-
-DEF_HELPER_1(wsr_rasid, void, i32)
-DEF_HELPER_2(rtlb0, i32, i32, i32)
-DEF_HELPER_2(rtlb1, i32, i32, i32)
-DEF_HELPER_2(itlb, void, i32, i32)
-DEF_HELPER_2(ptlb, i32, i32, i32)
-DEF_HELPER_3(wtlb, void, i32, i32, i32)
-
-DEF_HELPER_1(wsr_ibreakenable, void, i32)
-DEF_HELPER_2(wsr_ibreaka, void, i32, i32)
-DEF_HELPER_2(wsr_dbreaka, void, i32, i32)
-DEF_HELPER_2(wsr_dbreakc, void, i32, i32)
-
-#include "def-helper.h"
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index cdef0db..806384f 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -27,7 +27,7 @@
 
 #include "cpu.h"
 #include "dyngen-exec.h"
-#include "helpers.h"
+#include "helper.h"
 #include "host-utils.h"
 
 static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index e0ff72b..492dbcc 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -37,9 +37,9 @@
 #include "qemu-log.h"
 #include "sysemu.h"
 
-#include "helpers.h"
+#include "helper.h"
 #define GEN_HELPER 1
-#include "helpers.h"
+#include "helper.h"
 
 typedef struct DisasContext {
     const XtensaConfig *config;
@@ -183,7 +183,7 @@ void xtensa_translate_init(void)
         }
     }
 #define GEN_HELPER 2
-#include "helpers.h"
+#include "helper.h"
 }
 
 static inline bool option_bits_enabled(DisasContext *dc, uint64_t opt)
diff --git a/xtensa-semi.c b/xtensa-semi.c
index 5754b77..b7c8c34 100644
--- a/xtensa-semi.c
+++ b/xtensa-semi.c
@@ -31,7 +31,7 @@
 #include <stddef.h>
 #include "cpu.h"
 #include "dyngen-exec.h"
-#include "helpers.h"
+#include "helper.h"
 #include "qemu-log.h"
 
 enum {
commit fda1f7684935ae7290c8a31e3ba9fdb30eead4ed
Author: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Date:   Fri Apr 13 17:46:01 2012 +0000

    xen: introduce an event channel for buffered io event notifications
    
    Use the newly introduced HVM_PARAM_BUFIOREQ_EVTCHN to receive
    notifications for buffered io events.
    After the first notification is received leave the event channel masked
    and setup a timer to process the rest of the batch.
    Once we have completed processing the batch, unmask the event channel
    and delete the timer.
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/xen-all.c b/xen-all.c
index abd2b2d..a08eec0 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -59,6 +59,9 @@ static inline ioreq_t *xen_vcpu_ioreq(shared_iopage_t *shared_page, int vcpu)
 }
 #  define FMT_ioreq_size "u"
 #endif
+#ifndef HVM_PARAM_BUFIOREQ_EVTCHN
+#define HVM_PARAM_BUFIOREQ_EVTCHN 26
+#endif
 
 #define BUFFER_IO_MAX_DELAY  100
 
@@ -77,6 +80,8 @@ typedef struct XenIOState {
     QEMUTimer *buffered_io_timer;
     /* the evtchn port for polling the notification, */
     evtchn_port_t *ioreq_local_port;
+    /* evtchn local port for buffered io */
+    evtchn_port_t bufioreq_local_port;
     /* the evtchn fd for polling */
     XenEvtchn xce_handle;
     /* which vcpu we are serving */
@@ -629,6 +634,12 @@ static ioreq_t *cpu_get_ioreq(XenIOState *state)
     evtchn_port_t port;
 
     port = xc_evtchn_pending(state->xce_handle);
+    if (port == state->bufioreq_local_port) {
+        qemu_mod_timer(state->buffered_io_timer,
+                BUFFER_IO_MAX_DELAY + qemu_get_clock_ms(rt_clock));
+        return NULL;
+    }
+
     if (port != -1) {
         for (i = 0; i < smp_cpus; i++) {
             if (state->ioreq_local_port[i] == port) {
@@ -777,16 +788,18 @@ static void handle_ioreq(ioreq_t *req)
     }
 }
 
-static void handle_buffered_iopage(XenIOState *state)
+static int handle_buffered_iopage(XenIOState *state)
 {
     buf_ioreq_t *buf_req = NULL;
     ioreq_t req;
     int qw;
 
     if (!state->buffered_io_page) {
-        return;
+        return 0;
     }
 
+    memset(&req, 0x00, sizeof(req));
+
     while (state->buffered_io_page->read_pointer != state->buffered_io_page->write_pointer) {
         buf_req = &state->buffered_io_page->buf_ioreq[
             state->buffered_io_page->read_pointer % IOREQ_BUFFER_SLOT_NUM];
@@ -811,15 +824,21 @@ static void handle_buffered_iopage(XenIOState *state)
         xen_mb();
         state->buffered_io_page->read_pointer += qw ? 2 : 1;
     }
+
+    return req.count;
 }
 
 static void handle_buffered_io(void *opaque)
 {
     XenIOState *state = opaque;
 
-    handle_buffered_iopage(state);
-    qemu_mod_timer(state->buffered_io_timer,
-                   BUFFER_IO_MAX_DELAY + qemu_get_clock_ms(rt_clock));
+    if (handle_buffered_iopage(state)) {
+        qemu_mod_timer(state->buffered_io_timer,
+                BUFFER_IO_MAX_DELAY + qemu_get_clock_ms(rt_clock));
+    } else {
+        qemu_del_timer(state->buffered_io_timer);
+        xc_evtchn_unmask(state->xce_handle, state->bufioreq_local_port);
+    }
 }
 
 static void cpu_handle_ioreq(void *opaque)
@@ -949,7 +968,6 @@ static void xen_main_loop_prepare(XenIOState *state)
 
     state->buffered_io_timer = qemu_new_timer_ms(rt_clock, handle_buffered_io,
                                                  state);
-    qemu_mod_timer(state->buffered_io_timer, qemu_get_clock_ms(rt_clock));
 
     if (evtchn_fd != -1) {
         qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, state);
@@ -1050,6 +1068,7 @@ int xen_hvm_init(void)
 {
     int i, rc;
     unsigned long ioreq_pfn;
+    unsigned long bufioreq_evtchn;
     XenIOState *state;
 
     state = g_malloc0(sizeof (XenIOState));
@@ -1102,6 +1121,20 @@ int xen_hvm_init(void)
         state->ioreq_local_port[i] = rc;
     }
 
+    rc = xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_BUFIOREQ_EVTCHN,
+            &bufioreq_evtchn);
+    if (rc < 0) {
+        fprintf(stderr, "failed to get HVM_PARAM_BUFIOREQ_EVTCHN\n");
+        return -1;
+    }
+    rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
+            (uint32_t)bufioreq_evtchn);
+    if (rc == -1) {
+        fprintf(stderr, "bind interdomain ioctl error %d\n", errno);
+        return -1;
+    }
+    state->bufioreq_local_port = rc;
+
     /* Init RAM management */
     xen_map_cache_init(xen_phys_offset_to_gaddr, state);
     xen_ram_init(ram_size);
commit 852a7cec90f12516eb335bb29ed1398c2f0b7c2c
Author: Julien Grall <julien.grall at citrix.com>
Date:   Fri Apr 13 17:33:02 2012 +0000

    xen-mapcache: don't unmap locked entry during mapcache invalidation
    
    When an IOREQ_TYPE_INVALIDATE is sent to QEMU, it invalidates all entry
    of the map cache even if it's locked.
    
    QEMU is not able to know that entry was invalidated, so when an IO
    access is requested a segfault occured.
    
    Signed-off-by: Julien Grall <julien.grall at citrix.com>
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/xen-mapcache.c b/xen-mapcache.c
index 75ac313..59ba085 100644
--- a/xen-mapcache.c
+++ b/xen-mapcache.c
@@ -387,6 +387,9 @@ void xen_invalidate_map_cache(void)
         if (entry->vaddr_base == NULL) {
             continue;
         }
+        if (entry->lock > 0) {
+            continue;
+        }
 
         if (munmap(entry->vaddr_base, entry->size) != 0) {
             perror("unmap fails");
commit 09ab48ee6c7ec082f56f85e234b066ed4fd874e2
Author: Anthony PERARD <anthony.perard at citrix.com>
Date:   Fri Apr 13 17:18:56 2012 +0000

    Xen, mapcache: Fix the compute of the size of bucket.
    
    Because the size of a mapping is wrong when there is an offset and a
    size >= bucket_size.
    
    Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/xen-mapcache.c b/xen-mapcache.c
index a456479..75ac313 100644
--- a/xen-mapcache.c
+++ b/xen-mapcache.c
@@ -216,12 +216,14 @@ tryagain:
     }
 
     /* size is always a multiple of MCACHE_BUCKET_SIZE */
-    if ((address_offset + (__size % MCACHE_BUCKET_SIZE)) > MCACHE_BUCKET_SIZE)
-        __size += MCACHE_BUCKET_SIZE;
-    if (__size % MCACHE_BUCKET_SIZE)
-        __size += MCACHE_BUCKET_SIZE - (__size % MCACHE_BUCKET_SIZE);
-    if (!__size)
+    if (size) {
+        __size = size + address_offset;
+        if (__size % MCACHE_BUCKET_SIZE) {
+            __size += MCACHE_BUCKET_SIZE - (__size % MCACHE_BUCKET_SIZE);
+        }
+    } else {
         __size = MCACHE_BUCKET_SIZE;
+    }
 
     entry = &mapcache->entry[address_index % mapcache->nr_buckets];
 
commit 77ba8fef8972854b7fad89d97a14f4f9c3eae7a8
Author: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Date:   Fri Mar 30 14:33:03 2012 +0000

    xen: handle backend deletion from xenstore
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/hw/xen_backend.c b/hw/xen_backend.c
index 2673ace..66cb144 100644
--- a/hw/xen_backend.c
+++ b/hw/xen_backend.c
@@ -592,7 +592,7 @@ static void xenstore_update_be(char *watch, char *type, int dom,
                                struct XenDevOps *ops)
 {
     struct XenDevice *xendev;
-    char path[XEN_BUFSIZE], *dom0;
+    char path[XEN_BUFSIZE], *dom0, *bepath;
     unsigned int len, dev;
 
     dom0 = xs_get_domain_path(xenstore, 0);
@@ -611,15 +611,16 @@ static void xenstore_update_be(char *watch, char *type, int dom,
         return;
     }
 
-    if (0) {
-        /* FIXME: detect devices being deleted from xenstore ... */
-        xen_be_del_xendev(dom, dev);
-    }
-
     xendev = xen_be_get_xendev(type, dom, dev, ops);
     if (xendev != NULL) {
-        xen_be_backend_changed(xendev, path);
-        xen_be_check_state(xendev);
+        bepath = xs_read(xenstore, 0, xendev->be, &len);
+        if (bepath == NULL) {
+            xen_be_del_xendev(dom, dev);
+        } else {
+            free(bepath);
+            xen_be_backend_changed(xendev, path);
+            xen_be_check_state(xendev);
+        }
     }
 }
 
diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 9719395..22dbd10 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -745,6 +745,10 @@ static int blk_free(struct XenDevice *xendev)
     struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
     struct ioreq *ioreq;
 
+    if (blkdev->bs || blkdev->sring) {
+        blk_disconnect(xendev);
+    }
+
     while (!QLIST_EMPTY(&blkdev->freelist)) {
         ioreq = QLIST_FIRST(&blkdev->freelist);
         QLIST_REMOVE(ioreq, list);
commit 9468e9c41a89b1c9f3a905b8959e1dd3f055c732
Author: Wei Liu <wei.liu2 at citrix.com>
Date:   Thu Apr 12 10:02:47 2012 +0000

    Xen: Add xen-apic support and hook it up.
    
    Signed-off-by: Wei Liu <wei.liu2 at citrix.com>
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Acked-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.target b/Makefile.target
index e88b896..f9ce361 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -237,7 +237,7 @@ QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
 obj-$(CONFIG_XEN) += xen-all.o xen_machine_pv.o xen_domainbuild.o xen-mapcache.o
 obj-$(CONFIG_NO_XEN) += xen-stub.o
 
-obj-i386-$(CONFIG_XEN) += xen_platform.o
+obj-i386-$(CONFIG_XEN) += xen_platform.o xen_apic.o
 
 # Inter-VM PCI shared memory
 CONFIG_IVSHMEM =
diff --git a/hw/pc.c b/hw/pc.c
index 67f0479..1f5aacb 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -42,6 +42,7 @@
 #include "sysbus.h"
 #include "sysemu.h"
 #include "kvm.h"
+#include "xen.h"
 #include "blockdev.h"
 #include "ui/qemu-spice.h"
 #include "memory.h"
@@ -891,9 +892,12 @@ static DeviceState *apic_init(void *env, uint8_t apic_id)
 
     if (kvm_irqchip_in_kernel()) {
         dev = qdev_create(NULL, "kvm-apic");
+    } else if (xen_enabled()) {
+        dev = qdev_create(NULL, "xen-apic");
     } else {
         dev = qdev_create(NULL, "apic");
     }
+
     qdev_prop_set_uint8(dev, "id", apic_id);
     qdev_prop_set_ptr(dev, "cpu_env", env);
     qdev_init_nofail(dev);
@@ -912,6 +916,10 @@ static DeviceState *apic_init(void *env, uint8_t apic_id)
         msi_supported = true;
     }
 
+    if (xen_enabled()) {
+        msi_supported = true;
+    }
+
     return dev;
 }
 
diff --git a/hw/xen_apic.c b/hw/xen_apic.c
new file mode 100644
index 0000000..1725ff6
--- /dev/null
+++ b/hw/xen_apic.c
@@ -0,0 +1,90 @@
+/*
+ * Xen basic APIC support
+ *
+ * Copyright (c) 2012 Citrix
+ *
+ * Authors:
+ *  Wei Liu <wei.liu2 at citrix.com>
+ *
+ * This work is licensed under the terms of the GNU GPL version 2 or
+ * later. See the COPYING file in the top-level directory.
+ */
+#include "hw/apic_internal.h"
+#include "hw/msi.h"
+#include "xen.h"
+
+static uint64_t xen_apic_mem_read(void *opaque, target_phys_addr_t addr,
+                                  unsigned size)
+{
+    return ~(uint64_t)0;
+}
+
+static void xen_apic_mem_write(void *opaque, target_phys_addr_t addr,
+                               uint64_t data, unsigned size)
+{
+    if (size != sizeof(uint32_t)) {
+        fprintf(stderr, "Xen: APIC write data size = %d, invalid\n", size);
+        return;
+    }
+
+    xen_hvm_inject_msi(addr, data);
+}
+
+static const MemoryRegionOps xen_apic_io_ops = {
+    .read = xen_apic_mem_read,
+    .write = xen_apic_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void xen_apic_init(APICCommonState *s)
+{
+    memory_region_init_io(&s->io_memory, &xen_apic_io_ops, s, "xen-apic-msi",
+                          MSI_SPACE_SIZE);
+}
+
+static void xen_apic_set_base(APICCommonState *s, uint64_t val)
+{
+}
+
+static void xen_apic_set_tpr(APICCommonState *s, uint8_t val)
+{
+}
+
+static uint8_t xen_apic_get_tpr(APICCommonState *s)
+{
+    return 0;
+}
+
+static void xen_apic_vapic_base_update(APICCommonState *s)
+{
+}
+
+static void xen_apic_external_nmi(APICCommonState *s)
+{
+}
+
+static void xen_apic_class_init(ObjectClass *klass, void *data)
+{
+    APICCommonClass *k = APIC_COMMON_CLASS(klass);
+
+    k->init = xen_apic_init;
+    k->set_base = xen_apic_set_base;
+    k->set_tpr = xen_apic_set_tpr;
+    k->get_tpr = xen_apic_get_tpr;
+    k->vapic_base_update = xen_apic_vapic_base_update;
+    k->external_nmi = xen_apic_external_nmi;
+}
+
+static TypeInfo xen_apic_info = {
+    .name = "xen-apic",
+    .parent = TYPE_APIC_COMMON,
+    .instance_size = sizeof(APICCommonState),
+    .class_init = xen_apic_class_init,
+};
+
+static void xen_apic_register_types(void)
+{
+    type_register_static(&xen_apic_info);
+}
+
+type_init(xen_apic_register_types)
commit f1dbf015dfb0aa7f66f710a1f1bc58b662951de2
Author: Wei Liu <wei.liu2 at citrix.com>
Date:   Thu Apr 12 10:01:43 2012 +0000

    Xen: basic HVM MSI injection support.
    
    Signed-off-by: Wei Liu <wei.liu2 at citrix.com>
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/hw/xen.h b/hw/xen.h
index b46879c..e5926b7 100644
--- a/hw/xen.h
+++ b/hw/xen.h
@@ -34,6 +34,7 @@ static inline int xen_enabled(void)
 int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num);
 void xen_piix3_set_irq(void *opaque, int irq_num, int level);
 void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len);
+void xen_hvm_inject_msi(uint64_t addr, uint32_t data);
 void xen_cmos_set_s3_resume(void *opaque, int irq, int level);
 
 qemu_irq *xen_interrupt_controller_init(void);
diff --git a/xen-all.c b/xen-all.c
index 3e6de41..abd2b2d 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -122,6 +122,11 @@ void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
     }
 }
 
+void xen_hvm_inject_msi(uint64_t addr, uint32_t data)
+{
+    xc_hvm_inject_msi(xen_xc, xen_domid, addr, data);
+}
+
 static void xen_suspend_notifier(Notifier *notifier, void *data)
 {
     xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 3);
diff --git a/xen-stub.c b/xen-stub.c
index 9ea02d4..8ff2b79 100644
--- a/xen-stub.c
+++ b/xen-stub.c
@@ -29,6 +29,10 @@ void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
 {
 }
 
+void xen_hvm_inject_msi(uint64_t addr, uint32_t data)
+{
+}
+
 void xen_cmos_set_s3_resume(void *opaque, int irq, int level)
 {
 }
commit 7672725d41d1a04195affc1a7bd5676ba6314b14
Merge: 3cbe19b... 6ccea1e...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Apr 13 08:04:43 2012 -0500

    Merge remote-tracking branch 'stefanha/trivial-patches' into staging
    
    * stefanha/trivial-patches:
      configure: Insist on a Python 2, not Python 3
      bsd-user: fix compile failure
      ps2: avoid repeated header file includes
      make: Always set LC_ALL=C for makeinfo
      configure: Fix wrong preprocessor statement
      configure: Remove useless uses of ARCH_CFLAGS

commit 3cbe19b2e27238caa8b7518182eb674b8169b8df
Merge: a602e48... f349c12...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Apr 13 08:04:31 2012 -0500

    Merge remote-tracking branch 'qemu-kvm/uq/master' into staging
    
    * qemu-kvm/uq/master:
      kvmclock: guest stop notification
      kvm: update linux headers
      kvm: set gsi_bits and max_gsi correctly
      kvm: Drop unused kvm_pit_in_kernel
      kvm: allow arbitrarily sized mmio ioeventfd
      kvm: Drop redundant kvm_enabled from cpu_thread_is_idle
      kvm: add flightrecorder script

commit a602e48958eb70b33415407e6f64bc883e019c37
Merge: dadc106... 3eab169...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Apr 13 08:04:13 2012 -0500

    Merge remote-tracking branch 'afaerber/qom-cpu-lm32.v3' into staging
    
    * afaerber/qom-cpu-lm32.v3:
      target-lm32: QOM'ify CPU reset
      target-lm32: QOM'ify CPU init
      target-lm32: QOM'ify CPU

commit c79981ceec3ae1e712aa9c21cba94c152eea2fb5
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 13 11:39:09 2012 +0000

    hw/arm_gic: Remove stray hardcoded tab
    
    Remove the single instance of a hardcoded tab from hw/arm_gic.c.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index ba6117a..72298b4 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -160,7 +160,7 @@ static void gic_update(gic_state *s)
         cm = 1 << cpu;
         s->current_pending[cpu] = 1023;
         if (!s->enabled || !s->cpu_enabled[cpu]) {
-	    qemu_irq_lower(s->parent_irq[cpu]);
+            qemu_irq_lower(s->parent_irq[cpu]);
             return;
         }
         best_prio = 0x100;
commit b7dc1a597ab2d755c135852ce22d98fa00ab414f
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 13 11:39:09 2012 +0000

    hw/arm_gic: gic_set_pending_private() is NVIC only
    
    The function gic_set_pending_private() is now used by the NVIC
    only (for the GIC we now set PPI interrupts via gpio lines and
    gic_set_irq()). So make it #ifdef NVIC and remove the 'attribute
    unused' annotation.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 589ac5e..ba6117a 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -185,8 +185,8 @@ static void gic_update(gic_state *s)
     }
 }
 
-static void __attribute__((unused))
-gic_set_pending_private(gic_state *s, int cpu, int irq)
+#ifdef NVIC
+static void gic_set_pending_private(gic_state *s, int cpu, int irq)
 {
     int cm = 1 << cpu;
 
@@ -197,6 +197,7 @@ gic_set_pending_private(gic_state *s, int cpu, int irq)
     GIC_SET_PENDING(irq, cm);
     gic_update(s);
 }
+#endif
 
 /* Process a change in an external IRQ input.  */
 static void gic_set_irq(void *opaque, int irq, int level)
commit 0d256bdc8f540a52fe1f0475aeeed3bc9f6e2de4
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 13 11:39:09 2012 +0000

    hw/arm_gic: Use NVIC instead of LEGACY_INCLUDED_GIC define
    
    Now all the A profile cores have been switched to use the standalone
    sysbus GIC, the only remaining code which #includes arm_gic.c is
    the v7M NVIC. The coupling is much closer here so it's not so
    easily disentangled. For now, add a comment about how arm_gic.c
    is compiled, and assume that the NVIC always includes arm_gic.c
    and the non-NVIC GIC is always compiled standalone.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 81858c3..589ac5e 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -8,8 +8,15 @@
  */
 
 /* This file contains implementation code for the RealView EB interrupt
-   controller, MPCore distributed interrupt controller and ARMv7-M
-   Nested Vectored Interrupt Controller.  */
+ * controller, MPCore distributed interrupt controller and ARMv7-M
+ * Nested Vectored Interrupt Controller.
+ * It is compiled in two ways:
+ *  (1) as a standalone file to produce a sysbus device which is a GIC
+ *  that can be used on the realview board and as one of the builtin
+ *  private peripherals for the ARM MP CPUs (11MPCore, A9, etc)
+ *  (2) by being directly #included into armv7m_nvic.c to produce the
+ *  armv7m_nvic device.
+ */
 
 #include "sysbus.h"
 
@@ -909,7 +916,7 @@ static void gic_init(gic_state *s, int num_irq)
     register_savevm(NULL, "arm_gic", -1, 2, gic_save, gic_load, s);
 }
 
-#ifndef LEGACY_INCLUDED_GIC
+#ifndef NVIC
 
 static int arm_gic_init(SysBusDevice *dev)
 {
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index 5cfa971..986a6bb 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -16,7 +16,6 @@
 #include "exec-memory.h"
 
 #define NVIC 1
-#define LEGACY_INCLUDED_GIC
 
 static uint32_t nvic_readl(void *opaque, uint32_t offset);
 static void nvic_writel(void *opaque, uint32_t offset, uint32_t value);
commit aecff6924dab0197b6c8f132e44502b25fd98a38
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 13 11:39:09 2012 +0000

    hw/arm_gic: Make gic_reset a sysbus reset function
    
    Make gic_reset a sysbus reset function, so we actually
    reset the GIC on system reset rather than only at init.
    For the NVIC this requires us also to implement reset
    of the SysTick.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index b543570..81858c3 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -741,8 +741,9 @@ static const MemoryRegionOps gic_cpu_ops = {
 };
 #endif
 
-static void gic_reset(gic_state *s)
+static void gic_reset(DeviceState *dev)
 {
+    gic_state *s = FROM_SYSBUS(gic_state, sysbus_from_qdev(dev));
     int i;
     memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state));
     for (i = 0 ; i < NUM_CPU(s); i++) {
@@ -905,7 +906,6 @@ static void gic_init(gic_state *s, int num_irq)
     }
 #endif
 
-    gic_reset(s);
     register_savevm(NULL, "arm_gic", -1, 2, gic_save, gic_load, s);
 }
 
@@ -938,6 +938,7 @@ static void arm_gic_class_init(ObjectClass *klass, void *data)
     SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
     sbc->init = arm_gic_init;
     dc->props = arm_gic_properties;
+    dc->reset = gic_reset;
     dc->no_user = 1;
 }
 
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index 79cf448..5cfa971 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -76,6 +76,14 @@ static void systick_timer_tick(void * opaque)
     }
 }
 
+static void systick_reset(nvic_state *s)
+{
+    s->systick.control = 0;
+    s->systick.reload = 0;
+    s->systick.tick = 0;
+    qemu_del_timer(s->systick.timer);
+}
+
 /* The external routines use the hardware vector numbering, ie. the first
    IRQ is #16.  The internal GIC routines use #32 as the first IRQ.  */
 void armv7m_nvic_set_pending(void *opaque, int irq)
@@ -371,6 +379,13 @@ static const VMStateDescription vmstate_nvic = {
     }
 };
 
+static void armv7m_nvic_reset(DeviceState *dev)
+{
+    nvic_state *s = FROM_SYSBUSGIC(nvic_state, sysbus_from_qdev(dev));
+    gic_reset(&s->gic.busdev.qdev);
+    systick_reset(s);
+}
+
 static int armv7m_nvic_init(SysBusDevice *dev)
 {
     nvic_state *s= FROM_SYSBUSGIC(nvic_state, dev);
@@ -400,6 +415,7 @@ static void armv7m_nvic_class_init(ObjectClass *klass, void *data)
 
     sdc->init = armv7m_nvic_init;
     dc->vmsd  = &vmstate_nvic;
+    dc->reset = armv7m_nvic_reset;
     dc->props = armv7m_nvic_properties;
 }
 
commit 2e9dfe20a62d93f145ea12a1b4755bb9cd61c327
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 13 11:39:08 2012 +0000

    hw/arm11mpcore: Convert to using sysbus GIC device
    
    Convert arm11mpcore to using the standalone sysbus GIC device.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index e876a0e..c528d7a 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -10,21 +10,18 @@
 #include "sysbus.h"
 #include "qemu-timer.h"
 
-#define LEGACY_INCLUDED_GIC
-#include "arm_gic.c"
-
 /* MPCore private memory region.  */
 
 typedef struct mpcore_priv_state {
-    gic_state gic;
+    SysBusDevice busdev;
     uint32_t scu_control;
     int iomemtype;
     uint32_t old_timer_status[8];
     uint32_t num_cpu;
-    qemu_irq *timer_irq;
     MemoryRegion iomem;
     MemoryRegion container;
     DeviceState *mptimer;
+    DeviceState *gic;
     uint32_t num_irq;
 } mpcore_priv_state;
 
@@ -74,18 +71,16 @@ static const MemoryRegionOps mpcore_scu_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void mpcore_timer_irq_handler(void *opaque, int irq, int level)
+static void mpcore_priv_set_irq(void *opaque, int irq, int level)
 {
     mpcore_priv_state *s = (mpcore_priv_state *)opaque;
-    if (level && !s->old_timer_status[irq]) {
-        gic_set_pending_private(&s->gic, irq >> 1, 29 + (irq & 1));
-    }
-    s->old_timer_status[irq] = level;
+    qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
 }
 
 static void mpcore_priv_map_setup(mpcore_priv_state *s)
 {
     int i;
+    SysBusDevice *gicbusdev = sysbus_from_qdev(s->gic);
     SysBusDevice *busdev = sysbus_from_qdev(s->mptimer);
     memory_region_init(&s->container, "mpcode-priv-container", 0x2000);
     memory_region_init_io(&s->iomem, &mpcore_scu_ops, s, "mpcore-scu", 0x100);
@@ -95,31 +90,47 @@ static void mpcore_priv_map_setup(mpcore_priv_state *s)
      */
     for (i = 0; i < (s->num_cpu + 1); i++) {
         target_phys_addr_t offset = 0x100 + (i * 0x100);
-        memory_region_add_subregion(&s->container, offset, &s->gic.cpuiomem[i]);
+        memory_region_add_subregion(&s->container, offset,
+                                    sysbus_mmio_get_region(gicbusdev, i + 1));
     }
     /* Add the regions for timer and watchdog for "current CPU" and
      * for each specific CPU.
      */
-    s->timer_irq = qemu_allocate_irqs(mpcore_timer_irq_handler,
-                                      s, (s->num_cpu + 1) * 2);
     for (i = 0; i < (s->num_cpu + 1) * 2; i++) {
         /* Timers at 0x600, 0x700, ...; watchdogs at 0x620, 0x720, ... */
         target_phys_addr_t offset = 0x600 + (i >> 1) * 0x100 + (i & 1) * 0x20;
         memory_region_add_subregion(&s->container, offset,
                                     sysbus_mmio_get_region(busdev, i));
     }
-    memory_region_add_subregion(&s->container, 0x1000, &s->gic.iomem);
-    /* Wire up the interrupt from each watchdog and timer. */
-    for (i = 0; i < s->num_cpu * 2; i++) {
-        sysbus_connect_irq(busdev, i, s->timer_irq[i]);
+    memory_region_add_subregion(&s->container, 0x1000,
+                                sysbus_mmio_get_region(gicbusdev, 0));
+    /* Wire up the interrupt from each watchdog and timer.
+     * For each core the timer is PPI 29 and the watchdog PPI 30.
+     */
+    for (i = 0; i < s->num_cpu; i++) {
+        int ppibase = (s->num_irq - 32) + i * 32;
+        sysbus_connect_irq(busdev, i * 2,
+                           qdev_get_gpio_in(s->gic, ppibase + 29));
+        sysbus_connect_irq(busdev, i * 2 + 1,
+                           qdev_get_gpio_in(s->gic, ppibase + 30));
     }
 }
 
 static int mpcore_priv_init(SysBusDevice *dev)
 {
-    mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
+    mpcore_priv_state *s = FROM_SYSBUS(mpcore_priv_state, dev);
+
+    s->gic = qdev_create(NULL, "arm_gic");
+    qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
+    qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq);
+    qdev_init_nofail(s->gic);
+
+    /* Pass through outbound IRQ lines from the GIC */
+    sysbus_pass_irq(dev, sysbus_from_qdev(s->gic));
+
+    /* Pass through inbound GPIO lines to the GIC */
+    qdev_init_gpio_in(&s->busdev.qdev, mpcore_priv_set_irq, s->num_irq - 32);
 
-    gic_init(&s->gic, s->num_cpu, s->num_irq);
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
     qdev_init_nofail(s->mptimer);
commit 23b92f60280fd250fbe421727ecfe15676d9f6ca
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 13 11:39:08 2012 +0000

    hw/exynos4210_gic: Convert to using sysbus GIC
    
    Convert the Exynos GIC code to use the standalone sysbus
    GIC device.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Evgeny Voevodin <e.voevodin at samsung.com>

diff --git a/hw/exynos4210_gic.c b/hw/exynos4210_gic.c
index a05dab2..e1b215e 100644
--- a/hw/exynos4210_gic.c
+++ b/hw/exynos4210_gic.c
@@ -262,28 +262,44 @@ uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
 
 /********* GIC part *********/
 
-#define LEGACY_INCLUDED_GIC
-#include "arm_gic.c"
-
 typedef struct {
-    gic_state gic;
+    SysBusDevice busdev;
     MemoryRegion cpu_container;
     MemoryRegion dist_container;
     MemoryRegion cpu_alias[EXYNOS4210_NCPUS];
     MemoryRegion dist_alias[EXYNOS4210_NCPUS];
     uint32_t num_cpu;
+    DeviceState *gic;
 } Exynos4210GicState;
 
+static void exynos4210_gic_set_irq(void *opaque, int irq, int level)
+{
+    Exynos4210GicState *s = (Exynos4210GicState *)opaque;
+    qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
+}
+
 static int exynos4210_gic_init(SysBusDevice *dev)
 {
-    Exynos4210GicState *s = FROM_SYSBUSGIC(Exynos4210GicState, dev);
+    Exynos4210GicState *s = FROM_SYSBUS(Exynos4210GicState, dev);
     uint32_t i;
     const char cpu_prefix[] = "exynos4210-gic-alias_cpu";
     const char dist_prefix[] = "exynos4210-gic-alias_dist";
     char cpu_alias_name[sizeof(cpu_prefix) + 3];
     char dist_alias_name[sizeof(cpu_prefix) + 3];
+    SysBusDevice *busdev;
+
+    s->gic = qdev_create(NULL, "arm_gic");
+    qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
+    qdev_prop_set_uint32(s->gic, "num-irq", EXYNOS4210_GIC_NIRQ);
+    qdev_init_nofail(s->gic);
+    busdev = sysbus_from_qdev(s->gic);
+
+    /* Pass through outbound IRQ lines from the GIC */
+    sysbus_pass_irq(dev, busdev);
 
-    gic_init(&s->gic, s->num_cpu, EXYNOS4210_GIC_NIRQ);
+    /* Pass through inbound GPIO lines to the GIC */
+    qdev_init_gpio_in(&s->busdev.qdev, exynos4210_gic_set_irq,
+                      EXYNOS4210_GIC_NIRQ - 32);
 
     memory_region_init(&s->cpu_container, "exynos4210-cpu-container",
             EXYNOS4210_EXT_GIC_CPU_REGION_SIZE);
@@ -295,7 +311,7 @@ static int exynos4210_gic_init(SysBusDevice *dev)
         sprintf(cpu_alias_name, "%s%x", cpu_prefix, i);
         memory_region_init_alias(&s->cpu_alias[i],
                                  cpu_alias_name,
-                                 &s->gic.cpuiomem[0],
+                                 sysbus_mmio_get_region(busdev, 1),
                                  0,
                                  EXYNOS4210_GIC_CPU_REGION_SIZE);
         memory_region_add_subregion(&s->cpu_container,
@@ -305,7 +321,7 @@ static int exynos4210_gic_init(SysBusDevice *dev)
         sprintf(dist_alias_name, "%s%x", dist_prefix, i);
         memory_region_init_alias(&s->dist_alias[i],
                                  dist_alias_name,
-                                 &s->gic.iomem,
+                                 sysbus_mmio_get_region(busdev, 0),
                                  0,
                                  EXYNOS4210_GIC_DIST_REGION_SIZE);
         memory_region_add_subregion(&s->dist_container,
commit fbbd05dc2ad0965d3ffd7556b8af8a74b156f9f9
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 13 11:39:08 2012 +0000

    hw/realview_gic: switch to sysbus GIC
    
    Switch the realview_gic device to the standalone sysbus GIC.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index a3b5a04..5bc37a7 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -9,31 +9,45 @@
 
 #include "sysbus.h"
 
-#define LEGACY_INCLUDED_GIC
-#include "arm_gic.c"
-
 typedef struct {
-    gic_state gic;
+    SysBusDevice busdev;
+    DeviceState *gic;
     MemoryRegion container;
 } RealViewGICState;
 
-static void realview_gic_map_setup(RealViewGICState *s)
+static void realview_gic_set_irq(void *opaque, int irq, int level)
 {
-    memory_region_init(&s->container, "realview-gic-container", 0x2000);
-    memory_region_add_subregion(&s->container, 0, &s->gic.cpuiomem[0]);
-    memory_region_add_subregion(&s->container, 0x1000, &s->gic.iomem);
+    RealViewGICState *s = (RealViewGICState *)opaque;
+    qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
 }
 
 static int realview_gic_init(SysBusDevice *dev)
 {
-    RealViewGICState *s = FROM_SYSBUSGIC(RealViewGICState, dev);
-
+    RealViewGICState *s = FROM_SYSBUS(RealViewGICState, dev);
+    SysBusDevice *busdev;
     /* The GICs on the RealView boards have a fixed nonconfigurable
      * number of interrupt lines, so we don't need to expose this as
      * a qdev property.
      */
-    gic_init(&s->gic, 1, 96);
-    realview_gic_map_setup(s);
+    int numirq = 96;
+
+    s->gic = qdev_create(NULL, "arm_gic");
+    qdev_prop_set_uint32(s->gic, "num-cpu", 1);
+    qdev_prop_set_uint32(s->gic, "num-irq", numirq);
+    qdev_init_nofail(s->gic);
+    busdev = sysbus_from_qdev(s->gic);
+
+    /* Pass through outbound IRQ lines from the GIC */
+    sysbus_pass_irq(dev, busdev);
+
+    /* Pass through inbound GPIO lines to the GIC */
+    qdev_init_gpio_in(&s->busdev.qdev, realview_gic_set_irq, numirq - 32);
+
+    memory_region_init(&s->container, "realview-gic-container", 0x2000);
+    memory_region_add_subregion(&s->container, 0,
+                                sysbus_mmio_get_region(busdev, 1));
+    memory_region_add_subregion(&s->container, 0x1000,
+                                sysbus_mmio_get_region(busdev, 0));
     sysbus_init_mmio(dev, &s->container);
     return 0;
 }
commit ddd761653b14ffde7ee18d31f0350429f0402ab4
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 13 11:39:08 2012 +0000

    hw/a9mpcore: Switch to using sysbus GIC
    
    Switch the a9mpcore to using the sysbus GIC device rather
    than having the a9mp private memory region device subclass
    the GIC.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 164a0d3..c2ff74d 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -10,22 +10,19 @@
 
 #include "sysbus.h"
 
-#define LEGACY_INCLUDED_GIC
-#include "arm_gic.c"
-
 /* A9MP private memory region.  */
 
 typedef struct a9mp_priv_state {
-    gic_state gic;
+    SysBusDevice busdev;
     uint32_t scu_control;
     uint32_t scu_status;
     uint32_t old_timer_status[8];
     uint32_t num_cpu;
-    qemu_irq *timer_irq;
     MemoryRegion scu_iomem;
     MemoryRegion ptimer_iomem;
     MemoryRegion container;
     DeviceState *mptimer;
+    DeviceState *gic;
     uint32_t num_irq;
 } a9mp_priv_state;
 
@@ -114,18 +111,9 @@ static const MemoryRegionOps a9_scu_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void a9mpcore_timer_irq_handler(void *opaque, int irq, int level)
-{
-    a9mp_priv_state *s = (a9mp_priv_state *)opaque;
-    if (level && !s->old_timer_status[irq]) {
-        gic_set_pending_private(&s->gic, irq >> 1, 29 + (irq & 1));
-    }
-    s->old_timer_status[irq] = level;
-}
-
 static void a9mp_priv_reset(DeviceState *dev)
 {
-    a9mp_priv_state *s = FROM_SYSBUSGIC(a9mp_priv_state, sysbus_from_qdev(dev));
+    a9mp_priv_state *s = FROM_SYSBUS(a9mp_priv_state, sysbus_from_qdev(dev));
     int i;
     s->scu_control = 0;
     for (i = 0; i < ARRAY_SIZE(s->old_timer_status); i++) {
@@ -133,13 +121,29 @@ static void a9mp_priv_reset(DeviceState *dev)
     }
 }
 
+static void a9mp_priv_set_irq(void *opaque, int irq, int level)
+{
+    a9mp_priv_state *s = (a9mp_priv_state *)opaque;
+    qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
+}
+
 static int a9mp_priv_init(SysBusDevice *dev)
 {
-    a9mp_priv_state *s = FROM_SYSBUSGIC(a9mp_priv_state, dev);
-    SysBusDevice *busdev;
+    a9mp_priv_state *s = FROM_SYSBUS(a9mp_priv_state, dev);
+    SysBusDevice *busdev, *gicbusdev;
     int i;
 
-    gic_init(&s->gic, s->num_cpu, s->num_irq);
+    s->gic = qdev_create(NULL, "arm_gic");
+    qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
+    qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq);
+    qdev_init_nofail(s->gic);
+    gicbusdev = sysbus_from_qdev(s->gic);
+
+    /* Pass through outbound IRQ lines from the GIC */
+    sysbus_pass_irq(dev, gicbusdev);
+
+    /* Pass through inbound GPIO lines to the GIC */
+    qdev_init_gpio_in(&s->busdev.qdev, a9mp_priv_set_irq, s->num_irq - 32);
 
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
@@ -161,7 +165,8 @@ static int a9mp_priv_init(SysBusDevice *dev)
     memory_region_init_io(&s->scu_iomem, &a9_scu_ops, s, "a9mp-scu", 0x100);
     memory_region_add_subregion(&s->container, 0, &s->scu_iomem);
     /* GIC CPU interface */
-    memory_region_add_subregion(&s->container, 0x100, &s->gic.cpuiomem[0]);
+    memory_region_add_subregion(&s->container, 0x100,
+                                sysbus_mmio_get_region(gicbusdev, 1));
     /* Note that the A9 exposes only the "timer/watchdog for this core"
      * memory region, not the "timer/watchdog for core X" ones 11MPcore has.
      */
@@ -169,15 +174,20 @@ static int a9mp_priv_init(SysBusDevice *dev)
                                 sysbus_mmio_get_region(busdev, 0));
     memory_region_add_subregion(&s->container, 0x620,
                                 sysbus_mmio_get_region(busdev, 1));
-    memory_region_add_subregion(&s->container, 0x1000, &s->gic.iomem);
+    memory_region_add_subregion(&s->container, 0x1000,
+                                sysbus_mmio_get_region(gicbusdev, 0));
 
     sysbus_init_mmio(dev, &s->container);
 
-    /* Wire up the interrupt from each watchdog and timer. */
-    s->timer_irq = qemu_allocate_irqs(a9mpcore_timer_irq_handler,
-                                      s, (s->num_cpu + 1) * 2);
-    for (i = 0; i < s->num_cpu * 2; i++) {
-        sysbus_connect_irq(busdev, i, s->timer_irq[i]);
+    /* Wire up the interrupt from each watchdog and timer.
+     * For each core the timer is PPI 29 and the watchdog PPI 30.
+     */
+    for (i = 0; i < s->num_cpu; i++) {
+        int ppibase = (s->num_irq - 32) + i * 32;
+        sysbus_connect_irq(busdev, i * 2,
+                           qdev_get_gpio_in(s->gic, ppibase + 29));
+        sysbus_connect_irq(busdev, i * 2 + 1,
+                           qdev_get_gpio_in(s->gic, ppibase + 30));
     }
     return 0;
 }
commit 4637a02752f29f1b28c4a4ddb0c168d2d1299227
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 13 11:39:07 2012 +0000

    hw/a15mpcore: switch to using sysbus GIC
    
    Switch the a15mpcore private peripheral region to using
    the standalone sysbus GIC device.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/a15mpcore.c b/hw/a15mpcore.c
index 54c0dbf..5a7b365 100644
--- a/hw/a15mpcore.c
+++ b/hw/a15mpcore.c
@@ -20,23 +20,38 @@
 
 #include "sysbus.h"
 
-#define LEGACY_INCLUDED_GIC
-#include "arm_gic.c"
-
 /* A15MP private memory region.  */
 
 typedef struct A15MPPrivState {
-    gic_state gic;
+    SysBusDevice busdev;
     uint32_t num_cpu;
     uint32_t num_irq;
     MemoryRegion container;
+    DeviceState *gic;
 } A15MPPrivState;
 
+static void a15mp_priv_set_irq(void *opaque, int irq, int level)
+{
+    A15MPPrivState *s = (A15MPPrivState *)opaque;
+    qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
+}
+
 static int a15mp_priv_init(SysBusDevice *dev)
 {
-    A15MPPrivState *s = FROM_SYSBUSGIC(A15MPPrivState, dev);
+    A15MPPrivState *s = FROM_SYSBUS(A15MPPrivState, dev);
+    SysBusDevice *busdev;
+
+    s->gic = qdev_create(NULL, "arm_gic");
+    qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
+    qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq);
+    qdev_init_nofail(s->gic);
+    busdev = sysbus_from_qdev(s->gic);
+
+    /* Pass through outbound IRQ lines from the GIC */
+    sysbus_pass_irq(dev, busdev);
 
-    gic_init(&s->gic, s->num_cpu, s->num_irq);
+    /* Pass through inbound GPIO lines to the GIC */
+    qdev_init_gpio_in(&s->busdev.qdev, a15mp_priv_set_irq, s->num_irq - 32);
 
     /* Memory map (addresses are offsets from PERIPHBASE):
      *  0x0000-0x0fff -- reserved
@@ -47,8 +62,10 @@ static int a15mp_priv_init(SysBusDevice *dev)
      *  0x6000-0x7fff -- GIC virtual CPU interface (not modelled)
      */
     memory_region_init(&s->container, "a15mp-priv-container", 0x8000);
-    memory_region_add_subregion(&s->container, 0x1000, &s->gic.iomem);
-    memory_region_add_subregion(&s->container, 0x2000, &s->gic.cpuiomem[0]);
+    memory_region_add_subregion(&s->container, 0x1000,
+                                sysbus_mmio_get_region(busdev, 0));
+    memory_region_add_subregion(&s->container, 0x2000,
+                                sysbus_mmio_get_region(busdev, 1));
 
     sysbus_init_mmio(dev, &s->container);
     return 0;
@@ -72,7 +89,7 @@ static void a15mp_priv_class_init(ObjectClass *klass, void *data)
     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
     k->init = a15mp_priv_init;
     dc->props = a15mp_priv_properties;
-    /* We currently have no savable state outside the common GIC state */
+    /* We currently have no savable state */
 }
 
 static TypeInfo a15mp_priv_info = {
commit 496dbcd1a38c2ae4ada848445e4a1aa758af9f43
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 13 11:39:07 2012 +0000

    hw/arm_gic: Make the GIC its own sysbus device
    
    Compile arm_gic.c as a standalone C file to produce a self contained
    sysbus GIC device. Support the legacy usage by #include of the .c file
    by making those users #define LEGACY_INCLUDED_GIC, so we can convert
    them one by one.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Evgeny Voevodin <e.voevodin at samsung.com>

diff --git a/Makefile.target b/Makefile.target
index 1110796..0f09180 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -365,6 +365,7 @@ obj-arm-y += cadence_uart.o
 obj-arm-y += cadence_ttc.o
 obj-arm-y += cadence_gem.o
 obj-arm-y += xilinx_zynq.o zynq_slcr.o
+obj-arm-y += arm_gic.o
 obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
 obj-arm-y += exynos4210_gic.o exynos4210_combiner.o exynos4210.o
 obj-arm-y += exynos4_boards.o exynos4210_uart.o exynos4210_pwm.o
diff --git a/hw/a15mpcore.c b/hw/a15mpcore.c
index 2e2ed42..54c0dbf 100644
--- a/hw/a15mpcore.c
+++ b/hw/a15mpcore.c
@@ -20,6 +20,7 @@
 
 #include "sysbus.h"
 
+#define LEGACY_INCLUDED_GIC
 #include "arm_gic.c"
 
 /* A15MP private memory region.  */
diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 1d83c37..164a0d3 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -10,6 +10,7 @@
 
 #include "sysbus.h"
 
+#define LEGACY_INCLUDED_GIC
 #include "arm_gic.c"
 
 /* A9MP private memory region.  */
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index c4829d8..e876a0e 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -10,6 +10,7 @@
 #include "sysbus.h"
 #include "qemu-timer.h"
 
+#define LEGACY_INCLUDED_GIC
 #include "arm_gic.c"
 
 /* MPCore private memory region.  */
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index fabbcc5..b543570 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -11,6 +11,8 @@
    controller, MPCore distributed interrupt controller and ARMv7-M
    Nested Vectored Interrupt Controller.  */
 
+#include "sysbus.h"
+
 /* Maximum number of possible interrupts, determined by the GIC architecture */
 #define GIC_MAXIRQ 1020
 /* First 32 are private to each CPU (SGIs and PPIs). */
@@ -112,7 +114,7 @@ typedef struct gic_state
     int current_pending[NCPU];
 
 #if NCPU > 1
-    int num_cpu;
+    uint32_t num_cpu;
 #endif
 
     MemoryRegion iomem; /* Distributor */
@@ -906,3 +908,51 @@ static void gic_init(gic_state *s, int num_irq)
     gic_reset(s);
     register_savevm(NULL, "arm_gic", -1, 2, gic_save, gic_load, s);
 }
+
+#ifndef LEGACY_INCLUDED_GIC
+
+static int arm_gic_init(SysBusDevice *dev)
+{
+    /* Device instance init function for the GIC sysbus device */
+    int i;
+    gic_state *s = FROM_SYSBUS(gic_state, dev);
+    gic_init(s, s->num_cpu, s->num_irq);
+    /* Distributor */
+    sysbus_init_mmio(dev, &s->iomem);
+    /* cpu interfaces (one for "current cpu" plus one per cpu) */
+    for (i = 0; i <= NUM_CPU(s); i++) {
+        sysbus_init_mmio(dev, &s->cpuiomem[i]);
+    }
+    return 0;
+}
+
+static Property arm_gic_properties[] = {
+    DEFINE_PROP_UINT32("num-cpu", gic_state, num_cpu, 1),
+    DEFINE_PROP_UINT32("num-irq", gic_state, num_irq, 32),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void arm_gic_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
+    sbc->init = arm_gic_init;
+    dc->props = arm_gic_properties;
+    dc->no_user = 1;
+}
+
+static TypeInfo arm_gic_info = {
+    .name = "arm_gic",
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(gic_state),
+    .class_init = arm_gic_class_init,
+};
+
+static void arm_gic_register_types(void)
+{
+    type_register_static(&arm_gic_info);
+}
+
+type_init(arm_gic_register_types)
+
+#endif
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index 99ed85b..79cf448 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -16,6 +16,7 @@
 #include "exec-memory.h"
 
 #define NVIC 1
+#define LEGACY_INCLUDED_GIC
 
 static uint32_t nvic_readl(void *opaque, uint32_t offset);
 static void nvic_writel(void *opaque, uint32_t offset, uint32_t value);
diff --git a/hw/exynos4210_gic.c b/hw/exynos4210_gic.c
index ff7ab84..a05dab2 100644
--- a/hw/exynos4210_gic.c
+++ b/hw/exynos4210_gic.c
@@ -262,6 +262,7 @@ uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
 
 /********* GIC part *********/
 
+#define LEGACY_INCLUDED_GIC
 #include "arm_gic.c"
 
 typedef struct {
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index aa780fe..a3b5a04 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -9,6 +9,7 @@
 
 #include "sysbus.h"
 
+#define LEGACY_INCLUDED_GIC
 #include "arm_gic.c"
 
 typedef struct {
commit 544d1afa7013fce155f5afbbc24737f2fc0c0f26
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 13 11:39:07 2012 +0000

    hw/arm_gic: Expose PPI inputs as gpio inputs
    
    Expose the Private Peripheral Interrupt inputs as GPIO inputs.
    The layout of the GPIO array is thus:
      [0..N-1] SPIs
      [N..N+31] PPIs for CPU 0
      [N+32..N+63] PPIs for CPU 1
      ...
    
    Treating PPIs as being another kind of input line is in line with the
    GIC architecture specification, where they are clearly described that
    way. The 11MPCore TRM is a bit more ambiguous, but there is no practical
    difference between "set PPI X as pending" and "0->1 transition on a
    PPI input line configured as edge triggered", and PPIs are always
    edge triggered, so this change won't affect behaviour.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index df1a34b..fabbcc5 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -192,20 +192,40 @@ gic_set_pending_private(gic_state *s, int cpu, int irq)
 /* Process a change in an external IRQ input.  */
 static void gic_set_irq(void *opaque, int irq, int level)
 {
+    /* Meaning of the 'irq' parameter:
+     *  [0..N-1] : external interrupts
+     *  [N..N+31] : PPI (internal) interrupts for CPU 0
+     *  [N+32..N+63] : PPI (internal interrupts for CPU 1
+     *  ...
+     */
     gic_state *s = (gic_state *)opaque;
-    /* The first external input line is internal interrupt 32.  */
-    irq += GIC_INTERNAL;
-    if (level == GIC_TEST_LEVEL(irq, ALL_CPU_MASK))
+    int cm, target;
+    if (irq < (s->num_irq - GIC_INTERNAL)) {
+        /* The first external input line is internal interrupt 32.  */
+        cm = ALL_CPU_MASK;
+        irq += GIC_INTERNAL;
+        target = GIC_TARGET(irq);
+    } else {
+        int cpu;
+        irq -= (s->num_irq - GIC_INTERNAL);
+        cpu = irq / GIC_INTERNAL;
+        irq %= GIC_INTERNAL;
+        cm = 1 << cpu;
+        target = cm;
+    }
+
+    if (level == GIC_TEST_LEVEL(irq, cm)) {
         return;
+    }
 
     if (level) {
-        GIC_SET_LEVEL(irq, ALL_CPU_MASK);
-        if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq, ALL_CPU_MASK)) {
-            DPRINTF("Set %d pending mask %x\n", irq, GIC_TARGET(irq));
-            GIC_SET_PENDING(irq, GIC_TARGET(irq));
+        GIC_SET_LEVEL(irq, cm);
+        if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq, cm)) {
+            DPRINTF("Set %d pending mask %x\n", irq, target);
+            GIC_SET_PENDING(irq, target);
         }
     } else {
-        GIC_CLEAR_LEVEL(irq, ALL_CPU_MASK);
+        GIC_CLEAR_LEVEL(irq, cm);
     }
     gic_update(s);
 }
@@ -849,7 +869,18 @@ static void gic_init(gic_state *s, int num_irq)
                  num_irq);
     }
 
-    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - GIC_INTERNAL);
+    i = s->num_irq - GIC_INTERNAL;
+#ifndef NVIC
+    /* For the GIC, also expose incoming GPIO lines for PPIs for each CPU.
+     * GPIO array layout is thus:
+     *  [0..N-1] SPIs
+     *  [N..N+31] PPIs for CPU 0
+     *  [N+32..N+63] PPIs for CPU 1
+     *   ...
+     */
+    i += (GIC_INTERNAL * num_cpu);
+#endif
+    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, i);
     for (i = 0; i < NUM_CPU(s); i++) {
         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
     }
commit 926c4aff6ecf2b26b3508773196314a774bf5c4c
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 13 11:39:07 2012 +0000

    hw/arm_gic: Move gic_get_current_cpu into arm_gic.c
    
    Move the gic_get_current_cpu() function into arm_gic.c.
    There are only two implementations: (1) "get the index
    of the currently executing CPU", used by all multicore
    GICs, and (2) "always 0", used by all GICs instantiated
    with a single CPU interface (the Realview board GIC and
    the v7M NVIC). So we can move this into the main GIC
    source file.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Evgeny Voevodin <e.voevodin at samsung.com>

diff --git a/hw/a15mpcore.c b/hw/a15mpcore.c
index 67206ec..2e2ed42 100644
--- a/hw/a15mpcore.c
+++ b/hw/a15mpcore.c
@@ -20,14 +20,6 @@
 
 #include "sysbus.h"
 
-/* Configuration for arm_gic.c:
- * how to ID current CPU
- */
-static inline int gic_get_current_cpu(void)
-{
-  return cpu_single_env->cpu_index;
-}
-
 #include "arm_gic.c"
 
 /* A15MP private memory region.  */
diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 5bbe3c7..1d83c37 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -10,15 +10,6 @@
 
 #include "sysbus.h"
 
-/* Configuration for arm_gic.c:
- * how to ID current CPU
- */
-static inline int
-gic_get_current_cpu(void)
-{
-  return cpu_single_env->cpu_index;
-}
-
 #include "arm_gic.c"
 
 /* A9MP private memory region.  */
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index 99c1826..c4829d8 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -10,12 +10,6 @@
 #include "sysbus.h"
 #include "qemu-timer.h"
 
-static inline int
-gic_get_current_cpu(void)
-{
-  return cpu_single_env->cpu_index;
-}
-
 #include "arm_gic.c"
 
 /* MPCore private memory region.  */
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index f64a001..df1a34b 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -126,6 +126,16 @@ typedef struct gic_state
     uint32_t num_irq;
 } gic_state;
 
+static inline int gic_get_current_cpu(gic_state *s)
+{
+#if NCPU > 1
+    if (s->num_cpu > 1) {
+        return cpu_single_env->cpu_index;
+    }
+#endif
+    return 0;
+}
+
 /* TODO: Many places that call this routine could be optimized.  */
 /* Update interrupt status after enabled or pending bits have been changed.  */
 static void gic_update(gic_state *s)
@@ -285,7 +295,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     int cm;
     int mask;
 
-    cpu = gic_get_current_cpu();
+    cpu = gic_get_current_cpu(s);
     cm = 1 << cpu;
     if (offset < 0x100) {
 #ifndef NVIC
@@ -420,7 +430,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     int i;
     int cpu;
 
-    cpu = gic_get_current_cpu();
+    cpu = gic_get_current_cpu(s);
     if (offset < 0x100) {
 #ifdef NVIC
         goto bad_reg;
@@ -582,7 +592,7 @@ static void gic_dist_writel(void *opaque, target_phys_addr_t offset,
         int irq;
         int mask;
 
-        cpu = gic_get_current_cpu();
+        cpu = gic_get_current_cpu(s);
         irq = value & 0x3ff;
         switch ((value >> 24) & 3) {
         case 0:
@@ -665,14 +675,14 @@ static uint64_t gic_thiscpu_read(void *opaque, target_phys_addr_t addr,
                                  unsigned size)
 {
     gic_state *s = (gic_state *)opaque;
-    return gic_cpu_read(s, gic_get_current_cpu(), addr);
+    return gic_cpu_read(s, gic_get_current_cpu(s), addr);
 }
 
 static void gic_thiscpu_write(void *opaque, target_phys_addr_t addr,
                               uint64_t value, unsigned size)
 {
     gic_state *s = (gic_state *)opaque;
-    gic_cpu_write(s, gic_get_current_cpu(), addr, value);
+    gic_cpu_write(s, gic_get_current_cpu(s), addr, value);
 }
 
 /* Wrappers to read/write the GIC CPU interface for a specific CPU.
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index bdab709..99ed85b 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -17,13 +17,6 @@
 
 #define NVIC 1
 
-/* Only a single "CPU" interface is present.  */
-static inline int
-gic_get_current_cpu(void)
-{
-    return 0;
-}
-
 static uint32_t nvic_readl(void *opaque, uint32_t offset);
 static void nvic_writel(void *opaque, uint32_t offset, uint32_t value);
 
diff --git a/hw/exynos4210_gic.c b/hw/exynos4210_gic.c
index 426f540..ff7ab84 100644
--- a/hw/exynos4210_gic.c
+++ b/hw/exynos4210_gic.c
@@ -262,12 +262,6 @@ uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
 
 /********* GIC part *********/
 
-static inline int
-gic_get_current_cpu(void)
-{
-    return cpu_single_env->cpu_index;
-}
-
 #include "arm_gic.c"
 
 typedef struct {
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index d114242..aa780fe 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -9,13 +9,6 @@
 
 #include "sysbus.h"
 
-/* Only a single "CPU" interface is present.  */
-static inline int
-gic_get_current_cpu(void)
-{
-  return 0;
-}
-
 #include "arm_gic.c"
 
 typedef struct {
commit 386e29554e8f1a7e910682789418aed2094b4ef6
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 13 11:39:07 2012 +0000

    hw/arm_gic: Move NCPU definition to arm_gic.c
    
    Move the NCPU definition to arm_gic.c: the maximum number
    of CPU interfaces is defined by the GIC architecture specification
    to be 8, so we don't need to have this #define in each of the
    sources files which currently includes arm_gic.c.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Evgeny Voevodin <e.voevodin at samsung.com>

diff --git a/hw/a15mpcore.c b/hw/a15mpcore.c
index 71142e5..67206ec 100644
--- a/hw/a15mpcore.c
+++ b/hw/a15mpcore.c
@@ -21,10 +21,8 @@
 #include "sysbus.h"
 
 /* Configuration for arm_gic.c:
- * max number of CPUs, how to ID current CPU
+ * how to ID current CPU
  */
-#define NCPU 4
-
 static inline int gic_get_current_cpu(void)
 {
   return cpu_single_env->cpu_index;
@@ -45,10 +43,6 @@ static int a15mp_priv_init(SysBusDevice *dev)
 {
     A15MPPrivState *s = FROM_SYSBUSGIC(A15MPPrivState, dev);
 
-    if (s->num_cpu > NCPU) {
-        hw_error("a15mp_priv_init: num-cpu may not be more than %d\n", NCPU);
-    }
-
     gic_init(&s->gic, s->num_cpu, s->num_irq);
 
     /* Memory map (addresses are offsets from PERIPHBASE):
diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 03b128c..5bbe3c7 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -11,10 +11,8 @@
 #include "sysbus.h"
 
 /* Configuration for arm_gic.c:
- * max number of CPUs, how to ID current CPU
+ * how to ID current CPU
  */
-#define NCPU 4
-
 static inline int
 gic_get_current_cpu(void)
 {
@@ -149,10 +147,6 @@ static int a9mp_priv_init(SysBusDevice *dev)
     SysBusDevice *busdev;
     int i;
 
-    if (s->num_cpu > NCPU) {
-        hw_error("a9mp_priv_init: num-cpu may not be more than %d\n", NCPU);
-    }
-
     gic_init(&s->gic, s->num_cpu, s->num_irq);
 
     s->mptimer = qdev_create(NULL, "arm_mptimer");
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index ba6a89d..99c1826 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -10,8 +10,6 @@
 #include "sysbus.h"
 #include "qemu-timer.h"
 
-#define NCPU 4
-
 static inline int
 gic_get_current_cpu(void)
 {
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 6b34c06..f64a001 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -15,6 +15,13 @@
 #define GIC_MAXIRQ 1020
 /* First 32 are private to each CPU (SGIs and PPIs). */
 #define GIC_INTERNAL 32
+/* Maximum number of possible CPU interfaces, determined by GIC architecture */
+#ifdef NVIC
+#define NCPU 1
+#else
+#define NCPU 8
+#endif
+
 //#define DEBUG_GIC
 
 #ifdef DEBUG_GIC
@@ -50,7 +57,7 @@ typedef struct gic_irq_state
     unsigned trigger:1; /* nonzero = edge triggered.  */
 } gic_irq_state;
 
-#define ALL_CPU_MASK ((1 << NCPU) - 1)
+#define ALL_CPU_MASK ((unsigned)(((1 << NCPU) - 1)))
 #if NCPU > 1
 #define NUM_CPU(s) ((s)->num_cpu)
 #else
@@ -813,6 +820,10 @@ static void gic_init(gic_state *s, int num_irq)
 
 #if NCPU > 1
     s->num_cpu = num_cpu;
+    if (s->num_cpu > NCPU) {
+        hw_error("requested %u CPUs exceeds GIC maximum %d\n",
+                 num_cpu, NCPU);
+    }
 #endif
     s->num_irq = num_irq + GIC_BASE_IRQ;
     if (s->num_irq > GIC_MAXIRQ) {
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index 3210129..bdab709 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -15,7 +15,6 @@
 #include "arm-misc.h"
 #include "exec-memory.h"
 
-#define NCPU 1
 #define NVIC 1
 
 /* Only a single "CPU" interface is present.  */
diff --git a/hw/exynos4210_gic.c b/hw/exynos4210_gic.c
index 3ba9063..426f540 100644
--- a/hw/exynos4210_gic.c
+++ b/hw/exynos4210_gic.c
@@ -174,7 +174,6 @@ combiner_grp_to_gic_id[64-EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
 };
 
 #define EXYNOS4210_GIC_NIRQ 160
-#define NCPU                EXYNOS4210_NCPUS
 
 #define EXYNOS4210_EXT_GIC_CPU_REGION_SIZE     0x10000
 #define EXYNOS4210_EXT_GIC_DIST_REGION_SIZE    0x10000
@@ -275,8 +274,8 @@ typedef struct {
     gic_state gic;
     MemoryRegion cpu_container;
     MemoryRegion dist_container;
-    MemoryRegion cpu_alias[NCPU];
-    MemoryRegion dist_alias[NCPU];
+    MemoryRegion cpu_alias[EXYNOS4210_NCPUS];
+    MemoryRegion dist_alias[EXYNOS4210_NCPUS];
     uint32_t num_cpu;
 } Exynos4210GicState;
 
@@ -359,7 +358,7 @@ type_init(exynos4210_gic_register_types)
 typedef struct {
     SysBusDevice busdev;
 
-    qemu_irq pic_irq[NCPU]; /* output IRQs to PICs */
+    qemu_irq pic_irq[EXYNOS4210_NCPUS]; /* output IRQs to PICs */
     uint32_t gpio_level[EXYNOS4210_IRQ_GATE_NINPUTS]; /* Input levels */
 } Exynos4210IRQGateState;
 
@@ -424,7 +423,7 @@ static int exynos4210_irq_gate_init(SysBusDevice *dev)
             EXYNOS4210_IRQ_GATE_NINPUTS);
 
     /* Connect SysBusDev irqs to device specific irqs */
-    for (i = 0; i < NCPU; i++) {
+    for (i = 0; i < EXYNOS4210_NCPUS; i++) {
         sysbus_init_irq(dev, &s->pic_irq[i]);
     }
 
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index 071ef13..d114242 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -9,8 +9,6 @@
 
 #include "sysbus.h"
 
-#define NCPU 1
-
 /* Only a single "CPU" interface is present.  */
 static inline int
 gic_get_current_cpu(void)
@@ -40,7 +38,7 @@ static int realview_gic_init(SysBusDevice *dev)
      * number of interrupt lines, so we don't need to expose this as
      * a qdev property.
      */
-    gic_init(&s->gic, 96);
+    gic_init(&s->gic, 1, 96);
     realview_gic_map_setup(s);
     sysbus_init_mmio(dev, &s->container);
     return 0;
commit 5181b50fc89d321cf79ed2f2fff5bec0b55e3011
Author: Evgeny Voevodin <e.voevodin at samsung.com>
Date:   Fri Apr 13 11:39:06 2012 +0000

    hw/exynos4210_combiner.c: Drop excessive read/write access check.
    
    Access to reserved area at offset higher than 0x3c is allowed in
    External Combiner. Samsung Galaxy Kernel implements this. So, drop
    excessive checks in read/write functions.
    
    Signed-off-by: Evgeny Voevodin <e.voevodin at samsung.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/exynos4210_combiner.c b/hw/exynos4210_combiner.c
index 6110c19..80af22c 100644
--- a/hw/exynos4210_combiner.c
+++ b/hw/exynos4210_combiner.c
@@ -184,11 +184,6 @@ exynos4210_combiner_read(void *opaque, target_phys_addr_t offset, unsigned size)
     uint32_t reg_n;              /* Register number inside the quad */
     uint32_t val;
 
-    if (s->external && (offset > 0x3c && offset != 0x100)) {
-        hw_error("exynos4210.combiner: unallowed read access at offset 0x"
-                TARGET_FMT_plx "\n", offset);
-    }
-
     req_quad_base_n = offset >> 4;
     grp_quad_base_n = req_quad_base_n << 2;
     reg_n = (offset - (req_quad_base_n << 4)) >> 2;
@@ -281,11 +276,6 @@ static void exynos4210_combiner_write(void *opaque, target_phys_addr_t offset,
     uint32_t grp_quad_base_n;    /* Base of group quad */
     uint32_t reg_n;              /* Register number inside the quad */
 
-    if (s->external && (offset > 0x3c && offset != 0x100)) {
-        hw_error("exynos4210.combiner: unallowed write access at offset 0x"
-                TARGET_FMT_plx "\n", offset);
-    }
-
     req_quad_base_n = offset >> 4;
     grp_quad_base_n = req_quad_base_n << 2;
     reg_n = (offset - (req_quad_base_n << 4)) >> 2;
commit 3f088e36de5a72a69e530d4bbf1fabaa507da0db
Author: Evgeny Voevodin <e.voevodin at samsung.com>
Date:   Fri Apr 13 11:39:06 2012 +0000

    ARM: Exynos4210: Drop gic_cpu_write() after initialization.
    
    Remove gic_cpu_write() call after initialization that was emulating
    functionality of earliest SOC bootloader which enables external
    GIC CPU1 interface. Instead introduce Exynos4210-specific secondary
    CPU bootloader, which enables both Internal and External GIC CPU1
    interfaces.
    
    Signed-off-by: Evgeny Voevodin <e.voevodin at samsung.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/exynos4210.c b/hw/exynos4210.c
index f904370..afc4bdc 100644
--- a/hw/exynos4210.c
+++ b/hw/exynos4210.c
@@ -25,6 +25,7 @@
 #include "sysemu.h"
 #include "sysbus.h"
 #include "arm-misc.h"
+#include "loader.h"
 #include "exynos4210.h"
 
 #define EXYNOS4210_CHIPID_ADDR         0x10000000
@@ -64,6 +65,35 @@
 static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
                                     0x09, 0x00, 0x00, 0x00 };
 
+void exynos4210_write_secondary(CPUARMState *env,
+        const struct arm_boot_info *info)
+{
+    int n;
+    uint32_t smpboot[] = {
+        0xe59f3024, /* ldr r3, External gic_cpu_if */
+        0xe59f2024, /* ldr r2, Internal gic_cpu_if */
+        0xe59f0024, /* ldr r0, startaddr */
+        0xe3a01001, /* mov r1, #1 */
+        0xe5821000, /* str r1, [r2] */
+        0xe5831000, /* str r1, [r3] */
+        0xe320f003, /* wfi */
+        0xe5901000, /* ldr     r1, [r0] */
+        0xe1110001, /* tst     r1, r1 */
+        0x0afffffb, /* beq     <wfi> */
+        0xe12fff11, /* bx      r1 */
+        EXYNOS4210_EXT_GIC_CPU_BASE_ADDR,
+        0,          /* gic_cpu_if: base address of Internal GIC CPU interface */
+        0           /* bootreg: Boot register address is held here */
+    };
+    smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
+    smpboot[ARRAY_SIZE(smpboot) - 2] = info->gic_cpu_if_addr;
+    for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
+        smpboot[n] = tswap32(smpboot[n]);
+    }
+    rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
+                       info->smp_loader_start);
+}
+
 Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
         unsigned long ram_size)
 {
diff --git a/hw/exynos4210.h b/hw/exynos4210.h
index c112e03..f7c7027 100644
--- a/hw/exynos4210.h
+++ b/hw/exynos4210.h
@@ -97,6 +97,9 @@ typedef struct Exynos4210State {
     MemoryRegion bootreg_mem;
 } Exynos4210State;
 
+void exynos4210_write_secondary(CPUARMState *env,
+        const struct arm_boot_info *info);
+
 Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
         unsigned long ram_size);
 
diff --git a/hw/exynos4210_gic.c b/hw/exynos4210_gic.c
index ec13140..3ba9063 100644
--- a/hw/exynos4210_gic.c
+++ b/hw/exynos4210_gic.c
@@ -321,8 +321,6 @@ static int exynos4210_gic_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, &s->cpu_container);
     sysbus_init_mmio(dev, &s->dist_container);
 
-    gic_cpu_write(&s->gic, 1, 0, 1);
-
     return 0;
 }
 
diff --git a/hw/exynos4_boards.c b/hw/exynos4_boards.c
index 553a02b..ea32c51 100644
--- a/hw/exynos4_boards.c
+++ b/hw/exynos4_boards.c
@@ -70,6 +70,7 @@ static struct arm_boot_info exynos4_board_binfo = {
     .loader_start     = EXYNOS4210_BASE_BOOT_ADDR,
     .smp_loader_start = EXYNOS4210_SMP_BOOT_ADDR,
     .nb_cpus          = EXYNOS4210_NCPUS,
+    .write_secondary_boot = exynos4210_write_secondary,
 };
 
 static QEMUMachine exynos4_machines[EXYNOS4_NUM_OF_BOARDS];
commit b85f62d7811c80646065f8f96c2248ea86cfd911
Author: Daniel P. Berrange <berrange at redhat.com>
Date:   Fri Apr 13 11:39:06 2012 +0000

    Fix bit test in Exynos4210 UART emulation to use & instead of &&
    
    * hw/exynos4210_uart.c: s/&&/&/
    
    Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/exynos4210_uart.c b/hw/exynos4210_uart.c
index 73a9c18..ccc4780 100644
--- a/hw/exynos4210_uart.c
+++ b/hw/exynos4210_uart.c
@@ -246,7 +246,7 @@ static uint32_t exynos4210_uart_Tx_FIFO_trigger_level(Exynos4210UartState *s)
     uint32_t level = 0;
     uint32_t reg;
 
-    reg = (s->reg[I_(UFCON)] && UFCON_Tx_FIFO_TRIGGER_LEVEL) >>
+    reg = (s->reg[I_(UFCON)] & UFCON_Tx_FIFO_TRIGGER_LEVEL) >>
             UFCON_Tx_FIFO_TRIGGER_LEVEL_SHIFT;
 
     switch (s->channel) {
@@ -275,9 +275,9 @@ static void exynos4210_uart_update_irq(Exynos4210UartState *s)
      * The Tx interrupt is always requested if the number of data in the
      * transmit FIFO is smaller than the trigger level.
      */
-    if (s->reg[I_(UFCON)] && UFCON_FIFO_ENABLE) {
+    if (s->reg[I_(UFCON)] & UFCON_FIFO_ENABLE) {
 
-        uint32_t count = (s->reg[I_(UFSTAT)] && UFSTAT_Tx_FIFO_COUNT) >>
+        uint32_t count = (s->reg[I_(UFSTAT)] & UFSTAT_Tx_FIFO_COUNT) >>
                 UFSTAT_Tx_FIFO_COUNT_SHIFT;
 
         if (count <= exynos4210_uart_Tx_FIFO_trigger_level(s)) {
commit 6ccea1e4d9a39d0bcf5be5a7b49270c2132b9dcb
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Apr 12 19:09:52 2012 +0100

    configure: Insist on a Python 2, not Python 3
    
    Our Python scripts require Python 2 and will fail on Python 3, eg:
      File "/home/petmay01/linaro/qemu-from-laptop/qemu/scripts/qapi-commands.py", line 378
          except getopt.GetoptError, err:
                                   ^
      SyntaxError: invalid syntax
    
    Add a check to configure that Python is not a Python 3, so we can
    fail with a comprehensible error rather than an obscure one.
    
    Reported-by: Boris Matti <swiftos at lavabit.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/configure b/configure
index b392c6f..1d94acd 100755
--- a/configure
+++ b/configure
@@ -1242,6 +1242,14 @@ if ! has $python; then
   exit 1
 fi
 
+# Note that if the Python conditional here evaluates True we will exit
+# with status 1 which is a shell 'false' value.
+if ! "$python" -c 'import sys; sys.exit(sys.version_info[0] >= 3)'; then
+  echo "Python 2 required but '$python' is version 3 or better."
+  echo "Use --python=/path/to/python to specify a Python 2."
+  exit 1
+fi
+
 if test -z "$target_list" ; then
     target_list="$default_target_list"
 else
commit d6ef40bf1881ddc82c8d64e72d412090efe1190e
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Apr 12 12:43:41 2012 +0100

    bsd-user: fix compile failure
    
    bsd-user doesn't actually support reserving a memory area for the
    guest address space, but we need to at least define the reserved_va
    global so that cpu-all.h's RESERVED_VA macro will work correctly.
    
    This fixes a compilation error introduced in commit 39879bb
    which added a use of RESERVED_VA to h2g_valid().
    
    Reported-by: Brad Smith <brad at comstyle.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/bsd-user/main.c b/bsd-user/main.c
index 48cb715..0689e38 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -41,6 +41,7 @@ int singlestep;
 unsigned long mmap_min_addr;
 unsigned long guest_base;
 int have_guest_base;
+unsigned long reserved_va;
 #endif
 
 static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
commit f349c12c0434e29c79ecde89029320c4002f7253
Author: Eric B Munson <emunson at mgebm.net>
Date:   Sat Apr 7 06:17:47 2012 +0530

    kvmclock: guest stop notification
    
    Often when a guest is stopped from the qemu console, it will report spurious
    soft lockup warnings on resume.  There are kernel patches being discussed that
    will give the host the ability to tell the guest that it is being stopped and
    should ignore the soft lockup warning that generates.  This patch uses the qemu
    Notifier system to tell the guest it is about to be stopped.
    
    Signed-off-by: Eric B Munson <emunson at mgebm.net>
    Signed-off-by: Raghavendra K T <raghavendra.kt at linux.vnet.ibm.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/hw/kvm/clock.c b/hw/kvm/clock.c
index 446bd62..824b978 100644
--- a/hw/kvm/clock.c
+++ b/hw/kvm/clock.c
@@ -65,9 +65,25 @@ static void kvmclock_vm_state_change(void *opaque, int running,
                                      RunState state)
 {
     KVMClockState *s = opaque;
+    CPUArchState *penv = first_cpu;
+    int cap_clock_ctrl = kvm_check_extension(kvm_state, KVM_CAP_KVMCLOCK_CTRL);
+    int ret;
 
     if (running) {
         s->clock_valid = false;
+
+        if (!cap_clock_ctrl) {
+            return;
+        }
+        for (penv = first_cpu; penv != NULL; penv = penv->next_cpu) {
+            ret = kvm_vcpu_ioctl(penv, KVM_KVMCLOCK_CTRL, 0);
+            if (ret) {
+                if (ret != -EINVAL) {
+                    fprintf(stderr, "%s: %s\n", __func__, strerror(-ret));
+                }
+                return;
+            }
+        }
     }
 }
 
commit 9ab2195dcb2e7d202287b6db7cfaa4f9e01941f6
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Thu Apr 12 00:43:27 2012 -0300

    kvm: update linux headers
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h
index b921c3f..1bea4d8 100644
--- a/linux-headers/asm-powerpc/kvm.h
+++ b/linux-headers/asm-powerpc/kvm.h
@@ -277,6 +277,7 @@ struct kvm_sync_regs {
 #define KVM_CPU_E500V2		2
 #define KVM_CPU_3S_32		3
 #define KVM_CPU_3S_64		4
+#define KVM_CPU_E500MC		5
 
 /* for KVM_CAP_SPAPR_TCE */
 struct kvm_create_spapr_tce {
diff --git a/linux-headers/asm-s390/kvm.h b/linux-headers/asm-s390/kvm.h
index 9acbde4..9607667 100644
--- a/linux-headers/asm-s390/kvm.h
+++ b/linux-headers/asm-s390/kvm.h
@@ -44,10 +44,12 @@ struct kvm_guest_debug_arch {
 #define KVM_SYNC_PREFIX (1UL << 0)
 #define KVM_SYNC_GPRS   (1UL << 1)
 #define KVM_SYNC_ACRS   (1UL << 2)
+#define KVM_SYNC_CRS    (1UL << 3)
 /* definition of registers in kvm_run */
 struct kvm_sync_regs {
 	__u64 prefix;	/* prefix register */
 	__u64 gprs[16];	/* general purpose registers */
 	__u32 acrs[16];	/* access registers */
+	__u64 crs[16];	/* control registers */
 };
 #endif
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index f6b5343..ee7bd9c 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -588,6 +588,8 @@ struct kvm_ppc_pvinfo {
 #define KVM_CAP_TSC_DEADLINE_TIMER 72
 #define KVM_CAP_S390_UCONTROL 73
 #define KVM_CAP_SYNC_REGS 74
+#define KVM_CAP_PCI_2_3 75
+#define KVM_CAP_KVMCLOCK_CTRL 76
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -784,6 +786,9 @@ struct kvm_s390_ucas_mapping {
 /* Available with KVM_CAP_TSC_CONTROL */
 #define KVM_SET_TSC_KHZ           _IO(KVMIO,  0xa2)
 #define KVM_GET_TSC_KHZ           _IO(KVMIO,  0xa3)
+/* Available with KVM_CAP_PCI_2_3 */
+#define KVM_ASSIGN_SET_INTX_MASK  _IOW(KVMIO,  0xa4, \
+				       struct kvm_assigned_pci_dev)
 
 /*
  * ioctls for vcpu fds
@@ -855,8 +860,12 @@ struct kvm_s390_ucas_mapping {
 /* Available with KVM_CAP_ONE_REG */
 #define KVM_GET_ONE_REG		  _IOW(KVMIO,  0xab, struct kvm_one_reg)
 #define KVM_SET_ONE_REG		  _IOW(KVMIO,  0xac, struct kvm_one_reg)
+/* VM is being stopped by host */
+#define KVM_KVMCLOCK_CTRL	  _IO(KVMIO,   0xad)
 
 #define KVM_DEV_ASSIGN_ENABLE_IOMMU	(1 << 0)
+#define KVM_DEV_ASSIGN_PCI_2_3		(1 << 1)
+#define KVM_DEV_ASSIGN_MASK_INTX	(1 << 2)
 
 struct kvm_assigned_pci_dev {
 	__u32 assigned_dev_id;
commit bc8c6788b60cbbe56700568bcb645e139ab29b7d
Author: Jason Baron <jbaron at redhat.com>
Date:   Wed Mar 28 14:18:05 2012 -0400

    kvm: set gsi_bits and max_gsi correctly
    
    The current kvm_init_irq_routing() doesn't set up the used_gsi_bitmap
    correctly, and as a consequence pins max_gsi to 32 when it really
    should be 1024. I ran into this limitation while testing pci
    passthrough, where I consistently got an -ENOSPC return from
    kvm_get_irq_route_gsi() called from assigned_dev_update_msix_mmio().
    
    Signed-off-by: Jason Baron <jbaron at redhat.com>
    Acked-by: Alex Williamson <alex.williamson at redhat.com>
    Acked-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 5ff954a..b8e9dc6 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -871,7 +871,7 @@ static void kvm_init_irq_routing(KVMState *s)
         unsigned int gsi_bits, i;
 
         /* Round up so we can search ints using ffs */
-        gsi_bits = (gsi_count + 31) / 32;
+        gsi_bits = ALIGN(gsi_count, 32);
         s->used_gsi_bitmap = g_malloc0(gsi_bits / 8);
         s->max_gsi = gsi_bits;
 
commit c73b00973b13a4a1e823ce935bcfe264c758b40b
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Thu Mar 22 00:00:48 2012 +0100

    kvm: Drop unused kvm_pit_in_kernel
    
    This is now implied by kvm_irqchip_in_kernel.
    
    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 f1cb69f..5ff954a 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -75,7 +75,6 @@ struct KVMState
 #ifdef KVM_CAP_SET_GUEST_DEBUG
     struct kvm_sw_breakpoint_head kvm_sw_breakpoints;
 #endif
-    int pit_in_kernel;
     int pit_state2;
     int xsave, xcrs;
     int many_ioeventfds;
@@ -198,11 +197,6 @@ static void kvm_reset_vcpu(void *opaque)
     kvm_arch_reset_vcpu(env);
 }
 
-int kvm_pit_in_kernel(void)
-{
-    return kvm_state->pit_in_kernel;
-}
-
 int kvm_init_vcpu(CPUArchState *env)
 {
     KVMState *s = kvm_state;
diff --git a/kvm-stub.c b/kvm-stub.c
index 0d426db..47c573d 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -16,12 +16,6 @@
 #include "gdbstub.h"
 #include "kvm.h"
 
-int kvm_pit_in_kernel(void)
-{
-    return 0;
-}
-
-
 int kvm_init_vcpu(CPUArchState *env)
 {
     return -ENOSYS;
diff --git a/kvm.h b/kvm.h
index 9bdbdb0..4ccae8c 100644
--- a/kvm.h
+++ b/kvm.h
@@ -83,8 +83,6 @@ int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap);
 int kvm_set_signal_mask(CPUArchState *env, const sigset_t *sigset);
 #endif
 
-int kvm_pit_in_kernel(void);
-
 int kvm_on_sigbus_vcpu(CPUArchState *env, int code, void *addr);
 int kvm_on_sigbus(int code, void *addr);
 
commit 4b8f1c88e9de2ded754b12a967a93d395bed1245
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Tue Mar 20 14:31:38 2012 +0200

    kvm: allow arbitrarily sized mmio ioeventfd
    
    We use a 2 byte ioeventfd for virtio memory,
    add support for this.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Reviewed-by: Amos Kong <akong at redhat.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/ivshmem.c b/hw/ivshmem.c
index b80aa8f..df4f50a 100644
--- a/hw/ivshmem.c
+++ b/hw/ivshmem.c
@@ -354,8 +354,8 @@ static void close_guest_eventfds(IVShmemState *s, int posn)
     guest_curr_max = s->peers[posn].nb_eventfds;
 
     for (i = 0; i < guest_curr_max; i++) {
-        kvm_set_ioeventfd_mmio_long(s->peers[posn].eventfds[i],
-                    s->mmio_addr + DOORBELL, (posn << 16) | i, 0);
+        kvm_set_ioeventfd_mmio(s->peers[posn].eventfds[i],
+                    s->mmio_addr + DOORBELL, (posn << 16) | i, 0, 4);
         close(s->peers[posn].eventfds[i]);
     }
 
@@ -500,8 +500,8 @@ static void ivshmem_read(void *opaque, const uint8_t * buf, int flags)
     }
 
     if (ivshmem_has_feature(s, IVSHMEM_IOEVENTFD)) {
-        if (kvm_set_ioeventfd_mmio_long(incoming_fd, s->mmio_addr + DOORBELL,
-                        (incoming_posn << 16) | guest_max_eventfd, 1) < 0) {
+        if (kvm_set_ioeventfd_mmio(incoming_fd, s->mmio_addr + DOORBELL,
+                        (incoming_posn << 16) | guest_max_eventfd, 1, 4) < 0) {
             fprintf(stderr, "ivshmem: ioeventfd not available\n");
         }
     }
diff --git a/kvm-all.c b/kvm-all.c
index ba2cee1..f1cb69f 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -747,10 +747,10 @@ static void kvm_mem_ioeventfd_add(MemoryRegionSection *section,
 {
     int r;
 
-    assert(match_data && section->size == 4);
+    assert(match_data && section->size <= 8);
 
-    r = kvm_set_ioeventfd_mmio_long(fd, section->offset_within_address_space,
-                                    data, true);
+    r = kvm_set_ioeventfd_mmio(fd, section->offset_within_address_space,
+                               data, true, section->size);
     if (r < 0) {
         abort();
     }
@@ -761,8 +761,8 @@ static void kvm_mem_ioeventfd_del(MemoryRegionSection *section,
 {
     int r;
 
-    r = kvm_set_ioeventfd_mmio_long(fd, section->offset_within_address_space,
-                                    data, false);
+    r = kvm_set_ioeventfd_mmio(fd, section->offset_within_address_space,
+                               data, false, section->size);
     if (r < 0) {
         abort();
     }
@@ -1642,14 +1642,15 @@ int kvm_set_signal_mask(CPUArchState *env, const sigset_t *sigset)
     return r;
 }
 
-int kvm_set_ioeventfd_mmio_long(int fd, uint32_t addr, uint32_t val, bool assign)
+int kvm_set_ioeventfd_mmio(int fd, uint32_t addr, uint32_t val, bool assign,
+                           uint32_t size)
 {
     int ret;
     struct kvm_ioeventfd iofd;
 
     iofd.datamatch = val;
     iofd.addr = addr;
-    iofd.len = 4;
+    iofd.len = size;
     iofd.flags = KVM_IOEVENTFD_FLAG_DATAMATCH;
     iofd.fd = fd;
 
diff --git a/kvm-stub.c b/kvm-stub.c
index 69a1228..0d426db 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -120,7 +120,7 @@ int kvm_set_ioeventfd_pio_word(int fd, uint16_t addr, uint16_t val, bool assign)
     return -ENOSYS;
 }
 
-int kvm_set_ioeventfd_mmio_long(int fd, uint32_t adr, uint32_t val, bool assign)
+int kvm_set_ioeventfd_mmio(int fd, uint32_t adr, uint32_t val, bool assign, uint32_t len)
 {
     return -ENOSYS;
 }
diff --git a/kvm.h b/kvm.h
index 330f17b..9bdbdb0 100644
--- a/kvm.h
+++ b/kvm.h
@@ -210,7 +210,8 @@ int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr,
 #endif
 
 #endif
-int kvm_set_ioeventfd_mmio_long(int fd, uint32_t adr, uint32_t val, bool assign);
+int kvm_set_ioeventfd_mmio(int fd, uint32_t adr, uint32_t val, bool assign,
+                           uint32_t size);
 
 int kvm_set_ioeventfd_pio_word(int fd, uint16_t adr, uint16_t val, bool assign);
 #endif
commit 56b9ead234439317629054fa370c547c652ab09a
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Mar 21 13:36:22 2012 +0100

    kvm: Drop redundant kvm_enabled from cpu_thread_is_idle
    
    This is now implied by kvm_irqchip_in_kernel.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/cpus.c b/cpus.c
index eb22bd5..b182b3d 100644
--- a/cpus.c
+++ b/cpus.c
@@ -441,8 +441,7 @@ static bool cpu_thread_is_idle(CPUArchState *env)
     if (env->stopped || !runstate_is_running()) {
         return true;
     }
-    if (!env->halted || qemu_cpu_has_work(env) ||
-        (kvm_enabled() && kvm_irqchip_in_kernel())) {
+    if (!env->halted || qemu_cpu_has_work(env) || kvm_irqchip_in_kernel()) {
         return false;
     }
     return true;
commit b3c09bde4842f1b157bc4431135aad4f2031e312
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Fri Mar 9 14:13:40 2012 +0000

    kvm: add flightrecorder script
    
    The kvm kernel module includes a number of trace events which can be
    useful when debugging system behavior.  Even on production systems these
    trace events can be used to observe guest behavior and identify the
    source of problems.
    
    The kvm_flightrecorder script is a command-line wrapper for the
    /sys/kernel/debug/tracing interface.  Kernel symbols do not need to be
    installed.
    
    This script captures a fixed-size buffer of KVM trace events.  Recent
    events overwrite the oldest events when the buffer size is exceeded and
    it is possible to leave KVM tracing enabled for any period of time with
    just a fixed-size buffer.  If the buffer is large enough this script is
    a useful tool for collecting detailed information after an issue occurs
    with a guest.  Hence the name "flight recorder".
    
    The script can also be used in 'tail' mode to simply view KVM trace
    events as they occur.  This is handy for development and to ensure that
    the guest is indeed running.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/scripts/kvm/kvm_flightrecorder b/scripts/kvm/kvm_flightrecorder
new file mode 100755
index 0000000..7fb1c2d
--- /dev/null
+++ b/scripts/kvm/kvm_flightrecorder
@@ -0,0 +1,126 @@
+#!/usr/bin/env python
+#
+# KVM Flight Recorder - ring buffer tracing script
+#
+# Copyright (C) 2012 IBM Corp
+#
+# Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
+#
+# This script provides a command-line interface to kvm ftrace and is designed
+# to be used as a flight recorder that is always running.  To start in-memory
+# recording:
+#
+# sudo kvm_flightrecorder start 8192  # 8 MB per-cpu ring buffers
+#
+# The per-cpu ring buffer size can be given in KB as an optional argument to
+# the 'start' subcommand.
+#
+# To stop the flight recorder:
+#
+# sudo kvm_flightrecorder stop
+#
+# To dump the contents of the flight recorder (this can be done when the
+# recorder is stopped or while it is running):
+#
+# sudo kvm_flightrecorder dump >/path/to/dump.txt
+#
+# To observe the trace while it is running, use the 'tail' subcommand:
+#
+# sudo kvm_flightrecorder tail
+#
+# Note that the flight recorder may impact overall system performance by
+# consuming CPU cycles.  No disk I/O is performed since the ring buffer holds a
+# fixed-size in-memory trace.
+
+import sys
+import os
+
+tracing_dir = '/sys/kernel/debug/tracing'
+
+def trace_path(*args):
+    return os.path.join(tracing_dir, *args)
+
+def write_file(path, data):
+    open(path, 'wb').write(data)
+
+def enable_event(subsystem, event, enable):
+    write_file(trace_path('events', subsystem, event, 'enable'), '1' if enable else '0')
+
+def enable_subsystem(subsystem, enable):
+    write_file(trace_path('events', subsystem, 'enable'), '1' if enable else '0')
+
+def start_tracing():
+    enable_subsystem('kvm', True)
+    write_file(trace_path('tracing_on'), '1')
+
+def stop_tracing():
+    write_file(trace_path('tracing_on'), '0')
+    enable_subsystem('kvm', False)
+    write_file(trace_path('events', 'enable'), '0')
+    write_file(trace_path('current_tracer'), 'nop')
+
+def dump_trace():
+    tracefile = open(trace_path('trace'), 'r')
+    try:
+        lines = True
+        while lines:
+            lines = tracefile.readlines(64 * 1024)
+            sys.stdout.writelines(lines)
+    except KeyboardInterrupt:
+        pass
+
+def tail_trace():
+    try:
+        for line in open(trace_path('trace_pipe'), 'r'):
+            sys.stdout.write(line)
+    except KeyboardInterrupt:
+        pass
+
+def usage():
+    print 'Usage: %s start [buffer_size_kb] | stop | dump | tail' % sys.argv[0]
+    print 'Control the KVM flight recorder tracing.'
+    sys.exit(0)
+
+def main():
+    if len(sys.argv) < 2:
+        usage()
+
+    cmd = sys.argv[1]
+    if cmd == '--version':
+        print 'kvm_flightrecorder version 1.0'
+        sys.exit(0)
+
+    if not os.path.isdir(tracing_dir):
+        print 'Unable to tracing debugfs directory, try:'
+        print 'mount -t debugfs none /sys/kernel/debug'
+        sys.exit(1)
+    if not os.access(tracing_dir, os.W_OK):
+        print 'Unable to write to tracing debugfs directory, please run as root'
+        sys.exit(1)
+
+    if cmd == 'start':
+        stop_tracing() # clean up first
+
+        if len(sys.argv) == 3:
+            try:
+                buffer_size_kb = int(sys.argv[2])
+            except ValueError:
+                print 'Invalid per-cpu trace buffer size in KB'
+                sys.exit(1)
+            write_file(trace_path('buffer_size_kb'), str(buffer_size_kb))
+            print 'Per-CPU ring buffer size set to %d KB' % buffer_size_kb
+
+        start_tracing()
+        print 'KVM flight recorder enabled'
+    elif cmd == 'stop':
+        stop_tracing()
+        print 'KVM flight recorder disabled'
+    elif cmd == 'dump':
+        dump_trace()
+    elif cmd == 'tail':
+        tail_trace()
+    else:
+        usage()
+
+if __name__ == '__main__':
+    sys.exit(main())
commit fd65f595fe14dafeee1cd34df0dbe288ed6a5f06
Author: Wanpeng Li <liwp at linux.vnet.ibm.com>
Date:   Wed Apr 11 09:02:21 2012 +0800

    ps2: avoid repeated header file includes
    
    Signed-off-by: Wanpeng Li <liwp at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/ps2.h b/hw/ps2.h
index 32a4231..7c45ce7 100644
--- a/hw/ps2.h
+++ b/hw/ps2.h
@@ -1,3 +1,30 @@
+/*
+ * QEMU PS/2 keyboard/mouse emulation
+ *
+ * Copyright (C) 2003 Fabrice Bellard
+ *
+ * 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 HW_PS2_H
+#define HW_PS2_H
+
 /* ps2.c */
 void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg);
 void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg);
@@ -7,3 +34,5 @@ uint32_t ps2_read_data(void *);
 void ps2_queue(void *, int b);
 void ps2_keyboard_set_translation(void *opaque, int mode);
 void ps2_mouse_fake_event(void *opaque);
+
+#endif /* !HW_PS2_H */
commit 952ef67cc06a636fe11344e3a11137d146222bc4
Author: Stefan Weil <sw at weilnetz.de>
Date:   Tue Mar 27 19:15:27 2012 +0200

    make: Always set LC_ALL=C for makeinfo
    
    Otherwise the generated file qemu-doc.html will contain "Anhang"
    instead of "Appendix" with a German locale (de_DE.UTF-8).
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/Makefile b/Makefile
index a78f53d..e0fe680 100644
--- a/Makefile
+++ b/Makefile
@@ -328,7 +328,7 @@ TEXIFLAG=$(if $(V),,--quiet)
 	$(call quiet-command,texi2dvi $(TEXIFLAG) -I . $<,"  GEN   $@")
 
 %.html: %.texi
-	$(call quiet-command,$(MAKEINFO) $(MAKEINFOFLAGS) --html $< -o $@, \
+	$(call quiet-command,LC_ALL=C $(MAKEINFO) $(MAKEINFOFLAGS) --html $< -o $@, \
 	"  GEN   $@")
 
 %.info: %.texi
commit e172fe1177ffa14f6d13cc539dd80d2a2705aa73
Author: Stefan Weil <sw at weilnetz.de>
Date:   Fri Apr 6 21:33:20 2012 +0200

    configure: Fix wrong preprocessor statement
    
    #abort is not a preprocessor statement. It aborts, but the preprocessor
    statement #error is more common to abort a compilation.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/configure b/configure
index 5aaafa1..b392c6f 100755
--- a/configure
+++ b/configure
@@ -2624,7 +2624,7 @@ int main(void) {
 #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
 return fdatasync(0);
 #else
-#abort Not supported
+#error Not supported
 #endif
 }
 EOF
commit 8fb03151651cc61f68f8032374c9c08dc129b9d9
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Apr 4 17:03:15 2012 +0100

    configure: Remove useless uses of ARCH_CFLAGS
    
    Remove some useless uses of ARCH_CFLAGS -- this variable was never set
    so will always be empty. The uses were accidental: in commit 0c439cbf8
    Juan Quintela removed ARCH_CFLAGS in favour of CFLAGS (which in turn
    became QEMU_CFLAGS). However in commit be17dc90 a use of it was
    reintroduced (apparently accidentally) by Michael S. Tsirkin, and then
    I subsequently cut-n-pasted that into a number of other configure
    feature tests.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/configure b/configure
index e05f34b..5aaafa1 100755
--- a/configure
+++ b/configure
@@ -2369,7 +2369,7 @@ int main(void)
     return 0;
 }
 EOF
-if compile_prog "$ARCH_CFLAGS" "" ; then
+if compile_prog "" "" ; then
   fallocate=yes
 fi
 
@@ -2384,7 +2384,7 @@ int main(void)
     return 0;
 }
 EOF
-if compile_prog "$ARCH_CFLAGS" "" ; then
+if compile_prog "" "" ; then
   sync_file_range=yes
 fi
 
@@ -2401,7 +2401,7 @@ int main(void)
     return 0;
 }
 EOF
-if compile_prog "$ARCH_CFLAGS" "" ; then
+if compile_prog "" "" ; then
   fiemap=yes
 fi
 
@@ -2431,7 +2431,7 @@ int main(void)
     return 0;
 }
 EOF
-if compile_prog "$ARCH_CFLAGS" "" ; then
+if compile_prog "" "" ; then
   epoll=yes
 fi
 
@@ -2454,7 +2454,7 @@ int main(void)
     return epoll_create1 == epoll_create1;
 }
 EOF
-if compile_prog "$ARCH_CFLAGS" "" ; then
+if compile_prog "" "" ; then
   epoll_create1=yes
 fi
 
@@ -2468,7 +2468,7 @@ int main(void)
     return 0;
 }
 EOF
-if compile_prog "$ARCH_CFLAGS" "" ; then
+if compile_prog "" "" ; then
   epoll_pwait=yes
 fi
 
commit dadc1064c348545695b8a14d9dc72ccaa2983be7
Author: Peter A. G. Crosthwaite <peter.crosthwaite at petalogix.com>
Date:   Thu Apr 12 14:30:30 2012 +1000

    target-microblaze: added PetaLogix copyright
    
    Microblaze cpu development has been driven and funded by PetaLogix. Added (c)
    PetaLogix line accordingly.
    
    Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite at petalogix.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-microblaze/helper.c b/target-microblaze/helper.c
index 6e0e411..2412a58 100644
--- a/target-microblaze/helper.c
+++ b/target-microblaze/helper.c
@@ -2,6 +2,7 @@
  *  MicroBlaze helper routines.
  *
  *  Copyright (c) 2009 Edgar E. Iglesias <edgar.iglesias at gmail.com>
+ *  Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
diff --git a/target-microblaze/mmu.c b/target-microblaze/mmu.c
index 43092e5..53ad263 100644
--- a/target-microblaze/mmu.c
+++ b/target-microblaze/mmu.c
@@ -2,6 +2,7 @@
  *  Microblaze MMU emulation for qemu.
  *
  *  Copyright (c) 2009 Edgar E. Iglesias
+ *  Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index 76cc0e0..a83da8d 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -2,6 +2,7 @@
  *  Microblaze helper routines.
  *
  *  Copyright (c) 2009 Edgar E. Iglesias <edgar.iglesias at gmail.com>.
+ *  Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 64cbfb8..b602820 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -2,6 +2,7 @@
  *  Xilinx MicroBlaze emulation for qemu: main translation routines.
  *
  *  Copyright (c) 2009 Edgar E. Iglesias.
+ *  Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
commit 3eab1690851fa68698612d9dd9d5231759f549c2
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Apr 11 01:37:45 2012 +0200

    target-lm32: QOM'ify CPU reset
    
    Move code from cpu_state_reset() into QOM lm32_cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Michael Walle <michael at walle.cc>

diff --git a/target-lm32/cpu.c b/target-lm32/cpu.c
index 70251d0..48a5fe3 100644
--- a/target-lm32/cpu.c
+++ b/target-lm32/cpu.c
@@ -29,9 +29,17 @@ static void lm32_cpu_reset(CPUState *s)
     LM32CPUClass *lcc = LM32_CPU_GET_CLASS(cpu);
     CPULM32State *env = &cpu->env;
 
+    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+        log_cpu_state(env, 0);
+    }
+
     lcc->parent_reset(s);
 
-    cpu_state_reset(env);
+    tlb_flush(env, 1);
+
+    /* reset cpu state */
+    memset(env, 0, offsetof(CPULM32State, breakpoints));
 }
 
 static void lm32_cpu_initfn(Object *obj)
diff --git a/target-lm32/helper.c b/target-lm32/helper.c
index 9de777f..d0bc193 100644
--- a/target-lm32/helper.c
+++ b/target-lm32/helper.c
@@ -236,14 +236,6 @@ void cpu_lm32_set_phys_msb_ignore(CPULM32State *env, int value)
 
 void cpu_state_reset(CPULM32State *env)
 {
-    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
-        log_cpu_state(env, 0);
-    }
-
-    tlb_flush(env, 1);
-
-    /* reset cpu state */
-    memset(env, 0, offsetof(CPULM32State, breakpoints));
+    cpu_reset(ENV_GET_CPU(env));
 }
 
commit 8d7d505adda444220c93ee5ad09df4176b366bd7
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Apr 11 01:33:33 2012 +0200

    target-lm32: QOM'ify CPU init
    
    Move code from cpu_lm32_init() to an initfn; call cpu_reset()
    instead of cpu_state_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Michael Walle <michael at walle.cc>

diff --git a/target-lm32/cpu.c b/target-lm32/cpu.c
index 4ce7e3b..70251d0 100644
--- a/target-lm32/cpu.c
+++ b/target-lm32/cpu.c
@@ -34,6 +34,18 @@ static void lm32_cpu_reset(CPUState *s)
     cpu_state_reset(env);
 }
 
+static void lm32_cpu_initfn(Object *obj)
+{
+    LM32CPU *cpu = LM32_CPU(obj);
+    CPULM32State *env = &cpu->env;
+
+    cpu_exec_init(env);
+
+    env->flags = 0;
+
+    cpu_reset(CPU(cpu));
+}
+
 static void lm32_cpu_class_init(ObjectClass *oc, void *data)
 {
     LM32CPUClass *lcc = LM32_CPU_CLASS(oc);
@@ -47,6 +59,7 @@ static const TypeInfo lm32_cpu_type_info = {
     .name = TYPE_LM32_CPU,
     .parent = TYPE_CPU,
     .instance_size = sizeof(LM32CPU),
+    .instance_init = lm32_cpu_initfn,
     .abstract = false,
     .class_size = sizeof(LM32CPUClass),
     .class_init = lm32_cpu_class_init,
diff --git a/target-lm32/helper.c b/target-lm32/helper.c
index 3cf86d7..9de777f 100644
--- a/target-lm32/helper.c
+++ b/target-lm32/helper.c
@@ -211,10 +211,7 @@ CPULM32State *cpu_lm32_init(const char *cpu_model)
     env->num_bps = def->num_breakpoints;
     env->num_wps = def->num_watchpoints;
     env->cfg = cfg_by_def(def);
-    env->flags = 0;
 
-    cpu_exec_init(env);
-    cpu_state_reset(env);
     qemu_init_vcpu(env);
 
     if (tcg_enabled() && !tcg_initialized) {
commit fc0ced2fbd8d40672fcdd2f655bbdcd3e278f3ab
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Apr 11 01:22:08 2012 +0200

    target-lm32: QOM'ify CPU
    
    Embed CPULM32State as first member of QOM LM32CPU.
    Let CPUClass::reset() call cpu_state_reset() for now.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Michael Walle <michael at walle.cc>

diff --git a/Makefile.target b/Makefile.target
index 1110796..e88b896 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -93,6 +93,7 @@ libobj-$(TARGET_SPARC64) += vis_helper.o
 libobj-$(CONFIG_NEED_MMU) += mmu.o
 libobj-$(TARGET_ARM) += neon_helper.o iwmmxt_helper.o
 libobj-$(TARGET_ARM) += cpu.o
+libobj-$(TARGET_LM32) += cpu.o
 libobj-$(TARGET_S390X) += cpu.o
 ifeq ($(TARGET_BASE_ARCH), sparc)
 libobj-y += fop_helper.o cc_helper.o win_helper.o mmu_helper.o ldst_helper.o
diff --git a/target-lm32/cpu-qom.h b/target-lm32/cpu-qom.h
new file mode 100644
index 0000000..4ae2edd
--- /dev/null
+++ b/target-lm32/cpu-qom.h
@@ -0,0 +1,71 @@
+/*
+ * QEMU LatticeMico32 CPU
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * 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.1 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/lgpl-2.1.html>
+ */
+#ifndef QEMU_LM32_CPU_QOM_H
+#define QEMU_LM32_CPU_QOM_H
+
+#include "qemu/cpu.h"
+#include "cpu.h"
+
+#define TYPE_LM32_CPU "lm32-cpu"
+
+#define LM32_CPU_CLASS(klass) \
+    OBJECT_CLASS_CHECK(LM32CPUClass, (klass), TYPE_LM32_CPU)
+#define LM32_CPU(obj) \
+    OBJECT_CHECK(LM32CPU, (obj), TYPE_LM32_CPU)
+#define LM32_CPU_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(LM32CPUClass, (obj), TYPE_LM32_CPU)
+
+/**
+ * LM32CPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * A LatticeMico32 CPU model.
+ */
+typedef struct LM32CPUClass {
+    /*< private >*/
+    CPUClass parent_class;
+    /*< public >*/
+
+    void (*parent_reset)(CPUState *cpu);
+} LM32CPUClass;
+
+/**
+ * LM32CPU:
+ * @env: #CPULM32State
+ *
+ * A LatticeMico32 CPU.
+ */
+typedef struct LM32CPU {
+    /*< private >*/
+    CPUState parent_obj;
+    /*< public >*/
+
+    CPULM32State env;
+} LM32CPU;
+
+static inline LM32CPU *lm32_env_get_cpu(CPULM32State *env)
+{
+    return LM32_CPU(container_of(env, LM32CPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(lm32_env_get_cpu(e))
+
+
+#endif
diff --git a/target-lm32/cpu.c b/target-lm32/cpu.c
new file mode 100644
index 0000000..4ce7e3b
--- /dev/null
+++ b/target-lm32/cpu.c
@@ -0,0 +1,60 @@
+/*
+ * QEMU LatticeMico32 CPU
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * 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.1 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/lgpl-2.1.html>
+ */
+
+#include "cpu-qom.h"
+#include "qemu-common.h"
+
+
+/* CPUClass::reset() */
+static void lm32_cpu_reset(CPUState *s)
+{
+    LM32CPU *cpu = LM32_CPU(s);
+    LM32CPUClass *lcc = LM32_CPU_GET_CLASS(cpu);
+    CPULM32State *env = &cpu->env;
+
+    lcc->parent_reset(s);
+
+    cpu_state_reset(env);
+}
+
+static void lm32_cpu_class_init(ObjectClass *oc, void *data)
+{
+    LM32CPUClass *lcc = LM32_CPU_CLASS(oc);
+    CPUClass *cc = CPU_CLASS(oc);
+
+    lcc->parent_reset = cc->reset;
+    cc->reset = lm32_cpu_reset;
+}
+
+static const TypeInfo lm32_cpu_type_info = {
+    .name = TYPE_LM32_CPU,
+    .parent = TYPE_CPU,
+    .instance_size = sizeof(LM32CPU),
+    .abstract = false,
+    .class_size = sizeof(LM32CPUClass),
+    .class_init = lm32_cpu_class_init,
+};
+
+static void lm32_cpu_register_types(void)
+{
+    type_register_static(&lm32_cpu_type_info);
+}
+
+type_init(lm32_cpu_register_types)
diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index a7d9546..422a55b 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -184,6 +184,7 @@ struct CPULM32State {
 
 };
 
+#include "cpu-qom.h"
 
 CPULM32State *cpu_lm32_init(const char *cpu_model);
 void cpu_lm32_list(FILE *f, fprintf_function cpu_fprintf);
diff --git a/target-lm32/helper.c b/target-lm32/helper.c
index 78076e4..3cf86d7 100644
--- a/target-lm32/helper.c
+++ b/target-lm32/helper.c
@@ -194,6 +194,7 @@ static uint32_t cfg_by_def(const LM32Def *def)
 
 CPULM32State *cpu_lm32_init(const char *cpu_model)
 {
+    LM32CPU *cpu;
     CPULM32State *env;
     const LM32Def *def;
     static int tcg_initialized;
@@ -203,7 +204,8 @@ CPULM32State *cpu_lm32_init(const char *cpu_model)
         return NULL;
     }
 
-    env = g_malloc0(sizeof(CPULM32State));
+    cpu = LM32_CPU(object_new(TYPE_LM32_CPU));
+    env = &cpu->env;
 
     env->features = def->features;
     env->num_bps = def->num_breakpoints;
commit 3e48dd4a2d48aabafe22ce3611d65544d0234a69
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Wed Apr 11 12:01:44 2012 +0100

    rtl8139: do not assume TxStatus[] and TxAddr[] are adjacent
    
    Commit afe0a595356192d5f79703cf6462fcc112df007c ("rtl8139: support byte
    read to TxStatus registers") reused rtl8139_TxStatus_read() for reading
    TxAddr registers.  It relies on the fact that TxStatus[] and TxAddr[]
    are adjacent.
    
    This causes a gcc warning because the compiler can detect that array
    access is out-of-bounds:
    
      hw/rtl8139.c:2501:27: error: array subscript is above array bounds [-Werror=array-bounds]
    
    This patch refactors the function so that we don't rely on out-of-bounds
    accesses.
    
    Cc: Jason Wang <jasonwang at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 4d553a8..4d0f5ba 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -2482,15 +2482,17 @@ static void rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32
     rtl8139_transmit(s);
 }
 
-static uint32_t rtl8139_TxStatus_read(RTL8139State *s, uint8_t addr, int size)
+static uint32_t rtl8139_TxStatus_TxAddr_read(RTL8139State *s, uint32_t regs[],
+                                             uint32_t base, uint8_t addr,
+                                             int size)
 {
-    uint32_t reg = (addr - TxStatus0) / 4;
+    uint32_t reg = (addr - base) / 4;
     uint32_t offset = addr & 0x3;
     uint32_t ret = 0;
 
     if (addr & (size - 1)) {
-        DPRINTF("not implemented read for TxStatus addr=0x%x size=0x%x\n", addr,
-                size);
+        DPRINTF("not implemented read for TxStatus/TxAddr "
+                "addr=0x%x size=0x%x\n", addr, size);
         return ret;
     }
 
@@ -2498,12 +2500,12 @@ static uint32_t rtl8139_TxStatus_read(RTL8139State *s, uint8_t addr, int size)
     case 1: /* fall through */
     case 2: /* fall through */
     case 4:
-        ret = (s->TxStatus[reg] >> offset * 8) & ((1 << (size * 8)) - 1);
-        DPRINTF("TxStatus[%d] read addr=0x%x size=0x%x val=0x%08x\n", reg, addr,
-                size, ret);
+        ret = (regs[reg] >> offset * 8) & ((1 << (size * 8)) - 1);
+        DPRINTF("TxStatus/TxAddr[%d] read addr=0x%x size=0x%x val=0x%08x\n",
+                reg, addr, size, ret);
         break;
     default:
-        DPRINTF("unsupported size 0x%x of TxStatus reading\n", size);
+        DPRINTF("unsupported size 0x%x of TxStatus/TxAddr reading\n", size);
         break;
     }
 
@@ -2977,7 +2979,8 @@ static uint32_t rtl8139_io_readb(void *opaque, uint8_t addr)
             ret = s->mult[addr - MAR0];
             break;
         case TxStatus0 ... TxStatus0+4*4-1:
-            ret = rtl8139_TxStatus_read(s, addr, 1);
+            ret = rtl8139_TxStatus_TxAddr_read(s, s->TxStatus, TxStatus0,
+                                               addr, 1);
             break;
         case ChipCmd:
             ret = rtl8139_ChipCmd_read(s);
@@ -3043,7 +3046,7 @@ static uint32_t rtl8139_io_readw(void *opaque, uint8_t addr)
     switch (addr)
     {
         case TxAddr0 ... TxAddr0+4*4-1:
-            ret = rtl8139_TxStatus_read(s, addr, 2);
+            ret = rtl8139_TxStatus_TxAddr_read(s, s->TxAddr, TxAddr0, addr, 2);
             break;
         case IntrMask:
             ret = rtl8139_IntrMask_read(s);
@@ -3135,7 +3138,8 @@ static uint32_t rtl8139_io_readl(void *opaque, uint8_t addr)
             break;
 
         case TxStatus0 ... TxStatus0+4*4-1:
-            ret = rtl8139_TxStatus_read(s, addr, 4);
+            ret = rtl8139_TxStatus_TxAddr_read(s, s->TxStatus, TxStatus0,
+                                               addr, 4);
             break;
 
         case TxAddr0 ... TxAddr0+4*4-1:
commit 2ba1d381c2f5f5868fe071b45977c2ed459d78f0
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Apr 3 17:24:11 2012 +0300

    virtio-pci: change virtio balloon PCI class code
    
    Currently the virtio balloon device, when using the virtio-pci interface
    advertises itself with PCI class code MEMORY_RAM.  This is wrong; the
    balloon is vaguely related to memory, but is nothing like a PCI memory
    device in the meaning of the class code, and this code is not required
    or suggested by the virtio PCI specification.
    
    Worse, this patch causes problems on the pseries machine, because the
    firmware, seeing this class code, advertises the device as memory in the
    device tree, and then a guest kernel bug causes it to see this "memory"
    before the real system memory, leading to a crash in early boot.
    
    This patch fixes the problem by removing the bogus PCI class code on the
    balloon device.  The backwards compatibility PC machines get new compat
    properties so that they don't change.
    
    Cc: Rusty Russell <rusty at rustcorp.com.au>
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 0f61f00..5c08245 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -28,6 +28,7 @@
 #include "pc.h"
 #include "apic.h"
 #include "pci.h"
+#include "pci_ids.h"
 #include "net.h"
 #include "boards.h"
 #include "ide.h"
@@ -368,6 +369,10 @@ static QEMUMachine pc_machine_v1_1 = {
             .driver   = "isa-fdc",\
             .property = "check_media_rate",\
             .value    = "off",\
+        }, {\
+            .driver   = "virtio-balloon-pci",\
+            .property = "class",\
+            .value    = stringify(PCI_CLASS_MEMORY_RAM),\
         }
 
 static QEMUMachine pc_machine_v1_0 = {
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index a0fb7c1..4a4413d 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -790,6 +790,11 @@ static int virtio_balloon_init_pci(PCIDevice *pci_dev)
     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
     VirtIODevice *vdev;
 
+    if (proxy->class_code != PCI_CLASS_OTHERS &&
+        proxy->class_code != PCI_CLASS_MEMORY_RAM) { /* qemu < 1.1 */
+        proxy->class_code = PCI_CLASS_OTHERS;
+    }
+
     vdev = virtio_balloon_init(&pci_dev->qdev);
     if (!vdev) {
         return -1;
@@ -906,6 +911,7 @@ static TypeInfo virtio_serial_info = {
 
 static Property virtio_balloon_properties[] = {
     DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
+    DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -919,7 +925,7 @@ static void virtio_balloon_class_init(ObjectClass *klass, void *data)
     k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
     k->device_id = PCI_DEVICE_ID_VIRTIO_BALLOON;
     k->revision = VIRTIO_PCI_ABI_VERSION;
-    k->class_id = PCI_CLASS_MEMORY_RAM;
+    k->class_id = PCI_CLASS_OTHERS;
     dc->reset = virtio_pci_reset;
     dc->props = virtio_balloon_properties;
 }
commit 4490c71191b59dce2dd88f5f9ab49f2c92ab410c
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Dec 5 21:48:43 2011 +0200

    ivshmem: add missing msix calls
    
    ivshmem used msix but didn't call it on either reset or
    config write paths. This used to partically work since
    guests don't use all of msi-x configuration fields,
    and reset is rarely used, but the patch 'msix: track function masked
    in pci device state' broke that. Fix by adding appropriate calls.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Reported-by: Cam Macdonell <cam at cs.ualberta.ca>
    Tested-by: Cam Macdonell <cam at cs.ualberta.ca>

diff --git a/hw/ivshmem.c b/hw/ivshmem.c
index b80aa8f..c2bdd92 100644
--- a/hw/ivshmem.c
+++ b/hw/ivshmem.c
@@ -509,11 +509,29 @@ static void ivshmem_read(void *opaque, const uint8_t * buf, int flags)
     return;
 }
 
+/* Select the MSI-X vectors used by device.
+ * ivshmem maps events to vectors statically, so
+ * we just enable all vectors on init and after reset. */
+static void ivshmem_use_msix(IVShmemState * s)
+{
+    int i;
+
+    if (!msix_present(&s->dev)) {
+        return;
+    }
+
+    for (i = 0; i < s->vectors; i++) {
+        msix_vector_use(&s->dev, i);
+    }
+}
+
 static void ivshmem_reset(DeviceState *d)
 {
     IVShmemState *s = DO_UPCAST(IVShmemState, dev.qdev, d);
 
     s->intrstatus = 0;
+    msix_reset(&s->dev);
+    ivshmem_use_msix(s);
     return;
 }
 
@@ -544,12 +562,8 @@ static uint64_t ivshmem_get_size(IVShmemState * s) {
     return value;
 }
 
-static void ivshmem_setup_msi(IVShmemState * s) {
-
-    int i;
-
-    /* allocate the MSI-X vectors */
-
+static void ivshmem_setup_msi(IVShmemState * s)
+{
     memory_region_init(&s->msix_bar, "ivshmem-msix", 4096);
     if (!msix_init(&s->dev, s->vectors, &s->msix_bar, 1, 0)) {
         pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY,
@@ -560,13 +574,10 @@ static void ivshmem_setup_msi(IVShmemState * s) {
         exit(1);
     }
 
-    /* 'activate' the vectors */
-    for (i = 0; i < s->vectors; i++) {
-        msix_vector_use(&s->dev, i);
-    }
-
     /* allocate QEMU char devices for receiving interrupts */
     s->eventfd_table = g_malloc0(s->vectors * sizeof(EventfdEntry));
+
+    ivshmem_use_msix(s);
 }
 
 static void ivshmem_save(QEMUFile* f, void *opaque)
@@ -590,7 +601,7 @@ static int ivshmem_load(QEMUFile* f, void *opaque, int version_id)
     IVSHMEM_DPRINTF("ivshmem_load\n");
 
     IVShmemState *proxy = opaque;
-    int ret, i;
+    int ret;
 
     if (version_id > 0) {
         return -EINVAL;
@@ -608,9 +619,7 @@ static int ivshmem_load(QEMUFile* f, void *opaque, int version_id)
 
     if (ivshmem_has_feature(proxy, IVSHMEM_MSI)) {
         msix_load(&proxy->dev, f);
-        for (i = 0; i < proxy->vectors; i++) {
-            msix_vector_use(&proxy->dev, i);
-        }
+	ivshmem_use_msix(proxy);
     } else {
         proxy->intrstatus = qemu_get_be32(f);
         proxy->intrmask = qemu_get_be32(f);
@@ -619,6 +628,13 @@ static int ivshmem_load(QEMUFile* f, void *opaque, int version_id)
     return 0;
 }
 
+static void ivshmem_write_config(PCIDevice *pci_dev, uint32_t address,
+				 uint32_t val, int len)
+{
+    pci_default_write_config(pci_dev, address, val, len);
+    msix_write_config(pci_dev, address, val, len);
+}
+
 static int pci_ivshmem_init(PCIDevice *dev)
 {
     IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev);
@@ -744,6 +760,8 @@ static int pci_ivshmem_init(PCIDevice *dev)
 
     }
 
+    s->dev.config_write = ivshmem_write_config;
+
     return 0;
 }
 
commit fbbaf9ae88286f18b2ab32fb4174ebdbdc1d5919
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Sun Apr 1 11:39:43 2012 +0300

    vhost: readd assert statement
    
    It's clear from the surrounding code that
    start < end so it's enough to assert end < log_size.
    However, it's better to make this explicit in case
    we refactor the code again.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/vhost.c b/hw/vhost.c
index 7e282dd..43664e7 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -35,6 +35,7 @@ static void vhost_dev_sync_region(struct vhost_dev *dev,
         return;
     }
     assert(end / VHOST_LOG_CHUNK < dev->log_size);
+    assert(start / VHOST_LOG_CHUNK < dev->log_size);
 
     for (;from < to; ++from) {
         vhost_log_chunk_t log;
commit e314672a8a95f5dc98534f0682fce50fb83dbc5c
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Fri Aug 13 09:54:52 2010 -0400

    vhost: Fix size of dirty log sync on resize
    
    When the vhost log is resized, we want to sync up to
    the size of the old log.  With that end address in place,
    ignore regions that start after then end rather than
    hitting assert.
    
    This also addresses the following crash report:
    When migrating a vm using vhost-net we hit the following assertion:
    
    qemu-kvm: /usr/src/packages/BUILD/qemu-kvm-0.15.1/hw/vhost.c:30:
    vhost_dev_sync_region: Assertion `start / (0x1000 * (8 *
    sizeof(vhost_log_chunk_t))) < dev->log_size' failed.
    
    The cases which the end < start check is intended to catch, such as
    for vga video memory, will also likely trigger the assertion.
    Reorder the code to handle this correctly.
    
    Reported-by: Josh Durgin <josh.durgin at dreamhost.com>
    Signed-off-by: Bruce Rogers <brogers at suse.com>
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/vhost.c b/hw/vhost.c
index 8d3ba5b..7e282dd 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -31,11 +31,11 @@ static void vhost_dev_sync_region(struct vhost_dev *dev,
     vhost_log_chunk_t *to = dev->log + end / VHOST_LOG_CHUNK + 1;
     uint64_t addr = (start / VHOST_LOG_CHUNK) * VHOST_LOG_CHUNK;
 
-    assert(end / VHOST_LOG_CHUNK < dev->log_size);
-    assert(start / VHOST_LOG_CHUNK < dev->log_size);
     if (end < start) {
         return;
     }
+    assert(end / VHOST_LOG_CHUNK < dev->log_size);
+
     for (;from < to; ++from) {
         vhost_log_chunk_t log;
         int bit;
@@ -277,8 +277,9 @@ static inline void vhost_dev_log_resize(struct vhost_dev* dev, uint64_t size)
     r = ioctl(dev->control, VHOST_SET_LOG_BASE, &log_base);
     assert(r >= 0);
     for (i = 0; i < dev->n_mem_sections; ++i) {
-        vhost_sync_dirty_bitmap(dev, &dev->mem_sections[i],
-                                0, (target_phys_addr_t)~0x0ull);
+        /* Sync only the range covered by the old log */
+        vhost_sync_dirty_bitmap(dev, &dev->mem_sections[i], 0,
+                                dev->log_size * VHOST_LOG_CHUNK - 1);
     }
     if (dev->log) {
         g_free(dev->log);
commit d6c730086cbf24382eb8cff25551798769edfd84
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Mar 26 11:26:16 2012 +0200

    pc: reduce duplication in compat machine types
    
    Make it easier to add compat properties, by
    adding macros for properties duplicated across
    machine types.
    
    Note: there could be bugs in compat properties,
    this patch does not attempt to address them,
    the code is bug for bug identical to the original.
    
    Tested by: generated a preprocessed file, sorted and
    compared to sorted original.
    Lightly tested on x86_64.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index fadca4c..0f61f00 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -359,50 +359,69 @@ static QEMUMachine pc_machine_v1_1 = {
     .is_default = 1,
 };
 
+#define PC_COMPAT_1_0 \
+        {\
+            .driver   = "pc-sysfw",\
+            .property = "rom_only",\
+            .value    = stringify(1),\
+        }, {\
+            .driver   = "isa-fdc",\
+            .property = "check_media_rate",\
+            .value    = "off",\
+        }
+
 static QEMUMachine pc_machine_v1_0 = {
     .name = "pc-1.0",
     .desc = "Standard PC",
     .init = pc_init_pci,
     .max_cpus = 255,
     .compat_props = (GlobalProperty[]) {
-        {
-            .driver   = "pc-sysfw",
-            .property = "rom_only",
-            .value    = stringify(1),
-        }, {
-            .driver   = "isa-fdc",
-            .property = "check_media_rate",
-            .value    = "off",
-        },
+        PC_COMPAT_1_0,
         { /* end of list */ }
     },
 };
 
+#define PC_COMPAT_0_15 \
+        PC_COMPAT_1_0
+
 static QEMUMachine pc_machine_v0_15 = {
     .name = "pc-0.15",
     .desc = "Standard PC",
     .init = pc_init_pci,
     .max_cpus = 255,
     .compat_props = (GlobalProperty[]) {
-        {
-            .driver   = "pc-sysfw",
-            .property = "rom_only",
-            .value    = stringify(1),
-        }, {
-            .driver   = "isa-fdc",
-            .property = "check_media_rate",
-            .value    = "off",
-        },
+        PC_COMPAT_0_15,
         { /* end of list */ }
     },
 };
 
+#define PC_COMPAT_0_14 \
+        PC_COMPAT_0_15,\
+        {\
+            .driver   = "virtio-blk-pci",\
+            .property = "event_idx",\
+            .value    = "off",\
+        },{\
+            .driver   = "virtio-serial-pci",\
+            .property = "event_idx",\
+            .value    = "off",\
+        },{\
+            .driver   = "virtio-net-pci",\
+            .property = "event_idx",\
+            .value    = "off",\
+        },{\
+            .driver   = "virtio-balloon-pci",\
+            .property = "event_idx",\
+            .value    = "off",\
+        }
+
 static QEMUMachine pc_machine_v0_14 = {
     .name = "pc-0.14",
     .desc = "Standard PC",
     .init = pc_init_pci,
     .max_cpus = 255,
     .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_0_14, 
         {
             .driver   = "qxl",
             .property = "revision",
@@ -411,42 +430,30 @@ static QEMUMachine pc_machine_v0_14 = {
             .driver   = "qxl-vga",
             .property = "revision",
             .value    = stringify(2),
-        },{
-            .driver   = "virtio-blk-pci",
-            .property = "event_idx",
-            .value    = "off",
-        },{
-            .driver   = "virtio-serial-pci",
-            .property = "event_idx",
-            .value    = "off",
-        },{
-            .driver   = "virtio-net-pci",
-            .property = "event_idx",
-            .value    = "off",
-        },{
-            .driver   = "virtio-balloon-pci",
-            .property = "event_idx",
-            .value    = "off",
-        },{
-            .driver   = "isa-fdc",
-            .property = "check_media_rate",
-            .value    = "off",
-        },
-        {
-            .driver   = "pc-sysfw",
-            .property = "rom_only",
-            .value    = stringify(1),
         },
         { /* end of list */ }
     },
 };
 
+#define PC_COMPAT_0_13 \
+        PC_COMPAT_0_14,\
+        {\
+            .driver   = "PCI",\
+            .property = "command_serr_enable",\
+            .value    = "off",\
+        },{\
+            .driver   = "AC97",\
+            .property = "use_broken_id",\
+            .value    = stringify(1),\
+        }
+
 static QEMUMachine pc_machine_v0_13 = {
     .name = "pc-0.13",
     .desc = "Standard PC",
     .init = pc_init_pci_no_kvmclock,
     .max_cpus = 255,
     .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_0_13,
         {
             .driver   = "virtio-9p-pci",
             .property = "vectors",
@@ -459,59 +466,31 @@ static QEMUMachine pc_machine_v0_13 = {
             .driver   = "vmware-svga",
             .property = "rombar",
             .value    = stringify(0),
-        },{
-            .driver   = "PCI",
-            .property = "command_serr_enable",
-            .value    = "off",
-        },{
-            .driver   = "virtio-blk-pci",
-            .property = "event_idx",
-            .value    = "off",
-        },{
-            .driver   = "virtio-serial-pci",
-            .property = "event_idx",
-            .value    = "off",
-        },{
-            .driver   = "virtio-net-pci",
-            .property = "event_idx",
-            .value    = "off",
-        },{
-            .driver   = "virtio-balloon-pci",
-            .property = "event_idx",
-            .value    = "off",
-        },{
-            .driver   = "AC97",
-            .property = "use_broken_id",
-            .value    = stringify(1),
-        },{
-            .driver   = "isa-fdc",
-            .property = "check_media_rate",
-            .value    = "off",
-        },
-        {
-            .driver   = "pc-sysfw",
-            .property = "rom_only",
-            .value    = stringify(1),
         },
         { /* end of list */ }
     },
 };
 
+#define PC_COMPAT_0_12 \
+        PC_COMPAT_0_13,\
+        {\
+            .driver   = "virtio-serial-pci",\
+            .property = "max_ports",\
+            .value    = stringify(1),\
+        },{\
+            .driver   = "virtio-serial-pci",\
+            .property = "vectors",\
+            .value    = stringify(0),\
+        }
+
 static QEMUMachine pc_machine_v0_12 = {
     .name = "pc-0.12",
     .desc = "Standard PC",
     .init = pc_init_pci_no_kvmclock,
     .max_cpus = 255,
     .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_0_12,
         {
-            .driver   = "virtio-serial-pci",
-            .property = "max_ports",
-            .value    = stringify(1),
-        },{
-            .driver   = "virtio-serial-pci",
-            .property = "vectors",
-            .value    = stringify(0),
-        },{
             .driver   = "VGA",
             .property = "rombar",
             .value    = stringify(0),
@@ -519,63 +498,27 @@ static QEMUMachine pc_machine_v0_12 = {
             .driver   = "vmware-svga",
             .property = "rombar",
             .value    = stringify(0),
-        },{
-            .driver   = "PCI",
-            .property = "command_serr_enable",
-            .value    = "off",
-        },{
-            .driver   = "virtio-blk-pci",
-            .property = "event_idx",
-            .value    = "off",
-        },{
-            .driver   = "virtio-serial-pci",
-            .property = "event_idx",
-            .value    = "off",
-        },{
-            .driver   = "virtio-net-pci",
-            .property = "event_idx",
-            .value    = "off",
-        },{
-            .driver   = "virtio-balloon-pci",
-            .property = "event_idx",
-            .value    = "off",
-        },{
-            .driver   = "AC97",
-            .property = "use_broken_id",
-            .value    = stringify(1),
-        },{
-            .driver   = "isa-fdc",
-            .property = "check_media_rate",
-            .value    = "off",
-        },
-        {
-            .driver   = "pc-sysfw",
-            .property = "rom_only",
-            .value    = stringify(1),
         },
         { /* end of list */ }
     }
 };
 
+#define PC_COMPAT_0_11 \
+        PC_COMPAT_0_12,\
+        {\
+            .driver   = "virtio-blk-pci",\
+            .property = "vectors",\
+            .value    = stringify(0),\
+        }
+
 static QEMUMachine pc_machine_v0_11 = {
     .name = "pc-0.11",
     .desc = "Standard PC, qemu 0.11",
     .init = pc_init_pci_no_kvmclock,
     .max_cpus = 255,
     .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_0_11,
         {
-            .driver   = "virtio-blk-pci",
-            .property = "vectors",
-            .value    = stringify(0),
-        },{
-            .driver   = "virtio-serial-pci",
-            .property = "max_ports",
-            .value    = stringify(1),
-        },{
-            .driver   = "virtio-serial-pci",
-            .property = "vectors",
-            .value    = stringify(0),
-        },{
             .driver   = "ide-drive",
             .property = "ver",
             .value    = "0.11",
@@ -583,43 +526,6 @@ static QEMUMachine pc_machine_v0_11 = {
             .driver   = "scsi-disk",
             .property = "ver",
             .value    = "0.11",
-        },{
-            .driver   = "PCI",
-            .property = "rombar",
-            .value    = stringify(0),
-        },{
-            .driver   = "PCI",
-            .property = "command_serr_enable",
-            .value    = "off",
-        },{
-            .driver   = "virtio-blk-pci",
-            .property = "event_idx",
-            .value    = "off",
-        },{
-            .driver   = "virtio-serial-pci",
-            .property = "event_idx",
-            .value    = "off",
-        },{
-            .driver   = "virtio-net-pci",
-            .property = "event_idx",
-            .value    = "off",
-        },{
-            .driver   = "virtio-balloon-pci",
-            .property = "event_idx",
-            .value    = "off",
-        },{
-            .driver   = "AC97",
-            .property = "use_broken_id",
-            .value    = stringify(1),
-        },{
-            .driver   = "isa-fdc",
-            .property = "check_media_rate",
-            .value    = "off",
-        },
-        {
-            .driver   = "pc-sysfw",
-            .property = "rom_only",
-            .value    = stringify(1),
         },
         { /* end of list */ }
     }
@@ -631,6 +537,7 @@ static QEMUMachine pc_machine_v0_10 = {
     .init = pc_init_pci_no_kvmclock,
     .max_cpus = 255,
     .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_0_11,
         {
             .driver   = "virtio-blk-pci",
             .property = "class",
@@ -640,22 +547,10 @@ static QEMUMachine pc_machine_v0_10 = {
             .property = "class",
             .value    = stringify(PCI_CLASS_DISPLAY_OTHER),
         },{
-            .driver   = "virtio-serial-pci",
-            .property = "max_ports",
-            .value    = stringify(1),
-        },{
-            .driver   = "virtio-serial-pci",
-            .property = "vectors",
-            .value    = stringify(0),
-        },{
             .driver   = "virtio-net-pci",
             .property = "vectors",
             .value    = stringify(0),
         },{
-            .driver   = "virtio-blk-pci",
-            .property = "vectors",
-            .value    = stringify(0),
-        },{
             .driver   = "ide-drive",
             .property = "ver",
             .value    = "0.10",
@@ -663,43 +558,6 @@ static QEMUMachine pc_machine_v0_10 = {
             .driver   = "scsi-disk",
             .property = "ver",
             .value    = "0.10",
-        },{
-            .driver   = "PCI",
-            .property = "rombar",
-            .value    = stringify(0),
-        },{
-            .driver   = "PCI",
-            .property = "command_serr_enable",
-            .value    = "off",
-        },{
-            .driver   = "virtio-blk-pci",
-            .property = "event_idx",
-            .value    = "off",
-        },{
-            .driver   = "virtio-serial-pci",
-            .property = "event_idx",
-            .value    = "off",
-        },{
-            .driver   = "virtio-net-pci",
-            .property = "event_idx",
-            .value    = "off",
-        },{
-            .driver   = "virtio-balloon-pci",
-            .property = "event_idx",
-            .value    = "off",
-        },{
-            .driver   = "AC97",
-            .property = "use_broken_id",
-            .value    = stringify(1),
-        },{
-            .driver   = "isa-fdc",
-            .property = "check_media_rate",
-            .value    = "off",
-        },
-        {
-            .driver   = "pc-sysfw",
-            .property = "rom_only",
-            .value    = stringify(1),
         },
         { /* end of list */ }
     },
commit d50c6c8b0fc28c2dd91f3f7ab2a0bbb56419214b
Author: Alexey Korolev <alexey.korolev at endace.com>
Date:   Wed Feb 29 14:35:14 2012 +1300

    piix_pci: fix typo in i400FX chipset init code
    
    There is a typo in i440FX init code. This is causing problems when
    somebody wants to access the 64bit PCI range.
    
    Signed-off-by: Alexey Korolev <alexey.korolev at endace.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 179d9a6..09e84f5 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -349,7 +349,7 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn,
     b = i440fx_common_init("i440FX", pi440fx_state, piix3_devfn, isa_bus, pic,
                            address_space_mem, address_space_io, ram_size,
                            pci_hole_start, pci_hole_size,
-                           pci_hole64_size, pci_hole64_size,
+                           pci_hole64_start, pci_hole64_size,
                            pci_memory, ram_memory);
     return b;
 }
commit c1958aea51a14199d05d392edce932a956e1674d
Author: Andreas Färber <afaerber at suse.de>
Date:   Tue Apr 3 00:16:24 2012 +0200

    target-i386: QOM'ify CPU reset
    
    Move code from cpu_state_reset() into QOM x86_cpu_reset(),
    fixing style issues for FPU init.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index f4463e1..3df53ca 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -1374,10 +1374,80 @@ static void x86_cpu_reset(CPUState *s)
     X86CPU *cpu = X86_CPU(s);
     X86CPUClass *xcc = X86_CPU_GET_CLASS(cpu);
     CPUX86State *env = &cpu->env;
+    int i;
+
+    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+        log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
+    }
 
     xcc->parent_reset(s);
 
-    cpu_state_reset(env);
+
+    memset(env, 0, offsetof(CPUX86State, breakpoints));
+
+    tlb_flush(env, 1);
+
+    env->old_exception = -1;
+
+    /* init to reset state */
+
+#ifdef CONFIG_SOFTMMU
+    env->hflags |= HF_SOFTMMU_MASK;
+#endif
+    env->hflags2 |= HF2_GIF_MASK;
+
+    cpu_x86_update_cr0(env, 0x60000010);
+    env->a20_mask = ~0x0;
+    env->smbase = 0x30000;
+
+    env->idt.limit = 0xffff;
+    env->gdt.limit = 0xffff;
+    env->ldt.limit = 0xffff;
+    env->ldt.flags = DESC_P_MASK | (2 << DESC_TYPE_SHIFT);
+    env->tr.limit = 0xffff;
+    env->tr.flags = DESC_P_MASK | (11 << DESC_TYPE_SHIFT);
+
+    cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff,
+                           DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK |
+                           DESC_R_MASK | DESC_A_MASK);
+    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff,
+                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
+                           DESC_A_MASK);
+    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff,
+                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
+                           DESC_A_MASK);
+    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff,
+                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
+                           DESC_A_MASK);
+    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff,
+                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
+                           DESC_A_MASK);
+    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff,
+                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
+                           DESC_A_MASK);
+
+    env->eip = 0xfff0;
+    env->regs[R_EDX] = env->cpuid_version;
+
+    env->eflags = 0x2;
+
+    /* FPU init */
+    for (i = 0; i < 8; i++) {
+        env->fptags[i] = 1;
+    }
+    env->fpuc = 0x37f;
+
+    env->mxcsr = 0x1f80;
+
+    env->pat = 0x0007040600070406ULL;
+    env->msr_ia32_misc_enable = MSR_IA32_MISC_ENABLE_DEFAULT;
+
+    memset(env->dr, 0, sizeof(env->dr));
+    env->dr[6] = DR6_FIXED_1;
+    env->dr[7] = DR7_FIXED_1;
+    cpu_breakpoint_remove_all(env, BP_CPU);
+    cpu_watchpoint_remove_all(env, BP_CPU);
 }
 
 static void mce_init(X86CPU *cpu)
diff --git a/target-i386/helper.c b/target-i386/helper.c
index d8ceee1..87954f0 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -29,76 +29,7 @@
 /* NOTE: must be called outside the CPU execute loop */
 void cpu_state_reset(CPUX86State *env)
 {
-    int i;
-
-    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
-        log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
-    }
-
-    memset(env, 0, offsetof(CPUX86State, breakpoints));
-
-    tlb_flush(env, 1);
-
-    env->old_exception = -1;
-
-    /* init to reset state */
-
-#ifdef CONFIG_SOFTMMU
-    env->hflags |= HF_SOFTMMU_MASK;
-#endif
-    env->hflags2 |= HF2_GIF_MASK;
-
-    cpu_x86_update_cr0(env, 0x60000010);
-    env->a20_mask = ~0x0;
-    env->smbase = 0x30000;
-
-    env->idt.limit = 0xffff;
-    env->gdt.limit = 0xffff;
-    env->ldt.limit = 0xffff;
-    env->ldt.flags = DESC_P_MASK | (2 << DESC_TYPE_SHIFT);
-    env->tr.limit = 0xffff;
-    env->tr.flags = DESC_P_MASK | (11 << DESC_TYPE_SHIFT);
-
-    cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff,
-                           DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK |
-                           DESC_R_MASK | DESC_A_MASK);
-    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff,
-                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
-                           DESC_A_MASK);
-    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff,
-                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
-                           DESC_A_MASK);
-    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff,
-                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
-                           DESC_A_MASK);
-    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff,
-                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
-                           DESC_A_MASK);
-    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff,
-                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
-                           DESC_A_MASK);
-
-    env->eip = 0xfff0;
-    env->regs[R_EDX] = env->cpuid_version;
-
-    env->eflags = 0x2;
-
-    /* FPU init */
-    for(i = 0;i < 8; i++)
-        env->fptags[i] = 1;
-    env->fpuc = 0x37f;
-
-    env->mxcsr = 0x1f80;
-
-    env->pat = 0x0007040600070406ULL;
-    env->msr_ia32_misc_enable = MSR_IA32_MISC_ENABLE_DEFAULT;
-
-    memset(env->dr, 0, sizeof(env->dr));
-    env->dr[6] = DR6_FIXED_1;
-    env->dr[7] = DR7_FIXED_1;
-    cpu_breakpoint_remove_all(env, BP_CPU);
-    cpu_watchpoint_remove_all(env, BP_CPU);
+    cpu_reset(ENV_GET_CPU(env));
 }
 
 static void cpu_x86_version(CPUX86State *env, int *family, int *model)
commit de024815e3b523addf58f1f79846b7fe74643678
Author: Andreas Färber <afaerber at suse.de>
Date:   Tue Apr 3 00:00:17 2012 +0200

    target-i386: QOM'ify CPU init
    
    Move code from cpu_x86_init() to new QOM x86_cpu_initfn().
    Also move mce_init() to cpu.c since it's used nowhere else.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 36790da..f4463e1 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -1380,6 +1380,32 @@ static void x86_cpu_reset(CPUState *s)
     cpu_state_reset(env);
 }
 
+static void mce_init(X86CPU *cpu)
+{
+    CPUX86State *cenv = &cpu->env;
+    unsigned int bank;
+
+    if (((cenv->cpuid_version >> 8) & 0xf) >= 6
+        && (cenv->cpuid_features & (CPUID_MCE | CPUID_MCA)) ==
+            (CPUID_MCE | CPUID_MCA)) {
+        cenv->mcg_cap = MCE_CAP_DEF | MCE_BANKS_DEF;
+        cenv->mcg_ctl = ~(uint64_t)0;
+        for (bank = 0; bank < MCE_BANKS_DEF; bank++) {
+            cenv->mce_banks[bank * 4] = ~(uint64_t)0;
+        }
+    }
+}
+
+static void x86_cpu_initfn(Object *obj)
+{
+    X86CPU *cpu = X86_CPU(obj);
+    CPUX86State *env = &cpu->env;
+
+    cpu_exec_init(env);
+    env->cpuid_apic_id = env->cpu_index;
+    mce_init(cpu);
+}
+
 static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
 {
     X86CPUClass *xcc = X86_CPU_CLASS(oc);
@@ -1393,6 +1419,7 @@ static const TypeInfo x86_cpu_type_info = {
     .name = TYPE_X86_CPU,
     .parent = TYPE_CPU,
     .instance_size = sizeof(X86CPU),
+    .instance_init = x86_cpu_initfn,
     .abstract = false,
     .class_size = sizeof(X86CPUClass),
     .class_init = x86_cpu_common_class_init,
diff --git a/target-i386/helper.c b/target-i386/helper.c
index fb87975..d8ceee1 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1197,21 +1197,6 @@ void cpu_report_tpr_access(CPUX86State *env, TPRAccess access)
 }
 #endif /* !CONFIG_USER_ONLY */
 
-static void mce_init(CPUX86State *cenv)
-{
-    unsigned int bank;
-
-    if (((cenv->cpuid_version >> 8) & 0xf) >= 6
-        && (cenv->cpuid_features & (CPUID_MCE | CPUID_MCA)) ==
-            (CPUID_MCE | CPUID_MCA)) {
-        cenv->mcg_cap = MCE_CAP_DEF | MCE_BANKS_DEF;
-        cenv->mcg_ctl = ~(uint64_t)0;
-        for (bank = 0; bank < MCE_BANKS_DEF; bank++) {
-            cenv->mce_banks[bank * 4] = ~(uint64_t)0;
-        }
-    }
-}
-
 int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
                             target_ulong *base, unsigned int *limit,
                             unsigned int *flags)
@@ -1249,7 +1234,6 @@ CPUX86State *cpu_x86_init(const char *cpu_model)
 
     cpu = X86_CPU(object_new(TYPE_X86_CPU));
     env = &cpu->env;
-    cpu_exec_init(env);
     env->cpu_model_str = cpu_model;
 
     /* init various static tables used in TCG mode */
@@ -1265,8 +1249,6 @@ CPUX86State *cpu_x86_init(const char *cpu_model)
         object_delete(OBJECT(cpu));
         return NULL;
     }
-    env->cpuid_apic_id = env->cpu_index;
-    mce_init(env);
 
     qemu_init_vcpu(env);
 
commit 5fd2087a1b7b3075828de741d76188441ee35bc8
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon Apr 2 23:20:08 2012 +0200

    target-i386: QOM'ify CPU
    
    Embed CPUX86State as first member of X86CPU.
    Distinguish between "x86_64-cpu" and "i386-cpu".
    Drop cpu_x86_close() in favor of calling object_delete() directly.
    
    For now let CPUClass::reset() call cpu_state_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
new file mode 100644
index 0000000..40635c4
--- /dev/null
+++ b/target-i386/cpu-qom.h
@@ -0,0 +1,75 @@
+/*
+ * QEMU x86 CPU
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * 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.1 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/lgpl-2.1.html>
+ */
+#ifndef QEMU_I386_CPU_QOM_H
+#define QEMU_I386_CPU_QOM_H
+
+#include "qemu/cpu.h"
+#include "cpu.h"
+
+#ifdef TARGET_X86_64
+#define TYPE_X86_CPU "x86_64-cpu"
+#else
+#define TYPE_X86_CPU "i386-cpu"
+#endif
+
+#define X86_CPU_CLASS(klass) \
+    OBJECT_CLASS_CHECK(X86CPUClass, (klass), TYPE_X86_CPU)
+#define X86_CPU(obj) \
+    OBJECT_CHECK(X86CPU, (obj), TYPE_X86_CPU)
+#define X86_CPU_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(X86CPUClass, (obj), TYPE_X86_CPU)
+
+/**
+ * X86CPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * An x86 CPU model or family.
+ */
+typedef struct X86CPUClass {
+    /*< private >*/
+    CPUClass parent_class;
+    /*< public >*/
+
+    void (*parent_reset)(CPUState *cpu);
+} X86CPUClass;
+
+/**
+ * X86CPU:
+ * @env: #CPUX86State
+ *
+ * An x86 CPU.
+ */
+typedef struct X86CPU {
+    /*< private >*/
+    CPUState parent_obj;
+    /*< public >*/
+
+    CPUX86State env;
+} X86CPU;
+
+static inline X86CPU *x86_env_get_cpu(CPUX86State *env)
+{
+    return X86_CPU(container_of(env, X86CPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(x86_env_get_cpu(e))
+
+
+#endif
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 465ea15..36790da 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -1367,3 +1367,40 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
         break;
     }
 }
+
+/* CPUClass::reset() */
+static void x86_cpu_reset(CPUState *s)
+{
+    X86CPU *cpu = X86_CPU(s);
+    X86CPUClass *xcc = X86_CPU_GET_CLASS(cpu);
+    CPUX86State *env = &cpu->env;
+
+    xcc->parent_reset(s);
+
+    cpu_state_reset(env);
+}
+
+static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
+{
+    X86CPUClass *xcc = X86_CPU_CLASS(oc);
+    CPUClass *cc = CPU_CLASS(oc);
+
+    xcc->parent_reset = cc->reset;
+    cc->reset = x86_cpu_reset;
+}
+
+static const TypeInfo x86_cpu_type_info = {
+    .name = TYPE_X86_CPU,
+    .parent = TYPE_CPU,
+    .instance_size = sizeof(X86CPU),
+    .abstract = false,
+    .class_size = sizeof(X86CPUClass),
+    .class_init = x86_cpu_common_class_init,
+};
+
+static void x86_cpu_register_types(void)
+{
+    type_register_static(&x86_cpu_type_info);
+}
+
+type_init(x86_cpu_register_types)
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index a1ed3e7..4bb4592 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -783,9 +783,10 @@ typedef struct CPUX86State {
     TPRAccess tpr_access_type;
 } CPUX86State;
 
+#include "cpu-qom.h"
+
 CPUX86State *cpu_x86_init(const char *cpu_model);
 int cpu_x86_exec(CPUX86State *s);
-void cpu_x86_close(CPUX86State *s);
 void x86_cpu_list (FILE *f, fprintf_function cpu_fprintf, const char *optarg);
 void x86_cpudef_setup(void);
 int cpu_x86_support_mca_broadcast(CPUX86State *env);
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 83122bf..fb87975 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -101,11 +101,6 @@ void cpu_state_reset(CPUX86State *env)
     cpu_watchpoint_remove_all(env, BP_CPU);
 }
 
-void cpu_x86_close(CPUX86State *env)
-{
-    g_free(env);
-}
-
 static void cpu_x86_version(CPUX86State *env, int *family, int *model)
 {
     int cpuver = env->cpuid_version;
@@ -1248,10 +1243,12 @@ int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
 
 CPUX86State *cpu_x86_init(const char *cpu_model)
 {
+    X86CPU *cpu;
     CPUX86State *env;
     static int inited;
 
-    env = g_malloc0(sizeof(CPUX86State));
+    cpu = X86_CPU(object_new(TYPE_X86_CPU));
+    env = &cpu->env;
     cpu_exec_init(env);
     env->cpu_model_str = cpu_model;
 
@@ -1265,7 +1262,7 @@ CPUX86State *cpu_x86_init(const char *cpu_model)
 #endif
     }
     if (cpu_x86_register(env, cpu_model) < 0) {
-        cpu_x86_close(env);
+        object_delete(OBJECT(cpu));
         return NULL;
     }
     env->cpuid_apic_id = env->cpu_index;
commit 30471bc94e1eb4ce1c87a56b6210a3baa1698d58
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon Apr 2 22:22:12 2012 +0200

    target-i386: Rename cpuid.c
    
    Name it cpu.c to align with other QOM'ified targets.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/Makefile.target b/Makefile.target
index 14c8fa1..1110796 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -87,7 +87,7 @@ endif
 endif
 libobj-y += helper.o
 ifeq ($(TARGET_BASE_ARCH), i386)
-libobj-y += cpuid.o
+libobj-y += cpu.o
 endif
 libobj-$(TARGET_SPARC64) += vis_helper.o
 libobj-$(CONFIG_NEED_MMU) += mmu.o
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
new file mode 100644
index 0000000..465ea15
--- /dev/null
+++ b/target-i386/cpu.c
@@ -0,0 +1,1369 @@
+/*
+ *  i386 CPUID helper functions
+ *
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ * 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/>.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "cpu.h"
+#include "kvm.h"
+
+#include "qemu-option.h"
+#include "qemu-config.h"
+
+#include "hyperv.h"
+
+/* feature flags taken from "Intel Processor Identification and the CPUID
+ * Instruction" and AMD's "CPUID Specification".  In cases of disagreement
+ * between feature naming conventions, aliases may be added.
+ */
+static const char *feature_name[] = {
+    "fpu", "vme", "de", "pse",
+    "tsc", "msr", "pae", "mce",
+    "cx8", "apic", NULL, "sep",
+    "mtrr", "pge", "mca", "cmov",
+    "pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */,
+    NULL, "ds" /* Intel dts */, "acpi", "mmx",
+    "fxsr", "sse", "sse2", "ss",
+    "ht" /* Intel htt */, "tm", "ia64", "pbe",
+};
+static const char *ext_feature_name[] = {
+    "pni|sse3" /* Intel,AMD sse3 */, "pclmulqdq|pclmuldq", "dtes64", "monitor",
+    "ds_cpl", "vmx", "smx", "est",
+    "tm2", "ssse3", "cid", NULL,
+    "fma", "cx16", "xtpr", "pdcm",
+    NULL, NULL, "dca", "sse4.1|sse4_1",
+    "sse4.2|sse4_2", "x2apic", "movbe", "popcnt",
+    "tsc-deadline", "aes", "xsave", "osxsave",
+    "avx", NULL, NULL, "hypervisor",
+};
+static const char *ext2_feature_name[] = {
+    "fpu", "vme", "de", "pse",
+    "tsc", "msr", "pae", "mce",
+    "cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall",
+    "mtrr", "pge", "mca", "cmov",
+    "pat", "pse36", NULL, NULL /* Linux mp */,
+    "nx|xd", NULL, "mmxext", "mmx",
+    "fxsr", "fxsr_opt|ffxsr", "pdpe1gb" /* AMD Page1GB */, "rdtscp",
+    NULL, "lm|i64", "3dnowext", "3dnow",
+};
+static const char *ext3_feature_name[] = {
+    "lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */,
+    "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
+    "3dnowprefetch", "osvw", "ibs", "xop",
+    "skinit", "wdt", NULL, NULL,
+    "fma4", NULL, "cvt16", "nodeid_msr",
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+};
+
+static const char *kvm_feature_name[] = {
+    "kvmclock", "kvm_nopiodelay", "kvm_mmu", "kvmclock", "kvm_asyncpf", NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+};
+
+static const char *svm_feature_name[] = {
+    "npt", "lbrv", "svm_lock", "nrip_save",
+    "tsc_scale", "vmcb_clean",  "flushbyasid", "decodeassists",
+    NULL, NULL, "pause_filter", NULL,
+    "pfthreshold", NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+};
+
+/* collects per-function cpuid data
+ */
+typedef struct model_features_t {
+    uint32_t *guest_feat;
+    uint32_t *host_feat;
+    uint32_t check_feat;
+    const char **flag_names;
+    uint32_t cpuid;
+    } model_features_t;
+
+int check_cpuid = 0;
+int enforce_cpuid = 0;
+
+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];
+
+#ifdef __x86_64__
+    asm volatile("cpuid"
+                 : "=a"(vec[0]), "=b"(vec[1]),
+                   "=c"(vec[2]), "=d"(vec[3])
+                 : "0"(function), "c"(count) : "cc");
+#else
+    asm volatile("pusha \n\t"
+                 "cpuid \n\t"
+                 "mov %%eax, 0(%2) \n\t"
+                 "mov %%ebx, 4(%2) \n\t"
+                 "mov %%ecx, 8(%2) \n\t"
+                 "mov %%edx, 12(%2) \n\t"
+                 "popa"
+                 : : "a"(function), "c"(count), "S"(vec)
+                 : "memory", "cc");
+#endif
+
+    if (eax)
+        *eax = vec[0];
+    if (ebx)
+        *ebx = vec[1];
+    if (ecx)
+        *ecx = vec[2];
+    if (edx)
+        *edx = vec[3];
+#endif
+}
+
+#define iswhite(c) ((c) && ((c) <= ' ' || '~' < (c)))
+
+/* general substring compare of *[s1..e1) and *[s2..e2).  sx is start of
+ * a substring.  ex if !NULL points to the first char after a substring,
+ * otherwise the string is assumed to sized by a terminating nul.
+ * Return lexical ordering of *s1:*s2.
+ */
+static int sstrcmp(const char *s1, const char *e1, const char *s2,
+    const char *e2)
+{
+    for (;;) {
+        if (!*s1 || !*s2 || *s1 != *s2)
+            return (*s1 - *s2);
+        ++s1, ++s2;
+        if (s1 == e1 && s2 == e2)
+            return (0);
+        else if (s1 == e1)
+            return (*s2);
+        else if (s2 == e2)
+            return (*s1);
+    }
+}
+
+/* compare *[s..e) to *altstr.  *altstr may be a simple string or multiple
+ * '|' delimited (possibly empty) strings in which case search for a match
+ * within the alternatives proceeds left to right.  Return 0 for success,
+ * non-zero otherwise.
+ */
+static int altcmp(const char *s, const char *e, const char *altstr)
+{
+    const char *p, *q;
+
+    for (q = p = altstr; ; ) {
+        while (*p && *p != '|')
+            ++p;
+        if ((q == p && !*s) || (q != p && !sstrcmp(s, e, q, p)))
+            return (0);
+        if (!*p)
+            return (1);
+        else
+            q = ++p;
+    }
+}
+
+/* search featureset for flag *[s..e), if found set corresponding bit in
+ * *pval and return true, otherwise return false
+ */
+static bool lookup_feature(uint32_t *pval, const char *s, const char *e,
+                           const char **featureset)
+{
+    uint32_t mask;
+    const char **ppc;
+    bool found = false;
+
+    for (mask = 1, ppc = featureset; mask; mask <<= 1, ++ppc) {
+        if (*ppc && !altcmp(s, e, *ppc)) {
+            *pval |= mask;
+            found = true;
+        }
+    }
+    return found;
+}
+
+static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features,
+                                    uint32_t *ext_features,
+                                    uint32_t *ext2_features,
+                                    uint32_t *ext3_features,
+                                    uint32_t *kvm_features,
+                                    uint32_t *svm_features)
+{
+    if (!lookup_feature(features, flagname, NULL, feature_name) &&
+        !lookup_feature(ext_features, flagname, NULL, ext_feature_name) &&
+        !lookup_feature(ext2_features, flagname, NULL, ext2_feature_name) &&
+        !lookup_feature(ext3_features, flagname, NULL, ext3_feature_name) &&
+        !lookup_feature(kvm_features, flagname, NULL, kvm_feature_name) &&
+        !lookup_feature(svm_features, flagname, NULL, svm_feature_name))
+            fprintf(stderr, "CPU feature %s not found\n", flagname);
+}
+
+typedef struct x86_def_t {
+    struct x86_def_t *next;
+    const char *name;
+    uint32_t level;
+    uint32_t vendor1, vendor2, vendor3;
+    int family;
+    int model;
+    int stepping;
+    int tsc_khz;
+    uint32_t features, ext_features, ext2_features, ext3_features;
+    uint32_t kvm_features, svm_features;
+    uint32_t xlevel;
+    char model_id[48];
+    int vendor_override;
+    uint32_t flags;
+    /* Store the results of Centaur's CPUID instructions */
+    uint32_t ext4_features;
+    uint32_t xlevel2;
+} x86_def_t;
+
+#define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
+#define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \
+          CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX | CPUID_APIC)
+#define PENTIUM2_FEATURES (PENTIUM_FEATURES | CPUID_PAE | CPUID_SEP | \
+          CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
+          CPUID_PSE36 | CPUID_FXSR)
+#define PENTIUM3_FEATURES (PENTIUM2_FEATURES | CPUID_SSE)
+#define PPRO_FEATURES (CPUID_FP87 | CPUID_DE | CPUID_PSE | CPUID_TSC | \
+          CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \
+          CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \
+          CPUID_PAE | CPUID_SEP | CPUID_APIC)
+#define EXT2_FEATURE_MASK 0x0183F3FF
+
+#define TCG_FEATURES (CPUID_FP87 | CPUID_PSE | CPUID_TSC | CPUID_MSR | \
+          CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC | CPUID_SEP | \
+          CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
+          CPUID_PSE36 | CPUID_CLFLUSH | CPUID_ACPI | CPUID_MMX | \
+          CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS)
+          /* partly implemented:
+          CPUID_MTRR, CPUID_MCA, CPUID_CLFLUSH (needed for Win64)
+          CPUID_PSE36 (needed for Solaris) */
+          /* missing:
+          CPUID_VME, CPUID_DTS, CPUID_SS, CPUID_HT, CPUID_TM, CPUID_PBE */
+#define TCG_EXT_FEATURES (CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | \
+          CPUID_EXT_CX16 | CPUID_EXT_POPCNT | \
+          CPUID_EXT_HYPERVISOR)
+          /* missing:
+          CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_EST,
+          CPUID_EXT_TM2, CPUID_EXT_XTPR, CPUID_EXT_PDCM, CPUID_EXT_XSAVE */
+#define TCG_EXT2_FEATURES ((TCG_FEATURES & EXT2_FEATURE_MASK) | \
+          CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_RDTSCP | \
+          CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT)
+          /* missing:
+          CPUID_EXT2_PDPE1GB */
+#define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \
+          CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A)
+#define TCG_SVM_FEATURES 0
+
+/* maintains list of cpu model definitions
+ */
+static x86_def_t *x86_defs = {NULL};
+
+/* built-in cpu model definitions (deprecated)
+ */
+static x86_def_t builtin_x86_defs[] = {
+    {
+        .name = "qemu64",
+        .level = 4,
+        .vendor1 = CPUID_VENDOR_AMD_1,
+        .vendor2 = CPUID_VENDOR_AMD_2,
+        .vendor3 = CPUID_VENDOR_AMD_3,
+        .family = 6,
+        .model = 2,
+        .stepping = 3,
+        .features = PPRO_FEATURES |
+            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
+            CPUID_PSE36,
+        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT,
+        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) |
+            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
+        .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
+            CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
+        .xlevel = 0x8000000A,
+        .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
+    },
+    {
+        .name = "phenom",
+        .level = 5,
+        .vendor1 = CPUID_VENDOR_AMD_1,
+        .vendor2 = CPUID_VENDOR_AMD_2,
+        .vendor3 = CPUID_VENDOR_AMD_3,
+        .family = 16,
+        .model = 2,
+        .stepping = 3,
+        .features = PPRO_FEATURES |
+            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
+            CPUID_PSE36 | CPUID_VME | CPUID_HT,
+        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_CX16 |
+            CPUID_EXT_POPCNT,
+        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) |
+            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX |
+            CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_MMXEXT |
+            CPUID_EXT2_FFXSR | CPUID_EXT2_PDPE1GB | CPUID_EXT2_RDTSCP,
+        /* Missing: CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC,
+                    CPUID_EXT3_CR8LEG,
+                    CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
+                    CPUID_EXT3_OSVW, CPUID_EXT3_IBS */
+        .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
+            CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
+        .svm_features = CPUID_SVM_NPT | CPUID_SVM_LBRV,
+        .xlevel = 0x8000001A,
+        .model_id = "AMD Phenom(tm) 9550 Quad-Core Processor"
+    },
+    {
+        .name = "core2duo",
+        .level = 10,
+        .family = 6,
+        .model = 15,
+        .stepping = 11,
+        .features = PPRO_FEATURES |
+            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
+            CPUID_PSE36 | CPUID_VME | CPUID_DTS | CPUID_ACPI | CPUID_SS |
+            CPUID_HT | CPUID_TM | CPUID_PBE,
+        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 |
+            CPUID_EXT_DTES64 | CPUID_EXT_DSCPL | CPUID_EXT_VMX | CPUID_EXT_EST |
+            CPUID_EXT_TM2 | CPUID_EXT_CX16 | CPUID_EXT_XTPR | CPUID_EXT_PDCM,
+        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
+        .ext3_features = CPUID_EXT3_LAHF_LM,
+        .xlevel = 0x80000008,
+        .model_id = "Intel(R) Core(TM)2 Duo CPU     T7700  @ 2.40GHz",
+    },
+    {
+        .name = "kvm64",
+        .level = 5,
+        .vendor1 = CPUID_VENDOR_INTEL_1,
+        .vendor2 = CPUID_VENDOR_INTEL_2,
+        .vendor3 = CPUID_VENDOR_INTEL_3,
+        .family = 15,
+        .model = 6,
+        .stepping = 1,
+        /* Missing: CPUID_VME, CPUID_HT */
+        .features = PPRO_FEATURES |
+            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
+            CPUID_PSE36,
+        /* Missing: CPUID_EXT_POPCNT, CPUID_EXT_MONITOR */
+        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16,
+        /* Missing: CPUID_EXT2_PDPE1GB, CPUID_EXT2_RDTSCP */
+        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) |
+            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
+        /* Missing: CPUID_EXT3_LAHF_LM, CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC,
+                    CPUID_EXT3_CR8LEG, CPUID_EXT3_ABM, CPUID_EXT3_SSE4A,
+                    CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
+                    CPUID_EXT3_OSVW, CPUID_EXT3_IBS, CPUID_EXT3_SVM */
+        .ext3_features = 0,
+        .xlevel = 0x80000008,
+        .model_id = "Common KVM processor"
+    },
+    {
+        .name = "qemu32",
+        .level = 4,
+        .family = 6,
+        .model = 3,
+        .stepping = 3,
+        .features = PPRO_FEATURES,
+        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_POPCNT,
+        .xlevel = 0x80000004,
+        .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
+    },
+    {
+        .name = "kvm32",
+        .level = 5,
+        .family = 15,
+        .model = 6,
+        .stepping = 1,
+        .features = PPRO_FEATURES |
+            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36,
+        .ext_features = CPUID_EXT_SSE3,
+        .ext2_features = PPRO_FEATURES & EXT2_FEATURE_MASK,
+        .ext3_features = 0,
+        .xlevel = 0x80000008,
+        .model_id = "Common 32-bit KVM processor"
+    },
+    {
+        .name = "coreduo",
+        .level = 10,
+        .family = 6,
+        .model = 14,
+        .stepping = 8,
+        .features = PPRO_FEATURES | CPUID_VME |
+            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_DTS | CPUID_ACPI |
+            CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE,
+        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_VMX |
+            CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR | CPUID_EXT_PDCM,
+        .ext2_features = CPUID_EXT2_NX,
+        .xlevel = 0x80000008,
+        .model_id = "Genuine Intel(R) CPU           T2600  @ 2.16GHz",
+    },
+    {
+        .name = "486",
+        .level = 1,
+        .family = 4,
+        .model = 0,
+        .stepping = 0,
+        .features = I486_FEATURES,
+        .xlevel = 0,
+    },
+    {
+        .name = "pentium",
+        .level = 1,
+        .family = 5,
+        .model = 4,
+        .stepping = 3,
+        .features = PENTIUM_FEATURES,
+        .xlevel = 0,
+    },
+    {
+        .name = "pentium2",
+        .level = 2,
+        .family = 6,
+        .model = 5,
+        .stepping = 2,
+        .features = PENTIUM2_FEATURES,
+        .xlevel = 0,
+    },
+    {
+        .name = "pentium3",
+        .level = 2,
+        .family = 6,
+        .model = 7,
+        .stepping = 3,
+        .features = PENTIUM3_FEATURES,
+        .xlevel = 0,
+    },
+    {
+        .name = "athlon",
+        .level = 2,
+        .vendor1 = CPUID_VENDOR_AMD_1,
+        .vendor2 = CPUID_VENDOR_AMD_2,
+        .vendor3 = CPUID_VENDOR_AMD_3,
+        .family = 6,
+        .model = 2,
+        .stepping = 3,
+        .features = PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR | CPUID_MCA,
+        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
+        .xlevel = 0x80000008,
+        /* XXX: put another string ? */
+        .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
+    },
+    {
+        .name = "n270",
+        /* original is on level 10 */
+        .level = 5,
+        .family = 6,
+        .model = 28,
+        .stepping = 2,
+        .features = PPRO_FEATURES |
+            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_VME | CPUID_DTS |
+            CPUID_ACPI | CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE,
+            /* Some CPUs got no CPUID_SEP */
+        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 |
+            CPUID_EXT_DSCPL | CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR,
+        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | CPUID_EXT2_NX,
+        .ext3_features = CPUID_EXT3_LAHF_LM,
+        .xlevel = 0x8000000A,
+        .model_id = "Intel(R) Atom(TM) CPU N270   @ 1.60GHz",
+    },
+};
+
+static int cpu_x86_fill_model_id(char *str)
+{
+    uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
+    int i;
+
+    for (i = 0; i < 3; i++) {
+        host_cpuid(0x80000002 + i, 0, &eax, &ebx, &ecx, &edx);
+        memcpy(str + i * 16 +  0, &eax, 4);
+        memcpy(str + i * 16 +  4, &ebx, 4);
+        memcpy(str + i * 16 +  8, &ecx, 4);
+        memcpy(str + i * 16 + 12, &edx, 4);
+    }
+    return 0;
+}
+
+static int cpu_x86_fill_host(x86_def_t *x86_cpu_def)
+{
+    uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
+
+    x86_cpu_def->name = "host";
+    host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
+    x86_cpu_def->level = eax;
+    x86_cpu_def->vendor1 = ebx;
+    x86_cpu_def->vendor2 = edx;
+    x86_cpu_def->vendor3 = ecx;
+
+    host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx);
+    x86_cpu_def->family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF);
+    x86_cpu_def->model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12);
+    x86_cpu_def->stepping = eax & 0x0F;
+    x86_cpu_def->ext_features = ecx;
+    x86_cpu_def->features = edx;
+
+    host_cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx);
+    x86_cpu_def->xlevel = eax;
+
+    host_cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx);
+    x86_cpu_def->ext2_features = edx;
+    x86_cpu_def->ext3_features = ecx;
+    cpu_x86_fill_model_id(x86_cpu_def->model_id);
+    x86_cpu_def->vendor_override = 0;
+
+    /* Call Centaur's CPUID instruction. */
+    if (x86_cpu_def->vendor1 == CPUID_VENDOR_VIA_1 &&
+        x86_cpu_def->vendor2 == CPUID_VENDOR_VIA_2 &&
+        x86_cpu_def->vendor3 == CPUID_VENDOR_VIA_3) {
+        host_cpuid(0xC0000000, 0, &eax, &ebx, &ecx, &edx);
+        if (eax >= 0xC0000001) {
+            /* Support VIA max extended level */
+            x86_cpu_def->xlevel2 = eax;
+            host_cpuid(0xC0000001, 0, &eax, &ebx, &ecx, &edx);
+            x86_cpu_def->ext4_features = edx;
+        }
+    }
+
+    /*
+     * Every SVM feature requires emulation support in KVM - so we can't just
+     * read the host features here. KVM might even support SVM features not
+     * available on the host hardware. Just set all bits and mask out the
+     * unsupported ones later.
+     */
+    x86_cpu_def->svm_features = -1;
+
+    return 0;
+}
+
+static int unavailable_host_feature(struct model_features_t *f, uint32_t mask)
+{
+    int i;
+
+    for (i = 0; i < 32; ++i)
+        if (1 << i & mask) {
+            fprintf(stderr, "warning: host cpuid %04x_%04x lacks requested"
+                " flag '%s' [0x%08x]\n",
+                f->cpuid >> 16, f->cpuid & 0xffff,
+                f->flag_names[i] ? f->flag_names[i] : "[reserved]", mask);
+            break;
+        }
+    return 0;
+}
+
+/* best effort attempt to inform user requested cpu flags aren't making
+ * their way to the guest.  Note: ft[].check_feat ideally should be
+ * specified via a guest_def field to suppress report of extraneous flags.
+ */
+static int check_features_against_host(x86_def_t *guest_def)
+{
+    x86_def_t host_def;
+    uint32_t mask;
+    int rv, i;
+    struct model_features_t ft[] = {
+        {&guest_def->features, &host_def.features,
+            ~0, feature_name, 0x00000000},
+        {&guest_def->ext_features, &host_def.ext_features,
+            ~CPUID_EXT_HYPERVISOR, ext_feature_name, 0x00000001},
+        {&guest_def->ext2_features, &host_def.ext2_features,
+            ~PPRO_FEATURES, ext2_feature_name, 0x80000000},
+        {&guest_def->ext3_features, &host_def.ext3_features,
+            ~CPUID_EXT3_SVM, ext3_feature_name, 0x80000001}};
+
+    cpu_x86_fill_host(&host_def);
+    for (rv = 0, i = 0; i < ARRAY_SIZE(ft); ++i)
+        for (mask = 1; mask; mask <<= 1)
+            if (ft[i].check_feat & mask && *ft[i].guest_feat & mask &&
+                !(*ft[i].host_feat & mask)) {
+                    unavailable_host_feature(&ft[i], mask);
+                    rv = 1;
+                }
+    return rv;
+}
+
+static void x86_cpuid_version_set_family(CPUX86State *env, int family)
+{
+    env->cpuid_version &= ~0xff00f00;
+    if (family > 0x0f) {
+        env->cpuid_version |= 0xf00 | ((family - 0x0f) << 20);
+    } else {
+        env->cpuid_version |= family << 8;
+    }
+}
+
+static void x86_cpuid_version_set_model(CPUX86State *env, int model)
+{
+    env->cpuid_version &= ~0xf00f0;
+    env->cpuid_version |= ((model & 0xf) << 4) | ((model >> 4) << 16);
+}
+
+static void x86_cpuid_version_set_stepping(CPUX86State *env, int stepping)
+{
+    env->cpuid_version &= ~0xf;
+    env->cpuid_version |= stepping & 0xf;
+}
+
+static void x86_cpuid_set_model_id(CPUX86State *env, const char *model_id)
+{
+    int c, len, i;
+
+    if (model_id == NULL) {
+        model_id = "";
+    }
+    len = strlen(model_id);
+    for (i = 0; i < 48; i++) {
+        if (i >= len) {
+            c = '\0';
+        } else {
+            c = (uint8_t)model_id[i];
+        }
+        env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
+    }
+}
+
+static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
+{
+    unsigned int i;
+    x86_def_t *def;
+
+    char *s = g_strdup(cpu_model);
+    char *featurestr, *name = strtok(s, ",");
+    /* Features to be added*/
+    uint32_t plus_features = 0, plus_ext_features = 0;
+    uint32_t plus_ext2_features = 0, plus_ext3_features = 0;
+    uint32_t plus_kvm_features = 0, plus_svm_features = 0;
+    /* Features to be removed */
+    uint32_t minus_features = 0, minus_ext_features = 0;
+    uint32_t minus_ext2_features = 0, minus_ext3_features = 0;
+    uint32_t minus_kvm_features = 0, minus_svm_features = 0;
+    uint32_t numvalue;
+
+    for (def = x86_defs; def; def = def->next)
+        if (name && !strcmp(name, def->name))
+            break;
+    if (kvm_enabled() && name && strcmp(name, "host") == 0) {
+        cpu_x86_fill_host(x86_cpu_def);
+    } else if (!def) {
+        goto error;
+    } else {
+        memcpy(x86_cpu_def, def, sizeof(*def));
+    }
+
+    plus_kvm_features = ~0; /* not supported bits will be filtered out later */
+
+    add_flagname_to_bitmaps("hypervisor", &plus_features,
+        &plus_ext_features, &plus_ext2_features, &plus_ext3_features,
+        &plus_kvm_features, &plus_svm_features);
+
+    featurestr = strtok(NULL, ",");
+
+    while (featurestr) {
+        char *val;
+        if (featurestr[0] == '+') {
+            add_flagname_to_bitmaps(featurestr + 1, &plus_features,
+                            &plus_ext_features, &plus_ext2_features,
+                            &plus_ext3_features, &plus_kvm_features,
+                            &plus_svm_features);
+        } else if (featurestr[0] == '-') {
+            add_flagname_to_bitmaps(featurestr + 1, &minus_features,
+                            &minus_ext_features, &minus_ext2_features,
+                            &minus_ext3_features, &minus_kvm_features,
+                            &minus_svm_features);
+        } else if ((val = strchr(featurestr, '='))) {
+            *val = 0; val++;
+            if (!strcmp(featurestr, "family")) {
+                char *err;
+                numvalue = strtoul(val, &err, 0);
+                if (!*val || *err) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                x86_cpu_def->family = numvalue;
+            } else if (!strcmp(featurestr, "model")) {
+                char *err;
+                numvalue = strtoul(val, &err, 0);
+                if (!*val || *err || numvalue > 0xff) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                x86_cpu_def->model = numvalue;
+            } else if (!strcmp(featurestr, "stepping")) {
+                char *err;
+                numvalue = strtoul(val, &err, 0);
+                if (!*val || *err || numvalue > 0xf) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                x86_cpu_def->stepping = numvalue ;
+            } else if (!strcmp(featurestr, "level")) {
+                char *err;
+                numvalue = strtoul(val, &err, 0);
+                if (!*val || *err) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                x86_cpu_def->level = numvalue;
+            } else if (!strcmp(featurestr, "xlevel")) {
+                char *err;
+                numvalue = strtoul(val, &err, 0);
+                if (!*val || *err) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                if (numvalue < 0x80000000) {
+                    numvalue += 0x80000000;
+                }
+                x86_cpu_def->xlevel = numvalue;
+            } else if (!strcmp(featurestr, "vendor")) {
+                if (strlen(val) != 12) {
+                    fprintf(stderr, "vendor string must be 12 chars long\n");
+                    goto error;
+                }
+                x86_cpu_def->vendor1 = 0;
+                x86_cpu_def->vendor2 = 0;
+                x86_cpu_def->vendor3 = 0;
+                for(i = 0; i < 4; i++) {
+                    x86_cpu_def->vendor1 |= ((uint8_t)val[i    ]) << (8 * i);
+                    x86_cpu_def->vendor2 |= ((uint8_t)val[i + 4]) << (8 * i);
+                    x86_cpu_def->vendor3 |= ((uint8_t)val[i + 8]) << (8 * i);
+                }
+                x86_cpu_def->vendor_override = 1;
+            } else if (!strcmp(featurestr, "model_id")) {
+                pstrcpy(x86_cpu_def->model_id, sizeof(x86_cpu_def->model_id),
+                        val);
+            } else if (!strcmp(featurestr, "tsc_freq")) {
+                int64_t tsc_freq;
+                char *err;
+
+                tsc_freq = strtosz_suffix_unit(val, &err,
+                                               STRTOSZ_DEFSUFFIX_B, 1000);
+                if (tsc_freq < 0 || *err) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                x86_cpu_def->tsc_khz = tsc_freq / 1000;
+            } else if (!strcmp(featurestr, "hv_spinlocks")) {
+                char *err;
+                numvalue = strtoul(val, &err, 0);
+                if (!*val || *err) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                hyperv_set_spinlock_retries(numvalue);
+            } else {
+                fprintf(stderr, "unrecognized feature %s\n", featurestr);
+                goto error;
+            }
+        } else if (!strcmp(featurestr, "check")) {
+            check_cpuid = 1;
+        } else if (!strcmp(featurestr, "enforce")) {
+            check_cpuid = enforce_cpuid = 1;
+        } else if (!strcmp(featurestr, "hv_relaxed")) {
+            hyperv_enable_relaxed_timing(true);
+        } else if (!strcmp(featurestr, "hv_vapic")) {
+            hyperv_enable_vapic_recommended(true);
+        } else {
+            fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr);
+            goto error;
+        }
+        featurestr = strtok(NULL, ",");
+    }
+    x86_cpu_def->features |= plus_features;
+    x86_cpu_def->ext_features |= plus_ext_features;
+    x86_cpu_def->ext2_features |= plus_ext2_features;
+    x86_cpu_def->ext3_features |= plus_ext3_features;
+    x86_cpu_def->kvm_features |= plus_kvm_features;
+    x86_cpu_def->svm_features |= plus_svm_features;
+    x86_cpu_def->features &= ~minus_features;
+    x86_cpu_def->ext_features &= ~minus_ext_features;
+    x86_cpu_def->ext2_features &= ~minus_ext2_features;
+    x86_cpu_def->ext3_features &= ~minus_ext3_features;
+    x86_cpu_def->kvm_features &= ~minus_kvm_features;
+    x86_cpu_def->svm_features &= ~minus_svm_features;
+    if (check_cpuid) {
+        if (check_features_against_host(x86_cpu_def) && enforce_cpuid)
+            goto error;
+    }
+    g_free(s);
+    return 0;
+
+error:
+    g_free(s);
+    return -1;
+}
+
+/* generate a composite string into buf of all cpuid names in featureset
+ * selected by fbits.  indicate truncation at bufsize in the event of overflow.
+ * if flags, suppress names undefined in featureset.
+ */
+static void listflags(char *buf, int bufsize, uint32_t fbits,
+    const char **featureset, uint32_t flags)
+{
+    const char **p = &featureset[31];
+    char *q, *b, bit;
+    int nc;
+
+    b = 4 <= bufsize ? buf + (bufsize -= 3) - 1 : NULL;
+    *buf = '\0';
+    for (q = buf, bit = 31; fbits && bufsize; --p, fbits &= ~(1 << bit), --bit)
+        if (fbits & 1 << bit && (*p || !flags)) {
+            if (*p)
+                nc = snprintf(q, bufsize, "%s%s", q == buf ? "" : " ", *p);
+            else
+                nc = snprintf(q, bufsize, "%s[%d]", q == buf ? "" : " ", bit);
+            if (bufsize <= nc) {
+                if (b) {
+                    memcpy(b, "...", sizeof("..."));
+                }
+                return;
+            }
+            q += nc;
+            bufsize -= nc;
+        }
+}
+
+/* generate CPU information:
+ * -?        list model names
+ * -?model   list model names/IDs
+ * -?dump    output all model (x86_def_t) data
+ * -?cpuid   list all recognized cpuid flag names
+ */
+void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf, const char *optarg)
+{
+    unsigned char model = !strcmp("?model", optarg);
+    unsigned char dump = !strcmp("?dump", optarg);
+    unsigned char cpuid = !strcmp("?cpuid", optarg);
+    x86_def_t *def;
+    char buf[256];
+
+    if (cpuid) {
+        (*cpu_fprintf)(f, "Recognized CPUID flags:\n");
+        listflags(buf, sizeof (buf), (uint32_t)~0, feature_name, 1);
+        (*cpu_fprintf)(f, "  f_edx: %s\n", buf);
+        listflags(buf, sizeof (buf), (uint32_t)~0, ext_feature_name, 1);
+        (*cpu_fprintf)(f, "  f_ecx: %s\n", buf);
+        listflags(buf, sizeof (buf), (uint32_t)~0, ext2_feature_name, 1);
+        (*cpu_fprintf)(f, "  extf_edx: %s\n", buf);
+        listflags(buf, sizeof (buf), (uint32_t)~0, ext3_feature_name, 1);
+        (*cpu_fprintf)(f, "  extf_ecx: %s\n", buf);
+        return;
+    }
+    for (def = x86_defs; def; def = def->next) {
+        snprintf(buf, sizeof (buf), def->flags ? "[%s]": "%s", def->name);
+        if (model || dump) {
+            (*cpu_fprintf)(f, "x86 %16s  %-48s\n", buf, def->model_id);
+        } else {
+            (*cpu_fprintf)(f, "x86 %16s\n", buf);
+        }
+        if (dump) {
+            memcpy(buf, &def->vendor1, sizeof (def->vendor1));
+            memcpy(buf + 4, &def->vendor2, sizeof (def->vendor2));
+            memcpy(buf + 8, &def->vendor3, sizeof (def->vendor3));
+            buf[12] = '\0';
+            (*cpu_fprintf)(f,
+                "  family %d model %d stepping %d level %d xlevel 0x%x"
+                " vendor \"%s\"\n",
+                def->family, def->model, def->stepping, def->level,
+                def->xlevel, buf);
+            listflags(buf, sizeof (buf), def->features, feature_name, 0);
+            (*cpu_fprintf)(f, "  feature_edx %08x (%s)\n", def->features,
+                buf);
+            listflags(buf, sizeof (buf), def->ext_features, ext_feature_name,
+                0);
+            (*cpu_fprintf)(f, "  feature_ecx %08x (%s)\n", def->ext_features,
+                buf);
+            listflags(buf, sizeof (buf), def->ext2_features, ext2_feature_name,
+                0);
+            (*cpu_fprintf)(f, "  extfeature_edx %08x (%s)\n",
+                def->ext2_features, buf);
+            listflags(buf, sizeof (buf), def->ext3_features, ext3_feature_name,
+                0);
+            (*cpu_fprintf)(f, "  extfeature_ecx %08x (%s)\n",
+                def->ext3_features, buf);
+            (*cpu_fprintf)(f, "\n");
+        }
+    }
+    if (kvm_enabled()) {
+        (*cpu_fprintf)(f, "x86 %16s\n", "[host]");
+    }
+}
+
+int cpu_x86_register (CPUX86State *env, const char *cpu_model)
+{
+    x86_def_t def1, *def = &def1;
+
+    memset(def, 0, sizeof(*def));
+
+    if (cpu_x86_find_by_name(def, cpu_model) < 0)
+        return -1;
+    if (def->vendor1) {
+        env->cpuid_vendor1 = def->vendor1;
+        env->cpuid_vendor2 = def->vendor2;
+        env->cpuid_vendor3 = def->vendor3;
+    } else {
+        env->cpuid_vendor1 = CPUID_VENDOR_INTEL_1;
+        env->cpuid_vendor2 = CPUID_VENDOR_INTEL_2;
+        env->cpuid_vendor3 = CPUID_VENDOR_INTEL_3;
+    }
+    env->cpuid_vendor_override = def->vendor_override;
+    env->cpuid_level = def->level;
+    x86_cpuid_version_set_family(env, def->family);
+    x86_cpuid_version_set_model(env, def->model);
+    x86_cpuid_version_set_stepping(env, def->stepping);
+    env->cpuid_features = def->features;
+    env->cpuid_ext_features = def->ext_features;
+    env->cpuid_ext2_features = def->ext2_features;
+    env->cpuid_ext3_features = def->ext3_features;
+    env->cpuid_xlevel = def->xlevel;
+    env->cpuid_kvm_features = def->kvm_features;
+    env->cpuid_svm_features = def->svm_features;
+    env->cpuid_ext4_features = def->ext4_features;
+    env->cpuid_xlevel2 = def->xlevel2;
+    env->tsc_khz = def->tsc_khz;
+    if (!kvm_enabled()) {
+        env->cpuid_features &= TCG_FEATURES;
+        env->cpuid_ext_features &= TCG_EXT_FEATURES;
+        env->cpuid_ext2_features &= (TCG_EXT2_FEATURES
+#ifdef TARGET_X86_64
+            | CPUID_EXT2_SYSCALL | CPUID_EXT2_LM
+#endif
+            );
+        env->cpuid_ext3_features &= TCG_EXT3_FEATURES;
+        env->cpuid_svm_features &= TCG_SVM_FEATURES;
+    }
+    x86_cpuid_set_model_id(env, def->model_id);
+    return 0;
+}
+
+#if !defined(CONFIG_USER_ONLY)
+/* copy vendor id string to 32 bit register, nul pad as needed
+ */
+static void cpyid(const char *s, uint32_t *id)
+{
+    char *d = (char *)id;
+    char i;
+
+    for (i = sizeof (*id); i--; )
+        *d++ = *s ? *s++ : '\0';
+}
+
+/* interpret radix and convert from string to arbitrary scalar,
+ * otherwise flag failure
+ */
+#define setscalar(pval, str, perr)                      \
+{                                                       \
+    char *pend;                                         \
+    unsigned long ul;                                   \
+                                                        \
+    ul = strtoul(str, &pend, 0);                        \
+    *str && !*pend ? (*pval = ul) : (*perr = 1);        \
+}
+
+/* map cpuid options to feature bits, otherwise return failure
+ * (option tags in *str are delimited by whitespace)
+ */
+static void setfeatures(uint32_t *pval, const char *str,
+    const char **featureset, int *perr)
+{
+    const char *p, *q;
+
+    for (q = p = str; *p || *q; q = p) {
+        while (iswhite(*p))
+            q = ++p;
+        while (*p && !iswhite(*p))
+            ++p;
+        if (!*q && !*p)
+            return;
+        if (!lookup_feature(pval, q, p, featureset)) {
+            fprintf(stderr, "error: feature \"%.*s\" not available in set\n",
+                (int)(p - q), q);
+            *perr = 1;
+            return;
+        }
+    }
+}
+
+/* map config file options to x86_def_t form
+ */
+static int cpudef_setfield(const char *name, const char *str, void *opaque)
+{
+    x86_def_t *def = opaque;
+    int err = 0;
+
+    if (!strcmp(name, "name")) {
+        g_free((void *)def->name);
+        def->name = g_strdup(str);
+    } else if (!strcmp(name, "model_id")) {
+        strncpy(def->model_id, str, sizeof (def->model_id));
+    } else if (!strcmp(name, "level")) {
+        setscalar(&def->level, str, &err)
+    } else if (!strcmp(name, "vendor")) {
+        cpyid(&str[0], &def->vendor1);
+        cpyid(&str[4], &def->vendor2);
+        cpyid(&str[8], &def->vendor3);
+    } else if (!strcmp(name, "family")) {
+        setscalar(&def->family, str, &err)
+    } else if (!strcmp(name, "model")) {
+        setscalar(&def->model, str, &err)
+    } else if (!strcmp(name, "stepping")) {
+        setscalar(&def->stepping, str, &err)
+    } else if (!strcmp(name, "feature_edx")) {
+        setfeatures(&def->features, str, feature_name, &err);
+    } else if (!strcmp(name, "feature_ecx")) {
+        setfeatures(&def->ext_features, str, ext_feature_name, &err);
+    } else if (!strcmp(name, "extfeature_edx")) {
+        setfeatures(&def->ext2_features, str, ext2_feature_name, &err);
+    } else if (!strcmp(name, "extfeature_ecx")) {
+        setfeatures(&def->ext3_features, str, ext3_feature_name, &err);
+    } else if (!strcmp(name, "xlevel")) {
+        setscalar(&def->xlevel, str, &err)
+    } else {
+        fprintf(stderr, "error: unknown option [%s = %s]\n", name, str);
+        return (1);
+    }
+    if (err) {
+        fprintf(stderr, "error: bad option value [%s = %s]\n", name, str);
+        return (1);
+    }
+    return (0);
+}
+
+/* register config file entry as x86_def_t
+ */
+static int cpudef_register(QemuOpts *opts, void *opaque)
+{
+    x86_def_t *def = g_malloc0(sizeof (x86_def_t));
+
+    qemu_opt_foreach(opts, cpudef_setfield, def, 1);
+    def->next = x86_defs;
+    x86_defs = def;
+    return (0);
+}
+
+void cpu_clear_apic_feature(CPUX86State *env)
+{
+    env->cpuid_features &= ~CPUID_APIC;
+}
+
+#endif /* !CONFIG_USER_ONLY */
+
+/* register "cpudef" models defined in configuration file.  Here we first
+ * preload any built-in definitions
+ */
+void x86_cpudef_setup(void)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); ++i) {
+        builtin_x86_defs[i].next = x86_defs;
+        builtin_x86_defs[i].flags = 1;
+        x86_defs = &builtin_x86_defs[i];
+    }
+#if !defined(CONFIG_USER_ONLY)
+    qemu_opts_foreach(qemu_find_opts("cpudef"), cpudef_register, NULL, 0);
+#endif
+}
+
+static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx,
+                             uint32_t *ecx, uint32_t *edx)
+{
+    *ebx = env->cpuid_vendor1;
+    *edx = env->cpuid_vendor2;
+    *ecx = env->cpuid_vendor3;
+
+    /* sysenter isn't supported on compatibility mode on AMD, syscall
+     * isn't supported in compatibility mode on Intel.
+     * Normally we advertise the actual cpu vendor, but you can override
+     * this if you want to use KVM's sysenter/syscall emulation
+     * in compatibility mode and when doing cross vendor migration
+     */
+    if (kvm_enabled() && ! env->cpuid_vendor_override) {
+        host_cpuid(0, 0, NULL, ebx, ecx, edx);
+    }
+}
+
+void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
+                   uint32_t *eax, uint32_t *ebx,
+                   uint32_t *ecx, uint32_t *edx)
+{
+    /* test if maximum index reached */
+    if (index & 0x80000000) {
+        if (index > env->cpuid_xlevel) {
+            if (env->cpuid_xlevel2 > 0) {
+                /* Handle the Centaur's CPUID instruction. */
+                if (index > env->cpuid_xlevel2) {
+                    index = env->cpuid_xlevel2;
+                } else if (index < 0xC0000000) {
+                    index = env->cpuid_xlevel;
+                }
+            } else {
+                index =  env->cpuid_xlevel;
+            }
+        }
+    } else {
+        if (index > env->cpuid_level)
+            index = env->cpuid_level;
+    }
+
+    switch(index) {
+    case 0:
+        *eax = env->cpuid_level;
+        get_cpuid_vendor(env, ebx, ecx, edx);
+        break;
+    case 1:
+        *eax = env->cpuid_version;
+        *ebx = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
+        *ecx = env->cpuid_ext_features;
+        *edx = env->cpuid_features;
+        if (env->nr_cores * env->nr_threads > 1) {
+            *ebx |= (env->nr_cores * env->nr_threads) << 16;
+            *edx |= 1 << 28;    /* HTT bit */
+        }
+        break;
+    case 2:
+        /* cache info: needed for Pentium Pro compatibility */
+        *eax = 1;
+        *ebx = 0;
+        *ecx = 0;
+        *edx = 0x2c307d;
+        break;
+    case 4:
+        /* cache info: needed for Core compatibility */
+        if (env->nr_cores > 1) {
+            *eax = (env->nr_cores - 1) << 26;
+        } else {
+            *eax = 0;
+        }
+        switch (count) {
+            case 0: /* L1 dcache info */
+                *eax |= 0x0000121;
+                *ebx = 0x1c0003f;
+                *ecx = 0x000003f;
+                *edx = 0x0000001;
+                break;
+            case 1: /* L1 icache info */
+                *eax |= 0x0000122;
+                *ebx = 0x1c0003f;
+                *ecx = 0x000003f;
+                *edx = 0x0000001;
+                break;
+            case 2: /* L2 cache info */
+                *eax |= 0x0000143;
+                if (env->nr_threads > 1) {
+                    *eax |= (env->nr_threads - 1) << 14;
+                }
+                *ebx = 0x3c0003f;
+                *ecx = 0x0000fff;
+                *edx = 0x0000001;
+                break;
+            default: /* end of info */
+                *eax = 0;
+                *ebx = 0;
+                *ecx = 0;
+                *edx = 0;
+                break;
+        }
+        break;
+    case 5:
+        /* mwait info: needed for Core compatibility */
+        *eax = 0; /* Smallest monitor-line size in bytes */
+        *ebx = 0; /* Largest monitor-line size in bytes */
+        *ecx = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE;
+        *edx = 0;
+        break;
+    case 6:
+        /* Thermal and Power Leaf */
+        *eax = 0;
+        *ebx = 0;
+        *ecx = 0;
+        *edx = 0;
+        break;
+    case 7:
+        if (kvm_enabled()) {
+            KVMState *s = env->kvm_state;
+
+            *eax = kvm_arch_get_supported_cpuid(s, 0x7, count, R_EAX);
+            *ebx = kvm_arch_get_supported_cpuid(s, 0x7, count, R_EBX);
+            *ecx = kvm_arch_get_supported_cpuid(s, 0x7, count, R_ECX);
+            *edx = kvm_arch_get_supported_cpuid(s, 0x7, count, R_EDX);
+        } else {
+            *eax = 0;
+            *ebx = 0;
+            *ecx = 0;
+            *edx = 0;
+        }
+        break;
+    case 9:
+        /* Direct Cache Access Information Leaf */
+        *eax = 0; /* Bits 0-31 in DCA_CAP MSR */
+        *ebx = 0;
+        *ecx = 0;
+        *edx = 0;
+        break;
+    case 0xA:
+        /* Architectural Performance Monitoring Leaf */
+        if (kvm_enabled()) {
+            KVMState *s = env->kvm_state;
+
+            *eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX);
+            *ebx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EBX);
+            *ecx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_ECX);
+            *edx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EDX);
+        } else {
+            *eax = 0;
+            *ebx = 0;
+            *ecx = 0;
+            *edx = 0;
+        }
+        break;
+    case 0xD:
+        /* Processor Extended State */
+        if (!(env->cpuid_ext_features & CPUID_EXT_XSAVE)) {
+            *eax = 0;
+            *ebx = 0;
+            *ecx = 0;
+            *edx = 0;
+            break;
+        }
+        if (kvm_enabled()) {
+            KVMState *s = env->kvm_state;
+
+            *eax = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EAX);
+            *ebx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EBX);
+            *ecx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_ECX);
+            *edx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EDX);
+        } else {
+            *eax = 0;
+            *ebx = 0;
+            *ecx = 0;
+            *edx = 0;
+        }
+        break;
+    case 0x80000000:
+        *eax = env->cpuid_xlevel;
+        *ebx = env->cpuid_vendor1;
+        *edx = env->cpuid_vendor2;
+        *ecx = env->cpuid_vendor3;
+        break;
+    case 0x80000001:
+        *eax = env->cpuid_version;
+        *ebx = 0;
+        *ecx = env->cpuid_ext3_features;
+        *edx = env->cpuid_ext2_features;
+
+        /* The Linux kernel checks for the CMPLegacy bit and
+         * discards multiple thread information if it is set.
+         * So dont set it here for Intel to make Linux guests happy.
+         */
+        if (env->nr_cores * env->nr_threads > 1) {
+            uint32_t tebx, tecx, tedx;
+            get_cpuid_vendor(env, &tebx, &tecx, &tedx);
+            if (tebx != CPUID_VENDOR_INTEL_1 ||
+                tedx != CPUID_VENDOR_INTEL_2 ||
+                tecx != CPUID_VENDOR_INTEL_3) {
+                *ecx |= 1 << 1;    /* CmpLegacy bit */
+            }
+        }
+        break;
+    case 0x80000002:
+    case 0x80000003:
+    case 0x80000004:
+        *eax = env->cpuid_model[(index - 0x80000002) * 4 + 0];
+        *ebx = env->cpuid_model[(index - 0x80000002) * 4 + 1];
+        *ecx = env->cpuid_model[(index - 0x80000002) * 4 + 2];
+        *edx = env->cpuid_model[(index - 0x80000002) * 4 + 3];
+        break;
+    case 0x80000005:
+        /* cache info (L1 cache) */
+        *eax = 0x01ff01ff;
+        *ebx = 0x01ff01ff;
+        *ecx = 0x40020140;
+        *edx = 0x40020140;
+        break;
+    case 0x80000006:
+        /* cache info (L2 cache) */
+        *eax = 0;
+        *ebx = 0x42004200;
+        *ecx = 0x02008140;
+        *edx = 0;
+        break;
+    case 0x80000008:
+        /* virtual & phys address size in low 2 bytes. */
+/* XXX: This value must match the one used in the MMU code. */
+        if (env->cpuid_ext2_features & CPUID_EXT2_LM) {
+            /* 64 bit processor */
+/* XXX: The physical address space is limited to 42 bits in exec.c. */
+            *eax = 0x00003028;	/* 48 bits virtual, 40 bits physical */
+        } else {
+            if (env->cpuid_features & CPUID_PSE36)
+                *eax = 0x00000024; /* 36 bits physical */
+            else
+                *eax = 0x00000020; /* 32 bits physical */
+        }
+        *ebx = 0;
+        *ecx = 0;
+        *edx = 0;
+        if (env->nr_cores * env->nr_threads > 1) {
+            *ecx |= (env->nr_cores * env->nr_threads) - 1;
+        }
+        break;
+    case 0x8000000A:
+	if (env->cpuid_ext3_features & CPUID_EXT3_SVM) {
+		*eax = 0x00000001; /* SVM Revision */
+		*ebx = 0x00000010; /* nr of ASIDs */
+		*ecx = 0;
+		*edx = env->cpuid_svm_features; /* optional features */
+	} else {
+		*eax = 0;
+		*ebx = 0;
+		*ecx = 0;
+		*edx = 0;
+	}
+        break;
+    case 0xC0000000:
+        *eax = env->cpuid_xlevel2;
+        *ebx = 0;
+        *ecx = 0;
+        *edx = 0;
+        break;
+    case 0xC0000001:
+        /* Support for VIA CPU's CPUID instruction */
+        *eax = env->cpuid_version;
+        *ebx = 0;
+        *ecx = 0;
+        *edx = env->cpuid_ext4_features;
+        break;
+    case 0xC0000002:
+    case 0xC0000003:
+    case 0xC0000004:
+        /* Reserved for the future, and now filled with zero */
+        *eax = 0;
+        *ebx = 0;
+        *ecx = 0;
+        *edx = 0;
+        break;
+    default:
+        /* reserved values: zero */
+        *eax = 0;
+        *ebx = 0;
+        *ecx = 0;
+        *edx = 0;
+        break;
+    }
+}
diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
deleted file mode 100644
index 465ea15..0000000
--- a/target-i386/cpuid.c
+++ /dev/null
@@ -1,1369 +0,0 @@
-/*
- *  i386 CPUID helper functions
- *
- *  Copyright (c) 2003 Fabrice Bellard
- *
- * 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/>.
- */
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
-
-#include "cpu.h"
-#include "kvm.h"
-
-#include "qemu-option.h"
-#include "qemu-config.h"
-
-#include "hyperv.h"
-
-/* feature flags taken from "Intel Processor Identification and the CPUID
- * Instruction" and AMD's "CPUID Specification".  In cases of disagreement
- * between feature naming conventions, aliases may be added.
- */
-static const char *feature_name[] = {
-    "fpu", "vme", "de", "pse",
-    "tsc", "msr", "pae", "mce",
-    "cx8", "apic", NULL, "sep",
-    "mtrr", "pge", "mca", "cmov",
-    "pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */,
-    NULL, "ds" /* Intel dts */, "acpi", "mmx",
-    "fxsr", "sse", "sse2", "ss",
-    "ht" /* Intel htt */, "tm", "ia64", "pbe",
-};
-static const char *ext_feature_name[] = {
-    "pni|sse3" /* Intel,AMD sse3 */, "pclmulqdq|pclmuldq", "dtes64", "monitor",
-    "ds_cpl", "vmx", "smx", "est",
-    "tm2", "ssse3", "cid", NULL,
-    "fma", "cx16", "xtpr", "pdcm",
-    NULL, NULL, "dca", "sse4.1|sse4_1",
-    "sse4.2|sse4_2", "x2apic", "movbe", "popcnt",
-    "tsc-deadline", "aes", "xsave", "osxsave",
-    "avx", NULL, NULL, "hypervisor",
-};
-static const char *ext2_feature_name[] = {
-    "fpu", "vme", "de", "pse",
-    "tsc", "msr", "pae", "mce",
-    "cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall",
-    "mtrr", "pge", "mca", "cmov",
-    "pat", "pse36", NULL, NULL /* Linux mp */,
-    "nx|xd", NULL, "mmxext", "mmx",
-    "fxsr", "fxsr_opt|ffxsr", "pdpe1gb" /* AMD Page1GB */, "rdtscp",
-    NULL, "lm|i64", "3dnowext", "3dnow",
-};
-static const char *ext3_feature_name[] = {
-    "lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */,
-    "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
-    "3dnowprefetch", "osvw", "ibs", "xop",
-    "skinit", "wdt", NULL, NULL,
-    "fma4", NULL, "cvt16", "nodeid_msr",
-    NULL, NULL, NULL, NULL,
-    NULL, NULL, NULL, NULL,
-    NULL, NULL, NULL, NULL,
-};
-
-static const char *kvm_feature_name[] = {
-    "kvmclock", "kvm_nopiodelay", "kvm_mmu", "kvmclock", "kvm_asyncpf", NULL, NULL, NULL,
-    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-};
-
-static const char *svm_feature_name[] = {
-    "npt", "lbrv", "svm_lock", "nrip_save",
-    "tsc_scale", "vmcb_clean",  "flushbyasid", "decodeassists",
-    NULL, NULL, "pause_filter", NULL,
-    "pfthreshold", NULL, NULL, NULL,
-    NULL, NULL, NULL, NULL,
-    NULL, NULL, NULL, NULL,
-    NULL, NULL, NULL, NULL,
-    NULL, NULL, NULL, NULL,
-};
-
-/* collects per-function cpuid data
- */
-typedef struct model_features_t {
-    uint32_t *guest_feat;
-    uint32_t *host_feat;
-    uint32_t check_feat;
-    const char **flag_names;
-    uint32_t cpuid;
-    } model_features_t;
-
-int check_cpuid = 0;
-int enforce_cpuid = 0;
-
-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];
-
-#ifdef __x86_64__
-    asm volatile("cpuid"
-                 : "=a"(vec[0]), "=b"(vec[1]),
-                   "=c"(vec[2]), "=d"(vec[3])
-                 : "0"(function), "c"(count) : "cc");
-#else
-    asm volatile("pusha \n\t"
-                 "cpuid \n\t"
-                 "mov %%eax, 0(%2) \n\t"
-                 "mov %%ebx, 4(%2) \n\t"
-                 "mov %%ecx, 8(%2) \n\t"
-                 "mov %%edx, 12(%2) \n\t"
-                 "popa"
-                 : : "a"(function), "c"(count), "S"(vec)
-                 : "memory", "cc");
-#endif
-
-    if (eax)
-        *eax = vec[0];
-    if (ebx)
-        *ebx = vec[1];
-    if (ecx)
-        *ecx = vec[2];
-    if (edx)
-        *edx = vec[3];
-#endif
-}
-
-#define iswhite(c) ((c) && ((c) <= ' ' || '~' < (c)))
-
-/* general substring compare of *[s1..e1) and *[s2..e2).  sx is start of
- * a substring.  ex if !NULL points to the first char after a substring,
- * otherwise the string is assumed to sized by a terminating nul.
- * Return lexical ordering of *s1:*s2.
- */
-static int sstrcmp(const char *s1, const char *e1, const char *s2,
-    const char *e2)
-{
-    for (;;) {
-        if (!*s1 || !*s2 || *s1 != *s2)
-            return (*s1 - *s2);
-        ++s1, ++s2;
-        if (s1 == e1 && s2 == e2)
-            return (0);
-        else if (s1 == e1)
-            return (*s2);
-        else if (s2 == e2)
-            return (*s1);
-    }
-}
-
-/* compare *[s..e) to *altstr.  *altstr may be a simple string or multiple
- * '|' delimited (possibly empty) strings in which case search for a match
- * within the alternatives proceeds left to right.  Return 0 for success,
- * non-zero otherwise.
- */
-static int altcmp(const char *s, const char *e, const char *altstr)
-{
-    const char *p, *q;
-
-    for (q = p = altstr; ; ) {
-        while (*p && *p != '|')
-            ++p;
-        if ((q == p && !*s) || (q != p && !sstrcmp(s, e, q, p)))
-            return (0);
-        if (!*p)
-            return (1);
-        else
-            q = ++p;
-    }
-}
-
-/* search featureset for flag *[s..e), if found set corresponding bit in
- * *pval and return true, otherwise return false
- */
-static bool lookup_feature(uint32_t *pval, const char *s, const char *e,
-                           const char **featureset)
-{
-    uint32_t mask;
-    const char **ppc;
-    bool found = false;
-
-    for (mask = 1, ppc = featureset; mask; mask <<= 1, ++ppc) {
-        if (*ppc && !altcmp(s, e, *ppc)) {
-            *pval |= mask;
-            found = true;
-        }
-    }
-    return found;
-}
-
-static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features,
-                                    uint32_t *ext_features,
-                                    uint32_t *ext2_features,
-                                    uint32_t *ext3_features,
-                                    uint32_t *kvm_features,
-                                    uint32_t *svm_features)
-{
-    if (!lookup_feature(features, flagname, NULL, feature_name) &&
-        !lookup_feature(ext_features, flagname, NULL, ext_feature_name) &&
-        !lookup_feature(ext2_features, flagname, NULL, ext2_feature_name) &&
-        !lookup_feature(ext3_features, flagname, NULL, ext3_feature_name) &&
-        !lookup_feature(kvm_features, flagname, NULL, kvm_feature_name) &&
-        !lookup_feature(svm_features, flagname, NULL, svm_feature_name))
-            fprintf(stderr, "CPU feature %s not found\n", flagname);
-}
-
-typedef struct x86_def_t {
-    struct x86_def_t *next;
-    const char *name;
-    uint32_t level;
-    uint32_t vendor1, vendor2, vendor3;
-    int family;
-    int model;
-    int stepping;
-    int tsc_khz;
-    uint32_t features, ext_features, ext2_features, ext3_features;
-    uint32_t kvm_features, svm_features;
-    uint32_t xlevel;
-    char model_id[48];
-    int vendor_override;
-    uint32_t flags;
-    /* Store the results of Centaur's CPUID instructions */
-    uint32_t ext4_features;
-    uint32_t xlevel2;
-} x86_def_t;
-
-#define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
-#define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \
-          CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX | CPUID_APIC)
-#define PENTIUM2_FEATURES (PENTIUM_FEATURES | CPUID_PAE | CPUID_SEP | \
-          CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
-          CPUID_PSE36 | CPUID_FXSR)
-#define PENTIUM3_FEATURES (PENTIUM2_FEATURES | CPUID_SSE)
-#define PPRO_FEATURES (CPUID_FP87 | CPUID_DE | CPUID_PSE | CPUID_TSC | \
-          CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \
-          CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \
-          CPUID_PAE | CPUID_SEP | CPUID_APIC)
-#define EXT2_FEATURE_MASK 0x0183F3FF
-
-#define TCG_FEATURES (CPUID_FP87 | CPUID_PSE | CPUID_TSC | CPUID_MSR | \
-          CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC | CPUID_SEP | \
-          CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
-          CPUID_PSE36 | CPUID_CLFLUSH | CPUID_ACPI | CPUID_MMX | \
-          CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS)
-          /* partly implemented:
-          CPUID_MTRR, CPUID_MCA, CPUID_CLFLUSH (needed for Win64)
-          CPUID_PSE36 (needed for Solaris) */
-          /* missing:
-          CPUID_VME, CPUID_DTS, CPUID_SS, CPUID_HT, CPUID_TM, CPUID_PBE */
-#define TCG_EXT_FEATURES (CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | \
-          CPUID_EXT_CX16 | CPUID_EXT_POPCNT | \
-          CPUID_EXT_HYPERVISOR)
-          /* missing:
-          CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_EST,
-          CPUID_EXT_TM2, CPUID_EXT_XTPR, CPUID_EXT_PDCM, CPUID_EXT_XSAVE */
-#define TCG_EXT2_FEATURES ((TCG_FEATURES & EXT2_FEATURE_MASK) | \
-          CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_RDTSCP | \
-          CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT)
-          /* missing:
-          CPUID_EXT2_PDPE1GB */
-#define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \
-          CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A)
-#define TCG_SVM_FEATURES 0
-
-/* maintains list of cpu model definitions
- */
-static x86_def_t *x86_defs = {NULL};
-
-/* built-in cpu model definitions (deprecated)
- */
-static x86_def_t builtin_x86_defs[] = {
-    {
-        .name = "qemu64",
-        .level = 4,
-        .vendor1 = CPUID_VENDOR_AMD_1,
-        .vendor2 = CPUID_VENDOR_AMD_2,
-        .vendor3 = CPUID_VENDOR_AMD_3,
-        .family = 6,
-        .model = 2,
-        .stepping = 3,
-        .features = PPRO_FEATURES |
-            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
-            CPUID_PSE36,
-        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT,
-        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) |
-            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
-        .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
-            CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
-        .xlevel = 0x8000000A,
-        .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
-    },
-    {
-        .name = "phenom",
-        .level = 5,
-        .vendor1 = CPUID_VENDOR_AMD_1,
-        .vendor2 = CPUID_VENDOR_AMD_2,
-        .vendor3 = CPUID_VENDOR_AMD_3,
-        .family = 16,
-        .model = 2,
-        .stepping = 3,
-        .features = PPRO_FEATURES |
-            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
-            CPUID_PSE36 | CPUID_VME | CPUID_HT,
-        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_CX16 |
-            CPUID_EXT_POPCNT,
-        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) |
-            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX |
-            CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_MMXEXT |
-            CPUID_EXT2_FFXSR | CPUID_EXT2_PDPE1GB | CPUID_EXT2_RDTSCP,
-        /* Missing: CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC,
-                    CPUID_EXT3_CR8LEG,
-                    CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
-                    CPUID_EXT3_OSVW, CPUID_EXT3_IBS */
-        .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
-            CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
-        .svm_features = CPUID_SVM_NPT | CPUID_SVM_LBRV,
-        .xlevel = 0x8000001A,
-        .model_id = "AMD Phenom(tm) 9550 Quad-Core Processor"
-    },
-    {
-        .name = "core2duo",
-        .level = 10,
-        .family = 6,
-        .model = 15,
-        .stepping = 11,
-        .features = PPRO_FEATURES |
-            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
-            CPUID_PSE36 | CPUID_VME | CPUID_DTS | CPUID_ACPI | CPUID_SS |
-            CPUID_HT | CPUID_TM | CPUID_PBE,
-        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 |
-            CPUID_EXT_DTES64 | CPUID_EXT_DSCPL | CPUID_EXT_VMX | CPUID_EXT_EST |
-            CPUID_EXT_TM2 | CPUID_EXT_CX16 | CPUID_EXT_XTPR | CPUID_EXT_PDCM,
-        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
-        .ext3_features = CPUID_EXT3_LAHF_LM,
-        .xlevel = 0x80000008,
-        .model_id = "Intel(R) Core(TM)2 Duo CPU     T7700  @ 2.40GHz",
-    },
-    {
-        .name = "kvm64",
-        .level = 5,
-        .vendor1 = CPUID_VENDOR_INTEL_1,
-        .vendor2 = CPUID_VENDOR_INTEL_2,
-        .vendor3 = CPUID_VENDOR_INTEL_3,
-        .family = 15,
-        .model = 6,
-        .stepping = 1,
-        /* Missing: CPUID_VME, CPUID_HT */
-        .features = PPRO_FEATURES |
-            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
-            CPUID_PSE36,
-        /* Missing: CPUID_EXT_POPCNT, CPUID_EXT_MONITOR */
-        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16,
-        /* Missing: CPUID_EXT2_PDPE1GB, CPUID_EXT2_RDTSCP */
-        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) |
-            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
-        /* Missing: CPUID_EXT3_LAHF_LM, CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC,
-                    CPUID_EXT3_CR8LEG, CPUID_EXT3_ABM, CPUID_EXT3_SSE4A,
-                    CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
-                    CPUID_EXT3_OSVW, CPUID_EXT3_IBS, CPUID_EXT3_SVM */
-        .ext3_features = 0,
-        .xlevel = 0x80000008,
-        .model_id = "Common KVM processor"
-    },
-    {
-        .name = "qemu32",
-        .level = 4,
-        .family = 6,
-        .model = 3,
-        .stepping = 3,
-        .features = PPRO_FEATURES,
-        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_POPCNT,
-        .xlevel = 0x80000004,
-        .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
-    },
-    {
-        .name = "kvm32",
-        .level = 5,
-        .family = 15,
-        .model = 6,
-        .stepping = 1,
-        .features = PPRO_FEATURES |
-            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36,
-        .ext_features = CPUID_EXT_SSE3,
-        .ext2_features = PPRO_FEATURES & EXT2_FEATURE_MASK,
-        .ext3_features = 0,
-        .xlevel = 0x80000008,
-        .model_id = "Common 32-bit KVM processor"
-    },
-    {
-        .name = "coreduo",
-        .level = 10,
-        .family = 6,
-        .model = 14,
-        .stepping = 8,
-        .features = PPRO_FEATURES | CPUID_VME |
-            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_DTS | CPUID_ACPI |
-            CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE,
-        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_VMX |
-            CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR | CPUID_EXT_PDCM,
-        .ext2_features = CPUID_EXT2_NX,
-        .xlevel = 0x80000008,
-        .model_id = "Genuine Intel(R) CPU           T2600  @ 2.16GHz",
-    },
-    {
-        .name = "486",
-        .level = 1,
-        .family = 4,
-        .model = 0,
-        .stepping = 0,
-        .features = I486_FEATURES,
-        .xlevel = 0,
-    },
-    {
-        .name = "pentium",
-        .level = 1,
-        .family = 5,
-        .model = 4,
-        .stepping = 3,
-        .features = PENTIUM_FEATURES,
-        .xlevel = 0,
-    },
-    {
-        .name = "pentium2",
-        .level = 2,
-        .family = 6,
-        .model = 5,
-        .stepping = 2,
-        .features = PENTIUM2_FEATURES,
-        .xlevel = 0,
-    },
-    {
-        .name = "pentium3",
-        .level = 2,
-        .family = 6,
-        .model = 7,
-        .stepping = 3,
-        .features = PENTIUM3_FEATURES,
-        .xlevel = 0,
-    },
-    {
-        .name = "athlon",
-        .level = 2,
-        .vendor1 = CPUID_VENDOR_AMD_1,
-        .vendor2 = CPUID_VENDOR_AMD_2,
-        .vendor3 = CPUID_VENDOR_AMD_3,
-        .family = 6,
-        .model = 2,
-        .stepping = 3,
-        .features = PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR | CPUID_MCA,
-        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
-        .xlevel = 0x80000008,
-        /* XXX: put another string ? */
-        .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
-    },
-    {
-        .name = "n270",
-        /* original is on level 10 */
-        .level = 5,
-        .family = 6,
-        .model = 28,
-        .stepping = 2,
-        .features = PPRO_FEATURES |
-            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_VME | CPUID_DTS |
-            CPUID_ACPI | CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE,
-            /* Some CPUs got no CPUID_SEP */
-        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 |
-            CPUID_EXT_DSCPL | CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR,
-        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | CPUID_EXT2_NX,
-        .ext3_features = CPUID_EXT3_LAHF_LM,
-        .xlevel = 0x8000000A,
-        .model_id = "Intel(R) Atom(TM) CPU N270   @ 1.60GHz",
-    },
-};
-
-static int cpu_x86_fill_model_id(char *str)
-{
-    uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
-    int i;
-
-    for (i = 0; i < 3; i++) {
-        host_cpuid(0x80000002 + i, 0, &eax, &ebx, &ecx, &edx);
-        memcpy(str + i * 16 +  0, &eax, 4);
-        memcpy(str + i * 16 +  4, &ebx, 4);
-        memcpy(str + i * 16 +  8, &ecx, 4);
-        memcpy(str + i * 16 + 12, &edx, 4);
-    }
-    return 0;
-}
-
-static int cpu_x86_fill_host(x86_def_t *x86_cpu_def)
-{
-    uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
-
-    x86_cpu_def->name = "host";
-    host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
-    x86_cpu_def->level = eax;
-    x86_cpu_def->vendor1 = ebx;
-    x86_cpu_def->vendor2 = edx;
-    x86_cpu_def->vendor3 = ecx;
-
-    host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx);
-    x86_cpu_def->family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF);
-    x86_cpu_def->model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12);
-    x86_cpu_def->stepping = eax & 0x0F;
-    x86_cpu_def->ext_features = ecx;
-    x86_cpu_def->features = edx;
-
-    host_cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx);
-    x86_cpu_def->xlevel = eax;
-
-    host_cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx);
-    x86_cpu_def->ext2_features = edx;
-    x86_cpu_def->ext3_features = ecx;
-    cpu_x86_fill_model_id(x86_cpu_def->model_id);
-    x86_cpu_def->vendor_override = 0;
-
-    /* Call Centaur's CPUID instruction. */
-    if (x86_cpu_def->vendor1 == CPUID_VENDOR_VIA_1 &&
-        x86_cpu_def->vendor2 == CPUID_VENDOR_VIA_2 &&
-        x86_cpu_def->vendor3 == CPUID_VENDOR_VIA_3) {
-        host_cpuid(0xC0000000, 0, &eax, &ebx, &ecx, &edx);
-        if (eax >= 0xC0000001) {
-            /* Support VIA max extended level */
-            x86_cpu_def->xlevel2 = eax;
-            host_cpuid(0xC0000001, 0, &eax, &ebx, &ecx, &edx);
-            x86_cpu_def->ext4_features = edx;
-        }
-    }
-
-    /*
-     * Every SVM feature requires emulation support in KVM - so we can't just
-     * read the host features here. KVM might even support SVM features not
-     * available on the host hardware. Just set all bits and mask out the
-     * unsupported ones later.
-     */
-    x86_cpu_def->svm_features = -1;
-
-    return 0;
-}
-
-static int unavailable_host_feature(struct model_features_t *f, uint32_t mask)
-{
-    int i;
-
-    for (i = 0; i < 32; ++i)
-        if (1 << i & mask) {
-            fprintf(stderr, "warning: host cpuid %04x_%04x lacks requested"
-                " flag '%s' [0x%08x]\n",
-                f->cpuid >> 16, f->cpuid & 0xffff,
-                f->flag_names[i] ? f->flag_names[i] : "[reserved]", mask);
-            break;
-        }
-    return 0;
-}
-
-/* best effort attempt to inform user requested cpu flags aren't making
- * their way to the guest.  Note: ft[].check_feat ideally should be
- * specified via a guest_def field to suppress report of extraneous flags.
- */
-static int check_features_against_host(x86_def_t *guest_def)
-{
-    x86_def_t host_def;
-    uint32_t mask;
-    int rv, i;
-    struct model_features_t ft[] = {
-        {&guest_def->features, &host_def.features,
-            ~0, feature_name, 0x00000000},
-        {&guest_def->ext_features, &host_def.ext_features,
-            ~CPUID_EXT_HYPERVISOR, ext_feature_name, 0x00000001},
-        {&guest_def->ext2_features, &host_def.ext2_features,
-            ~PPRO_FEATURES, ext2_feature_name, 0x80000000},
-        {&guest_def->ext3_features, &host_def.ext3_features,
-            ~CPUID_EXT3_SVM, ext3_feature_name, 0x80000001}};
-
-    cpu_x86_fill_host(&host_def);
-    for (rv = 0, i = 0; i < ARRAY_SIZE(ft); ++i)
-        for (mask = 1; mask; mask <<= 1)
-            if (ft[i].check_feat & mask && *ft[i].guest_feat & mask &&
-                !(*ft[i].host_feat & mask)) {
-                    unavailable_host_feature(&ft[i], mask);
-                    rv = 1;
-                }
-    return rv;
-}
-
-static void x86_cpuid_version_set_family(CPUX86State *env, int family)
-{
-    env->cpuid_version &= ~0xff00f00;
-    if (family > 0x0f) {
-        env->cpuid_version |= 0xf00 | ((family - 0x0f) << 20);
-    } else {
-        env->cpuid_version |= family << 8;
-    }
-}
-
-static void x86_cpuid_version_set_model(CPUX86State *env, int model)
-{
-    env->cpuid_version &= ~0xf00f0;
-    env->cpuid_version |= ((model & 0xf) << 4) | ((model >> 4) << 16);
-}
-
-static void x86_cpuid_version_set_stepping(CPUX86State *env, int stepping)
-{
-    env->cpuid_version &= ~0xf;
-    env->cpuid_version |= stepping & 0xf;
-}
-
-static void x86_cpuid_set_model_id(CPUX86State *env, const char *model_id)
-{
-    int c, len, i;
-
-    if (model_id == NULL) {
-        model_id = "";
-    }
-    len = strlen(model_id);
-    for (i = 0; i < 48; i++) {
-        if (i >= len) {
-            c = '\0';
-        } else {
-            c = (uint8_t)model_id[i];
-        }
-        env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
-    }
-}
-
-static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
-{
-    unsigned int i;
-    x86_def_t *def;
-
-    char *s = g_strdup(cpu_model);
-    char *featurestr, *name = strtok(s, ",");
-    /* Features to be added*/
-    uint32_t plus_features = 0, plus_ext_features = 0;
-    uint32_t plus_ext2_features = 0, plus_ext3_features = 0;
-    uint32_t plus_kvm_features = 0, plus_svm_features = 0;
-    /* Features to be removed */
-    uint32_t minus_features = 0, minus_ext_features = 0;
-    uint32_t minus_ext2_features = 0, minus_ext3_features = 0;
-    uint32_t minus_kvm_features = 0, minus_svm_features = 0;
-    uint32_t numvalue;
-
-    for (def = x86_defs; def; def = def->next)
-        if (name && !strcmp(name, def->name))
-            break;
-    if (kvm_enabled() && name && strcmp(name, "host") == 0) {
-        cpu_x86_fill_host(x86_cpu_def);
-    } else if (!def) {
-        goto error;
-    } else {
-        memcpy(x86_cpu_def, def, sizeof(*def));
-    }
-
-    plus_kvm_features = ~0; /* not supported bits will be filtered out later */
-
-    add_flagname_to_bitmaps("hypervisor", &plus_features,
-        &plus_ext_features, &plus_ext2_features, &plus_ext3_features,
-        &plus_kvm_features, &plus_svm_features);
-
-    featurestr = strtok(NULL, ",");
-
-    while (featurestr) {
-        char *val;
-        if (featurestr[0] == '+') {
-            add_flagname_to_bitmaps(featurestr + 1, &plus_features,
-                            &plus_ext_features, &plus_ext2_features,
-                            &plus_ext3_features, &plus_kvm_features,
-                            &plus_svm_features);
-        } else if (featurestr[0] == '-') {
-            add_flagname_to_bitmaps(featurestr + 1, &minus_features,
-                            &minus_ext_features, &minus_ext2_features,
-                            &minus_ext3_features, &minus_kvm_features,
-                            &minus_svm_features);
-        } else if ((val = strchr(featurestr, '='))) {
-            *val = 0; val++;
-            if (!strcmp(featurestr, "family")) {
-                char *err;
-                numvalue = strtoul(val, &err, 0);
-                if (!*val || *err) {
-                    fprintf(stderr, "bad numerical value %s\n", val);
-                    goto error;
-                }
-                x86_cpu_def->family = numvalue;
-            } else if (!strcmp(featurestr, "model")) {
-                char *err;
-                numvalue = strtoul(val, &err, 0);
-                if (!*val || *err || numvalue > 0xff) {
-                    fprintf(stderr, "bad numerical value %s\n", val);
-                    goto error;
-                }
-                x86_cpu_def->model = numvalue;
-            } else if (!strcmp(featurestr, "stepping")) {
-                char *err;
-                numvalue = strtoul(val, &err, 0);
-                if (!*val || *err || numvalue > 0xf) {
-                    fprintf(stderr, "bad numerical value %s\n", val);
-                    goto error;
-                }
-                x86_cpu_def->stepping = numvalue ;
-            } else if (!strcmp(featurestr, "level")) {
-                char *err;
-                numvalue = strtoul(val, &err, 0);
-                if (!*val || *err) {
-                    fprintf(stderr, "bad numerical value %s\n", val);
-                    goto error;
-                }
-                x86_cpu_def->level = numvalue;
-            } else if (!strcmp(featurestr, "xlevel")) {
-                char *err;
-                numvalue = strtoul(val, &err, 0);
-                if (!*val || *err) {
-                    fprintf(stderr, "bad numerical value %s\n", val);
-                    goto error;
-                }
-                if (numvalue < 0x80000000) {
-                    numvalue += 0x80000000;
-                }
-                x86_cpu_def->xlevel = numvalue;
-            } else if (!strcmp(featurestr, "vendor")) {
-                if (strlen(val) != 12) {
-                    fprintf(stderr, "vendor string must be 12 chars long\n");
-                    goto error;
-                }
-                x86_cpu_def->vendor1 = 0;
-                x86_cpu_def->vendor2 = 0;
-                x86_cpu_def->vendor3 = 0;
-                for(i = 0; i < 4; i++) {
-                    x86_cpu_def->vendor1 |= ((uint8_t)val[i    ]) << (8 * i);
-                    x86_cpu_def->vendor2 |= ((uint8_t)val[i + 4]) << (8 * i);
-                    x86_cpu_def->vendor3 |= ((uint8_t)val[i + 8]) << (8 * i);
-                }
-                x86_cpu_def->vendor_override = 1;
-            } else if (!strcmp(featurestr, "model_id")) {
-                pstrcpy(x86_cpu_def->model_id, sizeof(x86_cpu_def->model_id),
-                        val);
-            } else if (!strcmp(featurestr, "tsc_freq")) {
-                int64_t tsc_freq;
-                char *err;
-
-                tsc_freq = strtosz_suffix_unit(val, &err,
-                                               STRTOSZ_DEFSUFFIX_B, 1000);
-                if (tsc_freq < 0 || *err) {
-                    fprintf(stderr, "bad numerical value %s\n", val);
-                    goto error;
-                }
-                x86_cpu_def->tsc_khz = tsc_freq / 1000;
-            } else if (!strcmp(featurestr, "hv_spinlocks")) {
-                char *err;
-                numvalue = strtoul(val, &err, 0);
-                if (!*val || *err) {
-                    fprintf(stderr, "bad numerical value %s\n", val);
-                    goto error;
-                }
-                hyperv_set_spinlock_retries(numvalue);
-            } else {
-                fprintf(stderr, "unrecognized feature %s\n", featurestr);
-                goto error;
-            }
-        } else if (!strcmp(featurestr, "check")) {
-            check_cpuid = 1;
-        } else if (!strcmp(featurestr, "enforce")) {
-            check_cpuid = enforce_cpuid = 1;
-        } else if (!strcmp(featurestr, "hv_relaxed")) {
-            hyperv_enable_relaxed_timing(true);
-        } else if (!strcmp(featurestr, "hv_vapic")) {
-            hyperv_enable_vapic_recommended(true);
-        } else {
-            fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr);
-            goto error;
-        }
-        featurestr = strtok(NULL, ",");
-    }
-    x86_cpu_def->features |= plus_features;
-    x86_cpu_def->ext_features |= plus_ext_features;
-    x86_cpu_def->ext2_features |= plus_ext2_features;
-    x86_cpu_def->ext3_features |= plus_ext3_features;
-    x86_cpu_def->kvm_features |= plus_kvm_features;
-    x86_cpu_def->svm_features |= plus_svm_features;
-    x86_cpu_def->features &= ~minus_features;
-    x86_cpu_def->ext_features &= ~minus_ext_features;
-    x86_cpu_def->ext2_features &= ~minus_ext2_features;
-    x86_cpu_def->ext3_features &= ~minus_ext3_features;
-    x86_cpu_def->kvm_features &= ~minus_kvm_features;
-    x86_cpu_def->svm_features &= ~minus_svm_features;
-    if (check_cpuid) {
-        if (check_features_against_host(x86_cpu_def) && enforce_cpuid)
-            goto error;
-    }
-    g_free(s);
-    return 0;
-
-error:
-    g_free(s);
-    return -1;
-}
-
-/* generate a composite string into buf of all cpuid names in featureset
- * selected by fbits.  indicate truncation at bufsize in the event of overflow.
- * if flags, suppress names undefined in featureset.
- */
-static void listflags(char *buf, int bufsize, uint32_t fbits,
-    const char **featureset, uint32_t flags)
-{
-    const char **p = &featureset[31];
-    char *q, *b, bit;
-    int nc;
-
-    b = 4 <= bufsize ? buf + (bufsize -= 3) - 1 : NULL;
-    *buf = '\0';
-    for (q = buf, bit = 31; fbits && bufsize; --p, fbits &= ~(1 << bit), --bit)
-        if (fbits & 1 << bit && (*p || !flags)) {
-            if (*p)
-                nc = snprintf(q, bufsize, "%s%s", q == buf ? "" : " ", *p);
-            else
-                nc = snprintf(q, bufsize, "%s[%d]", q == buf ? "" : " ", bit);
-            if (bufsize <= nc) {
-                if (b) {
-                    memcpy(b, "...", sizeof("..."));
-                }
-                return;
-            }
-            q += nc;
-            bufsize -= nc;
-        }
-}
-
-/* generate CPU information:
- * -?        list model names
- * -?model   list model names/IDs
- * -?dump    output all model (x86_def_t) data
- * -?cpuid   list all recognized cpuid flag names
- */
-void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf, const char *optarg)
-{
-    unsigned char model = !strcmp("?model", optarg);
-    unsigned char dump = !strcmp("?dump", optarg);
-    unsigned char cpuid = !strcmp("?cpuid", optarg);
-    x86_def_t *def;
-    char buf[256];
-
-    if (cpuid) {
-        (*cpu_fprintf)(f, "Recognized CPUID flags:\n");
-        listflags(buf, sizeof (buf), (uint32_t)~0, feature_name, 1);
-        (*cpu_fprintf)(f, "  f_edx: %s\n", buf);
-        listflags(buf, sizeof (buf), (uint32_t)~0, ext_feature_name, 1);
-        (*cpu_fprintf)(f, "  f_ecx: %s\n", buf);
-        listflags(buf, sizeof (buf), (uint32_t)~0, ext2_feature_name, 1);
-        (*cpu_fprintf)(f, "  extf_edx: %s\n", buf);
-        listflags(buf, sizeof (buf), (uint32_t)~0, ext3_feature_name, 1);
-        (*cpu_fprintf)(f, "  extf_ecx: %s\n", buf);
-        return;
-    }
-    for (def = x86_defs; def; def = def->next) {
-        snprintf(buf, sizeof (buf), def->flags ? "[%s]": "%s", def->name);
-        if (model || dump) {
-            (*cpu_fprintf)(f, "x86 %16s  %-48s\n", buf, def->model_id);
-        } else {
-            (*cpu_fprintf)(f, "x86 %16s\n", buf);
-        }
-        if (dump) {
-            memcpy(buf, &def->vendor1, sizeof (def->vendor1));
-            memcpy(buf + 4, &def->vendor2, sizeof (def->vendor2));
-            memcpy(buf + 8, &def->vendor3, sizeof (def->vendor3));
-            buf[12] = '\0';
-            (*cpu_fprintf)(f,
-                "  family %d model %d stepping %d level %d xlevel 0x%x"
-                " vendor \"%s\"\n",
-                def->family, def->model, def->stepping, def->level,
-                def->xlevel, buf);
-            listflags(buf, sizeof (buf), def->features, feature_name, 0);
-            (*cpu_fprintf)(f, "  feature_edx %08x (%s)\n", def->features,
-                buf);
-            listflags(buf, sizeof (buf), def->ext_features, ext_feature_name,
-                0);
-            (*cpu_fprintf)(f, "  feature_ecx %08x (%s)\n", def->ext_features,
-                buf);
-            listflags(buf, sizeof (buf), def->ext2_features, ext2_feature_name,
-                0);
-            (*cpu_fprintf)(f, "  extfeature_edx %08x (%s)\n",
-                def->ext2_features, buf);
-            listflags(buf, sizeof (buf), def->ext3_features, ext3_feature_name,
-                0);
-            (*cpu_fprintf)(f, "  extfeature_ecx %08x (%s)\n",
-                def->ext3_features, buf);
-            (*cpu_fprintf)(f, "\n");
-        }
-    }
-    if (kvm_enabled()) {
-        (*cpu_fprintf)(f, "x86 %16s\n", "[host]");
-    }
-}
-
-int cpu_x86_register (CPUX86State *env, const char *cpu_model)
-{
-    x86_def_t def1, *def = &def1;
-
-    memset(def, 0, sizeof(*def));
-
-    if (cpu_x86_find_by_name(def, cpu_model) < 0)
-        return -1;
-    if (def->vendor1) {
-        env->cpuid_vendor1 = def->vendor1;
-        env->cpuid_vendor2 = def->vendor2;
-        env->cpuid_vendor3 = def->vendor3;
-    } else {
-        env->cpuid_vendor1 = CPUID_VENDOR_INTEL_1;
-        env->cpuid_vendor2 = CPUID_VENDOR_INTEL_2;
-        env->cpuid_vendor3 = CPUID_VENDOR_INTEL_3;
-    }
-    env->cpuid_vendor_override = def->vendor_override;
-    env->cpuid_level = def->level;
-    x86_cpuid_version_set_family(env, def->family);
-    x86_cpuid_version_set_model(env, def->model);
-    x86_cpuid_version_set_stepping(env, def->stepping);
-    env->cpuid_features = def->features;
-    env->cpuid_ext_features = def->ext_features;
-    env->cpuid_ext2_features = def->ext2_features;
-    env->cpuid_ext3_features = def->ext3_features;
-    env->cpuid_xlevel = def->xlevel;
-    env->cpuid_kvm_features = def->kvm_features;
-    env->cpuid_svm_features = def->svm_features;
-    env->cpuid_ext4_features = def->ext4_features;
-    env->cpuid_xlevel2 = def->xlevel2;
-    env->tsc_khz = def->tsc_khz;
-    if (!kvm_enabled()) {
-        env->cpuid_features &= TCG_FEATURES;
-        env->cpuid_ext_features &= TCG_EXT_FEATURES;
-        env->cpuid_ext2_features &= (TCG_EXT2_FEATURES
-#ifdef TARGET_X86_64
-            | CPUID_EXT2_SYSCALL | CPUID_EXT2_LM
-#endif
-            );
-        env->cpuid_ext3_features &= TCG_EXT3_FEATURES;
-        env->cpuid_svm_features &= TCG_SVM_FEATURES;
-    }
-    x86_cpuid_set_model_id(env, def->model_id);
-    return 0;
-}
-
-#if !defined(CONFIG_USER_ONLY)
-/* copy vendor id string to 32 bit register, nul pad as needed
- */
-static void cpyid(const char *s, uint32_t *id)
-{
-    char *d = (char *)id;
-    char i;
-
-    for (i = sizeof (*id); i--; )
-        *d++ = *s ? *s++ : '\0';
-}
-
-/* interpret radix and convert from string to arbitrary scalar,
- * otherwise flag failure
- */
-#define setscalar(pval, str, perr)                      \
-{                                                       \
-    char *pend;                                         \
-    unsigned long ul;                                   \
-                                                        \
-    ul = strtoul(str, &pend, 0);                        \
-    *str && !*pend ? (*pval = ul) : (*perr = 1);        \
-}
-
-/* map cpuid options to feature bits, otherwise return failure
- * (option tags in *str are delimited by whitespace)
- */
-static void setfeatures(uint32_t *pval, const char *str,
-    const char **featureset, int *perr)
-{
-    const char *p, *q;
-
-    for (q = p = str; *p || *q; q = p) {
-        while (iswhite(*p))
-            q = ++p;
-        while (*p && !iswhite(*p))
-            ++p;
-        if (!*q && !*p)
-            return;
-        if (!lookup_feature(pval, q, p, featureset)) {
-            fprintf(stderr, "error: feature \"%.*s\" not available in set\n",
-                (int)(p - q), q);
-            *perr = 1;
-            return;
-        }
-    }
-}
-
-/* map config file options to x86_def_t form
- */
-static int cpudef_setfield(const char *name, const char *str, void *opaque)
-{
-    x86_def_t *def = opaque;
-    int err = 0;
-
-    if (!strcmp(name, "name")) {
-        g_free((void *)def->name);
-        def->name = g_strdup(str);
-    } else if (!strcmp(name, "model_id")) {
-        strncpy(def->model_id, str, sizeof (def->model_id));
-    } else if (!strcmp(name, "level")) {
-        setscalar(&def->level, str, &err)
-    } else if (!strcmp(name, "vendor")) {
-        cpyid(&str[0], &def->vendor1);
-        cpyid(&str[4], &def->vendor2);
-        cpyid(&str[8], &def->vendor3);
-    } else if (!strcmp(name, "family")) {
-        setscalar(&def->family, str, &err)
-    } else if (!strcmp(name, "model")) {
-        setscalar(&def->model, str, &err)
-    } else if (!strcmp(name, "stepping")) {
-        setscalar(&def->stepping, str, &err)
-    } else if (!strcmp(name, "feature_edx")) {
-        setfeatures(&def->features, str, feature_name, &err);
-    } else if (!strcmp(name, "feature_ecx")) {
-        setfeatures(&def->ext_features, str, ext_feature_name, &err);
-    } else if (!strcmp(name, "extfeature_edx")) {
-        setfeatures(&def->ext2_features, str, ext2_feature_name, &err);
-    } else if (!strcmp(name, "extfeature_ecx")) {
-        setfeatures(&def->ext3_features, str, ext3_feature_name, &err);
-    } else if (!strcmp(name, "xlevel")) {
-        setscalar(&def->xlevel, str, &err)
-    } else {
-        fprintf(stderr, "error: unknown option [%s = %s]\n", name, str);
-        return (1);
-    }
-    if (err) {
-        fprintf(stderr, "error: bad option value [%s = %s]\n", name, str);
-        return (1);
-    }
-    return (0);
-}
-
-/* register config file entry as x86_def_t
- */
-static int cpudef_register(QemuOpts *opts, void *opaque)
-{
-    x86_def_t *def = g_malloc0(sizeof (x86_def_t));
-
-    qemu_opt_foreach(opts, cpudef_setfield, def, 1);
-    def->next = x86_defs;
-    x86_defs = def;
-    return (0);
-}
-
-void cpu_clear_apic_feature(CPUX86State *env)
-{
-    env->cpuid_features &= ~CPUID_APIC;
-}
-
-#endif /* !CONFIG_USER_ONLY */
-
-/* register "cpudef" models defined in configuration file.  Here we first
- * preload any built-in definitions
- */
-void x86_cpudef_setup(void)
-{
-    int i;
-
-    for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); ++i) {
-        builtin_x86_defs[i].next = x86_defs;
-        builtin_x86_defs[i].flags = 1;
-        x86_defs = &builtin_x86_defs[i];
-    }
-#if !defined(CONFIG_USER_ONLY)
-    qemu_opts_foreach(qemu_find_opts("cpudef"), cpudef_register, NULL, 0);
-#endif
-}
-
-static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx,
-                             uint32_t *ecx, uint32_t *edx)
-{
-    *ebx = env->cpuid_vendor1;
-    *edx = env->cpuid_vendor2;
-    *ecx = env->cpuid_vendor3;
-
-    /* sysenter isn't supported on compatibility mode on AMD, syscall
-     * isn't supported in compatibility mode on Intel.
-     * Normally we advertise the actual cpu vendor, but you can override
-     * this if you want to use KVM's sysenter/syscall emulation
-     * in compatibility mode and when doing cross vendor migration
-     */
-    if (kvm_enabled() && ! env->cpuid_vendor_override) {
-        host_cpuid(0, 0, NULL, ebx, ecx, edx);
-    }
-}
-
-void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
-                   uint32_t *eax, uint32_t *ebx,
-                   uint32_t *ecx, uint32_t *edx)
-{
-    /* test if maximum index reached */
-    if (index & 0x80000000) {
-        if (index > env->cpuid_xlevel) {
-            if (env->cpuid_xlevel2 > 0) {
-                /* Handle the Centaur's CPUID instruction. */
-                if (index > env->cpuid_xlevel2) {
-                    index = env->cpuid_xlevel2;
-                } else if (index < 0xC0000000) {
-                    index = env->cpuid_xlevel;
-                }
-            } else {
-                index =  env->cpuid_xlevel;
-            }
-        }
-    } else {
-        if (index > env->cpuid_level)
-            index = env->cpuid_level;
-    }
-
-    switch(index) {
-    case 0:
-        *eax = env->cpuid_level;
-        get_cpuid_vendor(env, ebx, ecx, edx);
-        break;
-    case 1:
-        *eax = env->cpuid_version;
-        *ebx = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
-        *ecx = env->cpuid_ext_features;
-        *edx = env->cpuid_features;
-        if (env->nr_cores * env->nr_threads > 1) {
-            *ebx |= (env->nr_cores * env->nr_threads) << 16;
-            *edx |= 1 << 28;    /* HTT bit */
-        }
-        break;
-    case 2:
-        /* cache info: needed for Pentium Pro compatibility */
-        *eax = 1;
-        *ebx = 0;
-        *ecx = 0;
-        *edx = 0x2c307d;
-        break;
-    case 4:
-        /* cache info: needed for Core compatibility */
-        if (env->nr_cores > 1) {
-            *eax = (env->nr_cores - 1) << 26;
-        } else {
-            *eax = 0;
-        }
-        switch (count) {
-            case 0: /* L1 dcache info */
-                *eax |= 0x0000121;
-                *ebx = 0x1c0003f;
-                *ecx = 0x000003f;
-                *edx = 0x0000001;
-                break;
-            case 1: /* L1 icache info */
-                *eax |= 0x0000122;
-                *ebx = 0x1c0003f;
-                *ecx = 0x000003f;
-                *edx = 0x0000001;
-                break;
-            case 2: /* L2 cache info */
-                *eax |= 0x0000143;
-                if (env->nr_threads > 1) {
-                    *eax |= (env->nr_threads - 1) << 14;
-                }
-                *ebx = 0x3c0003f;
-                *ecx = 0x0000fff;
-                *edx = 0x0000001;
-                break;
-            default: /* end of info */
-                *eax = 0;
-                *ebx = 0;
-                *ecx = 0;
-                *edx = 0;
-                break;
-        }
-        break;
-    case 5:
-        /* mwait info: needed for Core compatibility */
-        *eax = 0; /* Smallest monitor-line size in bytes */
-        *ebx = 0; /* Largest monitor-line size in bytes */
-        *ecx = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE;
-        *edx = 0;
-        break;
-    case 6:
-        /* Thermal and Power Leaf */
-        *eax = 0;
-        *ebx = 0;
-        *ecx = 0;
-        *edx = 0;
-        break;
-    case 7:
-        if (kvm_enabled()) {
-            KVMState *s = env->kvm_state;
-
-            *eax = kvm_arch_get_supported_cpuid(s, 0x7, count, R_EAX);
-            *ebx = kvm_arch_get_supported_cpuid(s, 0x7, count, R_EBX);
-            *ecx = kvm_arch_get_supported_cpuid(s, 0x7, count, R_ECX);
-            *edx = kvm_arch_get_supported_cpuid(s, 0x7, count, R_EDX);
-        } else {
-            *eax = 0;
-            *ebx = 0;
-            *ecx = 0;
-            *edx = 0;
-        }
-        break;
-    case 9:
-        /* Direct Cache Access Information Leaf */
-        *eax = 0; /* Bits 0-31 in DCA_CAP MSR */
-        *ebx = 0;
-        *ecx = 0;
-        *edx = 0;
-        break;
-    case 0xA:
-        /* Architectural Performance Monitoring Leaf */
-        if (kvm_enabled()) {
-            KVMState *s = env->kvm_state;
-
-            *eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX);
-            *ebx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EBX);
-            *ecx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_ECX);
-            *edx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EDX);
-        } else {
-            *eax = 0;
-            *ebx = 0;
-            *ecx = 0;
-            *edx = 0;
-        }
-        break;
-    case 0xD:
-        /* Processor Extended State */
-        if (!(env->cpuid_ext_features & CPUID_EXT_XSAVE)) {
-            *eax = 0;
-            *ebx = 0;
-            *ecx = 0;
-            *edx = 0;
-            break;
-        }
-        if (kvm_enabled()) {
-            KVMState *s = env->kvm_state;
-
-            *eax = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EAX);
-            *ebx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EBX);
-            *ecx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_ECX);
-            *edx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EDX);
-        } else {
-            *eax = 0;
-            *ebx = 0;
-            *ecx = 0;
-            *edx = 0;
-        }
-        break;
-    case 0x80000000:
-        *eax = env->cpuid_xlevel;
-        *ebx = env->cpuid_vendor1;
-        *edx = env->cpuid_vendor2;
-        *ecx = env->cpuid_vendor3;
-        break;
-    case 0x80000001:
-        *eax = env->cpuid_version;
-        *ebx = 0;
-        *ecx = env->cpuid_ext3_features;
-        *edx = env->cpuid_ext2_features;
-
-        /* The Linux kernel checks for the CMPLegacy bit and
-         * discards multiple thread information if it is set.
-         * So dont set it here for Intel to make Linux guests happy.
-         */
-        if (env->nr_cores * env->nr_threads > 1) {
-            uint32_t tebx, tecx, tedx;
-            get_cpuid_vendor(env, &tebx, &tecx, &tedx);
-            if (tebx != CPUID_VENDOR_INTEL_1 ||
-                tedx != CPUID_VENDOR_INTEL_2 ||
-                tecx != CPUID_VENDOR_INTEL_3) {
-                *ecx |= 1 << 1;    /* CmpLegacy bit */
-            }
-        }
-        break;
-    case 0x80000002:
-    case 0x80000003:
-    case 0x80000004:
-        *eax = env->cpuid_model[(index - 0x80000002) * 4 + 0];
-        *ebx = env->cpuid_model[(index - 0x80000002) * 4 + 1];
-        *ecx = env->cpuid_model[(index - 0x80000002) * 4 + 2];
-        *edx = env->cpuid_model[(index - 0x80000002) * 4 + 3];
-        break;
-    case 0x80000005:
-        /* cache info (L1 cache) */
-        *eax = 0x01ff01ff;
-        *ebx = 0x01ff01ff;
-        *ecx = 0x40020140;
-        *edx = 0x40020140;
-        break;
-    case 0x80000006:
-        /* cache info (L2 cache) */
-        *eax = 0;
-        *ebx = 0x42004200;
-        *ecx = 0x02008140;
-        *edx = 0;
-        break;
-    case 0x80000008:
-        /* virtual & phys address size in low 2 bytes. */
-/* XXX: This value must match the one used in the MMU code. */
-        if (env->cpuid_ext2_features & CPUID_EXT2_LM) {
-            /* 64 bit processor */
-/* XXX: The physical address space is limited to 42 bits in exec.c. */
-            *eax = 0x00003028;	/* 48 bits virtual, 40 bits physical */
-        } else {
-            if (env->cpuid_features & CPUID_PSE36)
-                *eax = 0x00000024; /* 36 bits physical */
-            else
-                *eax = 0x00000020; /* 32 bits physical */
-        }
-        *ebx = 0;
-        *ecx = 0;
-        *edx = 0;
-        if (env->nr_cores * env->nr_threads > 1) {
-            *ecx |= (env->nr_cores * env->nr_threads) - 1;
-        }
-        break;
-    case 0x8000000A:
-	if (env->cpuid_ext3_features & CPUID_EXT3_SVM) {
-		*eax = 0x00000001; /* SVM Revision */
-		*ebx = 0x00000010; /* nr of ASIDs */
-		*ecx = 0;
-		*edx = env->cpuid_svm_features; /* optional features */
-	} else {
-		*eax = 0;
-		*ebx = 0;
-		*ecx = 0;
-		*edx = 0;
-	}
-        break;
-    case 0xC0000000:
-        *eax = env->cpuid_xlevel2;
-        *ebx = 0;
-        *ecx = 0;
-        *edx = 0;
-        break;
-    case 0xC0000001:
-        /* Support for VIA CPU's CPUID instruction */
-        *eax = env->cpuid_version;
-        *ebx = 0;
-        *ecx = 0;
-        *edx = env->cpuid_ext4_features;
-        break;
-    case 0xC0000002:
-    case 0xC0000003:
-    case 0xC0000004:
-        /* Reserved for the future, and now filled with zero */
-        *eax = 0;
-        *ebx = 0;
-        *ecx = 0;
-        *edx = 0;
-        break;
-    default:
-        /* reserved values: zero */
-        *eax = 0;
-        *ebx = 0;
-        *ecx = 0;
-        *edx = 0;
-        break;
-    }
-}
commit 4e1957acc854b2f3f3068c75cef2a429f9b97011
Merge: 6da25bd... ff71f2e...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Apr 10 08:21:58 2012 -0500

    Merge commit 'ff71f2e8cacefae99179993204172bc65e4303df' into staging
    
    * commit 'ff71f2e8cacefae99179993204172bc65e4303df': (21 commits)
      rtl8139: do the network/host communication only in normal operating mode
      rtl8139: correctly check the opmode
      net: move compute_mcast_idx() to net.h
      rtl8139: support byte read to TxStatus registers
      rtl8139: remove unused marco
      rtl8139: limit transmission buffer size in c+ mode
      pci_regs: Add PCI_EXP_TYPE_PCIE_BRIDGE
      virtio-net: add DATA_VALID flag
      pci_bridge: upper 32 bit are long registers
      pci: fix bridge IO/BASE
      pcie: drop functionality moved to core
      pci: set memory type for memory behind the bridge
      pci: add standard bridge device
      slotid: add slot id capability
      shpc: standard hot plug controller
      pci_bridge: user-friendly default bus name
      pci: make another unused extern function static
      pci: don't export an internal function
      pci_regs: Fix value of PCI_EXP_TYPE_RC_EC.
      pci: Do not check if a bus exist in pci_parse_devaddr.
      ...

commit 6da25bd5e8355230b9562417e386728c31783002
Merge: bb5d8dd... a15fef2...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Apr 10 08:17:36 2012 -0500

    Merge remote-tracking branch 'qmp/queue/qmp' into staging
    
    * qmp/queue/qmp:
      qapi: convert device_del
      qdev: qdev_unplug(): use error_set()

commit bb5d8dd757eaa8f9a048c5205c69bed20ea373d1
Merge: 72fe3aa... 50d30c2...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Apr 10 08:16:12 2012 -0500

    Merge remote-tracking branch 'kwolf/for-anthony' into staging
    
    * kwolf/for-anthony: (46 commits)
      qed: remove incoming live migration blocker
      qed: honor BDRV_O_INCOMING for incoming live migration
      migration: clear BDRV_O_INCOMING flags on end of incoming live migration
      qed: add bdrv_invalidate_cache to be called after incoming live migration
      blockdev: open images with BDRV_O_INCOMING on incoming live migration
      block: add a function to clear incoming live migration flags
      block: Add new BDRV_O_INCOMING flag to notice incoming live migration
      block stream: close unused files and update ->backing_hd
      qemu-iotests: Fix call syntax for qemu-io
      qemu-iotests: Fix call syntax for qemu-img
      qemu-iotests: Test unknown qcow2 header extensions
      qemu-iotests: qcow2.py
      sheepdog: fix send req helpers
      sheepdog: implement SD_OP_FLUSH_VDI operation
      block: bdrv_append() fixes
      qed: track dirty flag status
      qemu-img: add dirty flag status
      qed: image fragmentation statistics
      qemu-img: add image fragmentation statistics
      block: document job API
      ...

commit 72fe3aaed94936739abfa158fa28f147b75ae9ff
Merge: 2c097f6... 53fbf7b...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Apr 10 08:10:41 2012 -0500

    Merge remote-tracking branch 'stefanha/trivial-patches' into staging
    
    * stefanha/trivial-patches:
      make: fix clean rule by removing build file in qom/
      configure: Link qga against UST tracing related libraries
      configure: Link QEMU against 'liburcu-bp'
      main-loop: make qemu_event_handle static
      block/curl: Replace usleep by g_usleep
      qtest: Add missing GCC_FMT_ATTR
      w32: Undefine error constants before their redefinition
      configure: fix mingw32 libs_qga typo

commit 2c097f6003f2a11416706ae3252c2860ed2257a9
Author: Peter A. G. Crosthwaite <peter.crosthwaite at petalogix.com>
Date:   Tue Apr 10 14:05:52 2012 +1000

    petalogix_s3adsp1800: deleted bad FIXME comment
    
    This FIXME has already been actioned. Deleted comment.
    
    Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite at petalogix.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index ff154c7..8b37336 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -51,7 +51,6 @@
 
 static void machine_cpu_reset(CPUMBState *env)
 {
-    /* FIXME: move to machine specfic cpu reset */
     env->pvr.regs[10] = 0x0c000000; /* spartan 3a dsp family.  */
 }
 
commit a15fef21c746e3aa0a94cf7b5bd9799886236666
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Thu Mar 29 12:38:50 2012 -0300

    qapi: convert device_del
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hmp-commands.hx b/hmp-commands.hx
index bd35a3e..a6f5a84 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -622,8 +622,7 @@ ETEXI
         .args_type  = "id:s",
         .params     = "device",
         .help       = "remove device",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_device_del,
+        .mhandler.cmd = hmp_device_del,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index 9cf2d13..f3e5163 100644
--- a/hmp.c
+++ b/hmp.c
@@ -934,3 +934,12 @@ void hmp_migrate(Monitor *mon, const QDict *qdict)
         qemu_mod_timer(status->timer, qemu_get_clock_ms(rt_clock));
     }
 }
+
+void hmp_device_del(Monitor *mon, const QDict *qdict)
+{
+    const char *id = qdict_get_str(qdict, "id");
+    Error *err = NULL;
+
+    qmp_device_del(id, &err);
+    hmp_handle_error(mon, &err);
+}
diff --git a/hmp.h b/hmp.h
index 8807853..443b812 100644
--- a/hmp.h
+++ b/hmp.h
@@ -60,5 +60,6 @@ void hmp_block_stream(Monitor *mon, const QDict *qdict);
 void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict);
 void hmp_block_job_cancel(Monitor *mon, const QDict *qdict);
 void hmp_migrate(Monitor *mon, const QDict *qdict);
+void hmp_device_del(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c
index fd56afe..81d6548 100644
--- a/hw/qdev-monitor.c
+++ b/hw/qdev-monitor.c
@@ -19,6 +19,7 @@
 
 #include "qdev.h"
 #include "monitor.h"
+#include "qmp-commands.h"
 
 /*
  * Aliases were a bad idea from the start.  Let's keep them
@@ -570,26 +571,17 @@ int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
     return 0;
 }
 
-int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void qmp_device_del(const char *id, Error **errp)
 {
-    const char *id = qdict_get_str(qdict, "id");
-    Error *local_err = NULL;
     DeviceState *dev;
 
     dev = qdev_find_recursive(sysbus_get_default(), id);
     if (NULL == dev) {
-        qerror_report(QERR_DEVICE_NOT_FOUND, id);
-        return -1;
-    }
-
-    qdev_unplug(dev, &local_err);
-    if (error_is_set(&local_err)) {
-        qerror_report_err(local_err);
-        error_free(local_err);
-        return -1;
+        error_set(errp, QERR_DEVICE_NOT_FOUND, id);
+        return;
     }
 
-    return 0;
+    qdev_unplug(dev, errp);
 }
 
 void qdev_machine_init(void)
diff --git a/qapi-schema.json b/qapi-schema.json
index 0d11d6e..ace55f3 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1701,3 +1701,23 @@
 # Since: 1.1
 ##
 { 'command': 'xen-save-devices-state', 'data': {'filename': 'str'} }
+
+##
+# @device_del:
+#
+# Remove a device from a guest
+#
+# @id: the name of the device
+#
+# Returns: Nothing on success
+#          If @id is not a valid device, DeviceNotFound
+#          If the device does not support unplug, BusNoHotplug
+#
+# Notes: When this command completes, the device may not be removed from the
+#        guest.  Hot removal is an operation that requires guest cooperation.
+#        This command merely requests that the guest begin the hot removal
+#        process.
+#
+# Since: 0.14.0
+##
+{ 'command': 'device_del', 'data': {'id': 'str'} }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 9447871..c09ee85 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -314,10 +314,7 @@ EQMP
     {
         .name       = "device_del",
         .args_type  = "id:s",
-        .params     = "device",
-        .help       = "remove device",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_device_del,
+        .mhandler.cmd_new = qmp_marshal_input_device_del,
     },
 
 SQMP
commit 56f9107e439c32aa00d58d117a9b664551328f1e
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Mar 14 17:37:38 2012 -0300

    qdev: qdev_unplug(): use error_set()
    
    It currently uses qerror_report(), but next commit will convert
    the drive_del command to the QAPI and this requires using
    error_set().
    
    One particularity of qerror_report() is that it knows when it's
    running on monitor context or command-line context and prints the
    error message accordingly. error_set() doesn't do this, so we
    have to be careful not to drop error messages.
    
    qdev_unplug() has three kinds of usages:
    
     1. It's called when hot adding a device fails, to undo anything
        that has been done before hitting the error
    
     2. It's called by function monitor functions like device_del(),
        to unplug a device
    
     3. It's used by xen_platform.c in a way that doesn't _seem_ to
        be in monitor context
    
    Only item 2 can print an error message to the user, this commit
    maintains that.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index 5c6307f..c55d8b9 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -32,6 +32,7 @@
 #include "virtio-blk.h"
 #include "qemu-config.h"
 #include "blockdev.h"
+#include "error.h"
 
 #if defined(TARGET_I386)
 static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
@@ -191,7 +192,7 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
             dev = NULL;
         if (dev && dinfo) {
             if (scsi_hot_add(mon, &dev->qdev, dinfo, 0) != 0) {
-                qdev_unplug(&dev->qdev);
+                qdev_unplug(&dev->qdev, NULL);
                 dev = NULL;
             }
         }
@@ -258,6 +259,7 @@ static int pci_device_hot_remove(Monitor *mon, const char *pci_addr)
     PCIDevice *d;
     int dom, bus;
     unsigned slot;
+    Error *local_err = NULL;
 
     if (pci_read_devaddr(mon, pci_addr, &dom, &bus, &slot)) {
         return -1;
@@ -268,7 +270,15 @@ static int pci_device_hot_remove(Monitor *mon, const char *pci_addr)
         monitor_printf(mon, "slot %d empty\n", slot);
         return -1;
     }
-    return qdev_unplug(&d->qdev);
+
+    qdev_unplug(&d->qdev, &local_err);
+    if (error_is_set(&local_err)) {
+        monitor_printf(mon, "%s\n", error_get_pretty(local_err));
+        error_free(local_err);
+        return -1;
+    }
+
+    return 0;
 }
 
 void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict)
diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c
index 4783366..fd56afe 100644
--- a/hw/qdev-monitor.c
+++ b/hw/qdev-monitor.c
@@ -573,6 +573,7 @@ int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
 int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     const char *id = qdict_get_str(qdict, "id");
+    Error *local_err = NULL;
     DeviceState *dev;
 
     dev = qdev_find_recursive(sysbus_get_default(), id);
@@ -580,7 +581,15 @@ int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
         qerror_report(QERR_DEVICE_NOT_FOUND, id);
         return -1;
     }
-    return qdev_unplug(dev);
+
+    qdev_unplug(dev, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+        return -1;
+    }
+
+    return 0;
 }
 
 void qdev_machine_init(void)
diff --git a/hw/qdev.c b/hw/qdev.c
index 0d3c0fc..afbc975 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -28,6 +28,7 @@
 #include "net.h"
 #include "qdev.h"
 #include "sysemu.h"
+#include "error.h"
 
 int qdev_hotplug = 0;
 static bool qdev_hot_added = false;
@@ -182,19 +183,22 @@ void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
     dev->alias_required_for_version = required_for_version;
 }
 
-int qdev_unplug(DeviceState *dev)
+void qdev_unplug(DeviceState *dev, Error **errp)
 {
     DeviceClass *dc = DEVICE_GET_CLASS(dev);
 
     if (!dev->parent_bus->allow_hotplug) {
-        qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
-        return -1;
+        error_set(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
+        return;
     }
     assert(dc->unplug != NULL);
 
     qdev_hot_removed = true;
 
-    return dc->unplug(dev);
+    if (dc->unplug(dev) < 0) {
+        error_set(errp, QERR_UNDEFINED_ERROR);
+        return;
+    }
 }
 
 static int qdev_reset_one(DeviceState *dev, void *opaque)
diff --git a/hw/qdev.h b/hw/qdev.h
index a8df42f..7cafa8c 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -7,6 +7,7 @@
 #include "qemu-option.h"
 #include "qapi/qapi-visit-core.h"
 #include "qemu/object.h"
+#include "error.h"
 
 typedef struct Property Property;
 
@@ -148,7 +149,7 @@ int qdev_init(DeviceState *dev) QEMU_WARN_UNUSED_RESULT;
 void qdev_init_nofail(DeviceState *dev);
 void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
                                  int required_for_version);
-int qdev_unplug(DeviceState *dev);
+void qdev_unplug(DeviceState *dev, Error **errp);
 void qdev_free(DeviceState *dev);
 int qdev_simple_unplug_cb(DeviceState *dev);
 void qdev_machine_creation_done(void);
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index bdbe7bd..d865a5e 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -499,7 +499,7 @@ static void usb_msd_password_cb(void *opaque, int err)
         err = usb_device_attach(&s->dev);
 
     if (err)
-        qdev_unplug(&s->dev.qdev);
+        qdev_unplug(&s->dev.qdev, NULL);
 }
 
 static const struct SCSIBusInfo usb_msd_scsi_info = {
diff --git a/hw/xen_platform.c b/hw/xen_platform.c
index 5a7c4cc..a9c52a6 100644
--- a/hw/xen_platform.c
+++ b/hw/xen_platform.c
@@ -87,7 +87,7 @@ static void unplug_nic(PCIBus *b, PCIDevice *d)
 {
     if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
             PCI_CLASS_NETWORK_ETHERNET) {
-        qdev_unplug(&(d->qdev));
+        qdev_unplug(&(d->qdev), NULL);
     }
 }
 
@@ -100,7 +100,7 @@ static void unplug_disks(PCIBus *b, PCIDevice *d)
 {
     if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
             PCI_CLASS_STORAGE_IDE) {
-        qdev_unplug(&(d->qdev));
+        qdev_unplug(&(d->qdev), NULL);
     }
 }
 
commit 7914cb3c738a03a5d5f7cb32c3768bc62eb1e944
Merge: 4266717... 221b3a3...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Apr 8 18:00:42 2012 +0000

    Merge branch 'memory/core' of git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm
    
    * 'memory/core' of git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm:
      memory: check address space when a listener is registered
      memory: print aliased IO ranges in info mtree
      ioport: use INT64_MAX for IO ranges

commit 4266717d690987993d52f5e4745064f4dbb29824
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Apr 7 17:58:34 2012 +0200

    Add QEMU_NORETURN to function cpu_io_recompile
    
    cpu_io_recompile terminates by calling either cpu_abort or
    cpu_resume_from_signal which both never return.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/exec-all.h b/exec-all.h
index 4758d88..fa7bdfe 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -87,7 +87,7 @@ int cpu_gen_code(CPUArchState *env, struct TranslationBlock *tb,
 int cpu_restore_state(struct TranslationBlock *tb,
                       CPUArchState *env, uintptr_t searched_pc);
 void QEMU_NORETURN cpu_resume_from_signal(CPUArchState *env1, void *puc);
-void cpu_io_recompile(CPUArchState *env, void *retaddr);
+void QEMU_NORETURN cpu_io_recompile(CPUArchState *env, void *retaddr);
 TranslationBlock *tb_gen_code(CPUArchState *env, 
                               target_ulong pc, target_ulong cs_base, int flags,
                               int cflags);
commit 38c30fb7a534da82371311ca7a56f2141008b2a5
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Apr 7 17:58:33 2012 +0200

    Add QEMU_NORETURN to function cpu_resume_from_signal
    
    cpu_resume_from_signal terminates by calling longjmp.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/exec-all.h b/exec-all.h
index a6d6519..4758d88 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -86,7 +86,7 @@ int cpu_gen_code(CPUArchState *env, struct TranslationBlock *tb,
                  int *gen_code_size_ptr);
 int cpu_restore_state(struct TranslationBlock *tb,
                       CPUArchState *env, uintptr_t searched_pc);
-void cpu_resume_from_signal(CPUArchState *env1, void *puc);
+void QEMU_NORETURN cpu_resume_from_signal(CPUArchState *env1, void *puc);
 void cpu_io_recompile(CPUArchState *env, void *retaddr);
 TranslationBlock *tb_gen_code(CPUArchState *env, 
                               target_ulong pc, target_ulong cs_base, int flags,
commit 5cbdb3a34bce4ee64dd203cfd74979409fa3d51e
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Apr 7 09:23:39 2012 +0200

    Replace Qemu by QEMU in comments
    
    The official spelling is QEMU.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    [blauwirbel at gmail.com: fixed comment style in hw/sun4m.c]
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/ivshmem.c b/hw/ivshmem.c
index 64e1cd9..b80aa8f 100644
--- a/hw/ivshmem.c
+++ b/hw/ivshmem.c
@@ -565,7 +565,7 @@ static void ivshmem_setup_msi(IVShmemState * s) {
         msix_vector_use(&s->dev, i);
     }
 
-    /* allocate Qemu char devices for receiving interrupts */
+    /* allocate QEMU char devices for receiving interrupts */
     s->eventfd_table = g_malloc0(s->vectors * sizeof(EventfdEntry));
 }
 
diff --git a/hw/pc.c b/hw/pc.c
index 83a1b5b..67f0479 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -776,7 +776,7 @@ static void load_linux(void *fw_cfg,
     }
 
     /* loader type */
-    /* High nybble = B reserved for Qemu; low nybble is revision number.
+    /* High nybble = B reserved for QEMU; low nybble is revision number.
        If this code is substantially changed, you may want to consider
        incrementing the revision. */
     if (protocol >= 0x200)
diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
index 220c81d..f0a3ae4 100644
--- a/hw/ppc440_bamboo.c
+++ b/hw/ppc440_bamboo.c
@@ -1,5 +1,5 @@
 /*
- * Qemu PowerPC 440 Bamboo board emulation
+ * QEMU PowerPC 440 Bamboo board emulation
  *
  * Copyright 2007 IBM Corporation.
  * Authors:
diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index 5ee8cb3..f1dfbe1 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -1,5 +1,5 @@
 /*
- * Qemu PowerPC MPC8544DS board emualtion
+ * QEMU PowerPC MPC8544DS board emulation
  *
  * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
  *
diff --git a/hw/ps2.c b/hw/ps2.c
index b1a67bc..f93cd24 100644
--- a/hw/ps2.c
+++ b/hw/ps2.c
@@ -88,7 +88,7 @@ typedef struct {
 typedef struct {
     PS2State common;
     int scan_enabled;
-    /* Qemu uses translated PC scancodes internally.  To avoid multiple
+    /* QEMU uses translated PC scancodes internally.  To avoid multiple
        conversions we do the translation (if any) in the PS/2 emulation
        not the keyboard controller.  */
     int translate;
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 7bcbf37..34088ad 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -932,8 +932,8 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size,
 
     slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[14],
                               display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1);
-    // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device
-    // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device
+    /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device
+       Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */
     escc_init(hwdef->serial_base, slavio_irq[15], slavio_irq[15],
               serial_hds[0], serial_hds[1], ESCC_CLOCK, 1);
 
@@ -1581,8 +1581,8 @@ static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, ram_addr_t RAM_size,
 
     slavio_serial_ms_kbd_init(hwdef->ms_kb_base, sbi_irq[12],
                               display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1);
-    // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device
-    // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device
+    /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device
+       Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */
     escc_init(hwdef->serial_base, sbi_irq[12], sbi_irq[12],
               serial_hds[0], serial_hds[1], ESCC_CLOCK, 1);
 
@@ -1762,8 +1762,8 @@ static void sun4c_hw_init(const struct sun4c_hwdef *hwdef, ram_addr_t RAM_size,
 
     slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[1],
                               display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1);
-    // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device
-    // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device
+    /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device
+       Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */
     escc_init(hwdef->serial_base, slavio_irq[1],
               slavio_irq[1], serial_hds[0], serial_hds[1],
               ESCC_CLOCK, 1);
diff --git a/ppc-dis.c b/ppc-dis.c
index ffdbec1..bc98cbe 100644
--- a/ppc-dis.c
+++ b/ppc-dis.c
@@ -5152,7 +5152,7 @@ powerpc_dialect (struct disassemble_info *info)
   return dialect;
 }
 
-/* Qemu default */
+/* QEMU default */
 int
 print_insn_ppc (bfd_vma memaddr, struct disassemble_info *info)
 {
diff --git a/qemu-queue.h b/qemu-queue.h
index 74d7122..9288cd8 100644
--- a/qemu-queue.h
+++ b/qemu-queue.h
@@ -1,7 +1,7 @@
 /*      $NetBSD: queue.h,v 1.52 2009/04/20 09:56:08 mschuett Exp $ */
 
 /*
- * Qemu version: Copy from netbsd, removed debug code, removed some of
+ * QEMU version: Copy from netbsd, removed debug code, removed some of
  * the implementations.  Left in singly-linked lists, lists, simple
  * queues, and tail queues.
  */
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 6c5d28b..74bf7f7 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -276,7 +276,7 @@ struct CPUAlphaState {
     target_ulong t0, t1;
 #endif
 
-    /* Those resources are used only in Qemu core */
+    /* Those resources are used only in QEMU core */
     CPU_COMMON
 
     int error_code;
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 7430aa5..257c4c4 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -418,7 +418,7 @@ struct CPUMIPSState {
     /* We waste some space so we can handle shadow registers like TCs. */
     TCState tcs[MIPS_SHADOW_SET_MAX];
     CPUMIPSFPUContext fpus[MIPS_FPU_MAX];
-    /* Qemu */
+    /* QEMU */
     int error_code;
     uint32_t hflags;    /* CPU State */
     /* TMASK defines different execution modes */
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index ca6f1cb..e7fb364 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -233,10 +233,10 @@ enum {
     POWERPC_EXCP_DTLBE    = 93, /* Data TLB error                            */
     /* EOL                                                                   */
     POWERPC_EXCP_NB       = 96,
-    /* Qemu exceptions: used internally during code translation              */
+    /* QEMU exceptions: used internally during code translation              */
     POWERPC_EXCP_STOP         = 0x200, /* stop translation                   */
     POWERPC_EXCP_BRANCH       = 0x201, /* branch instruction                 */
-    /* Qemu exceptions: special cases we want to stop translation            */
+    /* QEMU exceptions: special cases we want to stop translation            */
     POWERPC_EXCP_SYNC         = 0x202, /* context synchronizing instruction  */
     POWERPC_EXCP_SYSCALL_USER = 0x203, /* System call in user mode only      */
     POWERPC_EXCP_STCX         = 0x204 /* Conditional stores in user mode     */
@@ -1041,7 +1041,7 @@ struct CPUPPCState {
     /* opcode handlers */
     opc_handler_t *opcodes[0x40];
 
-    /* Those resources are used only in Qemu core */
+    /* Those resources are used only in QEMU core */
     target_ulong hflags;      /* hflags is a MSR & HFLAGS_MASK         */
     target_ulong hflags_nmsr; /* specific hflags, not coming from MSR */
     int mmu_idx;         /* precomputed MMU index to speed up mem accesses */
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 39dcc27..e13b749 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -365,7 +365,7 @@ void ppc6xx_tlb_store (CPUPPCState *env, target_ulong EPN, int way, int is_code,
     tlb = &env->tlb.tlb6[nr];
     LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
               " PTE1 " TARGET_FMT_lx "\n", nr, env->nb_tlb, EPN, pte0, pte1);
-    /* Invalidate any pending reference in Qemu for this virtual address */
+    /* Invalidate any pending reference in QEMU for this virtual address */
     __ppc6xx_tlb_invalidate_virt(env, EPN, is_code, 1);
     tlb->pte0 = pte0;
     tlb->pte1 = pte1;
@@ -729,7 +729,7 @@ void ppc_slb_invalidate_all (CPUPPCState *env)
             slb->esid &= ~SLB_ESID_V;
             /* XXX: given the fact that segment size is 256 MB or 1TB,
              *      and we still don't have a tlb_flush_mask(env, n, mask)
-             *      in Qemu, we just invalidate all TLBs
+             *      in QEMU, we just invalidate all TLBs
              */
             do_invalidate = 1;
         }
@@ -752,7 +752,7 @@ void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
 
         /* XXX: given the fact that segment size is 256 MB or 1TB,
          *      and we still don't have a tlb_flush_mask(env, n, mask)
-         *      in Qemu, we just invalidate all TLBs
+         *      in QEMU, we just invalidate all TLBs
          */
         tlb_flush(env, 1);
     }
@@ -2319,7 +2319,7 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
     case POWERPC_MMU_2_06:
         /* tlbie invalidate TLBs for all segments */
         /* XXX: given the fact that there are too many segments to invalidate,
-         *      and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
+         *      and we still don't have a tlb_flush_mask(env, n, mask) in QEMU,
          *      we just invalidate all TLBs
          */
         tlb_flush(env, 1);
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 724f4c7..d929213 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -470,7 +470,7 @@ void kvm_arch_pre_run(CPUPPCState *env, struct kvm_run *run)
     int r;
     unsigned irq;
 
-    /* PowerPC Qemu tracks the various core input pins (interrupt, critical
+    /* PowerPC QEMU tracks the various core input pins (interrupt, critical
      * interrupt, reset, etc) in PPC-specific env->irq_input_state. */
     if (!cap_interrupt_level &&
         run->ready_for_interrupt_injection &&
diff --git a/target-ppc/kvm_ppc.c b/target-ppc/kvm_ppc.c
index 24fc6bc..a2e49cd 100644
--- a/target-ppc/kvm_ppc.c
+++ b/target-ppc/kvm_ppc.c
@@ -31,7 +31,7 @@ void kvmppc_init(void)
 {
     /* XXX The only reason KVM yields control back to qemu is device IO. Since
      * an idle guest does no IO, qemu's device model will never get a chance to
-     * run. So, until Qemu gains IO threads, we create this timer to ensure
+     * run. So, until QEMU gains IO threads, we create this timer to ensure
      * that the device model gets a chance to run. */
     kvmppc_timer_rate = get_ticks_per_sec() / 10;
     kvmppc_timer = qemu_new_timer_ns(vm_clock, &kvmppc_timer_hack, NULL);
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 367eefa..b1f8785 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -1796,17 +1796,17 @@ static void gen_spr_440 (CPUPPCState *env)
 static void gen_spr_40x (CPUPPCState *env)
 {
     /* Cache */
-    /* not emulated, as Qemu do not emulate caches */
+    /* not emulated, as QEMU do not emulate caches */
     spr_register(env, SPR_40x_DCCR, "DCCR",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
-    /* not emulated, as Qemu do not emulate caches */
+    /* not emulated, as QEMU do not emulate caches */
     spr_register(env, SPR_40x_ICCR, "ICCR",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
-    /* not emulated, as Qemu do not emulate caches */
+    /* not emulated, as QEMU do not emulate caches */
     spr_register(env, SPR_BOOKE_ICDBDR, "ICDBDR",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, SPR_NOACCESS,
@@ -1974,7 +1974,7 @@ static void gen_spr_401_403 (CPUPPCState *env)
                  SPR_NOACCESS, &spr_write_tbu,
                  0x00000000);
     /* Debug */
-    /* not emulated, as Qemu do not emulate caches */
+    /* not emulated, as QEMU do not emulate caches */
     spr_register(env, SPR_403_CDBCR, "CDBCR",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
@@ -2012,12 +2012,12 @@ static void gen_spr_401 (CPUPPCState *env)
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_40x_sler,
                  0x00000000);
-    /* not emulated, as Qemu never does speculative access */
+    /* not emulated, as QEMU never does speculative access */
     spr_register(env, SPR_40x_SGR, "SGR",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0xFFFFFFFF);
-    /* not emulated, as Qemu do not emulate caches */
+    /* not emulated, as QEMU do not emulate caches */
     spr_register(env, SPR_40x_DCWR, "DCWR",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
@@ -3436,12 +3436,12 @@ static void init_proc_403GCX (CPUPPCState *env)
     gen_spr_403_real(env);
     gen_spr_403_mmu(env);
     /* Bus access control */
-    /* not emulated, as Qemu never does speculative access */
+    /* not emulated, as QEMU never does speculative access */
     spr_register(env, SPR_40x_SGR, "SGR",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0xFFFFFFFF);
-    /* not emulated, as Qemu do not emulate caches */
+    /* not emulated, as QEMU do not emulate caches */
     spr_register(env, SPR_40x_DCWR, "DCWR",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
@@ -3488,12 +3488,12 @@ static void init_proc_405 (CPUPPCState *env)
     gen_spr_40x(env);
     gen_spr_405(env);
     /* Bus access control */
-    /* not emulated, as Qemu never does speculative access */
+    /* not emulated, as QEMU never does speculative access */
     spr_register(env, SPR_40x_SGR, "SGR",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0xFFFFFFFF);
-    /* not emulated, as Qemu do not emulate caches */
+    /* not emulated, as QEMU do not emulate caches */
     spr_register(env, SPR_40x_DCWR, "DCWR",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
@@ -9442,13 +9442,13 @@ static void init_ppc_proc (CPUPPCState *env, const ppc_def_t *def)
     }
     if (env->irq_inputs == NULL) {
         fprintf(stderr, "WARNING: no internal IRQ controller registered.\n"
-                " Attempt Qemu to crash very soon !\n");
+                " Attempt QEMU to crash very soon !\n");
     }
 #endif
     if (env->check_pow == NULL) {
         fprintf(stderr, "WARNING: no power management check handler "
                 "registered.\n"
-                " Attempt Qemu to crash very soon !\n");
+                " Attempt QEMU to crash very soon !\n");
     }
 }
 
diff --git a/ui/cocoa.m b/ui/cocoa.m
index 0711205..e7d6e89 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -772,7 +772,7 @@ QemuCocoaView *cocoaView;
               modalForWindow:normalWindow modalDelegate:self
               didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:NULL];
     } else {
-        // or Launch Qemu, with the global args
+        // or launch QEMU, with the global args
         [self startEmulationWithArgc:gArgc argv:(char **)gArgv];
     }
 }
diff --git a/ui/spice-display.c b/ui/spice-display.c
index cb8a7ad..5418eb3 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -219,7 +219,7 @@ static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
 /*
  * Called from spice server thread context (via interface_release_ressource)
  * We do *not* hold the global qemu mutex here, so extra care is needed
- * when calling qemu functions.  Qemu interfaces used:
+ * when calling qemu functions.  QEMU interfaces used:
  *    - g_free (underlying glibc free is re-entrant).
  */
 void qemu_spice_destroy_update(SimpleSpiceDisplay *sdpy, SimpleSpiceUpdate *update)
commit c5ec15ea3b9374e6d493f8de7dfc170cec058068
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Apr 7 09:23:38 2012 +0200

    Replace Qemu by QEMU in w32 installation path (prefix)
    
    The official spelling is QEMU.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/configure b/configure
index 6f850a6..671b232 100755
--- a/configure
+++ b/configure
@@ -519,7 +519,7 @@ EOF
   if compile_prog "" "-liberty" ; then
     LIBS="-liberty $LIBS"
   fi
-  prefix="c:/Program Files/Qemu"
+  prefix="c:/Program Files/QEMU"
   mandir="\${prefix}"
   datadir="\${prefix}"
   docdir="\${prefix}"
diff --git a/qemu-doc.texi b/qemu-doc.texi
index d18dff0..9e07ba6 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -2709,9 +2709,9 @@ MinGW's default header and linker search paths.
 @file{make}.  If you have problems using SDL, verify that
 @file{sdl-config} can be launched from the MSYS command line.
 
- at item You can install QEMU in @file{Program Files/Qemu} by typing
+ at item You can install QEMU in @file{Program Files/QEMU} by typing
 @file{make install}. Don't forget to copy @file{SDL.dll} in
- at file{Program Files/Qemu}.
+ at file{Program Files/QEMU}.
 
 @end itemize
 
@@ -2745,7 +2745,7 @@ The example assumes @file{sdl-config} is installed under @file{/usr/i686-pc-ming
 MinGW cross compilation tools have names like @file{i686-pc-mingw32-gcc} and @file{i686-pc-mingw32-strip}.
 We set the @code{PATH} environment variable to ensure the MinGW version of @file{sdl-config} is used and
 use --cross-prefix to specify the name of the cross compiler.
-You can also use --prefix to set the Win32 install path which defaults to @file{c:/Program Files/Qemu}.
+You can also use --prefix to set the Win32 install path which defaults to @file{c:/Program Files/QEMU}.
 
 Under Fedora Linux, you can run:
 @example
commit 6576b74b0ba068f252cc23c5a541c59621270483
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Apr 7 09:23:37 2012 +0200

    Replace Qemu by QEMU in internal documentation
    
    The official spelling is QEMU.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/CODING_STYLE b/CODING_STYLE
index 7c82d4d..dcbce28 100644
--- a/CODING_STYLE
+++ b/CODING_STYLE
@@ -1,4 +1,4 @@
-Qemu Coding Style
+QEMU Coding Style
 =================
 
 Please use the script checkpatch.pl in the scripts directory to check
diff --git a/docs/ccid.txt b/docs/ccid.txt
index b8e504a..450a66a 100644
--- a/docs/ccid.txt
+++ b/docs/ccid.txt
@@ -1,4 +1,4 @@
-Qemu CCID Device Documentation.
+QEMU CCID Device Documentation.
 
 Contents
 1. USB CCID device
diff --git a/docs/specs/ivshmem_device_spec.txt b/docs/specs/ivshmem_device_spec.txt
index 23dd2ba..667a862 100644
--- a/docs/specs/ivshmem_device_spec.txt
+++ b/docs/specs/ivshmem_device_spec.txt
@@ -24,7 +24,7 @@ The device currently supports 4 registers of 32-bits each.  Registers
 are used for synchronization between guests sharing the same memory object when
 interrupts are supported (this requires using the shared memory server).
 
-The server assigns each VM an ID number and sends this ID number to the Qemu
+The server assigns each VM an ID number and sends this ID number to the QEMU
 process when the guest starts.
 
 enum ivshmem_registers {
diff --git a/target-alpha/STATUS b/target-alpha/STATUS
index 742e370..6c97445 100644
--- a/target-alpha/STATUS
+++ b/target-alpha/STATUS
@@ -4,7 +4,7 @@ Alpha emulation structure:
 cpu.h           : CPU definitions globally exported
 exec.h          : CPU definitions used only for translated code execution
 helper.c        : helpers that can be called either by the translated code
-                  or the Qemu core, including the exception handler.
+                  or the QEMU core, including the exception handler.
 op_helper.c     : helpers that can be called only from TCG
 helper.h        : TCG helpers prototypes
 translate.c     : Alpha instructions to micro-operations translator
diff --git a/target-mips/TODO b/target-mips/TODO
index 9101881..2a3546f 100644
--- a/target-mips/TODO
+++ b/target-mips/TODO
@@ -16,7 +16,7 @@ General
   Existing documentation is x86-centric.
 - Reverse endianness bit not implemented
 - The TLB emulation is very inefficient:
-  Qemu's softmmu implements a x86-style MMU, with separate entries
+  QEMU's softmmu implements a x86-style MMU, with separate entries
   for read/write/execute, a TLB index which is just a modulo of the
   virtual address, and a set of TLBs for each user/kernel/supervisor
   MMU mode.
@@ -25,7 +25,7 @@ General
   up to 256 ASID tags as additional matching criterion (which roughly
   equates to 256 MMU modes). It also has a global flag which causes
   entries to match regardless of ASID.
-  To cope with these differences, Qemu currently flushes the TLB at
+  To cope with these differences, QEMU currently flushes the TLB at
   each ASID change. Using the MMU modes to implement ASIDs hinges on
   implementing the global bit efficiently.
 - save/restore of the CPU state is not implemented (see machine.c).
commit 071c93945825dcf8b8ec0d81f09e631d7c96142d
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Apr 7 09:23:36 2012 +0200

    Replace Qemu by QEMU in user visible documentation
    
    The official spelling is QEMU.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/fsdev/virtfs-proxy-helper.texi b/fsdev/virtfs-proxy-helper.texi
index faa0434..e60e3b9 100644
--- a/fsdev/virtfs-proxy-helper.texi
+++ b/fsdev/virtfs-proxy-helper.texi
@@ -24,7 +24,7 @@ in non-root mode, but doing privileged operations using socket IO.
 Proxy helper(a stand alone binary part of qemu) is invoked with
 root privileges. Proxy helper chroots into 9p export path and creates
 a socket pair or a named socket based on the command line parameter.
-Qemu and proxy helper communicate using this socket. QEMU proxy fs
+QEMU and proxy helper communicate using this socket. QEMU proxy fs
 driver sends filesystem request to proxy helper and receives the
 response from it.
 
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 83b2ad5..d18dff0 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -968,7 +968,7 @@ monitor (@pxref{pcsys_keys}).
 
 QEMU emulates a PCI UHCI USB controller. You can virtually plug
 virtual USB devices or real host USB devices (experimental, works only
-on Linux hosts).  Qemu will automatically create and connect virtual USB hubs
+on Linux hosts).  QEMU will automatically create and connect virtual USB hubs
 as necessary to connect multiple USB devices.
 
 @menu
diff --git a/qemu-nbd.texi b/qemu-nbd.texi
index 44996cc..6955d90 100644
--- a/qemu-nbd.texi
+++ b/qemu-nbd.texi
@@ -6,7 +6,7 @@ usage: qemu-nbd [OPTION]...  @var{filename}
 
 @c man begin DESCRIPTION
 
-Export Qemu disk image using NBD protocol.
+Export QEMU disk image using NBD protocol.
 
 @c man end
 
diff --git a/qemu-options.hx b/qemu-options.hx
index f72f9a0..a169792 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1310,7 +1310,7 @@ and a @var{name} can be assigned for use in monitor commands.
 Optionally, for PCI cards, you can specify the number @var{v} of MSI-X vectors
 that the card should have; this option currently only affects virtio cards; set
 @var{v} = 0 to disable MSI-X. If no @option{-net} option is specified, a single
-NIC is created.  Qemu can emulate several different models of network card.
+NIC is created.  QEMU can emulate several different models of network card.
 Valid values for @var{type} are
 @code{virtio}, @code{i82551}, @code{i82557b}, @code{i82559er},
 @code{ne2k_pci}, @code{ne2k_isa}, @code{pcnet}, @code{rtl8139},
@@ -2133,7 +2133,7 @@ activates telnet remote echo and single char transfer, then you can
 use the following options to step up a netcat redirector to allow
 telnet on port 5555 to access the qemu port.
 @table @code
- at item Qemu Options:
+ at item QEMU Options:
 -serial udp::4555@@:4556
 @item netcat options:
 -u -P 4555 -L 0.0.0.0:4556 -t -p 5555 -I -T
commit 97a33880e7c06332ea3498437c70a903cbbfe361
Author: Wanpeng Li <liwp at linux.vnet.ibm.com>
Date:   Fri Apr 6 15:52:09 2012 +0800

    remove useless comments in dma
    
    This comment is useless, just removes it and makes the codes clear.
    
    Signed-off-by: Wanpeng Li <liwp at linux.vnet.ibm.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/dma.h b/dma.h
index 20e86d2..5bd1fc8 100644
--- a/dma.h
+++ b/dma.h
@@ -11,7 +11,6 @@
 #define DMA_H
 
 #include <stdio.h>
-//#include "cpu.h"
 #include "hw/hw.h"
 #include "block.h"
 
commit 3b2aba2f1309cebbcb72a5f006479f2467aa4e9f
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Apr 7 11:48:39 2012 +0200

    tci: Support targets with CONFIG_TCG_PASS_AREG0 (fix broken build)
    
    Builds with --enable-tcg-interpreter failed because more and more
    targets (currently alpha and sparc) replaced the global env in AREG0
    by function parameters.
    
    Convert the TCG interpreter to use the new helper functions and add
    defines for those targets which still use AREG0.
    
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tci.c b/tci.c
index 70e7bfb..c43fe7d 100644
--- a/tci.c
+++ b/tci.c
@@ -63,6 +63,17 @@ void *tci_tb_ptr;
 
 static tcg_target_ulong tci_reg[TCG_TARGET_NB_REGS];
 
+#if !defined(CONFIG_TCG_PASS_AREG0)
+# define helper_ldb_mmu(env, addr, mmu_idx) __ldb_mmu(addr, mmu_idx)
+# define helper_ldw_mmu(env, addr, mmu_idx) __ldw_mmu(addr, mmu_idx)
+# define helper_ldl_mmu(env, addr, mmu_idx) __ldl_mmu(addr, mmu_idx)
+# define helper_ldq_mmu(env, addr, mmu_idx) __ldq_mmu(addr, mmu_idx)
+# define helper_stb_mmu(env, addr, val, mmu_idx) __stb_mmu(addr, val, mmu_idx)
+# define helper_stw_mmu(env, addr, val, mmu_idx) __stw_mmu(addr, val, mmu_idx)
+# define helper_stl_mmu(env, addr, val, mmu_idx) __stl_mmu(addr, val, mmu_idx)
+# define helper_stq_mmu(env, addr, val, mmu_idx) __stq_mmu(addr, val, mmu_idx)
+#endif /* !CONFIG_TCG_PASS_AREG0 */
+
 static tcg_target_ulong tci_read_reg(TCGReg index)
 {
     assert(index < ARRAY_SIZE(tci_reg));
@@ -1049,7 +1060,7 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr)
             t0 = *tb_ptr++;
             taddr = tci_read_ulong(&tb_ptr);
 #ifdef CONFIG_SOFTMMU
-            tmp8 = __ldb_mmu(taddr, tci_read_i(&tb_ptr));
+            tmp8 = helper_ldb_mmu(env, taddr, tci_read_i(&tb_ptr));
 #else
             host_addr = (tcg_target_ulong)taddr;
             assert(taddr == host_addr);
@@ -1061,7 +1072,7 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr)
             t0 = *tb_ptr++;
             taddr = tci_read_ulong(&tb_ptr);
 #ifdef CONFIG_SOFTMMU
-            tmp8 = __ldb_mmu(taddr, tci_read_i(&tb_ptr));
+            tmp8 = helper_ldb_mmu(env, taddr, tci_read_i(&tb_ptr));
 #else
             host_addr = (tcg_target_ulong)taddr;
             assert(taddr == host_addr);
@@ -1073,7 +1084,7 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr)
             t0 = *tb_ptr++;
             taddr = tci_read_ulong(&tb_ptr);
 #ifdef CONFIG_SOFTMMU
-            tmp16 = __ldw_mmu(taddr, tci_read_i(&tb_ptr));
+            tmp16 = helper_ldw_mmu(env, taddr, tci_read_i(&tb_ptr));
 #else
             host_addr = (tcg_target_ulong)taddr;
             assert(taddr == host_addr);
@@ -1085,7 +1096,7 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr)
             t0 = *tb_ptr++;
             taddr = tci_read_ulong(&tb_ptr);
 #ifdef CONFIG_SOFTMMU
-            tmp16 = __ldw_mmu(taddr, tci_read_i(&tb_ptr));
+            tmp16 = helper_ldw_mmu(env, taddr, tci_read_i(&tb_ptr));
 #else
             host_addr = (tcg_target_ulong)taddr;
             assert(taddr == host_addr);
@@ -1098,7 +1109,7 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr)
             t0 = *tb_ptr++;
             taddr = tci_read_ulong(&tb_ptr);
 #ifdef CONFIG_SOFTMMU
-            tmp32 = __ldl_mmu(taddr, tci_read_i(&tb_ptr));
+            tmp32 = helper_ldl_mmu(env, taddr, tci_read_i(&tb_ptr));
 #else
             host_addr = (tcg_target_ulong)taddr;
             assert(taddr == host_addr);
@@ -1110,7 +1121,7 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr)
             t0 = *tb_ptr++;
             taddr = tci_read_ulong(&tb_ptr);
 #ifdef CONFIG_SOFTMMU
-            tmp32 = __ldl_mmu(taddr, tci_read_i(&tb_ptr));
+            tmp32 = helper_ldl_mmu(env, taddr, tci_read_i(&tb_ptr));
 #else
             host_addr = (tcg_target_ulong)taddr;
             assert(taddr == host_addr);
@@ -1123,7 +1134,7 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr)
             t0 = *tb_ptr++;
             taddr = tci_read_ulong(&tb_ptr);
 #ifdef CONFIG_SOFTMMU
-            tmp32 = __ldl_mmu(taddr, tci_read_i(&tb_ptr));
+            tmp32 = helper_ldl_mmu(env, taddr, tci_read_i(&tb_ptr));
 #else
             host_addr = (tcg_target_ulong)taddr;
             assert(taddr == host_addr);
@@ -1138,7 +1149,7 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr)
 #endif
             taddr = tci_read_ulong(&tb_ptr);
 #ifdef CONFIG_SOFTMMU
-            tmp64 = __ldq_mmu(taddr, tci_read_i(&tb_ptr));
+            tmp64 = helper_ldq_mmu(env, taddr, tci_read_i(&tb_ptr));
 #else
             host_addr = (tcg_target_ulong)taddr;
             assert(taddr == host_addr);
@@ -1154,7 +1165,7 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr)
             taddr = tci_read_ulong(&tb_ptr);
 #ifdef CONFIG_SOFTMMU
             t2 = tci_read_i(&tb_ptr);
-            __stb_mmu(taddr, t0, t2);
+            helper_stb_mmu(env, taddr, t0, t2);
 #else
             host_addr = (tcg_target_ulong)taddr;
             assert(taddr == host_addr);
@@ -1166,7 +1177,7 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr)
             taddr = tci_read_ulong(&tb_ptr);
 #ifdef CONFIG_SOFTMMU
             t2 = tci_read_i(&tb_ptr);
-            __stw_mmu(taddr, t0, t2);
+            helper_stw_mmu(env, taddr, t0, t2);
 #else
             host_addr = (tcg_target_ulong)taddr;
             assert(taddr == host_addr);
@@ -1178,7 +1189,7 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr)
             taddr = tci_read_ulong(&tb_ptr);
 #ifdef CONFIG_SOFTMMU
             t2 = tci_read_i(&tb_ptr);
-            __stl_mmu(taddr, t0, t2);
+            helper_stl_mmu(env, taddr, t0, t2);
 #else
             host_addr = (tcg_target_ulong)taddr;
             assert(taddr == host_addr);
@@ -1190,7 +1201,7 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr)
             taddr = tci_read_ulong(&tb_ptr);
 #ifdef CONFIG_SOFTMMU
             t2 = tci_read_i(&tb_ptr);
-            __stq_mmu(taddr, tmp64, t2);
+            helper_stq_mmu(env, taddr, tmp64, t2);
 #else
             host_addr = (tcg_target_ulong)taddr;
             assert(taddr == host_addr);
commit adcd61f7fcd5a24e65b2ec087bfae2356805993b
Merge: 6375e09... d8fd295...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Apr 7 11:45:25 2012 +0000

    Merge branch 'linux-user-for-upstream' of git://git.linaro.org/people/rikuvoipio/qemu
    
    * 'linux-user-for-upstream' of git://git.linaro.org/people/rikuvoipio/qemu:
      Userspace ARM BE8 support
      elf.h: Update EF_ARM_ constants to newer ABI versions
      arm-linux-user: fix elfload.c's AT_HWCAP to reflect cpu features.
      linux-user/arm/syscall_nr.h: Add syscall number for ppoll
      linux-user: Add support for prctl PR_GET_NAME and PR_SET_NAME
      linux-user/syscall.c: Fix indentation in prctl handling
      linux-user: reserve 4GB of vmem for 32-on-64
      linux-user: resolve reserved_va vma downwards
      linux-user: take RESERVED_VA into account for g2h_valid()
      linux-user: fix fallocate
      linux-user: Add ioctl for BLKBSZGET
      linux-user: add BLKSSZGET ioctl wrapper
      linux-user: fix BLK ioctl arguments
      linux-user: add struct old_dev_t compat
      linux-user: implement device mapper ioctls
      linux-user: target_argv is placed on ts->bprm->argv and can't be freed()
      linux-user: improve fake /proc/self/stat making `ps` not segfault.

commit 6375e09e79964fa6eac3e8426d25c8b759185482
Author: Stefan Weil <sw at weilnetz.de>
Date:   Fri Apr 6 22:26:15 2012 +0200

    w64: Fix data type of tb_next and other variables used for host addresses
    
    QEMU host addresses must use uintptr_t to be portable for hosts with
    an unusual size of long (w64).
    
    tb_jmp_offset is an uint16_t value, therefore the local variable offset
    in function tb_set_jmp_target was changed from unsigned long to uint16_t.
    
    The type cast to long in function tb_add_jump now also uses uintptr_t.
    For the bit operation used here, the signedness of the type cast does
    not matter.
    
    Some remaining unsigned long values are either only used for ARM assembler
    code or will be fixed in a later patch for PPC.
    
    v2:
    Fix signature of tb_find_pc in exec.c, too (hint from Blue Swirl, thanks).
    There remain lots of other long / unsigned long in exec.c which must be
    replaced by uintptr_t. This will be done in a separate patch. Here
    only one of these type casts is fixed.
    
    v3:
    Also fix signature of page_unprotect.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/exec-all.h b/exec-all.h
index 93a5b22..a6d6519 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -85,7 +85,7 @@ void cpu_gen_init(void);
 int cpu_gen_code(CPUArchState *env, struct TranslationBlock *tb,
                  int *gen_code_size_ptr);
 int cpu_restore_state(struct TranslationBlock *tb,
-                      CPUArchState *env, unsigned long searched_pc);
+                      CPUArchState *env, uintptr_t searched_pc);
 void cpu_resume_from_signal(CPUArchState *env1, void *puc);
 void cpu_io_recompile(CPUArchState *env, void *retaddr);
 TranslationBlock *tb_gen_code(CPUArchState *env, 
@@ -93,7 +93,7 @@ TranslationBlock *tb_gen_code(CPUArchState *env,
                               int cflags);
 void cpu_exec_init(CPUArchState *env);
 void QEMU_NORETURN cpu_loop_exit(CPUArchState *env1);
-int page_unprotect(target_ulong address, unsigned long pc, void *puc);
+int page_unprotect(target_ulong address, uintptr_t pc, void *puc);
 void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
                                    int is_cpu_write_access);
 void tlb_flush_page(CPUArchState *env, target_ulong addr);
@@ -150,7 +150,7 @@ struct TranslationBlock {
 #ifdef USE_DIRECT_JUMP
     uint16_t tb_jmp_offset[2]; /* offset of jump instruction */
 #else
-    unsigned long tb_next[2]; /* address of jump generated code */
+    uintptr_t tb_next[2]; /* address of jump generated code */
 #endif
     /* list of TBs jumping to this one. This is a circular list using
        the two least significant bits of the pointers to tell what is
@@ -202,14 +202,14 @@ static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t 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)
+static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
 {
     /* patch the branch destination */
     *(uint32_t *)jmp_addr = addr - (jmp_addr + 4);
     /* no need to flush icache explicitly */
 }
 #elif defined(__arm__)
-static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
+static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
 {
 #if !QEMU_GNUC_PREREQ(4, 1)
     register unsigned long _beg __asm ("a1");
@@ -237,19 +237,17 @@ static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr
 #endif
 
 static inline void tb_set_jmp_target(TranslationBlock *tb,
-                                     int n, unsigned long addr)
+                                     int n, uintptr_t addr)
 {
-    unsigned long offset;
-
-    offset = tb->tb_jmp_offset[n];
-    tb_set_jmp_target1((unsigned long)(tb->tc_ptr + offset), addr);
+    uint16_t offset = tb->tb_jmp_offset[n];
+    tb_set_jmp_target1((uintptr_t)(tb->tc_ptr + offset), addr);
 }
 
 #else
 
 /* set the jump target */
 static inline void tb_set_jmp_target(TranslationBlock *tb,
-                                     int n, unsigned long addr)
+                                     int n, uintptr_t addr)
 {
     tb->tb_next[n] = addr;
 }
@@ -262,15 +260,15 @@ static inline void tb_add_jump(TranslationBlock *tb, int n,
     /* NOTE: this test is only needed for thread safety */
     if (!tb->jmp_next[n]) {
         /* patch the native jump address */
-        tb_set_jmp_target(tb, n, (unsigned long)tb_next->tc_ptr);
+        tb_set_jmp_target(tb, n, (uintptr_t)tb_next->tc_ptr);
 
         /* add in TB jmp circular list */
         tb->jmp_next[n] = tb_next->jmp_first;
-        tb_next->jmp_first = (TranslationBlock *)((long)(tb) | (n));
+        tb_next->jmp_first = (TranslationBlock *)((uintptr_t)(tb) | (n));
     }
 }
 
-TranslationBlock *tb_find_pc(unsigned long pc_ptr);
+TranslationBlock *tb_find_pc(uintptr_t pc_ptr);
 
 #include "qemu-lock.h"
 
@@ -288,13 +286,14 @@ extern void *tci_tb_ptr;
 #  define GETPC() tci_tb_ptr
 # endif
 #elif defined(__s390__) && !defined(__s390x__)
-# define GETPC() ((void*)(((unsigned long)__builtin_return_address(0) & 0x7fffffffUL) - 1))
+# define GETPC() \
+    ((void *)(((uintptr_t)__builtin_return_address(0) & 0x7fffffffUL) - 1))
 #elif defined(__arm__)
 /* Thumb return addresses have the low bit set, so we need to subtract two.
    This is still safe in ARM mode because instructions are 4 bytes.  */
-# define GETPC() ((void *)((unsigned long)__builtin_return_address(0) - 2))
+# define GETPC() ((void *)((uintptr_t)__builtin_return_address(0) - 2))
 #else
-# define GETPC() ((void *)((unsigned long)__builtin_return_address(0) - 1))
+# define GETPC() ((void *)((uintptr_t)__builtin_return_address(0) - 1))
 #endif
 
 #if !defined(CONFIG_USER_ONLY)
diff --git a/exec.c b/exec.c
index 6731ab8..03d3a6b 100644
--- a/exec.c
+++ b/exec.c
@@ -1380,7 +1380,7 @@ void tb_link_page(TranslationBlock *tb,
 
 /* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
    tb[1].tc_ptr. Return NULL if not found */
-TranslationBlock *tb_find_pc(unsigned long tc_ptr)
+TranslationBlock *tb_find_pc(uintptr_t tc_ptr)
 {
     int m_min, m_max, m;
     unsigned long v;
@@ -2502,7 +2502,7 @@ int page_check_range(target_ulong start, target_ulong len, int flags)
 
 /* called from signal handler: invalidate the code and unprotect the
    page. Return TRUE if the fault was successfully handled. */
-int page_unprotect(target_ulong address, unsigned long pc, void *puc)
+int page_unprotect(target_ulong address, uintptr_t pc, void *puc)
 {
     unsigned int prot;
     PageDesc *p;
@@ -4484,7 +4484,7 @@ void cpu_io_recompile(CPUArchState *env, void *retaddr)
     target_ulong pc, cs_base;
     uint64_t flags;
 
-    tb = tb_find_pc((unsigned long)retaddr);
+    tb = tb_find_pc((uintptr_t)retaddr);
     if (!tb) {
         cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p", 
                   retaddr);
diff --git a/translate-all.c b/translate-all.c
index 8c7d303..5bd2d37 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -109,11 +109,11 @@ int cpu_gen_code(CPUArchState *env, TranslationBlock *tb, int *gen_code_size_ptr
 /* The cpu state corresponding to 'searched_pc' is restored.
  */
 int cpu_restore_state(TranslationBlock *tb,
-                      CPUArchState *env, unsigned long searched_pc)
+                      CPUArchState *env, uintptr_t searched_pc)
 {
     TCGContext *s = &tcg_ctx;
     int j;
-    unsigned long tc_ptr;
+    uintptr_t tc_ptr;
 #ifdef CONFIG_PROFILER
     int64_t ti;
 #endif
@@ -133,7 +133,7 @@ int cpu_restore_state(TranslationBlock *tb,
     }
 
     /* find opc index corresponding to search_pc */
-    tc_ptr = (unsigned long)tb->tc_ptr;
+    tc_ptr = (uintptr_t)tb->tc_ptr;
     if (searched_pc < tc_ptr)
         return -1;
 
commit 760e141613f5f7c09f5c141658f1e7c23b4a5c33
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Apr 5 19:12:35 2012 +0100

    softfloat: roundAndPackInt{32, 64}: Don't assume int32 is 32 bits
    
    Fix code in roundAndPackInt32 that assumed that int32 was only
    32 bits, by simply using int32_t instead. Fix the parallel bug
    in roundAndPackInt64 as well, although that one is only theoretical
    since it's unlikely that int64 will ever be more than 64 bits.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 074fbc3..d37090a 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -117,7 +117,7 @@ static int32 roundAndPackInt32( flag zSign, uint64_t absZ STATUS_PARAM)
     int8 roundingMode;
     flag roundNearestEven;
     int8 roundIncrement, roundBits;
-    int32 z;
+    int32_t z;
 
     roundingMode = STATUS(float_rounding_mode);
     roundNearestEven = ( roundingMode == float_round_nearest_even );
@@ -166,7 +166,7 @@ static int64 roundAndPackInt64( flag zSign, uint64_t absZ0, uint64_t absZ1 STATU
 {
     int8 roundingMode;
     flag roundNearestEven, increment;
-    int64 z;
+    int64_t z;
 
     roundingMode = STATUS(float_rounding_mode);
     roundNearestEven = ( roundingMode == float_round_nearest_even );
commit b3a6a2e0417c78ec5491347eb85a7d125a5fefdc
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Apr 5 19:12:34 2012 +0100

    softfloat: float*_to_int32_round_to_zero: don't assume int32 is 32 bits
    
    Code in the float64_to_int32_round_to_zero() function was assuming
    that int32 would not be wider than 32 bits; this meant it might
    not correctly detect the overflow case. We take the simple approach
    of using int32_t. Also fix equivalent issues in the functions
    for other float sizes.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 81a7d1a..074fbc3 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -1378,7 +1378,7 @@ int32 float32_to_int32_round_to_zero( float32 a STATUS_PARAM )
     flag aSign;
     int16 aExp, shiftCount;
     uint32_t aSig;
-    int32 z;
+    int32_t z;
     a = float32_squash_input_denormal(a STATUS_VAR);
 
     aSig = extractFloat32Frac( a );
@@ -2762,7 +2762,7 @@ int32 float64_to_int32_round_to_zero( float64 a STATUS_PARAM )
     flag aSign;
     int16 aExp, shiftCount;
     uint64_t aSig, savedASig;
-    int32 z;
+    int32_t z;
     a = float64_squash_input_denormal(a STATUS_VAR);
 
     aSig = extractFloat64Frac( a );
@@ -4248,7 +4248,7 @@ int32 floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM )
     flag aSign;
     int32 aExp, shiftCount;
     uint64_t aSig, savedASig;
-    int32 z;
+    int32_t z;
 
     aSig = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
@@ -5277,7 +5277,7 @@ int32 float128_to_int32_round_to_zero( float128 a STATUS_PARAM )
     flag aSign;
     int32 aExp, shiftCount;
     uint64_t aSig0, aSig1, savedASig;
-    int32 z;
+    int32_t z;
 
     aSig1 = extractFloat128Frac1( a );
     aSig0 = extractFloat128Frac0( a );
commit a52d28afb4e825a5b28815370a268904a4c6dc11
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Apr 5 13:01:54 2012 +0200

    configure: require glib 2.12, 2.20 for mingw32
    
    These are pretty sane requirements to move forward with glib usage.
    2.12 is the version found in RHEL/CentOS 5, and 2.20 is the
    first version to support g_poll.  Without g_poll, we cannot
    integrate well with the glib main loop.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/configure b/configure
index 4b3adc9..6f850a6 100755
--- a/configure
+++ b/configure
@@ -1993,13 +1993,21 @@ fi
 
 ##########################################
 # glib support probe
-if $pkg_config --modversion gthread-2.0 > /dev/null 2>&1 ; then
+
+if test "$mingw32" = yes; then
+    # g_poll is required in order to integrate with the glib main loop.
+    glib_req_ver=2.20
+else
+    glib_req_ver=2.12
+fi
+if $pkg_config --atleast-version=$glib_req_ver gthread-2.0 > /dev/null 2>&1
+then
     glib_cflags=`$pkg_config --cflags gthread-2.0 2>/dev/null`
     glib_libs=`$pkg_config --libs gthread-2.0 2>/dev/null`
     LIBS="$glib_libs $LIBS"
     libs_qga="$glib_libs $libs_qga"
 else
-    echo "glib-2.0 required to compile QEMU"
+    echo "glib-$glib_req_ver required to compile QEMU"
     exit 1
 fi
 
commit ea26ce765cb661a13e4055f38744036a19465e87
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Mar 20 10:49:21 2012 +0100

    main-loop: integrate glib sources for w32
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/main-loop.c b/main-loop.c
index 4d02568..7e163f9 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -221,11 +221,10 @@ int main_loop_init(void)
 static fd_set rfds, wfds, xfds;
 static int nfds;
 static GPollFD poll_fds[1024 * 2]; /* this is probably overkill */
-
-#ifndef _WIN32
 static int n_poll_fds;
 static int max_priority;
 
+#ifndef _WIN32
 static void glib_select_fill(int *max_fd, fd_set *rfds, fd_set *wfds,
                              fd_set *xfds, int *cur_timeout)
 {
@@ -403,6 +402,7 @@ void qemu_fd_register(int fd)
 
 static int os_host_main_loop_wait(int timeout)
 {
+    GMainContext *context = g_main_context_default();
     int ret, i;
     PollingEntry *pe;
     WaitObjects *w = &wait_objects;
@@ -424,17 +424,22 @@ static int os_host_main_loop_wait(int timeout)
         }
     }
 
+    g_main_context_prepare(context, &max_priority);
+    n_poll_fds = g_main_context_query(context, max_priority, &timeout,
+                                      poll_fds, ARRAY_SIZE(poll_fds));
+    g_assert(n_poll_fds <= ARRAY_SIZE(poll_fds));
+
     for (i = 0; i < w->num; i++) {
-        poll_fds[i].fd = (DWORD) w->events[i];
-        poll_fds[i].events = G_IO_IN;
+        poll_fds[n_poll_fds + i].fd = (DWORD) w->events[i];
+        poll_fds[n_poll_fds + i].events = G_IO_IN;
     }
 
     qemu_mutex_unlock_iothread();
-    ret = g_poll(poll_fds, w->num, timeout);
+    ret = g_poll(poll_fds, n_poll_fds + w->num, timeout);
     qemu_mutex_lock_iothread();
     if (ret > 0) {
         for (i = 0; i < w->num; i++) {
-            w->revents[i] = poll_fds[i].revents;
+            w->revents[i] = poll_fds[n_poll_fds + i].revents;
         }
         for (i = 0; i < w->num; i++) {
             if (w->revents[i] && w->func[i]) {
@@ -443,6 +448,10 @@ static int os_host_main_loop_wait(int timeout)
         }
     }
 
+    if (g_main_context_check(context, max_priority, poll_fds, n_poll_fds)) {
+        g_main_context_dispatch(context);
+    }
+
     /* If an edge-triggered socket event occurred, select will return a
      * positive result on the next iteration.  We do not need to do anything
      * here.
commit 06ac7d49797daf8a5c05c7d25db0b205efda8e30
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Mar 20 10:49:20 2012 +0100

    main-loop: replace WaitForMultipleObjects with g_poll
    
    On w32, glib implements g_poll using WaitForMultipleObjects
    or MsgWaitForMultipleObjects.  This means that we can simplify
    our code by switching to g_poll, and at the same time prepare for
    adding back glib sources.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/main-loop.c b/main-loop.c
index 7364074..4d02568 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -220,9 +220,9 @@ int main_loop_init(void)
 
 static fd_set rfds, wfds, xfds;
 static int nfds;
+static GPollFD poll_fds[1024 * 2]; /* this is probably overkill */
 
 #ifndef _WIN32
-static GPollFD poll_fds[1024 * 2]; /* this is probably overkill */
 static int n_poll_fds;
 static int max_priority;
 
@@ -351,6 +351,7 @@ void qemu_del_polling_cb(PollingFunc *func, void *opaque)
 /* Wait objects support */
 typedef struct WaitObjects {
     int num;
+    int revents[MAXIMUM_WAIT_OBJECTS + 1];
     HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
     WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1];
     void *opaque[MAXIMUM_WAIT_OBJECTS + 1];
@@ -367,6 +368,7 @@ int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
     w->events[w->num] = handle;
     w->func[w->num] = func;
     w->opaque[w->num] = opaque;
+    w->revents[w->num] = 0;
     w->num++;
     return 0;
 }
@@ -385,6 +387,7 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
             w->events[i] = w->events[i + 1];
             w->func[i] = w->func[i + 1];
             w->opaque[i] = w->opaque[i + 1];
+            w->revents[i] = w->revents[i + 1];
         }
     }
     if (found) {
@@ -400,9 +403,8 @@ void qemu_fd_register(int fd)
 
 static int os_host_main_loop_wait(int timeout)
 {
-    int ret, ret2, i;
+    int ret, i;
     PollingEntry *pe;
-    int err;
     WaitObjects *w = &wait_objects;
     static struct timeval tv0;
 
@@ -422,33 +424,25 @@ static int os_host_main_loop_wait(int timeout)
         }
     }
 
+    for (i = 0; i < w->num; i++) {
+        poll_fds[i].fd = (DWORD) w->events[i];
+        poll_fds[i].events = G_IO_IN;
+    }
+
     qemu_mutex_unlock_iothread();
-    ret = WaitForMultipleObjects(w->num, w->events, FALSE, timeout);
+    ret = g_poll(poll_fds, w->num, timeout);
     qemu_mutex_lock_iothread();
-    if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
-        if (w->func[ret - WAIT_OBJECT_0]) {
-            w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
+    if (ret > 0) {
+        for (i = 0; i < w->num; i++) {
+            w->revents[i] = poll_fds[i].revents;
         }
-
-        /* Check for additional signaled events */
-        for (i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
-            /* Check if event is signaled */
-            ret2 = WaitForSingleObject(w->events[i], 0);
-            if (ret2 == WAIT_OBJECT_0) {
-                if (w->func[i]) {
-                    w->func[i](w->opaque[i]);
-                }
-            } else if (ret2 != WAIT_TIMEOUT) {
-                err = GetLastError();
-                fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
+        for (i = 0; i < w->num; i++) {
+            if (w->revents[i] && w->func[i]) {
+                w->func[i](w->opaque[i]);
             }
         }
-    } else if (ret != WAIT_TIMEOUT) {
-        err = GetLastError();
-        fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
     }
 
-
     /* If an edge-triggered socket event occurred, select will return a
      * positive result on the next iteration.  We do not need to do anything
      * here.
commit d3385eb448e38f828c78f8f68ec5d79c66a58b5d
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Mar 20 10:49:19 2012 +0100

    main-loop: interrupt wait when data arrives on a socket
    
    Right now, the main loop is not interrupted when data arrives on a
    socket.  To fix this, register each socket to interrupt the main loop
    with WSAEventSelect.  This does not replace select, it only communicates
    a change in socket state that requires a select call.
    
    Since the interrupt fires only once per recv call, or only once
    after a send call returns EWOULDBLOCK we can activate it on all events
    unconditionally.  If QEMU is momentarily uninterested on some condition,
    the main loop will not busy wait.  Instead, it may get one extra wakeup,
    but then it will ignore the condition until progress occurs and/or
    qemu_set_fd_handler is called to set a callback.  At this point the
    condition will be tested via select and the callback will be invoked
    even if it is still disabled on the event.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/main-loop.c b/main-loop.c
index dc6bdb5..7364074 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -392,10 +392,18 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
     }
 }
 
+void qemu_fd_register(int fd)
+{
+    WSAEventSelect(fd, qemu_event_handle, FD_READ | FD_ACCEPT | FD_CLOSE |
+                   FD_CONNECT | FD_WRITE | FD_OOB);
+}
+
 static int os_host_main_loop_wait(int timeout)
 {
     int ret, ret2, i;
     PollingEntry *pe;
+    int err;
+    WaitObjects *w = &wait_objects;
     static struct timeval tv0;
 
     /* XXX: need to suppress polling by better using win32 events */
@@ -403,38 +411,49 @@ static int os_host_main_loop_wait(int timeout)
     for (pe = first_polling_entry; pe != NULL; pe = pe->next) {
         ret |= pe->func(pe->opaque);
     }
-    if (ret == 0) {
-        int err;
-        WaitObjects *w = &wait_objects;
+    if (ret != 0) {
+        return ret;
+    }
 
-        qemu_mutex_unlock_iothread();
-        ret = WaitForMultipleObjects(w->num, w->events, FALSE, timeout);
-        qemu_mutex_lock_iothread();
-        if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
-            if (w->func[ret - WAIT_OBJECT_0]) {
-                w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
-            }
+    if (nfds >= 0) {
+        ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv0);
+        if (ret != 0) {
+            timeout = 0;
+        }
+    }
 
-            /* Check for additional signaled events */
-            for (i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
-                /* Check if event is signaled */
-                ret2 = WaitForSingleObject(w->events[i], 0);
-                if (ret2 == WAIT_OBJECT_0) {
-                    if (w->func[i]) {
-                        w->func[i](w->opaque[i]);
-                    }
-                } else if (ret2 != WAIT_TIMEOUT) {
-                    err = GetLastError();
-                    fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
+    qemu_mutex_unlock_iothread();
+    ret = WaitForMultipleObjects(w->num, w->events, FALSE, timeout);
+    qemu_mutex_lock_iothread();
+    if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
+        if (w->func[ret - WAIT_OBJECT_0]) {
+            w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
+        }
+
+        /* Check for additional signaled events */
+        for (i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
+            /* Check if event is signaled */
+            ret2 = WaitForSingleObject(w->events[i], 0);
+            if (ret2 == WAIT_OBJECT_0) {
+                if (w->func[i]) {
+                    w->func[i](w->opaque[i]);
                 }
+            } else if (ret2 != WAIT_TIMEOUT) {
+                err = GetLastError();
+                fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
             }
-        } else if (ret != WAIT_TIMEOUT) {
-            err = GetLastError();
-            fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
         }
+    } else if (ret != WAIT_TIMEOUT) {
+        err = GetLastError();
+        fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
     }
 
-    ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv0);
+
+    /* If an edge-triggered socket event occurred, select will return a
+     * positive result on the next iteration.  We do not need to do anything
+     * here.
+     */
+
     return ret;
 }
 #endif
diff --git a/main-loop.h b/main-loop.h
index 4987041..e743aa0 100644
--- a/main-loop.h
+++ b/main-loop.h
@@ -359,6 +359,7 @@ void qemu_mutex_unlock_iothread(void);
 
 /* internal interfaces */
 
+void qemu_fd_register(int fd);
 void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds);
 void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int rc);
 
diff --git a/oslib-win32.c b/oslib-win32.c
index ce3021e..ffbc6d0 100644
--- a/oslib-win32.c
+++ b/oslib-win32.c
@@ -28,6 +28,7 @@
 #include <windows.h>
 #include "config-host.h"
 #include "sysemu.h"
+#include "main-loop.h"
 #include "trace.h"
 #include "qemu_socket.h"
 
@@ -76,6 +77,7 @@ void qemu_vfree(void *ptr)
 void socket_set_block(int fd)
 {
     unsigned long opt = 0;
+    WSAEventSelect(fd, NULL, 0);
     ioctlsocket(fd, FIONBIO, &opt);
 }
 
@@ -83,6 +85,7 @@ void socket_set_nonblock(int fd)
 {
     unsigned long opt = 1;
     ioctlsocket(fd, FIONBIO, &opt);
+    qemu_fd_register(fd);
 }
 
 int inet_aton(const char *cp, struct in_addr *ia)
commit 15455536df5ef652759ccf465d5e6f73acb493df
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Mar 20 10:49:18 2012 +0100

    main-loop: disable fd_set-based glib integration under w32
    
    Using select with glib pollfds is wrong under w32.  Restrict
    the code to the POSIX case.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/main-loop.c b/main-loop.c
index a3fd993..dc6bdb5 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -218,7 +218,10 @@ int main_loop_init(void)
     return 0;
 }
 
+static fd_set rfds, wfds, xfds;
+static int nfds;
 
+#ifndef _WIN32
 static GPollFD poll_fds[1024 * 2]; /* this is probably overkill */
 static int n_poll_fds;
 static int max_priority;
@@ -286,7 +289,29 @@ static void glib_select_poll(fd_set *rfds, fd_set *wfds, fd_set *xfds,
     }
 }
 
-#ifdef _WIN32
+static int os_host_main_loop_wait(int timeout)
+{
+    struct timeval tv;
+    int ret;
+
+    glib_select_fill(&nfds, &rfds, &wfds, &xfds, &timeout);
+
+    if (timeout > 0) {
+        qemu_mutex_unlock_iothread();
+    }
+
+    tv.tv_sec = timeout / 1000;
+    tv.tv_usec = (timeout % 1000) * 1000;
+    ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
+
+    if (timeout > 0) {
+        qemu_mutex_lock_iothread();
+    }
+
+    glib_select_poll(&rfds, &wfds, &xfds, (ret < 0));
+    return ret;
+}
+#else
 /***********************************************************/
 /* Polling handling */
 
@@ -367,10 +392,11 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
     }
 }
 
-static void os_host_main_loop_wait(int *timeout)
+static int os_host_main_loop_wait(int timeout)
 {
     int ret, ret2, i;
     PollingEntry *pe;
+    static struct timeval tv0;
 
     /* XXX: need to suppress polling by better using win32 events */
     ret = 0;
@@ -382,7 +408,7 @@ static void os_host_main_loop_wait(int *timeout)
         WaitObjects *w = &wait_objects;
 
         qemu_mutex_unlock_iothread();
-        ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout);
+        ret = WaitForMultipleObjects(w->num, w->events, FALSE, timeout);
         qemu_mutex_lock_iothread();
         if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
             if (w->func[ret - WAIT_OBJECT_0]) {
@@ -408,20 +434,14 @@ static void os_host_main_loop_wait(int *timeout)
         }
     }
 
-    *timeout = 0;
-}
-#else
-static inline void os_host_main_loop_wait(int *timeout)
-{
+    ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv0);
+    return ret;
 }
 #endif
 
 int main_loop_wait(int nonblocking)
 {
-    fd_set rfds, wfds, xfds;
-    int ret, nfds;
-    struct timeval tv;
-    int timeout;
+    int ret, timeout;
 
     if (nonblocking) {
         timeout = 0;
@@ -441,24 +461,7 @@ int main_loop_wait(int nonblocking)
     slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
 #endif
     qemu_iohandler_fill(&nfds, &rfds, &wfds, &xfds);
-
-    glib_select_fill(&nfds, &rfds, &wfds, &xfds, &timeout);
-    os_host_main_loop_wait(&timeout);
-
-    tv.tv_sec = timeout / 1000;
-    tv.tv_usec = (timeout % 1000) * 1000;
-
-    if (timeout > 0) {
-        qemu_mutex_unlock_iothread();
-    }
-
-    ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
-
-    if (timeout > 0) {
-        qemu_mutex_lock_iothread();
-    }
-
-    glib_select_poll(&rfds, &wfds, &xfds, (ret < 0));
+    ret = os_host_main_loop_wait(timeout);
     qemu_iohandler_poll(&rfds, &wfds, &xfds, ret);
 #ifdef CONFIG_SLIRP
     slirp_select_poll(&rfds, &wfds, &xfds, (ret < 0));
commit 4dae83aeac63863af6b59f58552da68b35b1a40d
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Mar 20 10:49:17 2012 +0100

    main loop: use msec-based timeout in glib_select_fill
    
    The timeval-based timeout is not needed until we actually invoke select,
    so compute it only then.  Also group the two calls that modify the
    timeout, glib_select_fill and os_host_main_loop_wait.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/main-loop.c b/main-loop.c
index db23de0..a3fd993 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -224,11 +224,11 @@ static int n_poll_fds;
 static int max_priority;
 
 static void glib_select_fill(int *max_fd, fd_set *rfds, fd_set *wfds,
-                             fd_set *xfds, struct timeval *tv)
+                             fd_set *xfds, int *cur_timeout)
 {
     GMainContext *context = g_main_context_default();
     int i;
-    int timeout = 0, cur_timeout;
+    int timeout = 0;
 
     g_main_context_prepare(context, &max_priority);
 
@@ -253,10 +253,8 @@ static void glib_select_fill(int *max_fd, fd_set *rfds, fd_set *wfds,
         }
     }
 
-    cur_timeout = (tv->tv_sec * 1000) + ((tv->tv_usec + 500) / 1000);
-    if (timeout >= 0 && timeout < cur_timeout) {
-        tv->tv_sec = timeout / 1000;
-        tv->tv_usec = (timeout % 1000) * 1000;
+    if (timeout >= 0 && timeout < *cur_timeout) {
+        *cur_timeout = timeout;
     }
 }
 
@@ -432,11 +430,6 @@ int main_loop_wait(int nonblocking)
         qemu_bh_update_timeout(&timeout);
     }
 
-    os_host_main_loop_wait(&timeout);
-
-    tv.tv_sec = timeout / 1000;
-    tv.tv_usec = (timeout % 1000) * 1000;
-
     /* poll any events */
     /* XXX: separate device handlers from system ones */
     nfds = -1;
@@ -448,7 +441,12 @@ int main_loop_wait(int nonblocking)
     slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
 #endif
     qemu_iohandler_fill(&nfds, &rfds, &wfds, &xfds);
-    glib_select_fill(&nfds, &rfds, &wfds, &xfds, &tv);
+
+    glib_select_fill(&nfds, &rfds, &wfds, &xfds, &timeout);
+    os_host_main_loop_wait(&timeout);
+
+    tv.tv_sec = timeout / 1000;
+    tv.tv_usec = (timeout % 1000) * 1000;
 
     if (timeout > 0) {
         qemu_mutex_unlock_iothread();
commit ab7ab3d74c357e73a37b241fba27ea7f0595c085
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu Apr 5 01:29:40 2012 +0200

    target-sparc: QOM'ify CPU
    
    Embed CPUSPARCState as first member of SPARCCPU.
    Drop cpu_sparc_close() in favor of object_delete() and a finalizer.
    Let cpu_state_reset() call cpu_reset().
    
    Make TYPE_SPARC_CPU non-abstract for now.
    Distinguish between "sparc-cpu" and "sparc64-cpu".
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/cpu-qom.h b/target-sparc/cpu-qom.h
new file mode 100644
index 0000000..3d3ac0f
--- /dev/null
+++ b/target-sparc/cpu-qom.h
@@ -0,0 +1,75 @@
+/*
+ * QEMU SPARC CPU
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * 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.1 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/lgpl-2.1.html>
+ */
+#ifndef QEMU_SPARC_CPU_QOM_H
+#define QEMU_SPARC_CPU_QOM_H
+
+#include "qemu/cpu.h"
+#include "cpu.h"
+
+#ifdef TARGET_SPARC64
+#define TYPE_SPARC_CPU "sparc64-cpu"
+#else
+#define TYPE_SPARC_CPU "sparc-cpu"
+#endif
+
+#define SPARC_CPU_CLASS(klass) \
+    OBJECT_CLASS_CHECK(SPARCCPUClass, (klass), TYPE_SPARC_CPU)
+#define SPARC_CPU(obj) \
+    OBJECT_CHECK(SPARCCPU, (obj), TYPE_SPARC_CPU)
+#define SPARC_CPU_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(SPARCCPUClass, (obj), TYPE_SPARC_CPU)
+
+/**
+ * SPARCCPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * A SPARC CPU model.
+ */
+typedef struct SPARCCPUClass {
+    /*< private >*/
+    CPUClass parent_class;
+    /*< public >*/
+
+    void (*parent_reset)(CPUState *cpu);
+} SPARCCPUClass;
+
+/**
+ * SPARCCPU:
+ * @env: #CPUSPARCState
+ *
+ * A SPARC CPU.
+ */
+typedef struct SPARCCPU {
+    /*< private >*/
+    CPUState parent_obj;
+    /*< public >*/
+
+    CPUSPARCState env;
+} SPARCCPU;
+
+static inline SPARCCPU *sparc_env_get_cpu(CPUSPARCState *env)
+{
+    return SPARC_CPU(container_of(env, SPARCCPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(sparc_env_get_cpu(e))
+
+
+#endif
diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
index 5c03f0b..24f90f1 100644
--- a/target-sparc/cpu.c
+++ b/target-sparc/cpu.c
@@ -25,11 +25,23 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
 
 void cpu_state_reset(CPUSPARCState *env)
 {
+    cpu_reset(ENV_GET_CPU(env));
+}
+
+/* CPUClass::reset() */
+static void sparc_cpu_reset(CPUState *s)
+{
+    SPARCCPU *cpu = SPARC_CPU(s);
+    SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(cpu);
+    CPUSPARCState *env = &cpu->env;
+
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
         qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
         log_cpu_state(env, 0);
     }
 
+    scc->parent_reset(s);
+
     memset(env, 0, offsetof(CPUSPARCState, breakpoints));
     tlb_flush(env, 1);
     env->cwp = 0;
@@ -99,23 +111,18 @@ static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
     return 0;
 }
 
-static void cpu_sparc_close(CPUSPARCState *env)
-{
-    g_free(env->def);
-    g_free(env);
-}
-
 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
 {
+    SPARCCPU *cpu;
     CPUSPARCState *env;
 
-    env = g_new0(CPUSPARCState, 1);
-    cpu_exec_init(env);
+    cpu = SPARC_CPU(object_new(TYPE_SPARC_CPU));
+    env = &cpu->env;
 
     gen_intermediate_code_init(env);
 
     if (cpu_sparc_register(env, cpu_model) < 0) {
-        cpu_sparc_close(env);
+        object_delete(OBJECT(cpu));
         return NULL;
     }
     qemu_init_vcpu(env);
@@ -847,3 +854,46 @@ void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf,
                 env->fsr, env->y);
 #endif
 }
+
+static void sparc_cpu_initfn(Object *obj)
+{
+    SPARCCPU *cpu = SPARC_CPU(obj);
+    CPUSPARCState *env = &cpu->env;
+
+    cpu_exec_init(env);
+}
+
+static void sparc_cpu_uninitfn(Object *obj)
+{
+    SPARCCPU *cpu = SPARC_CPU(obj);
+    CPUSPARCState *env = &cpu->env;
+
+    g_free(env->def);
+}
+
+static void sparc_cpu_class_init(ObjectClass *oc, void *data)
+{
+    SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
+    CPUClass *cc = CPU_CLASS(oc);
+
+    scc->parent_reset = cc->reset;
+    cc->reset = sparc_cpu_reset;
+}
+
+static const TypeInfo sparc_cpu_type_info = {
+    .name = TYPE_SPARC_CPU,
+    .parent = TYPE_CPU,
+    .instance_size = sizeof(SPARCCPU),
+    .instance_init = sparc_cpu_initfn,
+    .instance_finalize = sparc_cpu_uninitfn,
+    .abstract = false,
+    .class_size = sizeof(SPARCCPUClass),
+    .class_init = sparc_cpu_class_init,
+};
+
+static void sparc_cpu_register_types(void)
+{
+    type_register_static(&sparc_cpu_type_info);
+}
+
+type_init(sparc_cpu_register_types)
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 885ad45..865288c 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -691,6 +691,7 @@ static inline void cpu_clone_regs(CPUSPARCState *env, target_ulong newsp)
 #endif
 
 #include "cpu-all.h"
+#include "cpu-qom.h"
 
 #ifdef TARGET_SPARC64
 /* sun4u.c */
commit 88ca012a1f0bb89d481e506eb4738382062da55f
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu Apr 5 01:29:39 2012 +0200

    target-sparc: Rename cpu_init.c
    
    Align QOM'ified targets, with a view to simplify Makefile.target.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 999a968..14c8fa1 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -96,7 +96,7 @@ libobj-$(TARGET_ARM) += cpu.o
 libobj-$(TARGET_S390X) += cpu.o
 ifeq ($(TARGET_BASE_ARCH), sparc)
 libobj-y += fop_helper.o cc_helper.o win_helper.o mmu_helper.o ldst_helper.o
-libobj-y += cpu_init.o
+libobj-y += cpu.o
 endif
 libobj-$(TARGET_SPARC) += int32_helper.o
 libobj-$(TARGET_SPARC64) += int64_helper.o
diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
new file mode 100644
index 0000000..5c03f0b
--- /dev/null
+++ b/target-sparc/cpu.c
@@ -0,0 +1,849 @@
+/*
+ * Sparc CPU init helpers
+ *
+ *  Copyright (c) 2003-2005 Fabrice Bellard
+ *
+ * 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/>.
+ */
+
+#include "cpu.h"
+
+//#define DEBUG_FEATURES
+
+static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
+
+void cpu_state_reset(CPUSPARCState *env)
+{
+    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+        log_cpu_state(env, 0);
+    }
+
+    memset(env, 0, offsetof(CPUSPARCState, breakpoints));
+    tlb_flush(env, 1);
+    env->cwp = 0;
+#ifndef TARGET_SPARC64
+    env->wim = 1;
+#endif
+    env->regwptr = env->regbase + (env->cwp * 16);
+    CC_OP = CC_OP_FLAGS;
+#if defined(CONFIG_USER_ONLY)
+#ifdef TARGET_SPARC64
+    env->cleanwin = env->nwindows - 2;
+    env->cansave = env->nwindows - 2;
+    env->pstate = PS_RMO | PS_PEF | PS_IE;
+    env->asi = 0x82; /* Primary no-fault */
+#endif
+#else
+#if !defined(TARGET_SPARC64)
+    env->psret = 0;
+    env->psrs = 1;
+    env->psrps = 1;
+#endif
+#ifdef TARGET_SPARC64
+    env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
+    env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
+    env->tl = env->maxtl;
+    cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
+    env->lsu = 0;
+#else
+    env->mmuregs[0] &= ~(MMU_E | MMU_NF);
+    env->mmuregs[0] |= env->def->mmu_bm;
+#endif
+    env->pc = 0;
+    env->npc = env->pc + 4;
+#endif
+    env->cache_control = 0;
+}
+
+static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
+{
+    sparc_def_t def1, *def = &def1;
+
+    if (cpu_sparc_find_by_name(def, cpu_model) < 0) {
+        return -1;
+    }
+
+    env->def = g_new0(sparc_def_t, 1);
+    memcpy(env->def, def, sizeof(*def));
+#if defined(CONFIG_USER_ONLY)
+    if ((env->def->features & CPU_FEATURE_FLOAT)) {
+        env->def->features |= CPU_FEATURE_FLOAT128;
+    }
+#endif
+    env->cpu_model_str = cpu_model;
+    env->version = def->iu_version;
+    env->fsr = def->fpu_version;
+    env->nwindows = def->nwindows;
+#if !defined(TARGET_SPARC64)
+    env->mmuregs[0] |= def->mmu_version;
+    cpu_sparc_set_id(env, 0);
+    env->mxccregs[7] |= def->mxcc_version;
+#else
+    env->mmu_version = def->mmu_version;
+    env->maxtl = def->maxtl;
+    env->version |= def->maxtl << 8;
+    env->version |= def->nwindows - 1;
+#endif
+    return 0;
+}
+
+static void cpu_sparc_close(CPUSPARCState *env)
+{
+    g_free(env->def);
+    g_free(env);
+}
+
+CPUSPARCState *cpu_sparc_init(const char *cpu_model)
+{
+    CPUSPARCState *env;
+
+    env = g_new0(CPUSPARCState, 1);
+    cpu_exec_init(env);
+
+    gen_intermediate_code_init(env);
+
+    if (cpu_sparc_register(env, cpu_model) < 0) {
+        cpu_sparc_close(env);
+        return NULL;
+    }
+    qemu_init_vcpu(env);
+
+    return env;
+}
+
+void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
+{
+#if !defined(TARGET_SPARC64)
+    env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
+#endif
+}
+
+static const sparc_def_t sparc_defs[] = {
+#ifdef TARGET_SPARC64
+    {
+        .name = "Fujitsu Sparc64",
+        .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 4,
+        .maxtl = 4,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Fujitsu Sparc64 III",
+        .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 5,
+        .maxtl = 4,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Fujitsu Sparc64 IV",
+        .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Fujitsu Sparc64 V",
+        .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI UltraSparc I",
+        .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI UltraSparc II",
+        .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI UltraSparc IIi",
+        .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI UltraSparc IIe",
+        .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Sun UltraSparc III",
+        .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Sun UltraSparc III Cu",
+        .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_3,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Sun UltraSparc IIIi",
+        .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Sun UltraSparc IV",
+        .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_4,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Sun UltraSparc IV+",
+        .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
+    },
+    {
+        .name = "Sun UltraSparc IIIi+",
+        .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_3,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Sun UltraSparc T1",
+        /* defined in sparc_ifu_fdp.v and ctu.h */
+        .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_sun4v,
+        .nwindows = 8,
+        .maxtl = 6,
+        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
+        | CPU_FEATURE_GL,
+    },
+    {
+        .name = "Sun UltraSparc T2",
+        /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
+        .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_sun4v,
+        .nwindows = 8,
+        .maxtl = 6,
+        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
+        | CPU_FEATURE_GL,
+    },
+    {
+        .name = "NEC UltraSparc I",
+        .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+#else
+    {
+        .name = "Fujitsu MB86900",
+        .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
+        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
+        .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 7,
+        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
+    },
+    {
+        .name = "Fujitsu MB86904",
+        .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
+        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
+        .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x00ffffc0,
+        .mmu_cxr_mask = 0x000000ff,
+        .mmu_sfsr_mask = 0x00016fff,
+        .mmu_trcr_mask = 0x00ffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Fujitsu MB86907",
+        .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
+        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
+        .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0xffffffc0,
+        .mmu_cxr_mask = 0x000000ff,
+        .mmu_sfsr_mask = 0x00016fff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "LSI L64811",
+        .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
+        .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
+        .mmu_version = 0x10 << 24,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
+        CPU_FEATURE_FSMULD,
+    },
+    {
+        .name = "Cypress CY7C601",
+        .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
+        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
+        .mmu_version = 0x10 << 24,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
+        CPU_FEATURE_FSMULD,
+    },
+    {
+        .name = "Cypress CY7C611",
+        .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
+        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
+        .mmu_version = 0x10 << 24,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
+        CPU_FEATURE_FSMULD,
+    },
+    {
+        .name = "TI MicroSparc I",
+        .iu_version = 0x41000000,
+        .fpu_version = 4 << 17,
+        .mmu_version = 0x41000000,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0x00016fff,
+        .mmu_trcr_mask = 0x0000003f,
+        .nwindows = 7,
+        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
+        CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
+        CPU_FEATURE_FMUL,
+    },
+    {
+        .name = "TI MicroSparc II",
+        .iu_version = 0x42000000,
+        .fpu_version = 4 << 17,
+        .mmu_version = 0x02000000,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x00ffffc0,
+        .mmu_cxr_mask = 0x000000ff,
+        .mmu_sfsr_mask = 0x00016fff,
+        .mmu_trcr_mask = 0x00ffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI MicroSparc IIep",
+        .iu_version = 0x42000000,
+        .fpu_version = 4 << 17,
+        .mmu_version = 0x04000000,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x00ffffc0,
+        .mmu_cxr_mask = 0x000000ff,
+        .mmu_sfsr_mask = 0x00016bff,
+        .mmu_trcr_mask = 0x00ffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI SuperSparc 40", /* STP1020NPGA */
+        .iu_version = 0x41000000, /* SuperSPARC 2.x */
+        .fpu_version = 0 << 17,
+        .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
+        .mmu_bm = 0x00002000,
+        .mmu_ctpr_mask = 0xffffffc0,
+        .mmu_cxr_mask = 0x0000ffff,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI SuperSparc 50", /* STP1020PGA */
+        .iu_version = 0x40000000, /* SuperSPARC 3.x */
+        .fpu_version = 0 << 17,
+        .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
+        .mmu_bm = 0x00002000,
+        .mmu_ctpr_mask = 0xffffffc0,
+        .mmu_cxr_mask = 0x0000ffff,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI SuperSparc 51",
+        .iu_version = 0x40000000, /* SuperSPARC 3.x */
+        .fpu_version = 0 << 17,
+        .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
+        .mmu_bm = 0x00002000,
+        .mmu_ctpr_mask = 0xffffffc0,
+        .mmu_cxr_mask = 0x0000ffff,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .mxcc_version = 0x00000104,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI SuperSparc 60", /* STP1020APGA */
+        .iu_version = 0x40000000, /* SuperSPARC 3.x */
+        .fpu_version = 0 << 17,
+        .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
+        .mmu_bm = 0x00002000,
+        .mmu_ctpr_mask = 0xffffffc0,
+        .mmu_cxr_mask = 0x0000ffff,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI SuperSparc 61",
+        .iu_version = 0x44000000, /* SuperSPARC 3.x */
+        .fpu_version = 0 << 17,
+        .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
+        .mmu_bm = 0x00002000,
+        .mmu_ctpr_mask = 0xffffffc0,
+        .mmu_cxr_mask = 0x0000ffff,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .mxcc_version = 0x00000104,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI SuperSparc II",
+        .iu_version = 0x40000000, /* SuperSPARC II 1.x */
+        .fpu_version = 0 << 17,
+        .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
+        .mmu_bm = 0x00002000,
+        .mmu_ctpr_mask = 0xffffffc0,
+        .mmu_cxr_mask = 0x0000ffff,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .mxcc_version = 0x00000104,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Ross RT625",
+        .iu_version = 0x1e000000,
+        .fpu_version = 1 << 17,
+        .mmu_version = 0x1e000000,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Ross RT620",
+        .iu_version = 0x1f000000,
+        .fpu_version = 1 << 17,
+        .mmu_version = 0x1f000000,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "BIT B5010",
+        .iu_version = 0x20000000,
+        .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
+        .mmu_version = 0x20000000,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
+        CPU_FEATURE_FSMULD,
+    },
+    {
+        .name = "Matsushita MN10501",
+        .iu_version = 0x50000000,
+        .fpu_version = 0 << 17,
+        .mmu_version = 0x50000000,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
+        CPU_FEATURE_FSMULD,
+    },
+    {
+        .name = "Weitek W8601",
+        .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
+        .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
+        .mmu_version = 0x10 << 24,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "LEON2",
+        .iu_version = 0xf2000000,
+        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
+        .mmu_version = 0xf2000000,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .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 = 0x00000000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
+        CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL,
+    },
+#endif
+};
+
+static const char * const feature_name[] = {
+    "float",
+    "float128",
+    "swap",
+    "mul",
+    "div",
+    "flush",
+    "fsqrt",
+    "fmul",
+    "vis1",
+    "vis2",
+    "fsmuld",
+    "hypv",
+    "cmt",
+    "gl",
+};
+
+static void print_features(FILE *f, fprintf_function cpu_fprintf,
+                           uint32_t features, const char *prefix)
+{
+    unsigned int i;
+
+    for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
+        if (feature_name[i] && (features & (1 << i))) {
+            if (prefix) {
+                (*cpu_fprintf)(f, "%s", prefix);
+            }
+            (*cpu_fprintf)(f, "%s ", feature_name[i]);
+        }
+    }
+}
+
+static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
+{
+    unsigned int i;
+
+    for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
+        if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
+            *features |= 1 << i;
+            return;
+        }
+    }
+    fprintf(stderr, "CPU feature %s not found\n", flagname);
+}
+
+static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
+{
+    unsigned int i;
+    const sparc_def_t *def = NULL;
+    char *s = strdup(cpu_model);
+    char *featurestr, *name = strtok(s, ",");
+    uint32_t plus_features = 0;
+    uint32_t minus_features = 0;
+    uint64_t iu_version;
+    uint32_t fpu_version, mmu_version, nwindows;
+
+    for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
+        if (strcasecmp(name, sparc_defs[i].name) == 0) {
+            def = &sparc_defs[i];
+        }
+    }
+    if (!def) {
+        goto error;
+    }
+    memcpy(cpu_def, def, sizeof(*def));
+
+    featurestr = strtok(NULL, ",");
+    while (featurestr) {
+        char *val;
+
+        if (featurestr[0] == '+') {
+            add_flagname_to_bitmaps(featurestr + 1, &plus_features);
+        } else if (featurestr[0] == '-') {
+            add_flagname_to_bitmaps(featurestr + 1, &minus_features);
+        } else if ((val = strchr(featurestr, '='))) {
+            *val = 0; val++;
+            if (!strcmp(featurestr, "iu_version")) {
+                char *err;
+
+                iu_version = strtoll(val, &err, 0);
+                if (!*val || *err) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                cpu_def->iu_version = iu_version;
+#ifdef DEBUG_FEATURES
+                fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
+#endif
+            } else if (!strcmp(featurestr, "fpu_version")) {
+                char *err;
+
+                fpu_version = strtol(val, &err, 0);
+                if (!*val || *err) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                cpu_def->fpu_version = fpu_version;
+#ifdef DEBUG_FEATURES
+                fprintf(stderr, "fpu_version %x\n", fpu_version);
+#endif
+            } else if (!strcmp(featurestr, "mmu_version")) {
+                char *err;
+
+                mmu_version = strtol(val, &err, 0);
+                if (!*val || *err) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                cpu_def->mmu_version = mmu_version;
+#ifdef DEBUG_FEATURES
+                fprintf(stderr, "mmu_version %x\n", mmu_version);
+#endif
+            } else if (!strcmp(featurestr, "nwindows")) {
+                char *err;
+
+                nwindows = strtol(val, &err, 0);
+                if (!*val || *err || nwindows > MAX_NWINDOWS ||
+                    nwindows < MIN_NWINDOWS) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                cpu_def->nwindows = nwindows;
+#ifdef DEBUG_FEATURES
+                fprintf(stderr, "nwindows %d\n", nwindows);
+#endif
+            } else {
+                fprintf(stderr, "unrecognized feature %s\n", featurestr);
+                goto error;
+            }
+        } else {
+            fprintf(stderr, "feature string `%s' not in format "
+                    "(+feature|-feature|feature=xyz)\n", featurestr);
+            goto error;
+        }
+        featurestr = strtok(NULL, ",");
+    }
+    cpu_def->features |= plus_features;
+    cpu_def->features &= ~minus_features;
+#ifdef DEBUG_FEATURES
+    print_features(stderr, fprintf, cpu_def->features, NULL);
+#endif
+    free(s);
+    return 0;
+
+ error:
+    free(s);
+    return -1;
+}
+
+void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
+{
+    unsigned int i;
+
+    for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
+        (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx
+                       " FPU %08x MMU %08x NWINS %d ",
+                       sparc_defs[i].name,
+                       sparc_defs[i].iu_version,
+                       sparc_defs[i].fpu_version,
+                       sparc_defs[i].mmu_version,
+                       sparc_defs[i].nwindows);
+        print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
+                       ~sparc_defs[i].features, "-");
+        print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
+                       sparc_defs[i].features, "+");
+        (*cpu_fprintf)(f, "\n");
+    }
+    (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
+    print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
+    (*cpu_fprintf)(f, "\n");
+    (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
+    print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
+    (*cpu_fprintf)(f, "\n");
+    (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
+                   "fpu_version mmu_version nwindows\n");
+}
+
+static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
+                         uint32_t cc)
+{
+    cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
+                cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
+                cc & PSR_CARRY ? 'C' : '-');
+}
+
+#ifdef TARGET_SPARC64
+#define REGS_PER_LINE 4
+#else
+#define REGS_PER_LINE 8
+#endif
+
+void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf,
+                    int flags)
+{
+    int i, x;
+
+    cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc,
+                env->npc);
+    cpu_fprintf(f, "General Registers:\n");
+
+    for (i = 0; i < 8; i++) {
+        if (i % REGS_PER_LINE == 0) {
+            cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
+        }
+        cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
+        if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
+            cpu_fprintf(f, "\n");
+        }
+    }
+    cpu_fprintf(f, "\nCurrent Register Window:\n");
+    for (x = 0; x < 3; x++) {
+        for (i = 0; i < 8; i++) {
+            if (i % REGS_PER_LINE == 0) {
+                cpu_fprintf(f, "%%%c%d-%d: ",
+                            x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
+                            i, i + REGS_PER_LINE - 1);
+            }
+            cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
+            if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
+                cpu_fprintf(f, "\n");
+            }
+        }
+    }
+    cpu_fprintf(f, "\nFloating Point Registers:\n");
+    for (i = 0; i < TARGET_DPREGS; i++) {
+        if ((i & 3) == 0) {
+            cpu_fprintf(f, "%%f%02d:", i * 2);
+        }
+        cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
+        if ((i & 3) == 3) {
+            cpu_fprintf(f, "\n");
+        }
+    }
+#ifdef TARGET_SPARC64
+    cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
+                (unsigned)cpu_get_ccr(env));
+    cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
+    cpu_fprintf(f, " xcc: ");
+    cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
+    cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
+                env->psrpil);
+    cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
+                "cleanwin: %d cwp: %d\n",
+                env->cansave, env->canrestore, env->otherwin, env->wstate,
+                env->cleanwin, env->nwindows - 1 - env->cwp);
+    cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
+                TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
+#else
+    cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
+    cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
+    cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
+                env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
+                env->wim);
+    cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
+                env->fsr, env->y);
+#endif
+}
diff --git a/target-sparc/cpu_init.c b/target-sparc/cpu_init.c
deleted file mode 100644
index 5c03f0b..0000000
--- a/target-sparc/cpu_init.c
+++ /dev/null
@@ -1,849 +0,0 @@
-/*
- * Sparc CPU init helpers
- *
- *  Copyright (c) 2003-2005 Fabrice Bellard
- *
- * 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/>.
- */
-
-#include "cpu.h"
-
-//#define DEBUG_FEATURES
-
-static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
-
-void cpu_state_reset(CPUSPARCState *env)
-{
-    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
-        log_cpu_state(env, 0);
-    }
-
-    memset(env, 0, offsetof(CPUSPARCState, breakpoints));
-    tlb_flush(env, 1);
-    env->cwp = 0;
-#ifndef TARGET_SPARC64
-    env->wim = 1;
-#endif
-    env->regwptr = env->regbase + (env->cwp * 16);
-    CC_OP = CC_OP_FLAGS;
-#if defined(CONFIG_USER_ONLY)
-#ifdef TARGET_SPARC64
-    env->cleanwin = env->nwindows - 2;
-    env->cansave = env->nwindows - 2;
-    env->pstate = PS_RMO | PS_PEF | PS_IE;
-    env->asi = 0x82; /* Primary no-fault */
-#endif
-#else
-#if !defined(TARGET_SPARC64)
-    env->psret = 0;
-    env->psrs = 1;
-    env->psrps = 1;
-#endif
-#ifdef TARGET_SPARC64
-    env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
-    env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
-    env->tl = env->maxtl;
-    cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
-    env->lsu = 0;
-#else
-    env->mmuregs[0] &= ~(MMU_E | MMU_NF);
-    env->mmuregs[0] |= env->def->mmu_bm;
-#endif
-    env->pc = 0;
-    env->npc = env->pc + 4;
-#endif
-    env->cache_control = 0;
-}
-
-static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
-{
-    sparc_def_t def1, *def = &def1;
-
-    if (cpu_sparc_find_by_name(def, cpu_model) < 0) {
-        return -1;
-    }
-
-    env->def = g_new0(sparc_def_t, 1);
-    memcpy(env->def, def, sizeof(*def));
-#if defined(CONFIG_USER_ONLY)
-    if ((env->def->features & CPU_FEATURE_FLOAT)) {
-        env->def->features |= CPU_FEATURE_FLOAT128;
-    }
-#endif
-    env->cpu_model_str = cpu_model;
-    env->version = def->iu_version;
-    env->fsr = def->fpu_version;
-    env->nwindows = def->nwindows;
-#if !defined(TARGET_SPARC64)
-    env->mmuregs[0] |= def->mmu_version;
-    cpu_sparc_set_id(env, 0);
-    env->mxccregs[7] |= def->mxcc_version;
-#else
-    env->mmu_version = def->mmu_version;
-    env->maxtl = def->maxtl;
-    env->version |= def->maxtl << 8;
-    env->version |= def->nwindows - 1;
-#endif
-    return 0;
-}
-
-static void cpu_sparc_close(CPUSPARCState *env)
-{
-    g_free(env->def);
-    g_free(env);
-}
-
-CPUSPARCState *cpu_sparc_init(const char *cpu_model)
-{
-    CPUSPARCState *env;
-
-    env = g_new0(CPUSPARCState, 1);
-    cpu_exec_init(env);
-
-    gen_intermediate_code_init(env);
-
-    if (cpu_sparc_register(env, cpu_model) < 0) {
-        cpu_sparc_close(env);
-        return NULL;
-    }
-    qemu_init_vcpu(env);
-
-    return env;
-}
-
-void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
-{
-#if !defined(TARGET_SPARC64)
-    env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
-#endif
-}
-
-static const sparc_def_t sparc_defs[] = {
-#ifdef TARGET_SPARC64
-    {
-        .name = "Fujitsu Sparc64",
-        .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 4,
-        .maxtl = 4,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Fujitsu Sparc64 III",
-        .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 5,
-        .maxtl = 4,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Fujitsu Sparc64 IV",
-        .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Fujitsu Sparc64 V",
-        .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI UltraSparc I",
-        .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI UltraSparc II",
-        .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI UltraSparc IIi",
-        .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI UltraSparc IIe",
-        .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Sun UltraSparc III",
-        .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Sun UltraSparc III Cu",
-        .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_3,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Sun UltraSparc IIIi",
-        .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Sun UltraSparc IV",
-        .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_4,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Sun UltraSparc IV+",
-        .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
-    },
-    {
-        .name = "Sun UltraSparc IIIi+",
-        .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_3,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Sun UltraSparc T1",
-        /* defined in sparc_ifu_fdp.v and ctu.h */
-        .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_sun4v,
-        .nwindows = 8,
-        .maxtl = 6,
-        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
-        | CPU_FEATURE_GL,
-    },
-    {
-        .name = "Sun UltraSparc T2",
-        /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
-        .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_sun4v,
-        .nwindows = 8,
-        .maxtl = 6,
-        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
-        | CPU_FEATURE_GL,
-    },
-    {
-        .name = "NEC UltraSparc I",
-        .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-#else
-    {
-        .name = "Fujitsu MB86900",
-        .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
-        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
-        .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 7,
-        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
-    },
-    {
-        .name = "Fujitsu MB86904",
-        .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
-        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
-        .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x00ffffc0,
-        .mmu_cxr_mask = 0x000000ff,
-        .mmu_sfsr_mask = 0x00016fff,
-        .mmu_trcr_mask = 0x00ffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Fujitsu MB86907",
-        .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
-        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
-        .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0xffffffc0,
-        .mmu_cxr_mask = 0x000000ff,
-        .mmu_sfsr_mask = 0x00016fff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "LSI L64811",
-        .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
-        .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
-        .mmu_version = 0x10 << 24,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
-        CPU_FEATURE_FSMULD,
-    },
-    {
-        .name = "Cypress CY7C601",
-        .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
-        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
-        .mmu_version = 0x10 << 24,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
-        CPU_FEATURE_FSMULD,
-    },
-    {
-        .name = "Cypress CY7C611",
-        .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
-        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
-        .mmu_version = 0x10 << 24,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
-        CPU_FEATURE_FSMULD,
-    },
-    {
-        .name = "TI MicroSparc I",
-        .iu_version = 0x41000000,
-        .fpu_version = 4 << 17,
-        .mmu_version = 0x41000000,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0x00016fff,
-        .mmu_trcr_mask = 0x0000003f,
-        .nwindows = 7,
-        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
-        CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
-        CPU_FEATURE_FMUL,
-    },
-    {
-        .name = "TI MicroSparc II",
-        .iu_version = 0x42000000,
-        .fpu_version = 4 << 17,
-        .mmu_version = 0x02000000,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x00ffffc0,
-        .mmu_cxr_mask = 0x000000ff,
-        .mmu_sfsr_mask = 0x00016fff,
-        .mmu_trcr_mask = 0x00ffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI MicroSparc IIep",
-        .iu_version = 0x42000000,
-        .fpu_version = 4 << 17,
-        .mmu_version = 0x04000000,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x00ffffc0,
-        .mmu_cxr_mask = 0x000000ff,
-        .mmu_sfsr_mask = 0x00016bff,
-        .mmu_trcr_mask = 0x00ffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI SuperSparc 40", /* STP1020NPGA */
-        .iu_version = 0x41000000, /* SuperSPARC 2.x */
-        .fpu_version = 0 << 17,
-        .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
-        .mmu_bm = 0x00002000,
-        .mmu_ctpr_mask = 0xffffffc0,
-        .mmu_cxr_mask = 0x0000ffff,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI SuperSparc 50", /* STP1020PGA */
-        .iu_version = 0x40000000, /* SuperSPARC 3.x */
-        .fpu_version = 0 << 17,
-        .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
-        .mmu_bm = 0x00002000,
-        .mmu_ctpr_mask = 0xffffffc0,
-        .mmu_cxr_mask = 0x0000ffff,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI SuperSparc 51",
-        .iu_version = 0x40000000, /* SuperSPARC 3.x */
-        .fpu_version = 0 << 17,
-        .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
-        .mmu_bm = 0x00002000,
-        .mmu_ctpr_mask = 0xffffffc0,
-        .mmu_cxr_mask = 0x0000ffff,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .mxcc_version = 0x00000104,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI SuperSparc 60", /* STP1020APGA */
-        .iu_version = 0x40000000, /* SuperSPARC 3.x */
-        .fpu_version = 0 << 17,
-        .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
-        .mmu_bm = 0x00002000,
-        .mmu_ctpr_mask = 0xffffffc0,
-        .mmu_cxr_mask = 0x0000ffff,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI SuperSparc 61",
-        .iu_version = 0x44000000, /* SuperSPARC 3.x */
-        .fpu_version = 0 << 17,
-        .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
-        .mmu_bm = 0x00002000,
-        .mmu_ctpr_mask = 0xffffffc0,
-        .mmu_cxr_mask = 0x0000ffff,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .mxcc_version = 0x00000104,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI SuperSparc II",
-        .iu_version = 0x40000000, /* SuperSPARC II 1.x */
-        .fpu_version = 0 << 17,
-        .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
-        .mmu_bm = 0x00002000,
-        .mmu_ctpr_mask = 0xffffffc0,
-        .mmu_cxr_mask = 0x0000ffff,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .mxcc_version = 0x00000104,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Ross RT625",
-        .iu_version = 0x1e000000,
-        .fpu_version = 1 << 17,
-        .mmu_version = 0x1e000000,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Ross RT620",
-        .iu_version = 0x1f000000,
-        .fpu_version = 1 << 17,
-        .mmu_version = 0x1f000000,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "BIT B5010",
-        .iu_version = 0x20000000,
-        .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
-        .mmu_version = 0x20000000,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
-        CPU_FEATURE_FSMULD,
-    },
-    {
-        .name = "Matsushita MN10501",
-        .iu_version = 0x50000000,
-        .fpu_version = 0 << 17,
-        .mmu_version = 0x50000000,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
-        CPU_FEATURE_FSMULD,
-    },
-    {
-        .name = "Weitek W8601",
-        .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
-        .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
-        .mmu_version = 0x10 << 24,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "LEON2",
-        .iu_version = 0xf2000000,
-        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
-        .mmu_version = 0xf2000000,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .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 = 0x00000000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
-        CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL,
-    },
-#endif
-};
-
-static const char * const feature_name[] = {
-    "float",
-    "float128",
-    "swap",
-    "mul",
-    "div",
-    "flush",
-    "fsqrt",
-    "fmul",
-    "vis1",
-    "vis2",
-    "fsmuld",
-    "hypv",
-    "cmt",
-    "gl",
-};
-
-static void print_features(FILE *f, fprintf_function cpu_fprintf,
-                           uint32_t features, const char *prefix)
-{
-    unsigned int i;
-
-    for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
-        if (feature_name[i] && (features & (1 << i))) {
-            if (prefix) {
-                (*cpu_fprintf)(f, "%s", prefix);
-            }
-            (*cpu_fprintf)(f, "%s ", feature_name[i]);
-        }
-    }
-}
-
-static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
-{
-    unsigned int i;
-
-    for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
-        if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
-            *features |= 1 << i;
-            return;
-        }
-    }
-    fprintf(stderr, "CPU feature %s not found\n", flagname);
-}
-
-static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
-{
-    unsigned int i;
-    const sparc_def_t *def = NULL;
-    char *s = strdup(cpu_model);
-    char *featurestr, *name = strtok(s, ",");
-    uint32_t plus_features = 0;
-    uint32_t minus_features = 0;
-    uint64_t iu_version;
-    uint32_t fpu_version, mmu_version, nwindows;
-
-    for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
-        if (strcasecmp(name, sparc_defs[i].name) == 0) {
-            def = &sparc_defs[i];
-        }
-    }
-    if (!def) {
-        goto error;
-    }
-    memcpy(cpu_def, def, sizeof(*def));
-
-    featurestr = strtok(NULL, ",");
-    while (featurestr) {
-        char *val;
-
-        if (featurestr[0] == '+') {
-            add_flagname_to_bitmaps(featurestr + 1, &plus_features);
-        } else if (featurestr[0] == '-') {
-            add_flagname_to_bitmaps(featurestr + 1, &minus_features);
-        } else if ((val = strchr(featurestr, '='))) {
-            *val = 0; val++;
-            if (!strcmp(featurestr, "iu_version")) {
-                char *err;
-
-                iu_version = strtoll(val, &err, 0);
-                if (!*val || *err) {
-                    fprintf(stderr, "bad numerical value %s\n", val);
-                    goto error;
-                }
-                cpu_def->iu_version = iu_version;
-#ifdef DEBUG_FEATURES
-                fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
-#endif
-            } else if (!strcmp(featurestr, "fpu_version")) {
-                char *err;
-
-                fpu_version = strtol(val, &err, 0);
-                if (!*val || *err) {
-                    fprintf(stderr, "bad numerical value %s\n", val);
-                    goto error;
-                }
-                cpu_def->fpu_version = fpu_version;
-#ifdef DEBUG_FEATURES
-                fprintf(stderr, "fpu_version %x\n", fpu_version);
-#endif
-            } else if (!strcmp(featurestr, "mmu_version")) {
-                char *err;
-
-                mmu_version = strtol(val, &err, 0);
-                if (!*val || *err) {
-                    fprintf(stderr, "bad numerical value %s\n", val);
-                    goto error;
-                }
-                cpu_def->mmu_version = mmu_version;
-#ifdef DEBUG_FEATURES
-                fprintf(stderr, "mmu_version %x\n", mmu_version);
-#endif
-            } else if (!strcmp(featurestr, "nwindows")) {
-                char *err;
-
-                nwindows = strtol(val, &err, 0);
-                if (!*val || *err || nwindows > MAX_NWINDOWS ||
-                    nwindows < MIN_NWINDOWS) {
-                    fprintf(stderr, "bad numerical value %s\n", val);
-                    goto error;
-                }
-                cpu_def->nwindows = nwindows;
-#ifdef DEBUG_FEATURES
-                fprintf(stderr, "nwindows %d\n", nwindows);
-#endif
-            } else {
-                fprintf(stderr, "unrecognized feature %s\n", featurestr);
-                goto error;
-            }
-        } else {
-            fprintf(stderr, "feature string `%s' not in format "
-                    "(+feature|-feature|feature=xyz)\n", featurestr);
-            goto error;
-        }
-        featurestr = strtok(NULL, ",");
-    }
-    cpu_def->features |= plus_features;
-    cpu_def->features &= ~minus_features;
-#ifdef DEBUG_FEATURES
-    print_features(stderr, fprintf, cpu_def->features, NULL);
-#endif
-    free(s);
-    return 0;
-
- error:
-    free(s);
-    return -1;
-}
-
-void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
-{
-    unsigned int i;
-
-    for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
-        (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx
-                       " FPU %08x MMU %08x NWINS %d ",
-                       sparc_defs[i].name,
-                       sparc_defs[i].iu_version,
-                       sparc_defs[i].fpu_version,
-                       sparc_defs[i].mmu_version,
-                       sparc_defs[i].nwindows);
-        print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
-                       ~sparc_defs[i].features, "-");
-        print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
-                       sparc_defs[i].features, "+");
-        (*cpu_fprintf)(f, "\n");
-    }
-    (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
-    print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
-    (*cpu_fprintf)(f, "\n");
-    (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
-    print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
-    (*cpu_fprintf)(f, "\n");
-    (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
-                   "fpu_version mmu_version nwindows\n");
-}
-
-static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
-                         uint32_t cc)
-{
-    cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
-                cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
-                cc & PSR_CARRY ? 'C' : '-');
-}
-
-#ifdef TARGET_SPARC64
-#define REGS_PER_LINE 4
-#else
-#define REGS_PER_LINE 8
-#endif
-
-void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf,
-                    int flags)
-{
-    int i, x;
-
-    cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc,
-                env->npc);
-    cpu_fprintf(f, "General Registers:\n");
-
-    for (i = 0; i < 8; i++) {
-        if (i % REGS_PER_LINE == 0) {
-            cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
-        }
-        cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
-        if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
-            cpu_fprintf(f, "\n");
-        }
-    }
-    cpu_fprintf(f, "\nCurrent Register Window:\n");
-    for (x = 0; x < 3; x++) {
-        for (i = 0; i < 8; i++) {
-            if (i % REGS_PER_LINE == 0) {
-                cpu_fprintf(f, "%%%c%d-%d: ",
-                            x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
-                            i, i + REGS_PER_LINE - 1);
-            }
-            cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
-            if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
-                cpu_fprintf(f, "\n");
-            }
-        }
-    }
-    cpu_fprintf(f, "\nFloating Point Registers:\n");
-    for (i = 0; i < TARGET_DPREGS; i++) {
-        if ((i & 3) == 0) {
-            cpu_fprintf(f, "%%f%02d:", i * 2);
-        }
-        cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
-        if ((i & 3) == 3) {
-            cpu_fprintf(f, "\n");
-        }
-    }
-#ifdef TARGET_SPARC64
-    cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
-                (unsigned)cpu_get_ccr(env));
-    cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
-    cpu_fprintf(f, " xcc: ");
-    cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
-    cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
-                env->psrpil);
-    cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
-                "cleanwin: %d cwp: %d\n",
-                env->cansave, env->canrestore, env->otherwin, env->wstate,
-                env->cleanwin, env->nwindows - 1 - env->cwp);
-    cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
-                TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
-#else
-    cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
-    cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
-    cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
-                env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
-                env->wim);
-    cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
-                env->fsr, env->y);
-#endif
-}
commit d8fd2954996255ba6ad610917e7849832d0120b7
Author: Paul Brook <paul at codesourcery.com>
Date:   Fri Mar 30 18:02:50 2012 +0100

    Userspace ARM BE8 support
    
    Add support for ARM BE8 userspace binaries.
    i.e. big-endian data and little-endian code.
    In principle LE8 mode is also possible, but AFAIK has never actually
    been implemented/used.
    
    System emulation doesn't have any useable big-endian board models,
    but should in principle work once you fix that.
    Dynamic endianness switching requires messing with data accesses,
    preferably with TCG cooperation, and is orthogonal to BE8 support.
    
    Signed-off-by: Paul Brook <paul at codesourcery.com>
    [PMM: various changes, mostly as per my suggestions in code review:
     * rebase
     * use EF_ defines rather than hardcoded constants
     * make bswap_code a bool for future VMSTATE macro compatibility
     * update comment in cpu.h about TB flags bit field usage
     * factor out load-code-and-swap into arm_ld*_code functions and
       get_user_code* macros
     * fix stray trailing space at end of line
     * added braces in disas.c to satisfy checkpatch
    ]
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/disas.c b/disas.c
index 9485824..4f2c4e4 100644
--- a/disas.c
+++ b/disas.c
@@ -138,7 +138,7 @@ print_insn_thumb1(bfd_vma pc, disassemble_info *info)
 /* Disassemble this for me please... (debugging). 'flags' has the following
    values:
     i386 - 1 means 16 bit code, 2 means 64 bit code
-    arm  - nonzero means thumb code
+    arm  - bit 0 = thumb, bit 1 = reverse endian
     ppc  - nonzero means little endian
     other targets - unused
  */
@@ -169,10 +169,18 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
         disasm_info.mach = bfd_mach_i386_i386;
     print_insn = print_insn_i386;
 #elif defined(TARGET_ARM)
-    if (flags)
-	print_insn = print_insn_thumb1;
-    else
-	print_insn = print_insn_arm;
+    if (flags & 1) {
+        print_insn = print_insn_thumb1;
+    } else {
+        print_insn = print_insn_arm;
+    }
+    if (flags & 2) {
+#ifdef TARGET_WORDS_BIGENDIAN
+        disasm_info.endian = BFD_ENDIAN_LITTLE;
+#else
+        disasm_info.endian = BFD_ENDIAN_BIG;
+#endif
+    }
 #elif defined(TARGET_SPARC)
     print_insn = print_insn_sparc;
 #ifdef TARGET_SPARC64
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 4ce9743..f3b1552 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1576,6 +1576,7 @@ static void load_elf_image(const char *image_name, int image_fd,
     info->start_data = -1;
     info->end_data = 0;
     info->brk = 0;
+    info->elf_flags = ehdr->e_flags;
 
     for (i = 0; i < ehdr->e_phnum; i++) {
         struct elf_phdr *eppnt = phdr + i;
diff --git a/linux-user/main.c b/linux-user/main.c
index 23ad357..191b750 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -33,6 +33,7 @@
 #include "tcg.h"
 #include "qemu-timer.h"
 #include "envlist.h"
+#include "elf.h"
 
 #define DEBUG_LOGFILE "/tmp/qemu.log"
 
@@ -474,6 +475,22 @@ void cpu_loop(CPUX86State *env)
 
 #ifdef TARGET_ARM
 
+#define get_user_code_u32(x, gaddr, doswap)             \
+    ({ abi_long __r = get_user_u32((x), (gaddr));       \
+        if (!__r && (doswap)) {                         \
+            (x) = bswap32(x);                           \
+        }                                               \
+        __r;                                            \
+    })
+
+#define get_user_code_u16(x, gaddr, doswap)             \
+    ({ abi_long __r = get_user_u16((x), (gaddr));       \
+        if (!__r && (doswap)) {                         \
+            (x) = bswap16(x);                           \
+        }                                               \
+        __r;                                            \
+    })
+
 /*
  * See the Linux kernel's Documentation/arm/kernel_user_helpers.txt
  * Input:
@@ -707,7 +724,7 @@ void cpu_loop(CPUARMState *env)
                 /* we handle the FPU emulation here, as Linux */
                 /* we get the opcode */
                 /* FIXME - what to do if get_user() fails? */
-                get_user_u32(opcode, env->regs[15]);
+                get_user_code_u32(opcode, env->regs[15], env->bswap_code);
 
                 rc = EmulateAll(opcode, &ts->fpa, env);
                 if (rc == 0) { /* illegal instruction */
@@ -777,23 +794,25 @@ void cpu_loop(CPUARMState *env)
                 if (trapnr == EXCP_BKPT) {
                     if (env->thumb) {
                         /* FIXME - what to do if get_user() fails? */
-                        get_user_u16(insn, env->regs[15]);
+                        get_user_code_u16(insn, env->regs[15], env->bswap_code);
                         n = insn & 0xff;
                         env->regs[15] += 2;
                     } else {
                         /* FIXME - what to do if get_user() fails? */
-                        get_user_u32(insn, env->regs[15]);
+                        get_user_code_u32(insn, env->regs[15], env->bswap_code);
                         n = (insn & 0xf) | ((insn >> 4) & 0xff0);
                         env->regs[15] += 4;
                     }
                 } else {
                     if (env->thumb) {
                         /* FIXME - what to do if get_user() fails? */
-                        get_user_u16(insn, env->regs[15] - 2);
+                        get_user_code_u16(insn, env->regs[15] - 2,
+                                          env->bswap_code);
                         n = insn & 0xff;
                     } else {
                         /* FIXME - what to do if get_user() fails? */
-                        get_user_u32(insn, env->regs[15] - 4);
+                        get_user_code_u32(insn, env->regs[15] - 4,
+                                          env->bswap_code);
                         n = insn & 0xffffff;
                     }
                 }
@@ -3657,6 +3676,11 @@ int main(int argc, char **argv, char **envp)
         for(i = 0; i < 16; i++) {
             env->regs[i] = regs->uregs[i];
         }
+        /* Enable BE8.  */
+        if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
+            && (info->elf_flags & EF_ARM_BE8)) {
+            env->bswap_code = 1;
+        }
     }
 #elif defined(TARGET_UNICORE32)
     {
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index dd74cc0..7b299b7 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -51,6 +51,7 @@ struct image_info {
         abi_ulong       auxv_len;
         abi_ulong       arg_start;
         abi_ulong       arg_end;
+        uint32_t        elf_flags;
 	int		personality;
 #ifdef CONFIG_USE_FDPIC
         abi_ulong       loadmap_addr;
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index e176c5f..c208c80 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -216,6 +216,9 @@ typedef struct CPUARMState {
         uint32_t cregs[16];
     } iwmmxt;
 
+    /* For mixed endian mode.  */
+    bool bswap_code;
+
 #if defined(CONFIG_USER_ONLY)
     /* For usermode syscall translation.  */
     int eabi;
@@ -491,7 +494,9 @@ static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp)
 #define ARM_TBFLAG_VFPEN_MASK       (1 << ARM_TBFLAG_VFPEN_SHIFT)
 #define ARM_TBFLAG_CONDEXEC_SHIFT   8
 #define ARM_TBFLAG_CONDEXEC_MASK    (0xff << ARM_TBFLAG_CONDEXEC_SHIFT)
-/* Bits 31..16 are currently unused. */
+#define ARM_TBFLAG_BSWAP_CODE_SHIFT 16
+#define ARM_TBFLAG_BSWAP_CODE_MASK  (1 << ARM_TBFLAG_BSWAP_CODE_SHIFT)
+/* Bits 31..17 are currently unused. */
 
 /* some convenience accessor macros */
 #define ARM_TBFLAG_THUMB(F) \
@@ -506,6 +511,8 @@ static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp)
     (((F) & ARM_TBFLAG_VFPEN_MASK) >> ARM_TBFLAG_VFPEN_SHIFT)
 #define ARM_TBFLAG_CONDEXEC(F) \
     (((F) & ARM_TBFLAG_CONDEXEC_MASK) >> ARM_TBFLAG_CONDEXEC_SHIFT)
+#define ARM_TBFLAG_BSWAP_CODE(F) \
+    (((F) & ARM_TBFLAG_BSWAP_CODE_MASK) >> ARM_TBFLAG_BSWAP_CODE_SHIFT)
 
 static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
@@ -516,7 +523,8 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
     *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
         | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
         | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
-        | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT);
+        | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
+        | (env->bswap_code << ARM_TBFLAG_BSWAP_CODE_SHIFT);
     if (arm_feature(env, ARM_FEATURE_M)) {
         privmode = !((env->v7m.exception == 0) && (env->v7m.control & 1));
     } else {
@@ -543,4 +551,24 @@ static inline void cpu_pc_from_tb(CPUARMState *env, TranslationBlock *tb)
     env->regs[15] = tb->pc;
 }
 
+/* Load an instruction and return it in the standard little-endian order */
+static inline uint32_t arm_ldl_code(uint32_t addr, bool do_swap)
+{
+    uint32_t insn = ldl_code(addr);
+    if (do_swap) {
+        return bswap32(insn);
+    }
+    return insn;
+}
+
+/* Ditto, for a halfword (Thumb) instruction */
+static inline uint16_t arm_lduw_code(uint32_t addr, bool do_swap)
+{
+    uint16_t insn = lduw_code(addr);
+    if (do_swap) {
+        return bswap16(insn);
+    }
+    return insn;
+}
+
 #endif
diff --git a/target-arm/helper.c b/target-arm/helper.c
index d974b57..28f127b 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -842,7 +842,7 @@ static void do_interrupt_v7m(CPUARMState *env)
     case EXCP_BKPT:
         if (semihosting_enabled) {
             int nr;
-            nr = lduw_code(env->regs[15]) & 0xff;
+            nr = arm_lduw_code(env->regs[15], env->bswap_code) & 0xff;
             if (nr == 0xab) {
                 env->regs[15] += 2;
                 env->regs[0] = do_arm_semihosting(env);
@@ -914,9 +914,10 @@ void do_interrupt(CPUARMState *env)
         if (semihosting_enabled) {
             /* Check for semihosting interrupt.  */
             if (env->thumb) {
-                mask = lduw_code(env->regs[15] - 2) & 0xff;
+                mask = arm_lduw_code(env->regs[15] - 2, env->bswap_code) & 0xff;
             } else {
-                mask = ldl_code(env->regs[15] - 4) & 0xffffff;
+                mask = arm_ldl_code(env->regs[15] - 4, env->bswap_code)
+                    & 0xffffff;
             }
             /* Only intercept calls from privileged modes, to provide some
                semblance of security.  */
@@ -936,7 +937,7 @@ void do_interrupt(CPUARMState *env)
     case EXCP_BKPT:
         /* See if this is a semihosting syscall.  */
         if (env->thumb && semihosting_enabled) {
-            mask = lduw_code(env->regs[15]) & 0xff;
+            mask = arm_lduw_code(env->regs[15], env->bswap_code) & 0xff;
             if (mask == 0xab
                   && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
                 env->regs[15] += 2;
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 46d1d3e..7a3c7d6 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -59,6 +59,7 @@ typedef struct DisasContext {
     struct TranslationBlock *tb;
     int singlestep_enabled;
     int thumb;
+    int bswap_code;
 #if !defined(CONFIG_USER_ONLY)
     int user;
 #endif
@@ -6705,7 +6706,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
     TCGv addr;
     TCGv_i64 tmp64;
 
-    insn = ldl_code(s->pc);
+    insn = arm_ldl_code(s->pc, s->bswap_code);
     s->pc += 4;
 
     /* M variants do not implement ARM mode.  */
@@ -8133,7 +8134,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
         /* Fall through to 32-bit decode.  */
     }
 
-    insn = lduw_code(s->pc);
+    insn = arm_lduw_code(s->pc, s->bswap_code);
     s->pc += 2;
     insn |= (uint32_t)insn_hw1 << 16;
 
@@ -9163,7 +9164,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
         }
     }
 
-    insn = lduw_code(s->pc);
+    insn = arm_lduw_code(s->pc, s->bswap_code);
     s->pc += 2;
 
     switch (insn >> 12) {
@@ -9872,6 +9873,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
     dc->singlestep_enabled = env->singlestep_enabled;
     dc->condjmp = 0;
     dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
+    dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags);
     dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
     dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
 #if !defined(CONFIG_USER_ONLY)
@@ -10105,7 +10107,8 @@ done_generating:
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
         qemu_log("----------------\n");
         qemu_log("IN: %s\n", lookup_symbol(pc_start));
-        log_target_disas(pc_start, dc->pc - pc_start, dc->thumb);
+        log_target_disas(pc_start, dc->pc - pc_start,
+                         dc->thumb | (dc->bswap_code << 1));
         qemu_log("\n");
     }
 #endif
commit ef8b0c0474aa7eab5172e866dc37428b41ff2934
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 30 18:02:49 2012 +0100

    elf.h: Update EF_ARM_ constants to newer ABI versions
    
    Update the EF_ARM_* constants (for the ELF header e_flags field)
    to include the newer flags specified for later versions of the ABI.
    (This set of constants is from include/elf/arm.h from binutils-2.17
    and so licensed under GPL-v2-or-later.)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/elf.h b/elf.h
index 36bcac4..e1422b8 100644
--- a/elf.h
+++ b/elf.h
@@ -538,6 +538,27 @@ typedef struct {
 #define EF_ALIGN8          0x40		/* 8-bit structure alignment is in use */
 #define EF_NEW_ABI         0x80
 #define EF_OLD_ABI         0x100
+#define EF_ARM_SOFT_FLOAT  0x200
+#define EF_ARM_VFP_FLOAT   0x400
+#define EF_ARM_MAVERICK_FLOAT 0x800
+
+/* Other constants defined in the ARM ELF spec. version B-01.  */
+#define EF_ARM_SYMSARESORTED 0x04       /* NB conflicts with EF_INTERWORK */
+#define EF_ARM_DYNSYMSUSESEGIDX 0x08    /* NB conflicts with EF_APCS26 */
+#define EF_ARM_MAPSYMSFIRST 0x10        /* NB conflicts with EF_APCS_FLOAT */
+#define EF_ARM_EABIMASK      0xFF000000
+
+/* Constants defined in AAELF.  */
+#define EF_ARM_BE8          0x00800000
+#define EF_ARM_LE8          0x00400000
+
+#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK)
+#define EF_ARM_EABI_UNKNOWN  0x00000000
+#define EF_ARM_EABI_VER1     0x01000000
+#define EF_ARM_EABI_VER2     0x02000000
+#define EF_ARM_EABI_VER3     0x03000000
+#define EF_ARM_EABI_VER4     0x04000000
+#define EF_ARM_EABI_VER5     0x05000000
 
 /* Additional symbol types for Thumb */
 #define STT_ARM_TFUNC      0xd
commit adf050b1b9f0fe7f921780eeb1888ce53d94d10b
Author: Benoit Canet <benoit.canet at gmail.com>
Date:   Wed Nov 9 03:37:23 2011 +0000

    arm-linux-user: fix elfload.c's AT_HWCAP to reflect cpu features.
    
    The cpu capabilities passed by the elf loader in AT_HWCAP where
    a constant.
    Make AT_HWCAP reflect the emulated cpu features in order to give
    correct clues to eglibc.
    
    Riku Voipio: fixed to apply to current head
    
    Fix :  [Bug 887516] [NEW] VFP support reported for the PXA270
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index e502b39..4ce9743 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -375,10 +375,33 @@ bool guest_validate_base(unsigned long guest_base)
     return 1; /* All good */
 }
 
-#define ELF_HWCAP (ARM_HWCAP_ARM_SWP | ARM_HWCAP_ARM_HALF               \
-                   | ARM_HWCAP_ARM_THUMB | ARM_HWCAP_ARM_FAST_MULT      \
-                   | ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP              \
-                   | ARM_HWCAP_ARM_NEON | ARM_HWCAP_ARM_VFPv3 )
+
+#define ELF_HWCAP get_elf_hwcap()
+
+static uint32_t get_elf_hwcap(void)
+{
+    CPUARMState *e = thread_env;
+    uint32_t hwcaps = 0;
+
+    hwcaps |= ARM_HWCAP_ARM_SWP;
+    hwcaps |= ARM_HWCAP_ARM_HALF;
+    hwcaps |= ARM_HWCAP_ARM_THUMB;
+    hwcaps |= ARM_HWCAP_ARM_FAST_MULT;
+    hwcaps |= ARM_HWCAP_ARM_FPA;
+
+    /* probe for the extra features */
+#define GET_FEATURE(feat, hwcap) \
+    do {if (arm_feature(e, feat)) { hwcaps |= hwcap; } } while (0)
+    GET_FEATURE(ARM_FEATURE_VFP, ARM_HWCAP_ARM_VFP);
+    GET_FEATURE(ARM_FEATURE_IWMMXT, ARM_HWCAP_ARM_IWMMXT);
+    GET_FEATURE(ARM_FEATURE_THUMB2EE, ARM_HWCAP_ARM_THUMBEE);
+    GET_FEATURE(ARM_FEATURE_NEON, ARM_HWCAP_ARM_NEON);
+    GET_FEATURE(ARM_FEATURE_VFP3, ARM_HWCAP_ARM_VFPv3);
+    GET_FEATURE(ARM_FEATURE_VFP_FP16, ARM_HWCAP_ARM_VFPv3D16);
+#undef GET_FEATURE
+
+    return hwcaps;
+}
 
 #endif
 
commit d1b02ea0dcd20998ef178ddc55fb9765f6aa1d44
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 16 17:16:36 2012 +0000

    linux-user/arm/syscall_nr.h: Add syscall number for ppoll
    
    The list of ARM syscall numbers was missing the entry for ppoll,
    which meant we were accidentally not providing it. (This wasn't
    causing any practical issues beyond warnings about unimplemented
    syscalls, because glibc will fall back to another code path if the
    syscall isn't present.)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/arm/syscall_nr.h b/linux-user/arm/syscall_nr.h
index 7f05879..5356395 100644
--- a/linux-user/arm/syscall_nr.h
+++ b/linux-user/arm/syscall_nr.h
@@ -339,7 +339,7 @@
 #define TARGET_NR_fchmodat			(333)
 #define TARGET_NR_faccessat			(334)
 #define TARGET_NR_pselect6			(335)
-					/* 336 for ppoll */
+#define TARGET_NR_ppoll                         (336)
 #define TARGET_NR_unshare			(337)
 #define TARGET_NR_set_robust_list		(338)
 #define TARGET_NR_get_robust_list		(339)
commit db9526b10a956fd80c08727685c300b63d5a7465
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Feb 3 14:48:03 2012 +0000

    linux-user: Add support for prctl PR_GET_NAME and PR_SET_NAME
    
    Add support for the prctl options PR_GET_NAME and PR_SET_NAME,
    which take or return a name in a 16 byte buffer pointed to by arg2.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index ea44f99..8a92162 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7253,6 +7253,30 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             }
             break;
         }
+#ifdef PR_GET_NAME
+        case PR_GET_NAME:
+        {
+            void *name = lock_user(VERIFY_WRITE, arg2, 16, 1);
+            if (!name) {
+                goto efault;
+            }
+            ret = get_errno(prctl(arg1, (unsigned long)name,
+                                  arg3, arg4, arg5));
+            unlock_user(name, arg2, 16);
+            break;
+        }
+        case PR_SET_NAME:
+        {
+            void *name = lock_user(VERIFY_READ, arg2, 16, 1);
+            if (!name) {
+                goto efault;
+            }
+            ret = get_errno(prctl(arg1, (unsigned long)name,
+                                  arg3, arg4, arg5));
+            unlock_user(name, arg2, 0);
+            break;
+        }
+#endif
         default:
             /* Most prctl options have no pointer arguments */
             ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
commit 1e6722f8b0c1eaff305c39d32c07054450ebdad1
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Feb 3 14:48:03 2012 +0000

    linux-user/syscall.c: Fix indentation in prctl handling
    
    Clean up the odd indentation of this switch statement before
    we double its size by adding new cases to it.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index fdd49b1..ea44f99 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7242,21 +7242,22 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         goto unimplemented;
 #endif
     case TARGET_NR_prctl:
-        switch (arg1)
-            {
-            case PR_GET_PDEATHSIG:
-                {
-                    int deathsig;
-                    ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
-                    if (!is_error(ret) && arg2
-                        && put_user_ual(deathsig, arg2))
-                        goto efault;
-                }
-                break;
-            default:
-                ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
-                break;
+        switch (arg1) {
+        case PR_GET_PDEATHSIG:
+        {
+            int deathsig;
+            ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
+            if (!is_error(ret) && arg2
+                && put_user_ual(deathsig, arg2)) {
+                goto efault;
             }
+            break;
+        }
+        default:
+            /* Most prctl options have no pointer arguments */
+            ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
+            break;
+        }
         break;
 #ifdef TARGET_NR_arch_prctl
     case TARGET_NR_arch_prctl:
commit 288e65b9eea0c9b3cbe21be46f3e24e4e8b2a090
Author: Alexander Graf <agraf at suse.de>
Date:   Wed Dec 14 00:33:28 2011 +0100

    linux-user: reserve 4GB of vmem for 32-on-64
    
    When running 32-on-64 bit guests, we should always reserve as much
    virtual memory as we possibly can for the guest process, so it can
    never overlap with QEMU address space.
    
    Fortunately we already have the infrastructure for that. All that's
    missing is some sane default value to also make use of it!
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/main.c b/linux-user/main.c
index aa95db3..23ad357 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -48,8 +48,19 @@ unsigned long mmap_min_addr;
 #if defined(CONFIG_USE_GUEST_BASE)
 unsigned long guest_base;
 int have_guest_base;
+#if (TARGET_LONG_BITS == 32) && (HOST_LONG_BITS == 64)
+/*
+ * When running 32-on-64 we should make sure we can fit all of the possible
+ * guest address space into a contiguous chunk of virtual host memory.
+ *
+ * This way we will never overlap with our own libraries or binaries or stack
+ * or anything else that QEMU maps.
+ */
+unsigned long reserved_va = 0xf7000000;
+#else
 unsigned long reserved_va;
 #endif
+#endif
 
 static void usage(void);
 
commit 59e9d91c7ae1b655997aec61c08eec1685414117
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Mar 8 14:40:33 2012 +0000

    linux-user: resolve reserved_va vma downwards
    
    After consulting with Paul Brook, we concluded that it's best to search
    the VMA space downwards, so that we don't even get the chance to conflict
    with the brk range.
    
    This patch resolves a bunch of allocation conflicts when using -R.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    [minor changes to get it to apply -- PMM]
    
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/main.c b/linux-user/main.c
index 2570140..aa95db3 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3420,6 +3420,7 @@ int main(int argc, char **argv, char **envp)
             guest_base = HOST_PAGE_ALIGN((unsigned long)p);
         }
         qemu_log("Reserved 0x%lx bytes of guest address space\n", reserved_va);
+        mmap_next_start = reserved_va;
     }
 
     if (reserved_va || have_guest_base) {
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 994c02b..7125d1c 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -212,7 +212,7 @@ static int mmap_frag(abi_ulong real_start,
 #else
 # define TASK_UNMAPPED_BASE  0x40000000
 #endif
-static abi_ulong mmap_next_start = TASK_UNMAPPED_BASE;
+abi_ulong mmap_next_start = TASK_UNMAPPED_BASE;
 
 unsigned long last_brk;
 
@@ -222,7 +222,7 @@ unsigned long last_brk;
 static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size)
 {
     abi_ulong addr;
-    abi_ulong last_addr;
+    abi_ulong end_addr;
     int prot;
     int looped = 0;
 
@@ -230,25 +230,38 @@ static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size)
         return (abi_ulong)-1;
     }
 
-    last_addr = start;
-    for (addr = start; last_addr + size != addr; addr += qemu_host_page_size) {
-        if (last_addr + size >= RESERVED_VA
-            || (abi_ulong)(last_addr + size) < last_addr) {
+    size = HOST_PAGE_ALIGN(size);
+    end_addr = start + size;
+    if (end_addr > RESERVED_VA) {
+        end_addr = RESERVED_VA;
+    }
+    addr = end_addr - qemu_host_page_size;
+
+    while (1) {
+        if (addr > end_addr) {
             if (looped) {
                 return (abi_ulong)-1;
             }
-            last_addr = qemu_host_page_size;
-            addr = 0;
+            end_addr = RESERVED_VA;
+            addr = end_addr - qemu_host_page_size;
             looped = 1;
             continue;
         }
         prot = page_get_flags(addr);
         if (prot) {
-            last_addr = addr + qemu_host_page_size;
+            end_addr = addr;
+        }
+        if (addr + size == end_addr) {
+            break;
         }
+        addr -= qemu_host_page_size;
+    }
+
+    if (start == mmap_next_start) {
+        mmap_next_start = addr;
     }
-    mmap_next_start = addr;
-    return last_addr;
+
+    return addr;
 }
 #endif
 
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 6889567..dd74cc0 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -251,6 +251,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
                        abi_ulong new_addr);
 int target_msync(abi_ulong start, abi_ulong len, int flags);
 extern unsigned long last_brk;
+extern abi_ulong mmap_next_start;
 void mmap_lock(void);
 void mmap_unlock(void);
 abi_ulong mmap_find_vma(abi_ulong, abi_ulong);
commit 39879bbbea4661a4004ca26673e3d1e6ae1e0bc3
Author: Alexander Graf <agraf at suse.de>
Date:   Thu Feb 2 03:14:18 2012 +0100

    linux-user: take RESERVED_VA into account for g2h_valid()
    
    When running with -R (RESERVED_VA > 0) all guest virtual addresses
    are within the [0..RESERVED_VA] range. Reflect this with g2h_valid()
    too so we can safely check for boundaries of our guest address space.
    
    This is required to have the /proc/self/maps code not show maps that
    aren't accessible from the guest process's point of view.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/cpu-all.h b/cpu-all.h
index 9621c3c..4512518 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -204,7 +204,8 @@ extern unsigned long reserved_va;
 #else
 #define h2g_valid(x) ({ \
     unsigned long __guest = (unsigned long)(x) - GUEST_BASE; \
-    __guest < (1ul << TARGET_VIRT_ADDR_SPACE_BITS); \
+    (__guest < (1ul << TARGET_VIRT_ADDR_SPACE_BITS)) && \
+    (!RESERVED_VA || (__guest < RESERVED_VA)); \
 })
 #endif
 
commit 20249ae189ac0baa5011770bccabf3ee802eb2ab
Author: Alexander Graf <agraf at suse.de>
Date:   Mon Feb 6 21:37:07 2012 +0100

    linux-user: fix fallocate
    
    Fallocate gets off_t parameters passed in, so we should also read them out
    accordingly.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    
    ---
    
    v1 -> v2:
    
      - unbreak 64-bit guests
    
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 9d1c8b2..fdd49b1 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -8485,7 +8485,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #endif /* CONFIG_EVENTFD  */
 #if defined(CONFIG_FALLOCATE) && defined(TARGET_NR_fallocate)
     case TARGET_NR_fallocate:
+#if TARGET_ABI_BITS == 32
+        ret = get_errno(fallocate(arg1, arg2, target_offset64(arg3, arg4),
+                                  target_offset64(arg5, arg6)));
+#else
         ret = get_errno(fallocate(arg1, arg2, arg3, arg4));
+#endif
         break;
 #endif
 #if defined(CONFIG_SYNC_FILE_RANGE)
commit 354a0008270e9167ce89527fdf8f1a85c3a7fb87
Author: Alexander Graf <agraf at suse.de>
Date:   Thu Feb 2 02:22:34 2012 +0100

    linux-user: Add ioctl for BLKBSZGET
    
    This patch adds the ioctl wrapper definition for BLKBSZGET.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 5b70f92..eb96a08 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -75,6 +75,7 @@
      IOCTL(BLKRASET, 0, TYPE_INT)
      IOCTL(BLKRAGET, IOC_R, MK_PTR(TYPE_LONG))
      IOCTL(BLKSSZGET, IOC_R, MK_PTR(TYPE_LONG))
+     IOCTL(BLKBSZGET, IOC_R, MK_PTR(TYPE_INT))
 #ifdef FIBMAP
      IOCTL(FIBMAP, IOC_W | IOC_R, MK_PTR(TYPE_LONG))
 #endif
commit 49e9a0775224039701d34b208d8a1da982477fc9
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Jan 31 20:11:37 2012 +0100

    linux-user: add BLKSSZGET ioctl wrapper
    
    This patch adds an ioctl definition for BLKSSZGET.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index fd8b7bb..5b70f92 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -74,6 +74,7 @@
      IOCTL(BLKFLSBUF, 0, TYPE_NULL)
      IOCTL(BLKRASET, 0, TYPE_INT)
      IOCTL(BLKRAGET, IOC_R, MK_PTR(TYPE_LONG))
+     IOCTL(BLKSSZGET, IOC_R, MK_PTR(TYPE_LONG))
 #ifdef FIBMAP
      IOCTL(FIBMAP, IOC_W | IOC_R, MK_PTR(TYPE_LONG))
 #endif
commit edafea1330133eb8f6580a1c4f84fc5ec766eb4c
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Jan 31 20:10:20 2012 +0100

    linux-user: fix BLK ioctl arguments
    
    Some BLK ioctls passed sizeof(x) into a macro that already did sizeof() on
    the passed in argument, rendering the size information inside the ioctl be
    the size of the host default integer type.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index f8f3af3..a79b67d 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -832,9 +832,11 @@ struct target_pollfd {
 #define TARGET_BLKSECTGET TARGET_IO(0x12,103)/* get max sectors per request (ll_rw_blk.c) */
 #define TARGET_BLKSSZGET  TARGET_IO(0x12,104)/* get block device sector size */
 /* A jump here: 108-111 have been used for various private purposes. */
-#define TARGET_BLKBSZGET  TARGET_IOR(0x12,112,sizeof(int))
-#define TARGET_BLKBSZSET  TARGET_IOW(0x12,113,sizeof(int))
-#define TARGET_BLKGETSIZE64 TARGET_IOR(0x12,114,sizeof(uint64_t)) /* return device size in bytes (u64 *arg) */
+#define TARGET_BLKBSZGET  TARGET_IOR(0x12,112,int)
+#define TARGET_BLKBSZSET  TARGET_IOW(0x12,113,int)
+#define TARGET_BLKGETSIZE64 TARGET_IOR(0x12,114,abi_ulong)
+                                             /* return device size in bytes
+                                                (u64 *arg) */
 #define TARGET_FIBMAP     TARGET_IO(0x00,1)  /* bmap access */
 #define TARGET_FIGETBSZ   TARGET_IO(0x00,2)  /* get the block size used for bmap */
 #define TARGET_FS_IOC_FIEMAP TARGET_IOWR('f',11,struct fiemap)
commit 6083abd9aa134c9b0804e584f8279f54e6c90a1c
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Jan 31 19:44:41 2012 +0100

    linux-user: add struct old_dev_t compat
    
    The compat LOOP_SET_STATUS ioctl uses struct old_dev_t in its passed
    struct. That variable type is vastly different between different
    architectures. Implement wrapping around it so we can use it.
    
    This fixes running arm kpartx on an x86_64 host for me.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h
index fb8c9c9..601618d 100644
--- a/linux-user/syscall_types.h
+++ b/linux-user/syscall_types.h
@@ -83,9 +83,9 @@ STRUCT(mixer_info,
 /* loop device ioctls */
 STRUCT(loop_info,
        TYPE_INT,                 /* lo_number */
-       TYPE_SHORT,               /* lo_device */
+       TYPE_OLDDEVT,             /* lo_device */
        TYPE_ULONG,               /* lo_inode */
-       TYPE_SHORT,               /* lo_rdevice */
+       TYPE_OLDDEVT,             /* lo_rdevice */
        TYPE_INT,                 /* lo_offset */
        TYPE_INT,                 /* lo_encrypt_type */
        TYPE_INT,                 /* lo_encrypt_key_size */
diff --git a/thunk.c b/thunk.c
index 0657188..8ebbbb4 100644
--- a/thunk.c
+++ b/thunk.c
@@ -46,6 +46,7 @@ static inline const argtype *thunk_type_next(const argtype *type_ptr)
     case TYPE_LONG:
     case TYPE_ULONG:
     case TYPE_PTRVOID:
+    case TYPE_OLDDEVT:
         return type_ptr;
     case TYPE_PTR:
         return thunk_type_next_ptr(type_ptr);
@@ -188,6 +189,33 @@ const argtype *thunk_convert(void *dst, const void *src,
 #else
 #warning unsupported conversion
 #endif
+    case TYPE_OLDDEVT:
+    {
+        uint64_t val = 0;
+        switch (thunk_type_size(type_ptr - 1, !to_host)) {
+        case 2:
+            val = *(uint16_t *)src;
+            break;
+        case 4:
+            val = *(uint32_t *)src;
+            break;
+        case 8:
+            val = *(uint64_t *)src;
+            break;
+        }
+        switch (thunk_type_size(type_ptr - 1, to_host)) {
+        case 2:
+            *(uint16_t *)dst = tswap16(val);
+            break;
+        case 4:
+            *(uint32_t *)dst = tswap32(val);
+            break;
+        case 8:
+            *(uint64_t *)dst = tswap64(val);
+            break;
+        }
+        break;
+    }
     case TYPE_ARRAY:
         {
             int array_length, i, dst_size, src_size;
diff --git a/thunk.h b/thunk.h
index 9810743..5be8f91 100644
--- a/thunk.h
+++ b/thunk.h
@@ -37,6 +37,7 @@ typedef enum argtype {
     TYPE_PTR,
     TYPE_ARRAY,
     TYPE_STRUCT,
+    TYPE_OLDDEVT,
 } argtype;
 
 #define MK_PTR(type) TYPE_PTR, type
@@ -104,6 +105,31 @@ static inline int thunk_type_size(const argtype *type_ptr, int is_host)
             return TARGET_ABI_BITS / 8;
         }
         break;
+    case TYPE_OLDDEVT:
+        if (is_host) {
+#if defined(HOST_X86_64)
+            return 8;
+#elif defined(HOST_ALPHA) || defined(HOST_IA64) || defined(HOST_MIPS) || \
+      defined(HOST_PARISC) || defined(HOST_SPARC64)
+            return 4;
+#elif defined(HOST_PPC)
+            return HOST_LONG_SIZE;
+#else
+            return 2;
+#endif
+        } else {
+#if defined(TARGET_X86_64)
+            return 8;
+#elif defined(TARGET_ALPHA) || defined(TARGET_IA64) || defined(TARGET_MIPS) || \
+      defined(TARGET_PARISC) || defined(TARGET_SPARC64)
+            return 4;
+#elif defined(TARGET_PPC)
+            return TARGET_ABI_BITS / 8;
+#else
+            return 2;
+#endif
+        }
+        break;
     case TYPE_ARRAY:
         size = type_ptr[1];
         return size * thunk_type_size_array(type_ptr + 2, is_host);
@@ -141,6 +167,8 @@ static inline int thunk_type_align(const argtype *type_ptr, int is_host)
             return TARGET_ABI_BITS / 8;
         }
         break;
+    case TYPE_OLDDEVT:
+        return thunk_type_size(type_ptr, is_host);
     case TYPE_ARRAY:
         return thunk_type_align_array(type_ptr + 2, is_host);
     case TYPE_STRUCT:
commit 56e904ecb2018e30b10e9ec846635ff3b1e1d923
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Jan 31 18:42:06 2012 +0100

    linux-user: implement device mapper ioctls
    
    This patch implements all ioctls currently implemented by device mapper,
    enabling us to run dmsetup and kpartx inside of linux-user.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 6514502..fd8b7bb 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -345,3 +345,35 @@
   IOCTL(VT_SETMODE, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_vt_mode)))
   IOCTL(VT_RELDISP, 0, TYPE_INT)
   IOCTL(VT_DISALLOCATE, 0, TYPE_INT)
+
+  IOCTL(DM_VERSION, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_REMOVE_ALL,   IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_LIST_DEVICES, IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_DEV_CREATE,   IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_DEV_REMOVE,   IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_DEV_RENAME,   IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_DEV_SUSPEND,  IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_DEV_STATUS,   IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_DEV_WAIT,     IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_TABLE_LOAD,   IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_TABLE_CLEAR,  IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_TABLE_DEPS,   IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_TABLE_STATUS, IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_LIST_VERSIONS,IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_TARGET_MSG,   IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_DEV_SET_GEOMETRY, IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 0e74ee0..9d1c8b2 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -95,6 +95,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
 #endif
 #include <linux/fb.h>
 #include <linux/vt.h>
+#include <linux/dm-ioctl.h>
 #include "linux_loop.h"
 #include "cpu-uname.h"
 
@@ -3354,6 +3355,231 @@ static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
     return ret;
 }
 
+static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
+                            abi_long cmd, abi_long arg)
+{
+    void *argptr;
+    struct dm_ioctl *host_dm;
+    abi_long guest_data;
+    uint32_t guest_data_size;
+    int target_size;
+    const argtype *arg_type = ie->arg_type;
+    abi_long ret;
+    void *big_buf = NULL;
+    char *host_data;
+
+    arg_type++;
+    target_size = thunk_type_size(arg_type, 0);
+    argptr = lock_user(VERIFY_READ, arg, target_size, 1);
+    if (!argptr) {
+        ret = -TARGET_EFAULT;
+        goto out;
+    }
+    thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
+    unlock_user(argptr, arg, 0);
+
+    /* buf_temp is too small, so fetch things into a bigger buffer */
+    big_buf = g_malloc0(((struct dm_ioctl*)buf_temp)->data_size * 2);
+    memcpy(big_buf, buf_temp, target_size);
+    buf_temp = big_buf;
+    host_dm = big_buf;
+
+    guest_data = arg + host_dm->data_start;
+    if ((guest_data - arg) < 0) {
+        ret = -EINVAL;
+        goto out;
+    }
+    guest_data_size = host_dm->data_size - host_dm->data_start;
+    host_data = (char*)host_dm + host_dm->data_start;
+
+    argptr = lock_user(VERIFY_READ, guest_data, guest_data_size, 1);
+    switch (ie->host_cmd) {
+    case DM_REMOVE_ALL:
+    case DM_LIST_DEVICES:
+    case DM_DEV_CREATE:
+    case DM_DEV_REMOVE:
+    case DM_DEV_SUSPEND:
+    case DM_DEV_STATUS:
+    case DM_DEV_WAIT:
+    case DM_TABLE_STATUS:
+    case DM_TABLE_CLEAR:
+    case DM_TABLE_DEPS:
+    case DM_LIST_VERSIONS:
+        /* no input data */
+        break;
+    case DM_DEV_RENAME:
+    case DM_DEV_SET_GEOMETRY:
+        /* data contains only strings */
+        memcpy(host_data, argptr, guest_data_size);
+        break;
+    case DM_TARGET_MSG:
+        memcpy(host_data, argptr, guest_data_size);
+        *(uint64_t*)host_data = tswap64(*(uint64_t*)argptr);
+        break;
+    case DM_TABLE_LOAD:
+    {
+        void *gspec = argptr;
+        void *cur_data = host_data;
+        const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
+        int spec_size = thunk_type_size(arg_type, 0);
+        int i;
+
+        for (i = 0; i < host_dm->target_count; i++) {
+            struct dm_target_spec *spec = cur_data;
+            uint32_t next;
+            int slen;
+
+            thunk_convert(spec, gspec, arg_type, THUNK_HOST);
+            slen = strlen((char*)gspec + spec_size) + 1;
+            next = spec->next;
+            spec->next = sizeof(*spec) + slen;
+            strcpy((char*)&spec[1], gspec + spec_size);
+            gspec += next;
+            cur_data += spec->next;
+        }
+        break;
+    }
+    default:
+        ret = -TARGET_EINVAL;
+        goto out;
+    }
+    unlock_user(argptr, guest_data, 0);
+
+    ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
+    if (!is_error(ret)) {
+        guest_data = arg + host_dm->data_start;
+        guest_data_size = host_dm->data_size - host_dm->data_start;
+        argptr = lock_user(VERIFY_WRITE, guest_data, guest_data_size, 0);
+        switch (ie->host_cmd) {
+        case DM_REMOVE_ALL:
+        case DM_DEV_CREATE:
+        case DM_DEV_REMOVE:
+        case DM_DEV_RENAME:
+        case DM_DEV_SUSPEND:
+        case DM_DEV_STATUS:
+        case DM_TABLE_LOAD:
+        case DM_TABLE_CLEAR:
+        case DM_TARGET_MSG:
+        case DM_DEV_SET_GEOMETRY:
+            /* no return data */
+            break;
+        case DM_LIST_DEVICES:
+        {
+            struct dm_name_list *nl = (void*)host_dm + host_dm->data_start;
+            uint32_t remaining_data = guest_data_size;
+            void *cur_data = argptr;
+            const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) };
+            int nl_size = 12; /* can't use thunk_size due to alignment */
+
+            while (1) {
+                uint32_t next = nl->next;
+                if (next) {
+                    nl->next = nl_size + (strlen(nl->name) + 1);
+                }
+                if (remaining_data < nl->next) {
+                    host_dm->flags |= DM_BUFFER_FULL_FLAG;
+                    break;
+                }
+                thunk_convert(cur_data, nl, arg_type, THUNK_TARGET);
+                strcpy(cur_data + nl_size, nl->name);
+                cur_data += nl->next;
+                remaining_data -= nl->next;
+                if (!next) {
+                    break;
+                }
+                nl = (void*)nl + next;
+            }
+            break;
+        }
+        case DM_DEV_WAIT:
+        case DM_TABLE_STATUS:
+        {
+            struct dm_target_spec *spec = (void*)host_dm + host_dm->data_start;
+            void *cur_data = argptr;
+            const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
+            int spec_size = thunk_type_size(arg_type, 0);
+            int i;
+
+            for (i = 0; i < host_dm->target_count; i++) {
+                uint32_t next = spec->next;
+                int slen = strlen((char*)&spec[1]) + 1;
+                spec->next = (cur_data - argptr) + spec_size + slen;
+                if (guest_data_size < spec->next) {
+                    host_dm->flags |= DM_BUFFER_FULL_FLAG;
+                    break;
+                }
+                thunk_convert(cur_data, spec, arg_type, THUNK_TARGET);
+                strcpy(cur_data + spec_size, (char*)&spec[1]);
+                cur_data = argptr + spec->next;
+                spec = (void*)host_dm + host_dm->data_start + next;
+            }
+            break;
+        }
+        case DM_TABLE_DEPS:
+        {
+            void *hdata = (void*)host_dm + host_dm->data_start;
+            int count = *(uint32_t*)hdata;
+            uint64_t *hdev = hdata + 8;
+            uint64_t *gdev = argptr + 8;
+            int i;
+
+            *(uint32_t*)argptr = tswap32(count);
+            for (i = 0; i < count; i++) {
+                *gdev = tswap64(*hdev);
+                gdev++;
+                hdev++;
+            }
+            break;
+        }
+        case DM_LIST_VERSIONS:
+        {
+            struct dm_target_versions *vers = (void*)host_dm + host_dm->data_start;
+            uint32_t remaining_data = guest_data_size;
+            void *cur_data = argptr;
+            const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_versions) };
+            int vers_size = thunk_type_size(arg_type, 0);
+
+            while (1) {
+                uint32_t next = vers->next;
+                if (next) {
+                    vers->next = vers_size + (strlen(vers->name) + 1);
+                }
+                if (remaining_data < vers->next) {
+                    host_dm->flags |= DM_BUFFER_FULL_FLAG;
+                    break;
+                }
+                thunk_convert(cur_data, vers, arg_type, THUNK_TARGET);
+                strcpy(cur_data + vers_size, vers->name);
+                cur_data += vers->next;
+                remaining_data -= vers->next;
+                if (!next) {
+                    break;
+                }
+                vers = (void*)vers + next;
+            }
+            break;
+        }
+        default:
+            ret = -TARGET_EINVAL;
+            goto out;
+        }
+        unlock_user(argptr, guest_data, guest_data_size);
+
+        argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
+        if (!argptr) {
+            ret = -TARGET_EFAULT;
+            goto out;
+        }
+        thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
+        unlock_user(argptr, arg, target_size);
+    }
+out:
+    if (big_buf) {
+        free(big_buf);
+    }
+    return ret;
+}
+
 static IOCTLEntry ioctl_entries[] = {
 #define IOCTL(cmd, access, ...) \
     { TARGET_ ## cmd, cmd, #cmd, access, 0, {  __VA_ARGS__ } },
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 41f0ff8..f8f3af3 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -989,6 +989,24 @@ struct target_pollfd {
 #define TARGET_VT_RELDISP             0x5605
 #define TARGET_VT_DISALLOCATE         0x5608
 
+/* device mapper */
+#define TARGET_DM_VERSION             TARGET_IOWRU(0xfd, 0x00)
+#define TARGET_DM_REMOVE_ALL          TARGET_IOWRU(0xfd, 0x01)
+#define TARGET_DM_LIST_DEVICES        TARGET_IOWRU(0xfd, 0x02)
+#define TARGET_DM_DEV_CREATE          TARGET_IOWRU(0xfd, 0x03)
+#define TARGET_DM_DEV_REMOVE          TARGET_IOWRU(0xfd, 0x04)
+#define TARGET_DM_DEV_RENAME          TARGET_IOWRU(0xfd, 0x05)
+#define TARGET_DM_DEV_SUSPEND         TARGET_IOWRU(0xfd, 0x06)
+#define TARGET_DM_DEV_STATUS          TARGET_IOWRU(0xfd, 0x07)
+#define TARGET_DM_DEV_WAIT            TARGET_IOWRU(0xfd, 0x08)
+#define TARGET_DM_TABLE_LOAD          TARGET_IOWRU(0xfd, 0x09)
+#define TARGET_DM_TABLE_CLEAR         TARGET_IOWRU(0xfd, 0x0a)
+#define TARGET_DM_TABLE_DEPS          TARGET_IOWRU(0xfd, 0x0b)
+#define TARGET_DM_TABLE_STATUS        TARGET_IOWRU(0xfd, 0x0c)
+#define TARGET_DM_LIST_VERSIONS       TARGET_IOWRU(0xfd, 0x0d)
+#define TARGET_DM_TARGET_MSG          TARGET_IOWRU(0xfd, 0x0e)
+#define TARGET_DM_DEV_SET_GEOMETRY    TARGET_IOWRU(0xfd, 0x0f)
+
 /* from asm/termbits.h */
 
 #define TARGET_NCC 8
diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h
index c370125..fb8c9c9 100644
--- a/linux-user/syscall_types.h
+++ b/linux-user/syscall_types.h
@@ -186,6 +186,42 @@ STRUCT(vt_mode,
        TYPE_SHORT, /* acqsig */
        TYPE_SHORT) /* frsig  */
 
+STRUCT(dm_ioctl,
+       MK_ARRAY(TYPE_INT, 3), /* version */
+       TYPE_INT, /* data_size */
+       TYPE_INT, /* data_start */
+       TYPE_INT, /* target_count*/
+       TYPE_INT, /* open_count */
+       TYPE_INT, /* flags */
+       TYPE_INT, /* event_nr */
+       TYPE_INT, /* padding */
+       TYPE_ULONGLONG, /* dev */
+       MK_ARRAY(TYPE_CHAR, 128), /* name */
+       MK_ARRAY(TYPE_CHAR, 129), /* uuid */
+       MK_ARRAY(TYPE_CHAR, 7)) /* data */
+
+STRUCT(dm_target_spec,
+       TYPE_ULONGLONG, /* sector_start */
+       TYPE_ULONGLONG, /* length */
+       TYPE_INT, /* status */
+       TYPE_INT, /* next */
+       MK_ARRAY(TYPE_CHAR, 16)) /* target_type */
+
+STRUCT(dm_target_deps,
+       TYPE_INT, /* count */
+       TYPE_INT) /* padding */
+
+STRUCT(dm_name_list,
+       TYPE_ULONGLONG, /* dev */
+       TYPE_INT) /* next */
+
+STRUCT(dm_target_versions,
+       TYPE_INT, /* next */
+       MK_ARRAY(TYPE_INT, 3)) /* version*/
+
+STRUCT(dm_target_msg,
+       TYPE_ULONGLONG) /* sector */
+
 STRUCT(fiemap_extent,
        TYPE_ULONGLONG, /* fe_logical */
        TYPE_ULONGLONG, /* fe_physical */
commit 84803b87a183bd71963584c3be5ca838d32c55df
Author: Fabio Erculiani <lxnay at sabayon.org>
Date:   Tue Jan 3 09:38:35 2012 +0000

    linux-user: target_argv is placed on ts->bprm->argv and can't be freed()
    
    TaskState contains linux_bprm struct which encapsulates argv among
    other things.
    argv might be used around the code and is expected to contain valid
    data. Before this patch, ts->bprm->argv was NULL due to it being
    freed right after loader_exec().
    
    Signed-off-by: Fabio Erculiani <lxnay at sabayon.org>
    Acked-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/main.c b/linux-user/main.c
index 962677e..2570140 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3486,11 +3486,6 @@ int main(int argc, char **argv, char **envp)
         _exit(1);
     }
 
-    for (i = 0; i < target_argc; i++) {
-        free(target_argv[i]);
-    }
-    free(target_argv);
-
     for (wrk = target_environ; *wrk; wrk++) {
         free(*wrk);
     }
commit e0e65bee16ae8515315d2bad02e021f3fb5dd236
Author: Fabio Erculiani <lxnay at sabayon.org>
Date:   Tue Jan 3 09:38:34 2012 +0000

    linux-user: improve fake /proc/self/stat making `ps` not segfault.
    
    With the current fake /proc/self/stat implementation `ps` is
    segfaulting because it expects to read PID and argv[0] as first and
    second field respectively, with the latter being enclosed between
    backets.
    
    Reproducing is as easy as running: `ps` inside qemu-user chroot
    with /proc mounted.
    
    Signed-off-by: Fabio Erculiani <lxnay at sabayon.org>
    Acked-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 9f5e53a..0e74ee0 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4662,11 +4662,22 @@ static int open_self_stat(void *cpu_env, int fd)
       int len;
       uint64_t val = 0;
 
-      if (i == 27) {
-          /* stack bottom */
-          val = start_stack;
+      if (i == 0) {
+        /* pid */
+        val = getpid();
+        snprintf(buf, sizeof(buf), "%"PRId64 " ", val);
+      } else if (i == 1) {
+        /* app name */
+        snprintf(buf, sizeof(buf), "(%s) ", ts->bprm->argv[0]);
+      } else if (i == 27) {
+        /* stack bottom */
+        val = start_stack;
+        snprintf(buf, sizeof(buf), "%"PRId64 " ", val);
+      } else {
+        /* for the rest, there is MasterCard */
+        snprintf(buf, sizeof(buf), "0%c", i == 43 ? '\n' : ' ');
       }
-      snprintf(buf, sizeof(buf), "%"PRId64 "%c", val, i == 43 ? '\n' : ' ');
+
       len = strlen(buf);
       if (write(fd, buf, len) != len) {
           return -1;
commit 50d30c267563bf492fd403dd23abc7888f3e220c
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Fri Mar 23 08:36:54 2012 +0100

    qed: remove incoming live migration blocker
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at gmail.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qed.c b/block/qed.c
index aea2772..366cde7 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -498,12 +498,6 @@ static int bdrv_qed_open(BlockDriverState *bs, int flags)
     s->need_check_timer = qemu_new_timer_ns(vm_clock,
                                             qed_need_check_timer_cb, s);
 
-    error_set(&s->migration_blocker,
-              QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
-              "qed", bs->device_name, "live migration");
-    migrate_add_blocker(s->migration_blocker);
-
-
 out:
     if (ret) {
         qed_free_l2_cache(&s->l2_cache);
@@ -516,9 +510,6 @@ static void bdrv_qed_close(BlockDriverState *bs)
 {
     BDRVQEDState *s = bs->opaque;
 
-    migrate_del_blocker(s->migration_blocker);
-    error_free(s->migration_blocker);
-
     qed_cancel_need_check_timer(s);
     qemu_free_timer(s->need_check_timer);
 
diff --git a/block/qed.h b/block/qed.h
index 62624a1..c716772 100644
--- a/block/qed.h
+++ b/block/qed.h
@@ -169,8 +169,6 @@ typedef struct {
 
     /* Periodic flush and clear need check flag */
     QEMUTimer *need_check_timer;
-
-    Error *migration_blocker;
 } BDRVQEDState;
 
 enum {
commit 2d1f3c2360053dec7dacc0292f52cff17104feff
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Fri Mar 23 08:36:53 2012 +0100

    qed: honor BDRV_O_INCOMING for incoming live migration
    
    From original commit with Patchwork-id: 31108 by
    Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    
    "The QED image format includes a file header bit to mark images dirty.
    QED normally checks dirty images on open and fixes inconsistent
    metadata.  This is undesirable during live migration since the dirty bit
    may be set if the source host is modifying the image file.  The check
    should be postponed until migration completes.
    
    Skip operations that modify the image file if the BDRV_O_INCOMING flag
    is set."
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at gmail.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qed.c b/block/qed.c
index a5e9d57..aea2772 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -450,7 +450,7 @@ static int bdrv_qed_open(BlockDriverState *bs, int flags)
      * feature is no longer valid.
      */
     if ((s->header.autoclear_features & ~QED_AUTOCLEAR_FEATURE_MASK) != 0 &&
-        !bdrv_is_read_only(bs->file)) {
+        !bdrv_is_read_only(bs->file) && !(flags & BDRV_O_INCOMING)) {
         s->header.autoclear_features &= QED_AUTOCLEAR_FEATURE_MASK;
 
         ret = qed_write_header_sync(s);
@@ -477,7 +477,8 @@ static int bdrv_qed_open(BlockDriverState *bs, int flags)
          * potentially inconsistent images to be opened read-only.  This can
          * aid data recovery from an otherwise inconsistent image.
          */
-        if (!bdrv_is_read_only(bs->file)) {
+        if (!bdrv_is_read_only(bs->file) &&
+            !(flags & BDRV_O_INCOMING)) {
             BdrvCheckResult result = {0};
 
             ret = qed_check(s, &result, true);
commit 901862cbf49639aaef23a575d40ae81282b6fcfc
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Fri Mar 23 08:36:52 2012 +0100

    migration: clear BDRV_O_INCOMING flags on end of incoming live migration
    
    Signed-off-by: Benoît Canet <benoit.canet at gmail.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at gmail.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/migration.c b/migration.c
index 8c119ba..94f7839 100644
--- a/migration.c
+++ b/migration.c
@@ -91,6 +91,7 @@ void process_incoming_migration(QEMUFile *f)
     qemu_announce_self();
     DPRINTF("successfully loaded vm state\n");
 
+    bdrv_clear_incoming_migration_all();
     /* Make sure all file formats flush their mutable metadata */
     bdrv_invalidate_cache_all();
 
commit c82954e529929c2d650589d8bccaaf19dec33431
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Fri Mar 23 08:36:51 2012 +0100

    qed: add bdrv_invalidate_cache to be called after incoming live migration
    
    The QED image is reopened to flush metadata and check consistency.
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at gmail.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qed.c b/block/qed.c
index 19d87f3..a5e9d57 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -1510,6 +1510,15 @@ static int bdrv_qed_change_backing_file(BlockDriverState *bs,
     return ret;
 }
 
+static void bdrv_qed_invalidate_cache(BlockDriverState *bs)
+{
+    BDRVQEDState *s = bs->opaque;
+
+    bdrv_qed_close(bs);
+    memset(s, 0, sizeof(BDRVQEDState));
+    bdrv_qed_open(bs, bs->open_flags);
+}
+
 static int bdrv_qed_check(BlockDriverState *bs, BdrvCheckResult *result)
 {
     BDRVQEDState *s = bs->opaque;
@@ -1561,6 +1570,7 @@ static BlockDriver bdrv_qed = {
     .bdrv_getlength           = bdrv_qed_getlength,
     .bdrv_get_info            = bdrv_qed_get_info,
     .bdrv_change_backing_file = bdrv_qed_change_backing_file,
+    .bdrv_invalidate_cache    = bdrv_qed_invalidate_cache,
     .bdrv_check               = bdrv_qed_check,
 };
 
commit ed9d4205cecb2f6c06821cb9d8fe9e1ca5f9b8ab
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Fri Mar 23 08:36:50 2012 +0100

    blockdev: open images with BDRV_O_INCOMING on incoming live migration
    
    Open images with BDRV_O_INCOMING in order to inform block drivers
    that an incoming live migration is coming.
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at gmail.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 4d17486..0c2440e 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -595,6 +595,10 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
         bdrv_flags |= BDRV_O_COPY_ON_READ;
     }
 
+    if (runstate_check(RUN_STATE_INMIGRATE)) {
+        bdrv_flags |= BDRV_O_INCOMING;
+    }
+
     if (media == MEDIA_CDROM) {
         /* CDROM is fine for any interface, don't check.  */
         ro = 1;
commit 077892696b900ebf88052fef917367213db80477
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Fri Mar 23 08:36:49 2012 +0100

    block: add a function to clear incoming live migration flags
    
    This function will clear all BDRV_O_INCOMING flags.
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at gmail.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index b3117ef..c0c90f0 100644
--- a/block.c
+++ b/block.c
@@ -3624,6 +3624,15 @@ void bdrv_invalidate_cache_all(void)
     }
 }
 
+void bdrv_clear_incoming_migration_all(void)
+{
+    BlockDriverState *bs;
+
+    QTAILQ_FOREACH(bs, &bdrv_states, list) {
+        bs->open_flags = bs->open_flags & ~(BDRV_O_INCOMING);
+    }
+}
+
 int bdrv_flush(BlockDriverState *bs)
 {
     Coroutine *co;
diff --git a/block.h b/block.h
index 5151dea..f163e54 100644
--- a/block.h
+++ b/block.h
@@ -229,6 +229,8 @@ BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
 void bdrv_invalidate_cache(BlockDriverState *bs);
 void bdrv_invalidate_cache_all(void);
 
+void bdrv_clear_incoming_migration_all(void);
+
 /* Ensure contents are flushed to disk.  */
 int bdrv_flush(BlockDriverState *bs);
 int coroutine_fn bdrv_co_flush(BlockDriverState *bs);
commit ccb1f4a7b32fbebcf0d49beab1d2614f0a657d5a
Author: Benoît Canet <benoit.canet at gmail.com>
Date:   Fri Mar 23 08:36:48 2012 +0100

    block: Add new BDRV_O_INCOMING flag to notice incoming live migration
    
    From original patch with Patchwork-id: 31110 by
    Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    
    "Add a flag to indicate that incoming migration is pending and care needs
    to be taken for data consistency.  Block drivers should not modify the
    image file before incoming migration is complete since the migration
    source host is still using the image file."
    
    The rationale for not using bdrv->read_only is the following.
    
    "Unfortunately this is not possible because too many other places in QEMU
    test bdrv_is_read_only() and use it for their own evil purposes.  For
    example, ide_init_drive() will error out because read-only harddisks are
    not supported.  We're mixing guest and host side read-only concepts so
    this simpler alternative does not work."
    
    Signed-off-by: Benoit Canet <benoit.canet at gmail.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at gmail.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.h b/block.h
index 4e99e18..5151dea 100644
--- a/block.h
+++ b/block.h
@@ -78,6 +78,7 @@ typedef struct BlockDevOps {
 #define BDRV_O_NO_BACKING  0x0100 /* don't open the backing file */
 #define BDRV_O_NO_FLUSH    0x0200 /* disable flushing on this disk */
 #define BDRV_O_COPY_ON_READ 0x0400 /* copy read backing sectors into image */
+#define BDRV_O_INCOMING    0x0800  /* consistency hint for incoming migration */
 
 #define BDRV_O_CACHE_MASK  (BDRV_O_NOCACHE | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH)
 
commit 5a67a1048e1294b35940e7432d57d8cd801e6571
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Mon Mar 26 21:22:10 2012 -0300

    block stream: close unused files and update ->backing_hd
    
    Close the now unused images that were part of the previous backing file
    chain and adjust ->backing_hd, backing_filename and backing_format
    properly.
    
    Fixes https://bugzilla.redhat.com/show_bug.cgi?id=801449
    
    Signed-off-by: Marcelo Tosatti <mtosatti 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/block/stream.c b/block/stream.c
index 61ff7a2..0efe1ad 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -76,6 +76,39 @@ static int coroutine_fn stream_populate(BlockDriverState *bs,
     return bdrv_co_copy_on_readv(bs, sector_num, nb_sectors, &qiov);
 }
 
+static void close_unused_images(BlockDriverState *top, BlockDriverState *base,
+                                const char *base_id)
+{
+    BlockDriverState *intermediate;
+    intermediate = top->backing_hd;
+
+    while (intermediate) {
+        BlockDriverState *unused;
+
+        /* reached base */
+        if (intermediate == base) {
+            break;
+        }
+
+        unused = intermediate;
+        intermediate = intermediate->backing_hd;
+        unused->backing_hd = NULL;
+        bdrv_delete(unused);
+    }
+    top->backing_hd = base;
+
+    pstrcpy(top->backing_file, sizeof(top->backing_file), "");
+    pstrcpy(top->backing_format, sizeof(top->backing_format), "");
+    if (base_id) {
+        pstrcpy(top->backing_file, sizeof(top->backing_file), base_id);
+        if (base->drv) {
+            pstrcpy(top->backing_format, sizeof(top->backing_format),
+                    base->drv->format_name);
+        }
+    }
+
+}
+
 /*
  * Given an image chain: [BASE] -> [INTER1] -> [INTER2] -> [TOP]
  *
@@ -223,6 +256,7 @@ retry:
             base_id = s->backing_file_id;
         }
         ret = bdrv_change_backing_file(bs, base_id, NULL);
+        close_unused_images(bs, base, base_id);
     }
 
     qemu_vfree(buf);
commit 28d3d1658a3692f9c34c3ecce14941faa1d2fe92
Author: Stefan Weil <sw at weilnetz.de>
Date:   Wed Mar 14 19:57:24 2012 +0100

    qemu-iotests: Fix call syntax for qemu-io
    
    qemu-io requires options first, then fixed parameters.
    
    GNU getopt also allows options at the end, but POSIX getopt
    doesn't. Try "export POSIXLY_CORRECT=y" to get the POSIX
    behaviour with GNU getopt, too.
    
    Cc: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/tests/qemu-iotests/009 b/tests/qemu-iotests/009
index f7262b5..25368c8 100755
--- a/tests/qemu-iotests/009
+++ b/tests/qemu-iotests/009
@@ -53,10 +53,10 @@ _make_test_img $size
 echo
 echo "creating pattern"
 $QEMU_IO \
-	-c "write 2048k 4k -P 65" \
+	-c "write -P 65 2048k 4k" \
 	-c "write 4k 4k" \
 	-c "write 9M 4k" \
-	-c "read 2044k 8k -P 65 -s 4k -l 4k" \
+	-c "read -P 65 -s 4k -l 4k 2044k 8k" \
 $TEST_IMG | _filter_qemu_io
 
 echo
diff --git a/tests/qemu-iotests/010 b/tests/qemu-iotests/010
index e3205aa..7b57929 100755
--- a/tests/qemu-iotests/010
+++ b/tests/qemu-iotests/010
@@ -53,11 +53,11 @@ _make_test_img $size
 echo
 echo "creating pattern"
 $QEMU_IO \
-	-c "write 2048k 4k -P 165" \
+	-c "write -P 165 2048k 4k" \
 	-c "write 64k 4k" \
 	-c "write 9M 4k" \
-	-c "write 2044k 4k -P 165" \
-	-c "write 8M 4k -P 99" \
+	-c "write -P 165 2044k 4k" \
+	-c "write -P 99 8M 4k" \
 	-c "read -P 165 2044k 8k" \
 $TEST_IMG | _filter_qemu_io
 
diff --git a/tests/qemu-iotests/011 b/tests/qemu-iotests/011
index 59df1ae..b03df68 100755
--- a/tests/qemu-iotests/011
+++ b/tests/qemu-iotests/011
@@ -60,7 +60,7 @@ for i in `seq 1 10`; do
     # Note that we filter away the actual offset.  That's because qemu
     # may re-order the two aio requests.  We only want to make sure the
     # filesystem isn't corrupted afterwards anyway.
-    $QEMU_IO $TEST_IMG -c "aio_write $off1 1M" -c "aio_write $off2 1M" | \
+    $QEMU_IO -c "aio_write $off1 1M" -c "aio_write $off2 1M" $TEST_IMG | \
     	_filter_qemu_io | \
 	sed -e 's/bytes at offset [0-9]*/bytes at offset XXX/g'
 done
commit 21af81488799e2290cb2e58eb2a91d1d8044ebc4
Author: Stefan Weil <sw at weilnetz.de>
Date:   Wed Mar 14 19:57:23 2012 +0100

    qemu-iotests: Fix call syntax for qemu-img
    
    qemu-img requires first options, then file name, then size.
    
    GNU getopt also allows options at the end, but POSIX getopt
    doesn't. Try "export POSIXLY_CORRECT=y" to get the POSIX
    behaviour with GNU getopt, too.
    
    Cc: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index 26811ca..4cb8dae 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -57,16 +57,21 @@ _make_test_img()
 {
     # extra qemu-img options can be added by tests
     # at least one argument (the image size) needs to be added
-    local extra_img_options=$*
+    local extra_img_options=""
     local cluster_size_filter="s# cluster_size=[0-9]\\+##g"
+    local image_size=$*
 
+    if [ "$1" = "-b" ]; then
+        extra_img_options="$1 $2"
+        image_size=$3
+    fi
     if [ \( "$IMGFMT" = "qcow2" -o "$IMGFMT" = "qed" \) -a -n "$CLUSTER_SIZE" ]; then
         extra_img_options="-o cluster_size=$CLUSTER_SIZE $extra_img_options"
         cluster_size_filter=""
     fi
 
     # XXX(hch): have global image options?
-    $QEMU_IMG create -f $IMGFMT $TEST_IMG $extra_img_options | \
+    $QEMU_IMG create -f $IMGFMT $extra_img_options $TEST_IMG $image_size | \
     	sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" | \
     	sed -e "s#$TEST_DIR#TEST_DIR#g" | \
     	sed -e "s#$IMGFMT#IMGFMT#g" | \
commit f394f1feb921d5a4b278e7ac95bdaa49e34a52f2
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu Feb 16 16:55:01 2012 +0100

    qemu-iotests: Test unknown qcow2 header extensions
    
    The immportant thing here is that header extensions don't get silently
    dropped when the header is rewritten, e.g. during a rebase.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/tests/qemu-iotests/031 b/tests/qemu-iotests/031
new file mode 100755
index 0000000..6365f28
--- /dev/null
+++ b/tests/qemu-iotests/031
@@ -0,0 +1,72 @@
+#!/bin/bash
+#
+# Test that all qcow2 header extensions survive a header rewrite
+#
+# Copyright (C) 2011 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=kwolf at redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+
+_cleanup()
+{
+	_cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.pattern
+
+# This tests qcow2-specific low-level functionality
+_supported_fmt qcow2
+_supported_proto generic
+_supported_os Linux
+
+CLUSTER_SIZE=65536
+echo
+echo === Create image with unknown header extension ===
+echo
+_make_test_img 64M
+./qcow2.py $TEST_IMG add-header-ext 0x12345678 "This is a test header extension"
+./qcow2.py $TEST_IMG dump-header
+_check_test_img
+
+echo
+echo === Rewrite header with no backing file ===
+echo
+$QEMU_IMG rebase -u -b "" $TEST_IMG
+./qcow2.py $TEST_IMG dump-header
+_check_test_img
+
+echo
+echo === Add a backing file and format ===
+echo
+$QEMU_IMG rebase -u -b "/some/backing/file/path" -F host_device $TEST_IMG
+./qcow2.py $TEST_IMG dump-header
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/031.out b/tests/qemu-iotests/031.out
new file mode 100644
index 0000000..0f1bf68
--- /dev/null
+++ b/tests/qemu-iotests/031.out
@@ -0,0 +1,76 @@
+QA output created by 031
+
+=== Create image with unknown header extension ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 cluster_size=65536 
+magic                     0x514649fb
+version                   2
+backing_file_offset       0x0
+backing_file_size         0x0
+cluster_bits              16
+size                      67108864
+crypt_method              0
+l1_size                   1
+l1_table_offset           0x30000
+refcount_table_offset     0x10000
+refcount_table_clusters   1
+nb_snapshots              0
+snapshot_offset           0x0
+
+Header extension:
+magic                     0x12345678
+length                    31
+data                      'This is a test header extension'
+
+No errors were found on the image.
+
+=== Rewrite header with no backing file ===
+
+magic                     0x514649fb
+version                   2
+backing_file_offset       0x0
+backing_file_size         0x0
+cluster_bits              16
+size                      67108864
+crypt_method              0
+l1_size                   1
+l1_table_offset           0x30000
+refcount_table_offset     0x10000
+refcount_table_clusters   1
+nb_snapshots              0
+snapshot_offset           0x0
+
+Header extension:
+magic                     0x12345678
+length                    31
+data                      'This is a test header extension'
+
+No errors were found on the image.
+
+=== Add a backing file and format ===
+
+magic                     0x514649fb
+version                   2
+backing_file_offset       0x90
+backing_file_size         0x17
+cluster_bits              16
+size                      67108864
+crypt_method              0
+l1_size                   1
+l1_table_offset           0x30000
+refcount_table_offset     0x10000
+refcount_table_clusters   1
+nb_snapshots              0
+snapshot_offset           0x0
+
+Header extension:
+magic                     0xe2792aca
+length                    11
+data                      'host_device'
+
+Header extension:
+magic                     0x12345678
+length                    31
+data                      'This is a test header extension'
+
+*** done
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index b549f10..1742ede 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -37,3 +37,4 @@
 028 rw backing auto
 029 rw auto quick
 030 rw auto
+031 rw auto quick
commit 6e19b3c4e0b40b08ccb550a0c0a65798f3a17ac8
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Feb 15 16:36:03 2012 +0100

    qemu-iotests: qcow2.py
    
    This adds a tool that is meant to inspect and edit qcow2 files in a
    low-level way, that wouldn't be possible with qemu-img/io, for example
    by adding yet unknown extensions or flags. This way we can test whether
    qemu deals properly with future backwards compatible extensions.
    
    For now, let's start with the image header and header extensions.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py
new file mode 100755
index 0000000..bfb47e8
--- /dev/null
+++ b/tests/qemu-iotests/qcow2.py
@@ -0,0 +1,207 @@
+#!/usr/bin/env python
+
+import sys
+import struct
+import string
+
+class QcowHeaderExtension:
+
+    def __init__(self, magic, length, data):
+        self.magic  = magic
+        self.length = length
+        self.data   = data
+
+    @classmethod
+    def create(cls, magic, data):
+        return QcowHeaderExtension(magic, len(data), data)
+
+class QcowHeader:
+
+    uint32_t = 'I'
+    uint64_t = 'Q'
+
+    fields = [
+        # Version 2 header fields
+        [ uint32_t, '%#x',  'magic' ],
+        [ uint32_t, '%d',   'version' ],
+        [ uint64_t, '%#x',  'backing_file_offset' ],
+        [ uint32_t, '%#x',  'backing_file_size' ],
+        [ uint32_t, '%d',   'cluster_bits' ],
+        [ uint64_t, '%d',   'size' ],
+        [ uint32_t, '%d',   'crypt_method' ],
+        [ uint32_t, '%d',   'l1_size' ],
+        [ uint64_t, '%#x',  'l1_table_offset' ],
+        [ uint64_t, '%#x',  'refcount_table_offset' ],
+        [ uint32_t, '%d',   'refcount_table_clusters' ],
+        [ uint32_t, '%d',   'nb_snapshots' ],
+        [ uint64_t, '%#x',  'snapshot_offset' ],
+    ];
+
+    fmt = '>' + ''.join(field[0] for field in fields)
+
+    def __init__(self, fd):
+
+        buf_size = struct.calcsize(QcowHeader.fmt)
+
+        fd.seek(0)
+        buf = fd.read(buf_size)
+
+        header = struct.unpack(QcowHeader.fmt, buf)
+        self.__dict__ = dict((field[2], header[i])
+            for i, field in enumerate(QcowHeader.fields))
+
+        self.cluster_size = 1 << self.cluster_bits
+
+        fd.seek(self.get_header_length())
+        self.load_extensions(fd)
+
+        if self.backing_file_offset:
+            fd.seek(self.backing_file_offset)
+            self.backing_file = fd.read(self.backing_file_size)
+        else:
+            self.backing_file = None
+
+    def get_header_length(self):
+        if self.version == 2:
+            return 72
+        else:
+            raise Exception("version != 2 not supported")
+
+    def load_extensions(self, fd):
+        self.extensions = []
+
+        if self.backing_file_offset != 0:
+            end = min(self.cluster_size, self.backing_file_offset)
+        else:
+            end = self.cluster_size
+
+        while fd.tell() < end:
+            (magic, length) = struct.unpack('>II', fd.read(8))
+            if magic == 0:
+                break
+            else:
+                padded = (length + 7) & ~7
+                data = fd.read(padded)
+                self.extensions.append(QcowHeaderExtension(magic, length, data))
+
+    def update_extensions(self, fd):
+
+        fd.seek(self.get_header_length())
+        extensions = self.extensions
+        extensions.append(QcowHeaderExtension(0, 0, ""))
+        for ex in extensions:
+            buf = struct.pack('>II', ex.magic, ex.length)
+            fd.write(buf)
+            fd.write(ex.data)
+
+        if self.backing_file != None:
+            self.backing_file_offset = fd.tell()
+            fd.write(self.backing_file)
+
+        if fd.tell() > self.cluster_size:
+            raise Exception("I think I just broke the image...")
+
+
+    def update(self, fd):
+        header_bytes = self.get_header_length()
+
+        self.update_extensions(fd)
+
+        fd.seek(0)
+        header = tuple(self.__dict__[f] for t, p, f in QcowHeader.fields)
+        buf = struct.pack(QcowHeader.fmt, *header)
+        buf = buf[0:header_bytes-1]
+        fd.write(buf)
+
+    def dump(self):
+        for f in QcowHeader.fields:
+            print "%-25s" % f[2], f[1] % self.__dict__[f[2]]
+        print ""
+
+    def dump_extensions(self):
+        for ex in self.extensions:
+
+            data = ex.data[:ex.length]
+            if all(c in string.printable for c in data):
+                data = "'%s'" % data
+            else:
+                data = "<binary>"
+
+            print "Header extension:"
+            print "%-25s %#x" % ("magic", ex.magic)
+            print "%-25s %d" % ("length", ex.length)
+            print "%-25s %s" % ("data", data)
+            print ""
+
+
+def cmd_dump_header(fd):
+    h = QcowHeader(fd)
+    h.dump()
+    h.dump_extensions()
+
+def cmd_add_header_ext(fd, magic, data):
+    try:
+        magic = int(magic, 0)
+    except:
+        print "'%s' is not a valid magic number" % magic
+        sys.exit(1)
+
+    h = QcowHeader(fd)
+    h.extensions.append(QcowHeaderExtension.create(magic, data))
+    h.update(fd)
+
+def cmd_del_header_ext(fd, magic):
+    try:
+        magic = int(magic, 0)
+    except:
+        print "'%s' is not a valid magic number" % magic
+        sys.exit(1)
+
+    h = QcowHeader(fd)
+    found = False
+
+    for ex in h.extensions:
+        if ex.magic == magic:
+            found = True
+            h.extensions.remove(ex)
+
+    if not found:
+        print "No such header extension"
+        return
+
+    h.update(fd)
+
+cmds = [
+    [ 'dump-header',    cmd_dump_header,    0, 'Dump image header and header extensions' ],
+    [ 'add-header-ext', cmd_add_header_ext, 2, 'Add a header extension' ],
+    [ 'del-header-ext', cmd_del_header_ext, 1, 'Delete a header extension' ],
+]
+
+def main(filename, cmd, args):
+    fd = open(filename, "r+b")
+    try:
+        for name, handler, num_args, desc in cmds:
+            if name != cmd:
+                continue
+            elif len(args) != num_args:
+                usage()
+                return
+            else:
+                handler(fd, *args)
+                return
+        print "Unknown command '%s'" % cmd
+    finally:
+        fd.close()
+
+def usage():
+    print "Usage: %s <file> <cmd> [<arg>, ...]" % sys.argv[0]
+    print ""
+    print "Supported commands:"
+    for name, handler, num_args, desc in cmds:
+        print "    %-20s - %s" % (name, desc)
+
+if len(sys.argv) < 3:
+    usage()
+    sys.exit(1)
+
+main(sys.argv[1], sys.argv[2], sys.argv[3:])
commit eb09218077a495bc55d84de91f448f72fe78a60b
Author: Liu Yuan <tailai.ly at taobao.com>
Date:   Tue Apr 3 18:04:21 2012 +0800

    sheepdog: fix send req helpers
    
    We should return if reading of the header fails.
    
    Cc: Kevin Wolf <kwolf at redhat.com>
    Cc: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
    Signed-off-by: Liu Yuan <tailai.ly at taobao.com>
    Acked-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 1248534..3eaf625 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -510,6 +510,7 @@ static int send_req(int sockfd, SheepdogReq *hdr, void *data,
     ret = qemu_send_full(sockfd, hdr, sizeof(*hdr), 0);
     if (ret < sizeof(*hdr)) {
         error_report("failed to send a req, %s", strerror(errno));
+        return ret;
     }
 
     ret = qemu_send_full(sockfd, data, *wlen, 0);
@@ -528,6 +529,7 @@ static int send_co_req(int sockfd, SheepdogReq *hdr, void *data,
     ret = qemu_co_send(sockfd, hdr, sizeof(*hdr));
     if (ret < sizeof(*hdr)) {
         error_report("failed to send a req, %s", strerror(errno));
+        return ret;
     }
 
     ret = qemu_co_send(sockfd, data, *wlen);
commit 47622c44d0d9a717c1a8f7f5fec6c25ff3b30eec
Author: Liu Yuan <tailai.ly at taobao.com>
Date:   Wed Apr 4 04:03:58 2012 +0800

    sheepdog: implement SD_OP_FLUSH_VDI operation
    
    Flush operation is supposed to flush the write-back cache of
    sheepdog cluster.
    
    By issuing flush operation, we can assure the Guest of data
    reaching the sheepdog cluster storage.
    
    Cc: Kevin Wolf <kwolf at redhat.com>
    Cc: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
    Signed-off-by: Liu Yuan <tailai.ly at taobao.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/sheepdog.c b/block/sheepdog.c
index 00276f6..1248534 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -32,9 +32,11 @@
 #define SD_OP_RELEASE_VDI    0x13
 #define SD_OP_GET_VDI_INFO   0x14
 #define SD_OP_READ_VDIS      0x15
+#define SD_OP_FLUSH_VDI      0x16
 
 #define SD_FLAG_CMD_WRITE    0x01
 #define SD_FLAG_CMD_COW      0x02
+#define SD_FLAG_CMD_CACHE    0x04
 
 #define SD_RES_SUCCESS       0x00 /* Success */
 #define SD_RES_UNKNOWN       0x01 /* Unknown error */
@@ -293,10 +295,12 @@ typedef struct BDRVSheepdogState {
 
     char name[SD_MAX_VDI_LEN];
     int is_snapshot;
+    uint8_t cache_enabled;
 
     char *addr;
     char *port;
     int fd;
+    int flush_fd;
 
     CoMutex lock;
     Coroutine *co_send;
@@ -516,6 +520,23 @@ static int send_req(int sockfd, SheepdogReq *hdr, void *data,
     return ret;
 }
 
+static int send_co_req(int sockfd, SheepdogReq *hdr, void *data,
+                       unsigned int *wlen)
+{
+    int ret;
+
+    ret = qemu_co_send(sockfd, hdr, sizeof(*hdr));
+    if (ret < sizeof(*hdr)) {
+        error_report("failed to send a req, %s", strerror(errno));
+    }
+
+    ret = qemu_co_send(sockfd, data, *wlen);
+    if (ret < *wlen) {
+        error_report("failed to send a req, %s", strerror(errno));
+    }
+
+    return ret;
+}
 static int do_req(int sockfd, SheepdogReq *hdr, void *data,
                   unsigned int *wlen, unsigned int *rlen)
 {
@@ -550,6 +571,40 @@ out:
     return ret;
 }
 
+static int do_co_req(int sockfd, SheepdogReq *hdr, void *data,
+                     unsigned int *wlen, unsigned int *rlen)
+{
+    int ret;
+
+    socket_set_block(sockfd);
+    ret = send_co_req(sockfd, hdr, data, wlen);
+    if (ret < 0) {
+        goto out;
+    }
+
+    ret = qemu_co_recv(sockfd, hdr, sizeof(*hdr));
+    if (ret < sizeof(*hdr)) {
+        error_report("failed to get a rsp, %s", strerror(errno));
+        goto out;
+    }
+
+    if (*rlen > hdr->data_length) {
+        *rlen = hdr->data_length;
+    }
+
+    if (*rlen) {
+        ret = qemu_co_recv(sockfd, data, *rlen);
+        if (ret < *rlen) {
+            error_report("failed to get the data, %s", strerror(errno));
+            goto out;
+        }
+    }
+    ret = 0;
+out:
+    socket_set_nonblock(sockfd);
+    return ret;
+}
+
 static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
                            struct iovec *iov, int niov, int create,
                            enum AIOCBState aiocb_type);
@@ -900,6 +955,10 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
         hdr.flags = SD_FLAG_CMD_WRITE | flags;
     }
 
+    if (s->cache_enabled) {
+        hdr.flags |= SD_FLAG_CMD_CACHE;
+    }
+
     hdr.oid = oid;
     hdr.cow_oid = old_oid;
     hdr.copies = s->inode.nr_copies;
@@ -942,7 +1001,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
 
 static int read_write_object(int fd, char *buf, uint64_t oid, int copies,
                              unsigned int datalen, uint64_t offset,
-                             int write, int create)
+                             int write, int create, uint8_t cache)
 {
     SheepdogObjReq hdr;
     SheepdogObjRsp *rsp = (SheepdogObjRsp *)&hdr;
@@ -965,6 +1024,11 @@ static int read_write_object(int fd, char *buf, uint64_t oid, int copies,
         rlen = datalen;
         hdr.opcode = SD_OP_READ_OBJ;
     }
+
+    if (cache) {
+        hdr.flags |= SD_FLAG_CMD_CACHE;
+    }
+
     hdr.oid = oid;
     hdr.data_length = datalen;
     hdr.offset = offset;
@@ -986,15 +1050,18 @@ static int read_write_object(int fd, char *buf, uint64_t oid, int copies,
 }
 
 static int read_object(int fd, char *buf, uint64_t oid, int copies,
-                       unsigned int datalen, uint64_t offset)
+                       unsigned int datalen, uint64_t offset, uint8_t cache)
 {
-    return read_write_object(fd, buf, oid, copies, datalen, offset, 0, 0);
+    return read_write_object(fd, buf, oid, copies, datalen, offset, 0, 0,
+                             cache);
 }
 
 static int write_object(int fd, char *buf, uint64_t oid, int copies,
-                        unsigned int datalen, uint64_t offset, int create)
+                        unsigned int datalen, uint64_t offset, int create,
+                        uint8_t cache)
 {
-    return read_write_object(fd, buf, oid, copies, datalen, offset, 1, create);
+    return read_write_object(fd, buf, oid, copies, datalen, offset, 1, create,
+                             cache);
 }
 
 static int sd_open(BlockDriverState *bs, const char *filename, int flags)
@@ -1026,6 +1093,15 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags)
         goto out;
     }
 
+    if (flags & BDRV_O_CACHE_WB) {
+        s->cache_enabled = 1;
+        s->flush_fd = connect_to_sdog(s->addr, s->port);
+        if (s->flush_fd < 0) {
+            error_report("failed to connect");
+            goto out;
+        }
+    }
+
     if (snapid) {
         dprintf("%" PRIx32 " snapshot inode was open.\n", vid);
         s->is_snapshot = 1;
@@ -1038,7 +1114,8 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags)
     }
 
     buf = g_malloc(SD_INODE_SIZE);
-    ret = read_object(fd, buf, vid_to_vdi_oid(vid), 0, SD_INODE_SIZE, 0);
+    ret = read_object(fd, buf, vid_to_vdi_oid(vid), 0, SD_INODE_SIZE, 0,
+                      s->cache_enabled);
 
     closesocket(fd);
 
@@ -1272,6 +1349,9 @@ static void sd_close(BlockDriverState *bs)
 
     qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL, NULL, NULL);
     closesocket(s->fd);
+    if (s->cache_enabled) {
+        closesocket(s->flush_fd);
+    }
     g_free(s->addr);
 }
 
@@ -1305,7 +1385,7 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
     datalen = SD_INODE_SIZE - sizeof(s->inode.data_vdi_id);
     s->inode.vdi_size = offset;
     ret = write_object(fd, (char *)&s->inode, vid_to_vdi_oid(s->inode.vdi_id),
-                       s->inode.nr_copies, datalen, 0, 0);
+                       s->inode.nr_copies, datalen, 0, 0, s->cache_enabled);
     close(fd);
 
     if (ret < 0) {
@@ -1387,7 +1467,7 @@ static int sd_create_branch(BDRVSheepdogState *s)
     }
 
     ret = read_object(fd, buf, vid_to_vdi_oid(vid), s->inode.nr_copies,
-                      SD_INODE_SIZE, 0);
+                      SD_INODE_SIZE, 0, s->cache_enabled);
 
     closesocket(fd);
 
@@ -1575,6 +1655,36 @@ static coroutine_fn int sd_co_readv(BlockDriverState *bs, int64_t sector_num,
     return acb->ret;
 }
 
+static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs)
+{
+    BDRVSheepdogState *s = bs->opaque;
+    SheepdogObjReq hdr = { 0 };
+    SheepdogObjRsp *rsp = (SheepdogObjRsp *)&hdr;
+    SheepdogInode *inode = &s->inode;
+    int ret;
+    unsigned int wlen = 0, rlen = 0;
+
+    if (!s->cache_enabled) {
+        return 0;
+    }
+
+    hdr.opcode = SD_OP_FLUSH_VDI;
+    hdr.oid = vid_to_vdi_oid(inode->vdi_id);
+
+    ret = do_co_req(s->flush_fd, (SheepdogReq *)&hdr, NULL, &wlen, &rlen);
+    if (ret) {
+        error_report("failed to send a request to the sheep");
+        return ret;
+    }
+
+    if (rsp->result != SD_RES_SUCCESS) {
+        error_report("%s", sd_strerror(rsp->result));
+        return -EIO;
+    }
+
+    return 0;
+}
+
 static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
 {
     BDRVSheepdogState *s = bs->opaque;
@@ -1610,7 +1720,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
     }
 
     ret = write_object(fd, (char *)&s->inode, vid_to_vdi_oid(s->inode.vdi_id),
-                       s->inode.nr_copies, datalen, 0, 0);
+                       s->inode.nr_copies, datalen, 0, 0, s->cache_enabled);
     if (ret < 0) {
         error_report("failed to write snapshot's inode.");
         ret = -EIO;
@@ -1629,7 +1739,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
     inode = (SheepdogInode *)g_malloc(datalen);
 
     ret = read_object(fd, (char *)inode, vid_to_vdi_oid(new_vid),
-                      s->inode.nr_copies, datalen, 0);
+                      s->inode.nr_copies, datalen, 0, s->cache_enabled);
 
     if (ret < 0) {
         error_report("failed to read new inode info. %s", strerror(errno));
@@ -1684,7 +1794,7 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
 
     buf = g_malloc(SD_INODE_SIZE);
     ret = read_object(fd, buf, vid_to_vdi_oid(vid), s->inode.nr_copies,
-                      SD_INODE_SIZE, 0);
+                      SD_INODE_SIZE, 0, s->cache_enabled);
 
     closesocket(fd);
 
@@ -1779,7 +1889,8 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
 
         /* we don't need to read entire object */
         ret = read_object(fd, (char *)&inode, vid_to_vdi_oid(vid),
-                          0, SD_INODE_SIZE - sizeof(inode.data_vdi_id), 0);
+                          0, SD_INODE_SIZE - sizeof(inode.data_vdi_id), 0,
+                          s->cache_enabled);
 
         if (ret) {
             continue;
@@ -1835,10 +1946,12 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
         create = (offset == 0);
         if (load) {
             ret = read_object(fd, (char *)data, vmstate_oid,
-                              s->inode.nr_copies, data_len, offset);
+                              s->inode.nr_copies, data_len, offset,
+                              s->cache_enabled);
         } else {
             ret = write_object(fd, (char *)data, vmstate_oid,
-                               s->inode.nr_copies, data_len, offset, create);
+                               s->inode.nr_copies, data_len, offset, create,
+                               s->cache_enabled);
         }
 
         if (ret < 0) {
@@ -1904,6 +2017,7 @@ BlockDriver bdrv_sheepdog = {
 
     .bdrv_co_readv  = sd_co_readv,
     .bdrv_co_writev = sd_co_writev,
+    .bdrv_co_flush_to_disk  = sd_co_flush_to_disk,
 
     .bdrv_snapshot_create   = sd_snapshot_create,
     .bdrv_snapshot_goto     = sd_snapshot_goto,
commit f6801b83d0e77ca025867800d805ee80f6bda938
Author: Jeff Cody <jcody at redhat.com>
Date:   Tue Mar 27 16:30:19 2012 -0400

    block: bdrv_append() fixes
    
    A few fixups for bdrv_append():
    
    The new bs (bs_new) passed into bdrv_append() should be anonymous.  Rather
    than call bdrv_make_anon() to enforce this, use an assert to catch when a caller
    is passing in a bs_new that is not anonymous.
    
    Also, the new top layer should have its backing_format reflect the original
    top's format.
    
    And last, after the swap of bs contents, the device_name will have been copied
    down. This needs to be cleared to reflect the anonymity of the bs that was
    pushed down.
    
    Signed-off-by: Jeff Cody <jcody at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 33630eb..b3117ef 100644
--- a/block.c
+++ b/block.c
@@ -892,14 +892,16 @@ void bdrv_make_anon(BlockDriverState *bs)
  * This will modify the BlockDriverState fields, and swap contents
  * between bs_new and bs_top. Both bs_new and bs_top are modified.
  *
+ * bs_new is required to be anonymous.
+ *
  * This function does not create any image files.
  */
 void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top)
 {
     BlockDriverState tmp;
 
-    /* the new bs must not be in bdrv_states */
-    bdrv_make_anon(bs_new);
+    /* bs_new must be anonymous */
+    assert(bs_new->device_name[0] == '\0');
 
     tmp = *bs_new;
 
@@ -944,11 +946,18 @@ void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top)
      * swapping bs_new and bs_top contents. */
     tmp.backing_hd = bs_new;
     pstrcpy(tmp.backing_file, sizeof(tmp.backing_file), bs_top->filename);
+    bdrv_get_format(bs_top, tmp.backing_format, sizeof(tmp.backing_format));
 
     /* swap contents of the fixed new bs and the current top */
     *bs_new = *bs_top;
     *bs_top = tmp;
 
+    /* device_name[] was carried over from the old bs_top.  bs_new
+     * shouldn't be in bdrv_states, so we need to make device_name[]
+     * reflect the anonymity of bs_new
+     */
+    bs_new->device_name[0] = '\0';
+
     /* clear the copied fields in the new backing file */
     bdrv_detach_dev(bs_new, bs_new->dev);
 
commit d68dbee80e3964d9bb0ab29ad64675da148c3cac
Author: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
Date:   Thu Mar 15 20:13:34 2012 +0800

    qed: track dirty flag status
    
    Signed-off-by: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
    Reviewed-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 d6c1580..19d87f3 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -1434,6 +1434,7 @@ static int bdrv_qed_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
 
     memset(bdi, 0, sizeof(*bdi));
     bdi->cluster_size = s->header.cluster_size;
+    bdi->is_dirty = s->header.features & QED_F_NEED_CHECK;
     return 0;
 }
 
commit 64c79160b456c2d6aabc63e40b32e392a9ea3c90
Author: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
Date:   Thu Mar 15 20:13:33 2012 +0800

    qemu-img: add dirty flag status
    
    Some block drivers can verify their image files are clean or not. So we can show
    it while using "qemu-img info".
    
    Signed-off-by: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.h b/block.h
index ea12f5d..4e99e18 100644
--- a/block.h
+++ b/block.h
@@ -15,6 +15,7 @@ typedef struct BlockDriverInfo {
     int cluster_size;
     /* offset at which the VM state can be saved (0 if not possible) */
     int64_t vm_state_offset;
+    bool is_dirty;
 } BlockDriverInfo;
 
 typedef struct BlockFragInfo {
diff --git a/qemu-img.c b/qemu-img.c
index 4de48ba..6a61ca8 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1132,6 +1132,9 @@ static int img_info(int argc, char **argv)
         if (bdi.cluster_size != 0) {
             printf("cluster_size: %d\n", bdi.cluster_size);
         }
+        if (bdi.is_dirty) {
+            printf("cleanly shut down: no\n");
+        }
     }
     bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
     if (backing_filename[0] != '\0') {
commit 11c9c615c8e776e59ad0c6c6ed00ec7d38b5d865
Author: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
Date:   Thu Mar 15 20:13:32 2012 +0800

    qed: image fragmentation statistics
    
    Signed-off-by: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qed-check.c b/block/qed-check.c
index e4a49ce..94327ff 100644
--- a/block/qed-check.c
+++ b/block/qed-check.c
@@ -68,6 +68,7 @@ static unsigned int qed_check_l2_table(QEDCheck *check, QEDTable *table)
 {
     BDRVQEDState *s = check->s;
     unsigned int i, num_invalid = 0;
+    uint64_t last_offset = 0;
 
     for (i = 0; i < s->table_nelems; i++) {
         uint64_t offset = table->offsets[i];
@@ -76,6 +77,11 @@ static unsigned int qed_check_l2_table(QEDCheck *check, QEDTable *table)
             qed_offset_is_zero_cluster(offset)) {
             continue;
         }
+        check->result->bfi.allocated_clusters++;
+        if (last_offset && (last_offset + s->header.cluster_size != offset)) {
+            check->result->bfi.fragmented_clusters++;
+        }
+        last_offset = offset;
 
         /* Detect invalid cluster offset */
         if (!qed_check_cluster_offset(s, offset)) {
@@ -200,6 +206,9 @@ int qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix)
     check.used_clusters = g_malloc0(((check.nclusters + 31) / 32) *
                                        sizeof(check.used_clusters[0]));
 
+    check.result->bfi.total_clusters =
+        (s->header.image_size + s->header.cluster_size - 1) /
+            s->header.cluster_size;
     ret = qed_check_l1_table(&check, s->l1_table);
     if (ret == 0) {
         /* Only check for leaks if entire image was scanned successfully */
commit f8111c241afa75544032dcfa23df0699c91f9866
Author: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
Date:   Thu Mar 15 20:13:31 2012 +0800

    qemu-img: add image fragmentation statistics
    
    Discussion can be found at:
    http://patchwork.ozlabs.org/patch/128730/
    
    This patch add image fragmentation statistics while using qemu-img check.
    
    Signed-off-by: Dong Xu Wang <wdongxu at linux.vnet.ibm.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.h b/block.h
index c51ab16..ea12f5d 100644
--- a/block.h
+++ b/block.h
@@ -17,6 +17,12 @@ typedef struct BlockDriverInfo {
     int64_t vm_state_offset;
 } BlockDriverInfo;
 
+typedef struct BlockFragInfo {
+    uint64_t allocated_clusters;
+    uint64_t total_clusters;
+    uint64_t fragmented_clusters;
+} BlockFragInfo;
+
 typedef struct QEMUSnapshotInfo {
     char id_str[128]; /* unique snapshot id */
     /* the following fields are informative. They are not needed for
@@ -175,6 +181,7 @@ typedef struct BdrvCheckResult {
     int corruptions;
     int leaks;
     int check_errors;
+    BlockFragInfo bfi;
 } BdrvCheckResult;
 
 int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res);
diff --git a/qemu-img.c b/qemu-img.c
index 0e48b35..4de48ba 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -428,6 +428,13 @@ static int img_check(int argc, char **argv)
         }
     }
 
+    if (result.bfi.total_clusters != 0 && result.bfi.allocated_clusters != 0) {
+        printf("%" PRId64 "/%" PRId64 "= %0.2f%% allocated, %0.2f%% fragmented\n",
+        result.bfi.allocated_clusters, result.bfi.total_clusters,
+        result.bfi.allocated_clusters * 100.0 / result.bfi.total_clusters,
+        result.bfi.fragmented_clusters * 100.0 / result.bfi.allocated_clusters);
+    }
+
     bdrv_delete(bs);
 
     if (ret < 0 || result.check_errors) {
@@ -716,7 +723,7 @@ static int img_convert(int argc, char **argv)
         ret = -1;
         goto out;
     }
-        
+
     qemu_progress_init(progress, 2.0);
     qemu_progress_print(0, 100);
 
commit dc534f8fc045a51a8eb678ab3d330fba1e9e631c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Mar 30 13:17:13 2012 +0200

    block: document job API
    
    I am not sure that these are really proper GtkDoc, but they follow
    the existing documentation in block_int.h.
    
    Signed-off-by: Paolo Bonzini <pbonzini 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/block_int.h b/block_int.h
index a96aabd..0e5a032 100644
--- a/block_int.h
+++ b/block_int.h
@@ -63,8 +63,13 @@ typedef struct BlockIOBaseValue {
     uint64_t ios[2];
 } BlockIOBaseValue;
 
-typedef void BlockJobCancelFunc(void *opaque);
 typedef struct BlockJob BlockJob;
+
+/**
+ * BlockJobType:
+ *
+ * A class type for block job objects.
+ */
 typedef struct BlockJobType {
     /** Derived BlockJob struct size */
     size_t instance_size;
@@ -77,20 +82,48 @@ typedef struct BlockJobType {
 } BlockJobType;
 
 /**
- * Long-running operation on a BlockDriverState
+ * BlockJob:
+ *
+ * Long-running operation on a BlockDriverState.
  */
 struct BlockJob {
+    /** The job type, including the job vtable.  */
     const BlockJobType *job_type;
+
+    /** The block device on which the job is operating.  */
     BlockDriverState *bs;
+
+    /**
+     * Set to true if the job should cancel itself.  The flag must
+     * always be tested just before toggling the busy flag from false
+     * to true.  After a job has detected that the cancelled flag is
+     * true, it should not anymore issue any I/O operation to the
+     * block device.
+     */
     bool cancelled;
+
+    /**
+     * Set to false by the job while it is in a quiescent state, where
+     * no I/O is pending and cancellation can be processed without
+     * issuing new I/O.  The busy flag must be set to false when the
+     * job goes to sleep on any condition that is not detected by
+     * #qemu_aio_wait, such as a timer.
+     */
     bool busy;
 
-    /* These fields are published by the query-block-jobs QMP API */
+    /** Offset that is published by the query-block-jobs QMP API */
     int64_t offset;
+
+    /** Length that is published by the query-block-jobs QMP API */
     int64_t len;
+
+    /** Speed that was set with @block_job_set_speed.  */
     int64_t speed;
 
+    /** The completion function that will be called when the job completes.  */
     BlockDriverCompletionFunc *cb;
+
+    /** The opaque value that is passed to the completion function.  */
     void *opaque;
 };
 
@@ -306,14 +339,90 @@ void bdrv_set_io_limits(BlockDriverState *bs,
 int is_windows_drive(const char *filename);
 #endif
 
+/**
+ * block_job_create:
+ * @job_type: The class object for the newly-created job.
+ * @bs: The block
+ * @cb: Completion function for the job.
+ * @opaque: Opaque pointer value passed to @cb.
+ *
+ * Create a new long-running block device job and return it.  The job
+ * will call @cb asynchronously when the job completes.  Note that
+ * @bs may have been closed at the time the @cb it is called.  If
+ * this is the case, the job may be reported as either cancelled or
+ * completed.
+ *
+ * This function is not part of the public job interface; it should be
+ * called from a wrapper that is specific to the job type.
+ */
 void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs,
                        BlockDriverCompletionFunc *cb, void *opaque);
+
+/**
+ * block_job_complete:
+ * @job: The job being completed.
+ * @ret: The status code.
+ *
+ * Call the completion function that was registered at creation time, and
+ * free @job.
+ */
 void block_job_complete(BlockJob *job, int ret);
+
+/**
+ * block_job_set_speed:
+ * @job: The job to set the speed for.
+ * @speed: The new value
+ *
+ * Set a rate-limiting parameter for the job; the actual meaning may
+ * vary depending on the job type.
+ */
 int block_job_set_speed(BlockJob *job, int64_t value);
+
+/**
+ * block_job_cancel:
+ * @job: The job to be canceled.
+ *
+ * Asynchronously cancel the specified job.
+ */
 void block_job_cancel(BlockJob *job);
+
+/**
+ * block_job_is_cancelled:
+ * @job: The job being queried.
+ *
+ * Returns whether the job is scheduled for cancellation.
+ */
 bool block_job_is_cancelled(BlockJob *job);
+
+/**
+ * block_job_cancel:
+ * @job: The job to be canceled.
+ *
+ * Asynchronously cancel the job and wait for it to reach a quiescent
+ * state.  Note that the completion callback will still be called
+ * asynchronously, hence it is *not* valid to call #bdrv_delete
+ * immediately after #block_job_cancel_sync.  Users of block jobs
+ * will usually protect the BlockDriverState objects with a reference
+ * count, should this be a concern.
+ */
 void block_job_cancel_sync(BlockJob *job);
 
+/**
+ * stream_start:
+ * @bs: Block device to operate on.
+ * @base: Block device that will become the new base, or %NULL to
+ * flatten the whole backing file chain onto @bs.
+ * @base_id: The file name that will be written to @bs as the new
+ * backing file if the job completes.  Ignored if @base is %NULL.
+ * @cb: Completion function for the job.
+ * @opaque: Opaque pointer value passed to @cb.
+ *
+ * Start a streaming operation on @bs.  Clusters that are unallocated
+ * in @bs, but allocated in any image between @base and @bs (both
+ * exclusive) will be written to @bs.  At the end of a successful
+ * streaming job, the backing file of @bs will be changed to
+ * @base_id in the written image and to @base in the live BlockDriverState.
+ */
 int stream_start(BlockDriverState *bs, BlockDriverState *base,
                  const char *base_id, BlockDriverCompletionFunc *cb,
                  void *opaque);
commit 9f25eccc1cdbe6ee985b7a5954fa621c2012912e
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Mar 30 13:17:12 2012 +0200

    block: set job->speed in block_set_speed
    
    There is no need to do this in every implementation of set_speed
    (even though there is only one right now).
    
    Signed-off-by: Paolo Bonzini <pbonzini 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/block.c b/block.c
index 16e14fa..33630eb 100644
--- a/block.c
+++ b/block.c
@@ -4085,10 +4085,16 @@ void block_job_complete(BlockJob *job, int ret)
 
 int block_job_set_speed(BlockJob *job, int64_t value)
 {
+    int rc;
+
     if (!job->job_type->set_speed) {
         return -ENOTSUP;
     }
-    return job->job_type->set_speed(job, value);
+    rc = job->job_type->set_speed(job, value);
+    if (rc == 0) {
+        job->speed = value;
+    }
+    return rc;
 }
 
 void block_job_cancel(BlockJob *job)
diff --git a/block/stream.c b/block/stream.c
index f186bfd..61ff7a2 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -236,7 +236,6 @@ static int stream_set_speed(BlockJob *job, int64_t value)
     if (value < 0) {
         return -EINVAL;
     }
-    job->speed = value;
     ratelimit_set_speed(&s->limit, value / BDRV_SECTOR_SIZE);
     return 0;
 }
commit 3e914655f268f627ef004a8f1ea0355311b5aca6
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Mar 30 13:17:11 2012 +0200

    block: fix streaming/closing race
    
    Streaming can issue I/O while qcow2_close is running.  This causes the
    L2 caches to become very confused or, alternatively, could cause a
    segfault when the streaming coroutine is reentered after closing its
    block device.  The fix is to cancel streaming jobs when closing their
    underlying device.
    
    The cancellation must be synchronous, on the other hand qemu_aio_wait
    will not restart a coroutine that is sleeping in co_sleep.  So add
    a flag saying whether streaming has in-flight I/O.  If the busy flag
    is false, the coroutine is quiescent and, when cancelled, will not
    issue any new I/O.
    
    This protects streaming against closing, but not against deleting.
    We have a reference count protecting us against concurrent deletion,
    but I still added an assertion to ensure nothing bad happens.
    
    Signed-off-by: Paolo Bonzini <pbonzini 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/block.c b/block.c
index 0344673..16e14fa 100644
--- a/block.c
+++ b/block.c
@@ -813,6 +813,9 @@ unlink_and_fail:
 void bdrv_close(BlockDriverState *bs)
 {
     if (bs->drv) {
+        if (bs->job) {
+            block_job_cancel_sync(bs->job);
+        }
         if (bs == bs_snapshots) {
             bs_snapshots = NULL;
         }
@@ -966,6 +969,8 @@ void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top)
 void bdrv_delete(BlockDriverState *bs)
 {
     assert(!bs->dev);
+    assert(!bs->job);
+    assert(!bs->in_use);
 
     /* remove from list, if necessary */
     bdrv_make_anon(bs);
@@ -4095,3 +4100,14 @@ bool block_job_is_cancelled(BlockJob *job)
 {
     return job->cancelled;
 }
+
+void block_job_cancel_sync(BlockJob *job)
+{
+    BlockDriverState *bs = job->bs;
+
+    assert(bs->job == job);
+    block_job_cancel(job);
+    while (bs->job != NULL && bs->job->busy) {
+        qemu_aio_wait();
+    }
+}
diff --git a/block/stream.c b/block/stream.c
index d1b3986..f186bfd 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -175,7 +175,7 @@ retry:
             break;
         }
 
-
+        s->common.busy = true;
         if (base) {
             ret = is_allocated_base(bs, base, sector_num,
                                     STREAM_BUFFER_SIZE / BDRV_SECTOR_SIZE, &n);
@@ -189,6 +189,7 @@ retry:
             if (s->common.speed) {
                 uint64_t delay_ns = ratelimit_calculate_delay(&s->limit, n);
                 if (delay_ns > 0) {
+                    s->common.busy = false;
                     co_sleep_ns(rt_clock, delay_ns);
 
                     /* Recheck cancellation and that sectors are unallocated */
@@ -208,6 +209,7 @@ retry:
         /* Note that even when no rate limit is applied we need to yield
          * with no pending I/O here so that qemu_aio_flush() returns.
          */
+        s->common.busy = false;
         co_sleep_ns(rt_clock, 0);
     }
 
@@ -215,7 +217,7 @@ retry:
         bdrv_disable_copy_on_read(bs);
     }
 
-    if (sector_num == end && ret == 0) {
+    if (!block_job_is_cancelled(&s->common) && sector_num == end && ret == 0) {
         const char *base_id = NULL;
         if (base) {
             base_id = s->backing_file_id;
diff --git a/block_int.h b/block_int.h
index 22c86a5..a96aabd 100644
--- a/block_int.h
+++ b/block_int.h
@@ -83,6 +83,7 @@ struct BlockJob {
     const BlockJobType *job_type;
     BlockDriverState *bs;
     bool cancelled;
+    bool busy;
 
     /* These fields are published by the query-block-jobs QMP API */
     int64_t offset;
@@ -311,6 +312,7 @@ void block_job_complete(BlockJob *job, int ret);
 int block_job_set_speed(BlockJob *job, int64_t value);
 void block_job_cancel(BlockJob *job);
 bool block_job_is_cancelled(BlockJob *job);
+void block_job_cancel_sync(BlockJob *job);
 
 int stream_start(BlockDriverState *bs, BlockDriverState *base,
                  const char *base_id, BlockDriverCompletionFunc *cb,
commit 12bde0eed6b740787bca2c998a838b20c556d0ec
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Mar 30 13:17:10 2012 +0200

    block: cancel jobs when a device is ready to go away
    
    We do not want jobs to keep a device busy for a possibly very long
    time, and management could become confused because they thought a
    device was not even there anymore.  So, cancel long-running jobs
    as soon as their device is going to disappear.
    
    Signed-off-by: Paolo Bonzini <pbonzini 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 f5e7dba..4d17486 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -64,6 +64,9 @@ void blockdev_mark_auto_del(BlockDriverState *bs)
 {
     DriveInfo *dinfo = drive_get_by_blockdev(bs);
 
+    if (bs->job) {
+        block_job_cancel(bs->job);
+    }
     if (dinfo) {
         dinfo->auto_del = 1;
     }
commit 498e386c58497f621a37301ea6e8ca886f9f2e07
Author: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com>
Date:   Mon Apr 2 18:59:34 2012 +0800

    block: disable I/O throttling on sync api
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 8858be0..0344673 100644
--- a/block.c
+++ b/block.c
@@ -1463,6 +1463,17 @@ static int bdrv_rw_co(BlockDriverState *bs, int64_t sector_num, uint8_t *buf,
 
     qemu_iovec_init_external(&qiov, &iov, 1);
 
+    /**
+     * In sync call context, when the vcpu is blocked, this throttling timer
+     * will not fire; so the I/O throttling function has to be disabled here
+     * if it has been enabled.
+     */
+    if (bs->io_limits_enabled) {
+        fprintf(stderr, "Disabling I/O throttling on '%s' due "
+                        "to synchronous I/O.\n", bdrv_get_device_name(bs));
+        bdrv_io_limits_disable(bs);
+    }
+
     if (qemu_in_coroutine()) {
         /* Fast-path if already in coroutine context */
         bdrv_rw_co_entry(&rwco);
@@ -1969,10 +1980,19 @@ static int guess_disk_lchs(BlockDriverState *bs,
     struct partition *p;
     uint32_t nr_sects;
     uint64_t nb_sectors;
+    bool enabled;
 
     bdrv_get_geometry(bs, &nb_sectors);
 
+    /**
+     * The function will be invoked during startup not only in sync I/O mode,
+     * but also in async I/O mode. So the I/O throttling function has to
+     * be disabled temporarily here, not permanently.
+     */
+    enabled = bs->io_limits_enabled;
+    bs->io_limits_enabled = false;
     ret = bdrv_read(bs, 0, buf, 1);
+    bs->io_limits_enabled = enabled;
     if (ret < 0)
         return -1;
     /* test msdos magic */
commit 43cf8ae69ba8510e45d7bd42dd67bc8ae13c48ec
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 27 13:42:23 2012 +1100

    Use DMADirection type for dma_bdrv_io
    
    Currently dma_bdrv_io() takes a 'to_dev' boolean parameter to
    determine the direction of DMA it is emulating.  We already have a
    DMADirection enum designed specifically to encode DMA directions.
    This patch uses it for dma_bdrv_io() as well.  This involves removing
    the DMADirection definition from the #ifdef it was inside, but since that
    only existed to protect the definition of dma_addr_t from places where
    config.h is not included, there wasn't any reason for it to be there in
    the first place.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/dma-helpers.c b/dma-helpers.c
index 7fcc86d..7971a89 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -41,7 +41,7 @@ typedef struct {
     BlockDriverAIOCB *acb;
     QEMUSGList *sg;
     uint64_t sector_num;
-    bool to_dev;
+    DMADirection dir;
     bool in_cancel;
     int sg_cur_index;
     dma_addr_t sg_cur_byte;
@@ -75,7 +75,8 @@ static void dma_bdrv_unmap(DMAAIOCB *dbs)
 
     for (i = 0; i < dbs->iov.niov; ++i) {
         cpu_physical_memory_unmap(dbs->iov.iov[i].iov_base,
-                                  dbs->iov.iov[i].iov_len, !dbs->to_dev,
+                                  dbs->iov.iov[i].iov_len,
+                                  dbs->dir != DMA_DIRECTION_TO_DEVICE,
                                   dbs->iov.iov[i].iov_len);
     }
     qemu_iovec_reset(&dbs->iov);
@@ -122,7 +123,8 @@ static void dma_bdrv_cb(void *opaque, int ret)
     while (dbs->sg_cur_index < dbs->sg->nsg) {
         cur_addr = dbs->sg->sg[dbs->sg_cur_index].base + dbs->sg_cur_byte;
         cur_len = dbs->sg->sg[dbs->sg_cur_index].len - dbs->sg_cur_byte;
-        mem = cpu_physical_memory_map(cur_addr, &cur_len, !dbs->to_dev);
+        mem = cpu_physical_memory_map(cur_addr, &cur_len,
+                                      dbs->dir != DMA_DIRECTION_TO_DEVICE);
         if (!mem)
             break;
         qemu_iovec_add(&dbs->iov, mem, cur_len);
@@ -169,11 +171,11 @@ static AIOPool dma_aio_pool = {
 BlockDriverAIOCB *dma_bdrv_io(
     BlockDriverState *bs, QEMUSGList *sg, uint64_t sector_num,
     DMAIOFunc *io_func, BlockDriverCompletionFunc *cb,
-    void *opaque, bool to_dev)
+    void *opaque, DMADirection dir)
 {
     DMAAIOCB *dbs = qemu_aio_get(&dma_aio_pool, bs, cb, opaque);
 
-    trace_dma_bdrv_io(dbs, bs, sector_num, to_dev);
+    trace_dma_bdrv_io(dbs, bs, sector_num, (dir == DMA_DIRECTION_TO_DEVICE));
 
     dbs->acb = NULL;
     dbs->bs = bs;
@@ -181,7 +183,7 @@ BlockDriverAIOCB *dma_bdrv_io(
     dbs->sector_num = sector_num;
     dbs->sg_cur_index = 0;
     dbs->sg_cur_byte = 0;
-    dbs->to_dev = to_dev;
+    dbs->dir = dir;
     dbs->io_func = io_func;
     dbs->bh = NULL;
     qemu_iovec_init(&dbs->iov, sg->nsg);
@@ -194,14 +196,16 @@ BlockDriverAIOCB *dma_bdrv_read(BlockDriverState *bs,
                                 QEMUSGList *sg, uint64_t sector,
                                 void (*cb)(void *opaque, int ret), void *opaque)
 {
-    return dma_bdrv_io(bs, sg, sector, bdrv_aio_readv, cb, opaque, false);
+    return dma_bdrv_io(bs, sg, sector, bdrv_aio_readv, cb, opaque,
+                       DMA_DIRECTION_FROM_DEVICE);
 }
 
 BlockDriverAIOCB *dma_bdrv_write(BlockDriverState *bs,
                                  QEMUSGList *sg, uint64_t sector,
                                  void (*cb)(void *opaque, int ret), void *opaque)
 {
-    return dma_bdrv_io(bs, sg, sector, bdrv_aio_writev, cb, opaque, true);
+    return dma_bdrv_io(bs, sg, sector, bdrv_aio_writev, cb, opaque,
+                       DMA_DIRECTION_TO_DEVICE);
 }
 
 
diff --git a/dma.h b/dma.h
index 20e86d2..05ac325 100644
--- a/dma.h
+++ b/dma.h
@@ -17,6 +17,11 @@
 
 typedef struct ScatterGatherEntry ScatterGatherEntry;
 
+typedef enum {
+    DMA_DIRECTION_TO_DEVICE = 0,
+    DMA_DIRECTION_FROM_DEVICE = 1,
+} DMADirection;
+
 struct QEMUSGList {
     ScatterGatherEntry *sg;
     int nsg;
@@ -29,11 +34,6 @@ typedef target_phys_addr_t dma_addr_t;
 
 #define DMA_ADDR_FMT TARGET_FMT_plx
 
-typedef enum {
-    DMA_DIRECTION_TO_DEVICE = 0,
-    DMA_DIRECTION_FROM_DEVICE = 1,
-} DMADirection;
-
 struct ScatterGatherEntry {
     dma_addr_t base;
     dma_addr_t len;
@@ -51,7 +51,7 @@ typedef BlockDriverAIOCB *DMAIOFunc(BlockDriverState *bs, int64_t sector_num,
 BlockDriverAIOCB *dma_bdrv_io(BlockDriverState *bs,
                               QEMUSGList *sg, uint64_t sector_num,
                               DMAIOFunc *io_func, BlockDriverCompletionFunc *cb,
-                              void *opaque, bool to_dev);
+                              void *opaque, DMADirection dir);
 BlockDriverAIOCB *dma_bdrv_read(BlockDriverState *bs,
                                 QEMUSGList *sg, uint64_t sector,
                                 BlockDriverCompletionFunc *cb, void *opaque);
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 6e25338..35723fd 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -618,7 +618,8 @@ void ide_dma_cb(void *opaque, int ret)
         break;
     case IDE_DMA_TRIM:
         s->bus->dma->aiocb = dma_bdrv_io(s->bs, &s->sg, sector_num,
-                                         ide_issue_trim, ide_dma_cb, s, true);
+                                         ide_issue_trim, ide_dma_cb, s,
+                                         DMA_DIRECTION_TO_DEVICE);
         break;
     }
     return;
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index a4df244..7b38d9e 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -149,7 +149,8 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
         break;
     case IDE_DMA_TRIM:
         m->aiocb = dma_bdrv_io(s->bs, &s->sg, sector_num,
-                               ide_issue_trim, pmac_ide_transfer_cb, s, true);
+                               ide_issue_trim, pmac_ide_transfer_cb, s,
+                               DMA_DIRECTION_TO_DEVICE);
         break;
     }
     return;
commit eb9566d13e30dd7e20d978632a13915cbdb9a668
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Mar 19 18:07:51 2012 +0100

    vdi: change goto to loop
    
    Finally reindent all code and change goto statements to a loop.
    
    Acked-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vdi.c b/block/vdi.c
index bfeafea..119d3c7 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -474,41 +474,38 @@ static int vdi_co_read(BlockDriverState *bs,
     uint32_t block_index;
     uint32_t sector_in_block;
     uint32_t n_sectors;
-    int ret;
+    int ret = 0;
 
     logout("\n");
 
-restart:
-    block_index = sector_num / s->block_sectors;
-    sector_in_block = sector_num % s->block_sectors;
-    n_sectors = s->block_sectors - sector_in_block;
-    if (n_sectors > nb_sectors) {
-        n_sectors = nb_sectors;
-    }
-
-    logout("will read %u sectors starting at sector %" PRIu64 "\n",
-           n_sectors, sector_num);
+    while (ret >= 0 && nb_sectors > 0) {
+        block_index = sector_num / s->block_sectors;
+        sector_in_block = sector_num % s->block_sectors;
+        n_sectors = s->block_sectors - sector_in_block;
+        if (n_sectors > nb_sectors) {
+            n_sectors = nb_sectors;
+        }
 
-    /* prepare next AIO request */
-    bmap_entry = le32_to_cpu(s->bmap[block_index]);
-    if (!VDI_IS_ALLOCATED(bmap_entry)) {
-        /* Block not allocated, return zeros, no need to wait. */
-        memset(buf, 0, n_sectors * SECTOR_SIZE);
-        ret = 0;
-    } else {
-        uint64_t offset = s->header.offset_data / SECTOR_SIZE +
-                          (uint64_t)bmap_entry * s->block_sectors +
-                          sector_in_block;
-        ret = bdrv_read(bs->file, offset, buf, n_sectors);
-    }
-    logout("%u sectors read\n", n_sectors);
+        logout("will read %u sectors starting at sector %" PRIu64 "\n",
+               n_sectors, sector_num);
 
-    nb_sectors -= n_sectors;
-    sector_num += n_sectors;
-    buf += n_sectors * SECTOR_SIZE;
+        /* prepare next AIO request */
+        bmap_entry = le32_to_cpu(s->bmap[block_index]);
+        if (!VDI_IS_ALLOCATED(bmap_entry)) {
+            /* Block not allocated, return zeros, no need to wait. */
+            memset(buf, 0, n_sectors * SECTOR_SIZE);
+            ret = 0;
+        } else {
+            uint64_t offset = s->header.offset_data / SECTOR_SIZE +
+                              (uint64_t)bmap_entry * s->block_sectors +
+                              sector_in_block;
+            ret = bdrv_read(bs->file, offset, buf, n_sectors);
+        }
+        logout("%u sectors read\n", n_sectors);
 
-    if (ret >= 0 && nb_sectors > 0) {
-        goto restart;
+        nb_sectors -= n_sectors;
+        sector_num += n_sectors;
+        buf += n_sectors * SECTOR_SIZE;
     }
 
     return ret;
@@ -525,57 +522,55 @@ static int vdi_co_write(BlockDriverState *bs,
     uint32_t bmap_first = VDI_UNALLOCATED;
     uint32_t bmap_last = VDI_UNALLOCATED;
     uint8_t *block = NULL;
-    int ret;
+    int ret = 0;
 
     logout("\n");
 
-restart:
-    block_index = sector_num / s->block_sectors;
-    sector_in_block = sector_num % s->block_sectors;
-    n_sectors = s->block_sectors - sector_in_block;
-    if (n_sectors > nb_sectors) {
-        n_sectors = nb_sectors;
-    }
-
-    logout("will write %u sectors starting at sector %" PRIu64 "\n",
-           n_sectors, sector_num);
+    while (ret >= 0 && nb_sectors > 0) {
+        block_index = sector_num / s->block_sectors;
+        sector_in_block = sector_num % s->block_sectors;
+        n_sectors = s->block_sectors - sector_in_block;
+        if (n_sectors > nb_sectors) {
+            n_sectors = nb_sectors;
+        }
 
-    /* prepare next AIO request */
-    bmap_entry = le32_to_cpu(s->bmap[block_index]);
-    if (!VDI_IS_ALLOCATED(bmap_entry)) {
-        /* Allocate new block and write to it. */
-        uint64_t offset;
-        bmap_entry = s->header.blocks_allocated;
-        s->bmap[block_index] = cpu_to_le32(bmap_entry);
-        s->header.blocks_allocated++;
-        offset = s->header.offset_data / SECTOR_SIZE +
-                 (uint64_t)bmap_entry * s->block_sectors;
-        if (block == NULL) {
-            block = g_malloc(s->block_size);
-            bmap_first = block_index;
+        logout("will write %u sectors starting at sector %" PRIu64 "\n",
+               n_sectors, sector_num);
+
+        /* prepare next AIO request */
+        bmap_entry = le32_to_cpu(s->bmap[block_index]);
+        if (!VDI_IS_ALLOCATED(bmap_entry)) {
+            /* Allocate new block and write to it. */
+            uint64_t offset;
+            bmap_entry = s->header.blocks_allocated;
+            s->bmap[block_index] = cpu_to_le32(bmap_entry);
+            s->header.blocks_allocated++;
+            offset = s->header.offset_data / SECTOR_SIZE +
+                     (uint64_t)bmap_entry * s->block_sectors;
+            if (block == NULL) {
+                block = g_malloc(s->block_size);
+                bmap_first = block_index;
+            }
+            bmap_last = block_index;
+            /* Copy data to be written to new block and zero unused parts. */
+            memset(block, 0, sector_in_block * SECTOR_SIZE);
+            memcpy(block + sector_in_block * SECTOR_SIZE,
+                   buf, n_sectors * SECTOR_SIZE);
+            memset(block + (sector_in_block + n_sectors) * SECTOR_SIZE, 0,
+                   (s->block_sectors - n_sectors - sector_in_block) * SECTOR_SIZE);
+            ret = bdrv_write(bs->file, offset, block, s->block_sectors);
+        } else {
+            uint64_t offset = s->header.offset_data / SECTOR_SIZE +
+                              (uint64_t)bmap_entry * s->block_sectors +
+                              sector_in_block;
+            ret = bdrv_write(bs->file, offset, buf, n_sectors);
         }
-        bmap_last = block_index;
-        /* Copy data to be written to new block and zero unused parts. */
-        memset(block, 0, sector_in_block * SECTOR_SIZE);
-        memcpy(block + sector_in_block * SECTOR_SIZE,
-               buf, n_sectors * SECTOR_SIZE);
-        memset(block + (sector_in_block + n_sectors) * SECTOR_SIZE, 0,
-               (s->block_sectors - n_sectors - sector_in_block) * SECTOR_SIZE);
-        ret = bdrv_write(bs->file, offset, block, s->block_sectors);
-    } else {
-        uint64_t offset = s->header.offset_data / SECTOR_SIZE +
-                          (uint64_t)bmap_entry * s->block_sectors +
-                          sector_in_block;
-        ret = bdrv_write(bs->file, offset, buf, n_sectors);
-    }
 
-    nb_sectors -= n_sectors;
-    sector_num += n_sectors;
-    buf += n_sectors * SECTOR_SIZE;
+        nb_sectors -= n_sectors;
+        sector_num += n_sectors;
+        buf += n_sectors * SECTOR_SIZE;
 
-    logout("%u sectors written\n", n_sectors);
-    if (ret >= 0 && nb_sectors > 0) {
-        goto restart;
+        logout("%u sectors written\n", n_sectors);
     }
 
     logout("finished data write\n");
commit 4eea78e6345518bfe87493d8b163e1e268e64f74
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Mar 19 18:07:50 2012 +0100

    vdi: do not create useless iovecs
    
    Reads and writes to the underlying file can also occur with the simple
    non-vectored I/O interfaces.
    
    Acked-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vdi.c b/block/vdi.c
index 790b61e..bfeafea 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -474,8 +474,6 @@ static int vdi_co_read(BlockDriverState *bs,
     uint32_t block_index;
     uint32_t sector_in_block;
     uint32_t n_sectors;
-    struct iovec hd_iov;
-    QEMUIOVector hd_qiov;
     int ret;
 
     logout("\n");
@@ -501,10 +499,7 @@ restart:
         uint64_t offset = s->header.offset_data / SECTOR_SIZE +
                           (uint64_t)bmap_entry * s->block_sectors +
                           sector_in_block;
-        hd_iov.iov_base = (void *)buf;
-        hd_iov.iov_len = n_sectors * SECTOR_SIZE;
-        qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
-        ret = bdrv_co_readv(bs->file, offset, n_sectors, &hd_qiov);
+        ret = bdrv_read(bs->file, offset, buf, n_sectors);
     }
     logout("%u sectors read\n", n_sectors);
 
@@ -529,8 +524,6 @@ static int vdi_co_write(BlockDriverState *bs,
     uint32_t n_sectors;
     uint32_t bmap_first = VDI_UNALLOCATED;
     uint32_t bmap_last = VDI_UNALLOCATED;
-    struct iovec hd_iov;
-    QEMUIOVector hd_qiov;
     uint8_t *block = NULL;
     int ret;
 
@@ -568,18 +561,12 @@ restart:
                buf, n_sectors * SECTOR_SIZE);
         memset(block + (sector_in_block + n_sectors) * SECTOR_SIZE, 0,
                (s->block_sectors - n_sectors - sector_in_block) * SECTOR_SIZE);
-        hd_iov.iov_base = (void *)block;
-        hd_iov.iov_len = s->block_size;
-        qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
-        ret = bdrv_co_writev(bs->file, offset, s->block_sectors, &hd_qiov);
+        ret = bdrv_write(bs->file, offset, block, s->block_sectors);
     } else {
         uint64_t offset = s->header.offset_data / SECTOR_SIZE +
                           (uint64_t)bmap_entry * s->block_sectors +
                           sector_in_block;
-        hd_iov.iov_base = (void *)buf;
-        hd_iov.iov_len = n_sectors * SECTOR_SIZE;
-        qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
-        ret = bdrv_co_writev(bs->file, offset, n_sectors, &hd_qiov);
+        ret = bdrv_write(bs->file, offset, buf, n_sectors);
     }
 
     nb_sectors -= n_sectors;
@@ -592,39 +579,39 @@ restart:
     }
 
     logout("finished data write\n");
-    if (ret >= 0) {
-        ret = 0;
-        if (block) {
-            VdiHeader *header = (VdiHeader *) block;
-            logout("now writing modified header\n");
-            assert(VDI_IS_ALLOCATED(bmap_first));
-            *header = s->header;
-            vdi_header_to_le(header);
-            hd_iov.iov_base = block;
-            hd_iov.iov_len = SECTOR_SIZE;
-            qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
-            ret = bdrv_co_writev(bs->file, 0, 1, &hd_qiov);
-        }
+    if (ret < 0) {
+        return ret;
+    }
+
+    if (block) {
+        /* One or more new blocks were allocated. */
+        VdiHeader *header = (VdiHeader *) block;
+        uint8_t *base;
+        uint64_t offset;
+
+        logout("now writing modified header\n");
+        assert(VDI_IS_ALLOCATED(bmap_first));
+        *header = s->header;
+        vdi_header_to_le(header);
+        ret = bdrv_write(bs->file, 0, block, 1);
         g_free(block);
         block = NULL;
-        if (ret >= 0 && VDI_IS_ALLOCATED(bmap_first)) {
-            /* One or more new blocks were allocated. */
-            uint64_t offset;
-            logout("now writing modified block map entry %u...%u\n",
-                   bmap_first, bmap_last);
-            /* Write modified sectors from block map. */
-            bmap_first /= (SECTOR_SIZE / sizeof(uint32_t));
-            bmap_last /= (SECTOR_SIZE / sizeof(uint32_t));
-            n_sectors = bmap_last - bmap_first + 1;
-            offset = s->bmap_sector + bmap_first;
-            hd_iov.iov_base = (void *)((uint8_t *)&s->bmap[0] +
-                                            bmap_first * SECTOR_SIZE);
-            hd_iov.iov_len = n_sectors * SECTOR_SIZE;
-            qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
-            logout("will write %u block map sectors starting from entry %u\n",
-                   n_sectors, bmap_first);
-            ret = bdrv_co_writev(bs->file, offset, n_sectors, &hd_qiov);
+
+        if (ret < 0) {
+            return ret;
         }
+
+        logout("now writing modified block map entry %u...%u\n",
+               bmap_first, bmap_last);
+        /* Write modified sectors from block map. */
+        bmap_first /= (SECTOR_SIZE / sizeof(uint32_t));
+        bmap_last /= (SECTOR_SIZE / sizeof(uint32_t));
+        n_sectors = bmap_last - bmap_first + 1;
+        offset = s->bmap_sector + bmap_first;
+        base = ((uint8_t *)&s->bmap[0]) + bmap_first * SECTOR_SIZE;
+        logout("will write %u block map sectors starting from entry %u\n",
+               n_sectors, bmap_first);
+        ret = bdrv_write(bs->file, offset, base, n_sectors);
     }
 
     return ret;
commit a7a43aa199571a336b76a9a9310c95476c6dc5c4
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Mar 19 18:07:49 2012 +0100

    vdi: leave bounce buffering to block layer
    
    vdi.c really works as if it implemented bdrv_read and bdrv_write.  However,
    because only vector I/O is supported by the asynchronous callbacks, it
    went through extra pain to bounce-buffer the I/O.  This can be handled
    by the block layer now that the format is coroutine-based.
    
    Acked-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vdi.c b/block/vdi.c
index 0c1cff6..790b61e 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -144,12 +144,6 @@ void uuid_unparse(const uuid_t uu, char *out)
 #endif
 
 typedef struct {
-    BlockDriverAIOCB common;
-    uint8_t *buf;
-    void *orig_buf;
-} VdiAIOCB;
-
-typedef struct {
     char text[0x40];
     uint32_t signature;
     uint32_t version;
@@ -472,31 +466,9 @@ static int coroutine_fn vdi_co_is_allocated(BlockDriverState *bs,
     return VDI_IS_ALLOCATED(bmap_entry);
 }
 
-static AIOPool vdi_aio_pool = {
-    .aiocb_size = sizeof(VdiAIOCB),
-};
-
-static VdiAIOCB *vdi_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov)
+static int vdi_co_read(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors)
 {
-    VdiAIOCB *acb;
-
-    logout("%p, %p\n", bs, qiov);
-
-    acb = qemu_aio_get(&vdi_aio_pool, bs, NULL, NULL);
-
-    if (qiov->niov > 1) {
-        acb->buf = qemu_blockalign(bs, qiov->size);
-        acb->orig_buf = acb->buf;
-    } else {
-        acb->buf = (uint8_t *)qiov->iov->iov_base;
-    }
-    return acb;
-}
-
-static int vdi_co_readv(BlockDriverState *bs,
-        int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
-{
-    VdiAIOCB *acb;
     BDRVVdiState *s = bs->opaque;
     uint32_t bmap_entry;
     uint32_t block_index;
@@ -507,7 +479,6 @@ static int vdi_co_readv(BlockDriverState *bs,
     int ret;
 
     logout("\n");
-    acb = vdi_aio_setup(bs, qiov);
 
 restart:
     block_index = sector_num / s->block_sectors;
@@ -524,13 +495,13 @@ restart:
     bmap_entry = le32_to_cpu(s->bmap[block_index]);
     if (!VDI_IS_ALLOCATED(bmap_entry)) {
         /* Block not allocated, return zeros, no need to wait. */
-        memset(acb->buf, 0, n_sectors * SECTOR_SIZE);
+        memset(buf, 0, n_sectors * SECTOR_SIZE);
         ret = 0;
     } else {
         uint64_t offset = s->header.offset_data / SECTOR_SIZE +
                           (uint64_t)bmap_entry * s->block_sectors +
                           sector_in_block;
-        hd_iov.iov_base = (void *)acb->buf;
+        hd_iov.iov_base = (void *)buf;
         hd_iov.iov_len = n_sectors * SECTOR_SIZE;
         qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
         ret = bdrv_co_readv(bs->file, offset, n_sectors, &hd_qiov);
@@ -539,24 +510,18 @@ restart:
 
     nb_sectors -= n_sectors;
     sector_num += n_sectors;
-    acb->buf += n_sectors * SECTOR_SIZE;
+    buf += n_sectors * SECTOR_SIZE;
 
     if (ret >= 0 && nb_sectors > 0) {
         goto restart;
     }
 
-    if (acb->orig_buf) {
-        qemu_iovec_from_buffer(qiov, acb->orig_buf, qiov->size);
-        qemu_vfree(acb->orig_buf);
-    }
-    qemu_aio_release(acb);
     return ret;
 }
 
-static int vdi_co_writev(BlockDriverState *bs,
-        int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
+static int vdi_co_write(BlockDriverState *bs,
+        int64_t sector_num, const uint8_t *buf, int nb_sectors)
 {
-    VdiAIOCB *acb;
     BDRVVdiState *s = bs->opaque;
     uint32_t bmap_entry;
     uint32_t block_index;
@@ -570,10 +535,6 @@ static int vdi_co_writev(BlockDriverState *bs,
     int ret;
 
     logout("\n");
-    acb = vdi_aio_setup(bs, qiov);
-    if (acb->orig_buf) {
-        qemu_iovec_to_buffer(qiov, acb->buf);
-    }
 
 restart:
     block_index = sector_num / s->block_sectors;
@@ -604,7 +565,7 @@ restart:
         /* Copy data to be written to new block and zero unused parts. */
         memset(block, 0, sector_in_block * SECTOR_SIZE);
         memcpy(block + sector_in_block * SECTOR_SIZE,
-               acb->buf, n_sectors * SECTOR_SIZE);
+               buf, n_sectors * SECTOR_SIZE);
         memset(block + (sector_in_block + n_sectors) * SECTOR_SIZE, 0,
                (s->block_sectors - n_sectors - sector_in_block) * SECTOR_SIZE);
         hd_iov.iov_base = (void *)block;
@@ -615,7 +576,7 @@ restart:
         uint64_t offset = s->header.offset_data / SECTOR_SIZE +
                           (uint64_t)bmap_entry * s->block_sectors +
                           sector_in_block;
-        hd_iov.iov_base = (void *)acb->buf;
+        hd_iov.iov_base = (void *)buf;
         hd_iov.iov_len = n_sectors * SECTOR_SIZE;
         qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
         ret = bdrv_co_writev(bs->file, offset, n_sectors, &hd_qiov);
@@ -623,7 +584,7 @@ restart:
 
     nb_sectors -= n_sectors;
     sector_num += n_sectors;
-    acb->buf += n_sectors * SECTOR_SIZE;
+    buf += n_sectors * SECTOR_SIZE;
 
     logout("%u sectors written\n", n_sectors);
     if (ret >= 0 && nb_sectors > 0) {
@@ -666,10 +627,6 @@ restart:
         }
     }
 
-    if (acb->orig_buf) {
-        qemu_vfree(acb->orig_buf);
-    }
-    qemu_aio_release(acb);
     return ret;
 }
 
@@ -821,9 +778,9 @@ static BlockDriver bdrv_vdi = {
     .bdrv_co_is_allocated = vdi_co_is_allocated,
     .bdrv_make_empty = vdi_make_empty,
 
-    .bdrv_co_readv = vdi_co_readv,
+    .bdrv_read = vdi_co_read,
 #if defined(CONFIG_VDI_WRITE)
-    .bdrv_co_writev = vdi_co_writev,
+    .bdrv_write = vdi_co_write,
 #endif
 
     .bdrv_get_info = vdi_get_info,
commit bfc45fc183619eb4f76e3979598a510f41cd88e3
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Mar 19 18:07:48 2012 +0100

    vdi: move aiocb fields to locals
    
    Most of the AIOCB really holds local variables that need to persist
    across callback invocation.  It can go away now.
    
    Acked-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vdi.c b/block/vdi.c
index 407fccc..0c1cff6 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -145,24 +145,8 @@ void uuid_unparse(const uuid_t uu, char *out)
 
 typedef struct {
     BlockDriverAIOCB common;
-    int64_t sector_num;
-    QEMUIOVector *qiov;
     uint8_t *buf;
-    /* Total number of sectors. */
-    int nb_sectors;
-    /* Number of sectors for current AIO. */
-    int n_sectors;
-    /* New allocated block map entry. */
-    uint32_t bmap_first;
-    uint32_t bmap_last;
-    /* Buffer for new allocated block. */
-    void *block_buffer;
     void *orig_buf;
-    bool is_write;
-    int header_modified;
-    struct iovec hd_iov;
-    QEMUIOVector hd_qiov;
-    QEMUBH *bh;
 } VdiAIOCB;
 
 typedef struct {
@@ -492,34 +476,20 @@ static AIOPool vdi_aio_pool = {
     .aiocb_size = sizeof(VdiAIOCB),
 };
 
-static VdiAIOCB *vdi_aio_setup(BlockDriverState *bs, int64_t sector_num,
-        QEMUIOVector *qiov, int nb_sectors, int is_write)
+static VdiAIOCB *vdi_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov)
 {
     VdiAIOCB *acb;
 
-    logout("%p, %" PRId64 ", %p, %d, %p, %p, %d\n",
-           bs, sector_num, qiov, nb_sectors, is_write);
+    logout("%p, %p\n", bs, qiov);
 
     acb = qemu_aio_get(&vdi_aio_pool, bs, NULL, NULL);
-    acb->sector_num = sector_num;
-    acb->qiov = qiov;
-    acb->is_write = is_write;
 
     if (qiov->niov > 1) {
         acb->buf = qemu_blockalign(bs, qiov->size);
         acb->orig_buf = acb->buf;
-        if (is_write) {
-            qemu_iovec_to_buffer(qiov, acb->buf);
-        }
     } else {
         acb->buf = (uint8_t *)qiov->iov->iov_base;
     }
-    acb->nb_sectors = nb_sectors;
-    acb->n_sectors = 0;
-    acb->bmap_first = VDI_UNALLOCATED;
-    acb->bmap_last = VDI_UNALLOCATED;
-    acb->block_buffer = NULL;
-    acb->header_modified = 0;
     return acb;
 }
 
@@ -532,24 +502,25 @@ static int vdi_co_readv(BlockDriverState *bs,
     uint32_t block_index;
     uint32_t sector_in_block;
     uint32_t n_sectors;
+    struct iovec hd_iov;
+    QEMUIOVector hd_qiov;
     int ret;
 
     logout("\n");
-    acb = vdi_aio_setup(bs, sector_num, qiov, nb_sectors, 0);
+    acb = vdi_aio_setup(bs, qiov);
 
 restart:
-    block_index = acb->sector_num / s->block_sectors;
-    sector_in_block = acb->sector_num % s->block_sectors;
+    block_index = sector_num / s->block_sectors;
+    sector_in_block = sector_num % s->block_sectors;
     n_sectors = s->block_sectors - sector_in_block;
-    if (n_sectors > acb->nb_sectors) {
-        n_sectors = acb->nb_sectors;
+    if (n_sectors > nb_sectors) {
+        n_sectors = nb_sectors;
     }
 
     logout("will read %u sectors starting at sector %" PRIu64 "\n",
-           n_sectors, acb->sector_num);
+           n_sectors, sector_num);
 
     /* prepare next AIO request */
-    acb->n_sectors = n_sectors;
     bmap_entry = le32_to_cpu(s->bmap[block_index]);
     if (!VDI_IS_ALLOCATED(bmap_entry)) {
         /* Block not allocated, return zeros, no need to wait. */
@@ -559,23 +530,23 @@ restart:
         uint64_t offset = s->header.offset_data / SECTOR_SIZE +
                           (uint64_t)bmap_entry * s->block_sectors +
                           sector_in_block;
-        acb->hd_iov.iov_base = (void *)acb->buf;
-        acb->hd_iov.iov_len = n_sectors * SECTOR_SIZE;
-        qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-        ret = bdrv_co_readv(bs->file, offset, n_sectors, &acb->hd_qiov);
+        hd_iov.iov_base = (void *)acb->buf;
+        hd_iov.iov_len = n_sectors * SECTOR_SIZE;
+        qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
+        ret = bdrv_co_readv(bs->file, offset, n_sectors, &hd_qiov);
     }
-    logout("%u sectors read\n", acb->n_sectors);
+    logout("%u sectors read\n", n_sectors);
 
-    acb->nb_sectors -= acb->n_sectors;
-    acb->sector_num += acb->n_sectors;
-    acb->buf += acb->n_sectors * SECTOR_SIZE;
+    nb_sectors -= n_sectors;
+    sector_num += n_sectors;
+    acb->buf += n_sectors * SECTOR_SIZE;
 
-    if (ret >= 0 && acb->nb_sectors > 0) {
+    if (ret >= 0 && nb_sectors > 0) {
         goto restart;
     }
 
-    if (acb->qiov->niov > 1) {
-        qemu_iovec_from_buffer(acb->qiov, acb->orig_buf, acb->qiov->size);
+    if (acb->orig_buf) {
+        qemu_iovec_from_buffer(qiov, acb->orig_buf, qiov->size);
         qemu_vfree(acb->orig_buf);
     }
     qemu_aio_release(acb);
@@ -591,96 +562,93 @@ static int vdi_co_writev(BlockDriverState *bs,
     uint32_t block_index;
     uint32_t sector_in_block;
     uint32_t n_sectors;
+    uint32_t bmap_first = VDI_UNALLOCATED;
+    uint32_t bmap_last = VDI_UNALLOCATED;
+    struct iovec hd_iov;
+    QEMUIOVector hd_qiov;
+    uint8_t *block = NULL;
     int ret;
 
     logout("\n");
-    acb = vdi_aio_setup(bs, sector_num, qiov, nb_sectors, 1);
+    acb = vdi_aio_setup(bs, qiov);
+    if (acb->orig_buf) {
+        qemu_iovec_to_buffer(qiov, acb->buf);
+    }
 
 restart:
-    block_index = acb->sector_num / s->block_sectors;
-    sector_in_block = acb->sector_num % s->block_sectors;
+    block_index = sector_num / s->block_sectors;
+    sector_in_block = sector_num % s->block_sectors;
     n_sectors = s->block_sectors - sector_in_block;
-    if (n_sectors > acb->nb_sectors) {
-        n_sectors = acb->nb_sectors;
+    if (n_sectors > nb_sectors) {
+        n_sectors = nb_sectors;
     }
 
     logout("will write %u sectors starting at sector %" PRIu64 "\n",
-           n_sectors, acb->sector_num);
+           n_sectors, sector_num);
 
     /* prepare next AIO request */
-    acb->n_sectors = n_sectors;
     bmap_entry = le32_to_cpu(s->bmap[block_index]);
     if (!VDI_IS_ALLOCATED(bmap_entry)) {
         /* Allocate new block and write to it. */
         uint64_t offset;
-        uint8_t *block;
         bmap_entry = s->header.blocks_allocated;
         s->bmap[block_index] = cpu_to_le32(bmap_entry);
         s->header.blocks_allocated++;
         offset = s->header.offset_data / SECTOR_SIZE +
                  (uint64_t)bmap_entry * s->block_sectors;
-        block = acb->block_buffer;
         if (block == NULL) {
             block = g_malloc(s->block_size);
-            acb->block_buffer = block;
-            acb->bmap_first = block_index;
-            assert(!acb->header_modified);
-            acb->header_modified = 1;
+            bmap_first = block_index;
         }
-        acb->bmap_last = block_index;
+        bmap_last = block_index;
         /* Copy data to be written to new block and zero unused parts. */
         memset(block, 0, sector_in_block * SECTOR_SIZE);
         memcpy(block + sector_in_block * SECTOR_SIZE,
                acb->buf, n_sectors * SECTOR_SIZE);
         memset(block + (sector_in_block + n_sectors) * SECTOR_SIZE, 0,
                (s->block_sectors - n_sectors - sector_in_block) * SECTOR_SIZE);
-        acb->hd_iov.iov_base = (void *)block;
-        acb->hd_iov.iov_len = s->block_size;
-        qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-        ret = bdrv_co_writev(bs->file, offset, s->block_sectors, &acb->hd_qiov);
+        hd_iov.iov_base = (void *)block;
+        hd_iov.iov_len = s->block_size;
+        qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
+        ret = bdrv_co_writev(bs->file, offset, s->block_sectors, &hd_qiov);
     } else {
         uint64_t offset = s->header.offset_data / SECTOR_SIZE +
                           (uint64_t)bmap_entry * s->block_sectors +
                           sector_in_block;
-        acb->hd_iov.iov_base = (void *)acb->buf;
-        acb->hd_iov.iov_len = n_sectors * SECTOR_SIZE;
-        qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-        ret = bdrv_co_writev(bs->file, offset, n_sectors, &acb->hd_qiov);
+        hd_iov.iov_base = (void *)acb->buf;
+        hd_iov.iov_len = n_sectors * SECTOR_SIZE;
+        qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
+        ret = bdrv_co_writev(bs->file, offset, n_sectors, &hd_qiov);
     }
 
-    acb->nb_sectors -= acb->n_sectors;
-    acb->sector_num += acb->n_sectors;
-    acb->buf += acb->n_sectors * SECTOR_SIZE;
+    nb_sectors -= n_sectors;
+    sector_num += n_sectors;
+    acb->buf += n_sectors * SECTOR_SIZE;
 
-    logout("%u sectors written\n", acb->n_sectors);
-    if (ret >= 0 && acb->nb_sectors > 0) {
+    logout("%u sectors written\n", n_sectors);
+    if (ret >= 0 && nb_sectors > 0) {
         goto restart;
     }
 
     logout("finished data write\n");
     if (ret >= 0) {
         ret = 0;
-        if (acb->header_modified) {
-            VdiHeader *header = acb->block_buffer;
+        if (block) {
+            VdiHeader *header = (VdiHeader *) block;
             logout("now writing modified header\n");
-            assert(VDI_IS_ALLOCATED(acb->bmap_first));
+            assert(VDI_IS_ALLOCATED(bmap_first));
             *header = s->header;
             vdi_header_to_le(header);
-            acb->header_modified = 0;
-            acb->hd_iov.iov_base = acb->block_buffer;
-            acb->hd_iov.iov_len = SECTOR_SIZE;
-            qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-            ret = bdrv_co_writev(bs->file, 0, 1, &acb->hd_qiov);
+            hd_iov.iov_base = block;
+            hd_iov.iov_len = SECTOR_SIZE;
+            qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
+            ret = bdrv_co_writev(bs->file, 0, 1, &hd_qiov);
         }
-        if (ret >= 0 && VDI_IS_ALLOCATED(acb->bmap_first)) {
+        g_free(block);
+        block = NULL;
+        if (ret >= 0 && VDI_IS_ALLOCATED(bmap_first)) {
             /* One or more new blocks were allocated. */
             uint64_t offset;
-            uint32_t bmap_first;
-            uint32_t bmap_last;
-            g_free(acb->block_buffer);
-            acb->block_buffer = NULL;
-            bmap_first = acb->bmap_first;
-            bmap_last = acb->bmap_last;
             logout("now writing modified block map entry %u...%u\n",
                    bmap_first, bmap_last);
             /* Write modified sectors from block map. */
@@ -688,18 +656,17 @@ restart:
             bmap_last /= (SECTOR_SIZE / sizeof(uint32_t));
             n_sectors = bmap_last - bmap_first + 1;
             offset = s->bmap_sector + bmap_first;
-            acb->bmap_first = VDI_UNALLOCATED;
-            acb->hd_iov.iov_base = (void *)((uint8_t *)&s->bmap[0] +
+            hd_iov.iov_base = (void *)((uint8_t *)&s->bmap[0] +
                                             bmap_first * SECTOR_SIZE);
-            acb->hd_iov.iov_len = n_sectors * SECTOR_SIZE;
-            qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
+            hd_iov.iov_len = n_sectors * SECTOR_SIZE;
+            qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
             logout("will write %u block map sectors starting from entry %u\n",
                    n_sectors, bmap_first);
-            ret = bdrv_co_writev(bs->file, offset, n_sectors, &acb->hd_qiov);
+            ret = bdrv_co_writev(bs->file, offset, n_sectors, &hd_qiov);
         }
     }
 
-    if (acb->qiov->niov > 1) {
+    if (acb->orig_buf) {
         qemu_vfree(acb->orig_buf);
     }
     qemu_aio_release(acb);
commit 4de659e8eb75df995310c5e57018c5a089c8fc6f
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Mar 19 18:07:47 2012 +0100

    vdi: merge aio_read_cb and aio_write_cb into callers
    
    Now inline the former AIO callbacks into vdi_co_readv and vdi_co_writev.
    While many cleanups are possible, the code now really looks synchronous.
    
    Acked-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vdi.c b/block/vdi.c
index df0f431..407fccc 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -523,15 +523,19 @@ static VdiAIOCB *vdi_aio_setup(BlockDriverState *bs, int64_t sector_num,
     return acb;
 }
 
-static int vdi_aio_read_cb(void *opaque, int ret)
+static int vdi_co_readv(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
 {
-    VdiAIOCB *acb = opaque;
-    BlockDriverState *bs = acb->common.bs;
+    VdiAIOCB *acb;
     BDRVVdiState *s = bs->opaque;
     uint32_t bmap_entry;
     uint32_t block_index;
     uint32_t sector_in_block;
     uint32_t n_sectors;
+    int ret;
+
+    logout("\n");
+    acb = vdi_aio_setup(bs, sector_num, qiov, nb_sectors, 0);
 
 restart:
     block_index = acb->sector_num / s->block_sectors;
@@ -578,27 +582,19 @@ restart:
     return ret;
 }
 
-static int vdi_co_readv(BlockDriverState *bs,
+static int vdi_co_writev(BlockDriverState *bs,
         int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
 {
     VdiAIOCB *acb;
-    int ret;
-
-    logout("\n");
-    acb = vdi_aio_setup(bs, sector_num, qiov, nb_sectors, 0);
-    ret = vdi_aio_read_cb(acb, 0);
-    return ret;
-}
-
-static int vdi_aio_write_cb(void *opaque, int ret)
-{
-    VdiAIOCB *acb = opaque;
-    BlockDriverState *bs = acb->common.bs;
     BDRVVdiState *s = bs->opaque;
     uint32_t bmap_entry;
     uint32_t block_index;
     uint32_t sector_in_block;
     uint32_t n_sectors;
+    int ret;
+
+    logout("\n");
+    acb = vdi_aio_setup(bs, sector_num, qiov, nb_sectors, 1);
 
 restart:
     block_index = acb->sector_num / s->block_sectors;
@@ -710,18 +706,6 @@ restart:
     return ret;
 }
 
-static int vdi_co_writev(BlockDriverState *bs,
-        int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
-{
-    VdiAIOCB *acb;
-    int ret;
-
-    logout("\n");
-    acb = vdi_aio_setup(bs, sector_num, qiov, nb_sectors, 1);
-    ret = vdi_aio_write_cb(acb, 0);
-    return ret;
-}
-
 static int vdi_create(const char *filename, QEMUOptionParameter *options)
 {
     int fd;
commit 0c7bfc321b4d19c91a59f1ff7b31418e67b8681a
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Mar 19 18:07:46 2012 +0100

    vdi: move end-of-I/O handling at the end
    
    The next step is to take code that only triggers after the first operation,
    and move it at the end of vdi_aio_read_cb and vdi_aio_write_cb.
    
    Acked-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vdi.c b/block/vdi.c
index 5fd8700..df0f431 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -533,20 +533,7 @@ static int vdi_aio_read_cb(void *opaque, int ret)
     uint32_t sector_in_block;
     uint32_t n_sectors;
 
-    logout("%u sectors read\n", acb->n_sectors);
-
 restart:
-    acb->nb_sectors -= acb->n_sectors;
-
-    if (acb->nb_sectors == 0) {
-        /* request completed */
-        ret = 0;
-        goto done;
-    }
-
-    acb->sector_num += acb->n_sectors;
-    acb->buf += acb->n_sectors * SECTOR_SIZE;
-
     block_index = acb->sector_num / s->block_sectors;
     sector_in_block = acb->sector_num % s->block_sectors;
     n_sectors = s->block_sectors - sector_in_block;
@@ -573,11 +560,16 @@ restart:
         qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
         ret = bdrv_co_readv(bs->file, offset, n_sectors, &acb->hd_qiov);
     }
-    if (ret >= 0) {
+    logout("%u sectors read\n", acb->n_sectors);
+
+    acb->nb_sectors -= acb->n_sectors;
+    acb->sector_num += acb->n_sectors;
+    acb->buf += acb->n_sectors * SECTOR_SIZE;
+
+    if (ret >= 0 && acb->nb_sectors > 0) {
         goto restart;
     }
 
-done:
     if (acb->qiov->niov > 1) {
         qemu_iovec_from_buffer(acb->qiov, acb->orig_buf, acb->qiov->size);
         qemu_vfree(acb->orig_buf);
@@ -609,56 +601,6 @@ static int vdi_aio_write_cb(void *opaque, int ret)
     uint32_t n_sectors;
 
 restart:
-    acb->nb_sectors -= acb->n_sectors;
-    acb->sector_num += acb->n_sectors;
-    acb->buf += acb->n_sectors * SECTOR_SIZE;
-
-    if (acb->nb_sectors == 0) {
-        logout("finished data write\n");
-        acb->n_sectors = 0;
-        ret = 0;
-        if (acb->header_modified) {
-            VdiHeader *header = acb->block_buffer;
-            logout("now writing modified header\n");
-            assert(VDI_IS_ALLOCATED(acb->bmap_first));
-            *header = s->header;
-            vdi_header_to_le(header);
-            acb->header_modified = 0;
-            acb->hd_iov.iov_base = acb->block_buffer;
-            acb->hd_iov.iov_len = SECTOR_SIZE;
-            qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-            ret = bdrv_co_writev(bs->file, 0, 1, &acb->hd_qiov);
-        }
-        if (ret >= 0 && VDI_IS_ALLOCATED(acb->bmap_first)) {
-            /* One or more new blocks were allocated. */
-            uint64_t offset;
-            uint32_t bmap_first;
-            uint32_t bmap_last;
-            g_free(acb->block_buffer);
-            acb->block_buffer = NULL;
-            bmap_first = acb->bmap_first;
-            bmap_last = acb->bmap_last;
-            logout("now writing modified block map entry %u...%u\n",
-                   bmap_first, bmap_last);
-            /* Write modified sectors from block map. */
-            bmap_first /= (SECTOR_SIZE / sizeof(uint32_t));
-            bmap_last /= (SECTOR_SIZE / sizeof(uint32_t));
-            n_sectors = bmap_last - bmap_first + 1;
-            offset = s->bmap_sector + bmap_first;
-            acb->bmap_first = VDI_UNALLOCATED;
-            acb->hd_iov.iov_base = (void *)((uint8_t *)&s->bmap[0] +
-                                            bmap_first * SECTOR_SIZE);
-            acb->hd_iov.iov_len = n_sectors * SECTOR_SIZE;
-            qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-            logout("will write %u block map sectors starting from entry %u\n",
-                   n_sectors, bmap_first);
-            ret = bdrv_co_writev(bs->file, offset, n_sectors, &acb->hd_qiov);
-        }
-        goto done;
-    }
-
-    logout("%u sectors written\n", acb->n_sectors);
-
     block_index = acb->sector_num / s->block_sectors;
     sector_in_block = acb->sector_num % s->block_sectors;
     n_sectors = s->block_sectors - sector_in_block;
@@ -709,11 +651,58 @@ restart:
         qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
         ret = bdrv_co_writev(bs->file, offset, n_sectors, &acb->hd_qiov);
     }
-    if (ret >= 0) {
+
+    acb->nb_sectors -= acb->n_sectors;
+    acb->sector_num += acb->n_sectors;
+    acb->buf += acb->n_sectors * SECTOR_SIZE;
+
+    logout("%u sectors written\n", acb->n_sectors);
+    if (ret >= 0 && acb->nb_sectors > 0) {
         goto restart;
     }
 
-done:
+    logout("finished data write\n");
+    if (ret >= 0) {
+        ret = 0;
+        if (acb->header_modified) {
+            VdiHeader *header = acb->block_buffer;
+            logout("now writing modified header\n");
+            assert(VDI_IS_ALLOCATED(acb->bmap_first));
+            *header = s->header;
+            vdi_header_to_le(header);
+            acb->header_modified = 0;
+            acb->hd_iov.iov_base = acb->block_buffer;
+            acb->hd_iov.iov_len = SECTOR_SIZE;
+            qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
+            ret = bdrv_co_writev(bs->file, 0, 1, &acb->hd_qiov);
+        }
+        if (ret >= 0 && VDI_IS_ALLOCATED(acb->bmap_first)) {
+            /* One or more new blocks were allocated. */
+            uint64_t offset;
+            uint32_t bmap_first;
+            uint32_t bmap_last;
+            g_free(acb->block_buffer);
+            acb->block_buffer = NULL;
+            bmap_first = acb->bmap_first;
+            bmap_last = acb->bmap_last;
+            logout("now writing modified block map entry %u...%u\n",
+                   bmap_first, bmap_last);
+            /* Write modified sectors from block map. */
+            bmap_first /= (SECTOR_SIZE / sizeof(uint32_t));
+            bmap_last /= (SECTOR_SIZE / sizeof(uint32_t));
+            n_sectors = bmap_last - bmap_first + 1;
+            offset = s->bmap_sector + bmap_first;
+            acb->bmap_first = VDI_UNALLOCATED;
+            acb->hd_iov.iov_base = (void *)((uint8_t *)&s->bmap[0] +
+                                            bmap_first * SECTOR_SIZE);
+            acb->hd_iov.iov_len = n_sectors * SECTOR_SIZE;
+            qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
+            logout("will write %u block map sectors starting from entry %u\n",
+                   n_sectors, bmap_first);
+            ret = bdrv_co_writev(bs->file, offset, n_sectors, &acb->hd_qiov);
+        }
+    }
+
     if (acb->qiov->niov > 1) {
         qemu_vfree(acb->orig_buf);
     }
commit 3d46a75aa5031788cb283ab4429acca23cf1cf92
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Mar 19 18:07:45 2012 +0100

    vdi: basic conversion to coroutines
    
    Even a basic conversion changing the bdrv_aio_readv/bdrv_aio_writev calls
    to bdrv_co_readv/bdrv_co_writev, and callbacks to goto statements can
    eliminate a lot of code.  This is because error handling is simplified
    and indirections through bottom halves can go away.
    
    After this patch, I/O to the underlying file already happens via
    coroutines, but the code still looks a lot like if asynchronous I/O was
    being used.
    
    Acked-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vdi.c b/block/vdi.c
index f8fa865..5fd8700 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -160,7 +160,6 @@ typedef struct {
     void *orig_buf;
     bool is_write;
     int header_modified;
-    BlockDriverAIOCB *hd_aiocb;
     struct iovec hd_iov;
     QEMUIOVector hd_qiov;
     QEMUBH *bh;
@@ -489,33 +488,19 @@ static int coroutine_fn vdi_co_is_allocated(BlockDriverState *bs,
     return VDI_IS_ALLOCATED(bmap_entry);
 }
 
-static void vdi_aio_cancel(BlockDriverAIOCB *blockacb)
-{
-    /* TODO: This code is untested. How can I get it executed? */
-    VdiAIOCB *acb = container_of(blockacb, VdiAIOCB, common);
-    logout("\n");
-    if (acb->hd_aiocb) {
-        bdrv_aio_cancel(acb->hd_aiocb);
-    }
-    qemu_aio_release(acb);
-}
-
 static AIOPool vdi_aio_pool = {
     .aiocb_size = sizeof(VdiAIOCB),
-    .cancel = vdi_aio_cancel,
 };
 
 static VdiAIOCB *vdi_aio_setup(BlockDriverState *bs, int64_t sector_num,
-        QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque, int is_write)
+        QEMUIOVector *qiov, int nb_sectors, int is_write)
 {
     VdiAIOCB *acb;
 
     logout("%p, %" PRId64 ", %p, %d, %p, %p, %d\n",
-           bs, sector_num, qiov, nb_sectors, cb, opaque, is_write);
+           bs, sector_num, qiov, nb_sectors, is_write);
 
-    acb = qemu_aio_get(&vdi_aio_pool, bs, cb, opaque);
-    acb->hd_aiocb = NULL;
+    acb = qemu_aio_get(&vdi_aio_pool, bs, NULL, NULL);
     acb->sector_num = sector_num;
     acb->qiov = qiov;
     acb->is_write = is_write;
@@ -538,42 +523,7 @@ static VdiAIOCB *vdi_aio_setup(BlockDriverState *bs, int64_t sector_num,
     return acb;
 }
 
-static int vdi_schedule_bh(QEMUBHFunc *cb, VdiAIOCB *acb)
-{
-    logout("\n");
-
-    if (acb->bh) {
-        return -EIO;
-    }
-
-    acb->bh = qemu_bh_new(cb, acb);
-    if (!acb->bh) {
-        return -EIO;
-    }
-
-    qemu_bh_schedule(acb->bh);
-
-    return 0;
-}
-
-static void vdi_aio_read_cb(void *opaque, int ret);
-static void vdi_aio_write_cb(void *opaque, int ret);
-
-static void vdi_aio_rw_bh(void *opaque)
-{
-    VdiAIOCB *acb = opaque;
-    logout("\n");
-    qemu_bh_delete(acb->bh);
-    acb->bh = NULL;
-
-    if (acb->is_write) {
-        vdi_aio_write_cb(opaque, 0);
-    } else {
-        vdi_aio_read_cb(opaque, 0);
-    }
-}
-
-static void vdi_aio_read_cb(void *opaque, int ret)
+static int vdi_aio_read_cb(void *opaque, int ret)
 {
     VdiAIOCB *acb = opaque;
     BlockDriverState *bs = acb->common.bs;
@@ -585,12 +535,7 @@ static void vdi_aio_read_cb(void *opaque, int ret)
 
     logout("%u sectors read\n", acb->n_sectors);
 
-    acb->hd_aiocb = NULL;
-
-    if (ret < 0) {
-        goto done;
-    }
-
+restart:
     acb->nb_sectors -= acb->n_sectors;
 
     if (acb->nb_sectors == 0) {
@@ -618,10 +563,7 @@ static void vdi_aio_read_cb(void *opaque, int ret)
     if (!VDI_IS_ALLOCATED(bmap_entry)) {
         /* Block not allocated, return zeros, no need to wait. */
         memset(acb->buf, 0, n_sectors * SECTOR_SIZE);
-        ret = vdi_schedule_bh(vdi_aio_rw_bh, acb);
-        if (ret < 0) {
-            goto done;
-        }
+        ret = 0;
     } else {
         uint64_t offset = s->header.offset_data / SECTOR_SIZE +
                           (uint64_t)bmap_entry * s->block_sectors +
@@ -629,41 +571,34 @@ static void vdi_aio_read_cb(void *opaque, int ret)
         acb->hd_iov.iov_base = (void *)acb->buf;
         acb->hd_iov.iov_len = n_sectors * SECTOR_SIZE;
         qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-        acb->hd_aiocb = bdrv_aio_readv(bs->file, offset, &acb->hd_qiov,
-                                       n_sectors, vdi_aio_read_cb, acb);
+        ret = bdrv_co_readv(bs->file, offset, n_sectors, &acb->hd_qiov);
+    }
+    if (ret >= 0) {
+        goto restart;
     }
-    return;
+
 done:
     if (acb->qiov->niov > 1) {
         qemu_iovec_from_buffer(acb->qiov, acb->orig_buf, acb->qiov->size);
         qemu_vfree(acb->orig_buf);
     }
-    acb->common.cb(acb->common.opaque, ret);
     qemu_aio_release(acb);
+    return ret;
 }
 
-static BlockDriverAIOCB *vdi_aio_readv(BlockDriverState *bs,
-        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque)
+static int vdi_co_readv(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
 {
     VdiAIOCB *acb;
     int ret;
 
     logout("\n");
-    acb = vdi_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
-    ret = vdi_schedule_bh(vdi_aio_rw_bh, acb);
-    if (ret < 0) {
-        if (acb->qiov->niov > 1) {
-            qemu_vfree(acb->orig_buf);
-        }
-        qemu_aio_release(acb);
-        return NULL;
-    }
-
-    return &acb->common;
+    acb = vdi_aio_setup(bs, sector_num, qiov, nb_sectors, 0);
+    ret = vdi_aio_read_cb(acb, 0);
+    return ret;
 }
 
-static void vdi_aio_write_cb(void *opaque, int ret)
+static int vdi_aio_write_cb(void *opaque, int ret)
 {
     VdiAIOCB *acb = opaque;
     BlockDriverState *bs = acb->common.bs;
@@ -673,12 +608,7 @@ static void vdi_aio_write_cb(void *opaque, int ret)
     uint32_t sector_in_block;
     uint32_t n_sectors;
 
-    acb->hd_aiocb = NULL;
-
-    if (ret < 0) {
-        goto done;
-    }
-
+restart:
     acb->nb_sectors -= acb->n_sectors;
     acb->sector_num += acb->n_sectors;
     acb->buf += acb->n_sectors * SECTOR_SIZE;
@@ -686,6 +616,7 @@ static void vdi_aio_write_cb(void *opaque, int ret)
     if (acb->nb_sectors == 0) {
         logout("finished data write\n");
         acb->n_sectors = 0;
+        ret = 0;
         if (acb->header_modified) {
             VdiHeader *header = acb->block_buffer;
             logout("now writing modified header\n");
@@ -696,10 +627,9 @@ static void vdi_aio_write_cb(void *opaque, int ret)
             acb->hd_iov.iov_base = acb->block_buffer;
             acb->hd_iov.iov_len = SECTOR_SIZE;
             qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-            acb->hd_aiocb = bdrv_aio_writev(bs->file, 0, &acb->hd_qiov, 1,
-                                            vdi_aio_write_cb, acb);
-            return;
-        } else if (VDI_IS_ALLOCATED(acb->bmap_first)) {
+            ret = bdrv_co_writev(bs->file, 0, 1, &acb->hd_qiov);
+        }
+        if (ret >= 0 && VDI_IS_ALLOCATED(acb->bmap_first)) {
             /* One or more new blocks were allocated. */
             uint64_t offset;
             uint32_t bmap_first;
@@ -722,11 +652,8 @@ static void vdi_aio_write_cb(void *opaque, int ret)
             qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
             logout("will write %u block map sectors starting from entry %u\n",
                    n_sectors, bmap_first);
-            acb->hd_aiocb = bdrv_aio_writev(bs->file, offset, &acb->hd_qiov,
-                                            n_sectors, vdi_aio_write_cb, acb);
-            return;
+            ret = bdrv_co_writev(bs->file, offset, n_sectors, &acb->hd_qiov);
         }
-        ret = 0;
         goto done;
     }
 
@@ -772,9 +699,7 @@ static void vdi_aio_write_cb(void *opaque, int ret)
         acb->hd_iov.iov_base = (void *)block;
         acb->hd_iov.iov_len = s->block_size;
         qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-        acb->hd_aiocb = bdrv_aio_writev(bs->file, offset,
-                                        &acb->hd_qiov, s->block_sectors,
-                                        vdi_aio_write_cb, acb);
+        ret = bdrv_co_writev(bs->file, offset, s->block_sectors, &acb->hd_qiov);
     } else {
         uint64_t offset = s->header.offset_data / SECTOR_SIZE +
                           (uint64_t)bmap_entry * s->block_sectors +
@@ -782,39 +707,30 @@ static void vdi_aio_write_cb(void *opaque, int ret)
         acb->hd_iov.iov_base = (void *)acb->buf;
         acb->hd_iov.iov_len = n_sectors * SECTOR_SIZE;
         qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-        acb->hd_aiocb = bdrv_aio_writev(bs->file, offset, &acb->hd_qiov,
-                                        n_sectors, vdi_aio_write_cb, acb);
+        ret = bdrv_co_writev(bs->file, offset, n_sectors, &acb->hd_qiov);
+    }
+    if (ret >= 0) {
+        goto restart;
     }
-
-    return;
 
 done:
     if (acb->qiov->niov > 1) {
         qemu_vfree(acb->orig_buf);
     }
-    acb->common.cb(acb->common.opaque, ret);
     qemu_aio_release(acb);
+    return ret;
 }
 
-static BlockDriverAIOCB *vdi_aio_writev(BlockDriverState *bs,
-        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque)
+static int vdi_co_writev(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
 {
     VdiAIOCB *acb;
     int ret;
 
     logout("\n");
-    acb = vdi_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
-    ret = vdi_schedule_bh(vdi_aio_rw_bh, acb);
-    if (ret < 0) {
-        if (acb->qiov->niov > 1) {
-            qemu_vfree(acb->orig_buf);
-        }
-        qemu_aio_release(acb);
-        return NULL;
-    }
-
-    return &acb->common;
+    acb = vdi_aio_setup(bs, sector_num, qiov, nb_sectors, 1);
+    ret = vdi_aio_write_cb(acb, 0);
+    return ret;
 }
 
 static int vdi_create(const char *filename, QEMUOptionParameter *options)
@@ -965,9 +881,9 @@ static BlockDriver bdrv_vdi = {
     .bdrv_co_is_allocated = vdi_co_is_allocated,
     .bdrv_make_empty = vdi_make_empty,
 
-    .bdrv_aio_readv = vdi_aio_readv,
+    .bdrv_co_readv = vdi_co_readv,
 #if defined(CONFIG_VDI_WRITE)
-    .bdrv_aio_writev = vdi_aio_writev,
+    .bdrv_co_writev = vdi_co_writev,
 #endif
 
     .bdrv_get_info = vdi_get_info,
commit 1fc86bf963a0617bc9eabfa6c14dbca76cd57976
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Wed Mar 14 15:57:06 2012 +0000

    block: enforce constraints on block size properties
    
    Nicolae Mogoreanu <mogo at google.com> noticed that I/O requests can lead
    to QEMU crashes when the logical_block_size property is smaller than 512
    bytes.
    
    Using the new "blocksize" property we can properly enforce constraints
    on the block size such that QEMU's block layer is able to operate
    correctly.
    
    Reported-by: Nicolae Mogoreanu <mogo at google.com>
    Reported-by: Michael Halcrow <mhalcrow at google.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.h b/block.h
index e670606..c51ab16 100644
--- a/block.h
+++ b/block.h
@@ -435,10 +435,10 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
 
 #define DEFINE_BLOCK_PROPERTIES(_state, _conf)                          \
     DEFINE_PROP_DRIVE("drive", _state, _conf.bs),                       \
-    DEFINE_PROP_UINT16("logical_block_size", _state,                    \
-                       _conf.logical_block_size, 512),                  \
-    DEFINE_PROP_UINT16("physical_block_size", _state,                   \
-                       _conf.physical_block_size, 512),                 \
+    DEFINE_PROP_BLOCKSIZE("logical_block_size", _state,                 \
+                          _conf.logical_block_size, 512),               \
+    DEFINE_PROP_BLOCKSIZE("physical_block_size", _state,                \
+                          _conf.physical_block_size, 512),              \
     DEFINE_PROP_UINT16("min_io_size", _state, _conf.min_io_size, 0),  \
     DEFINE_PROP_UINT32("opt_io_size", _state, _conf.opt_io_size, 0),    \
     DEFINE_PROP_INT32("bootindex", _state, _conf.bootindex, -1),        \
commit 02fda01c3024463e561820afb0ba09daba4014d9
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Wed Mar 14 15:57:05 2012 +0000

    qdev: add blocksize property type
    
    Storage interfaces like virtio-blk can be configured with block size
    information so that the guest can take advantage of efficient I/O
    request sizes.
    
    According to the SCSI Block Commands (SBC) standard a device's block
    size is "almost always greater than one byte and may be a multiple of
    512 bytes".  QEMU currently has a 512 byte minimum block size because
    the block layer functions work at that granularity.  Furthermore, the
    block size should be a power of 2 because QEMU calculates bitmasks from
    the value.
    
    Introduce a "blocksize" property type so devices can enforce these
    constraints on block size values.  If the constraints are relaxed in the
    future then this property can be updated.
    
    Introduce the new PropertyValueNotPowerOf2 QError so QMP clients know
    exactly why a block size value was rejected.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index bff9152..98dd06a 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -877,6 +877,52 @@ PropertyInfo qdev_prop_pci_devfn = {
     .max   = 0xFFFFFFFFULL,
 };
 
+/* --- blocksize --- */
+
+static void set_blocksize(Object *obj, Visitor *v, void *opaque,
+                          const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    int16_t *ptr = qdev_get_prop_ptr(dev, prop);
+    Error *local_err = NULL;
+    int64_t value;
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    visit_type_int(v, &value, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+    if (value < prop->info->min || value > prop->info->max) {
+        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
+                  dev->id?:"", name, value, prop->info->min,
+                  prop->info->max);
+        return;
+    }
+
+    /* We rely on power-of-2 blocksizes for bitmasks */
+    if ((value & (value - 1)) != 0) {
+        error_set(errp, QERR_PROPERTY_VALUE_NOT_POWER_OF_2,
+                  dev->id?:"", name, value);
+        return;
+    }
+
+    *ptr = value;
+}
+
+PropertyInfo qdev_prop_blocksize = {
+    .name  = "blocksize",
+    .get   = get_int16,
+    .set   = set_blocksize,
+    .min   = 512,
+    .max   = 65024,
+};
+
 /* --- public helpers --- */
 
 static Property *qdev_prop_walk(Property *props, const char *name)
diff --git a/hw/qdev.h b/hw/qdev.h
index a8df42f..1c10960 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -223,6 +223,7 @@ extern PropertyInfo qdev_prop_drive;
 extern PropertyInfo qdev_prop_netdev;
 extern PropertyInfo qdev_prop_vlan;
 extern PropertyInfo qdev_prop_pci_devfn;
+extern PropertyInfo qdev_prop_blocksize;
 
 #define DEFINE_PROP(_name, _state, _field, _prop, _type) { \
         .name      = (_name),                                    \
@@ -284,6 +285,8 @@ extern PropertyInfo qdev_prop_pci_devfn;
 #define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \
     DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_losttickpolicy, \
                         LostTickPolicy)
+#define DEFINE_PROP_BLOCKSIZE(_n, _s, _f, _d) \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_blocksize, uint16_t)
 
 #define DEFINE_PROP_END_OF_LIST()               \
     {}
diff --git a/qerror.c b/qerror.c
index 1f565fc..96fbe71 100644
--- a/qerror.c
+++ b/qerror.c
@@ -241,6 +241,11 @@ static const QErrorStringTable qerror_table[] = {
         .desc      = "Property '%(device).%(property)' can't find value '%(value)'",
     },
     {
+        .error_fmt = QERR_PROPERTY_VALUE_NOT_POWER_OF_2,
+        .desc      = "Property '%(device).%(property)' doesn't take "
+                     "value '%(value)', it's not a power of 2",
+    },
+    {
         .error_fmt = QERR_PROPERTY_VALUE_OUT_OF_RANGE,
         .desc      = "Property '%(device).%(property)' doesn't take "
                      "value %(value) (minimum: %(min), maximum: %(max))",
diff --git a/qerror.h b/qerror.h
index e16f9c2..5c23c1f 100644
--- a/qerror.h
+++ b/qerror.h
@@ -202,6 +202,10 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_PROPERTY_VALUE_NOT_FOUND \
     "{ 'class': 'PropertyValueNotFound', 'data': { 'device': %s, 'property': %s, 'value': %s } }"
 
+#define QERR_PROPERTY_VALUE_NOT_POWER_OF_2 \
+    "{ 'class': 'PropertyValueNotPowerOf2', 'data': { " \
+    "'device': %s, 'property': %s, 'value': %"PRId64" } }"
+
 #define QERR_PROPERTY_VALUE_OUT_OF_RANGE \
     "{ 'class': 'PropertyValueOutOfRange', 'data': { 'device': %s, 'property': %s, 'value': %"PRId64", 'min': %"PRId64", 'max': %"PRId64" } }"
 
commit 41453412ca16ff1871ed2bd6ee83cb9a5c734823
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Wed Mar 14 15:57:04 2012 +0000

    qerror: fix QERR_PROPERTY_VALUE_OUT_OF_RANGE description
    
    Fix a typo in the description for QERR_PROPERTY_VALUE_OUT_OF_RANGE where
    "'" was used instead of ")".
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qerror.c b/qerror.c
index 41c729a..1f565fc 100644
--- a/qerror.c
+++ b/qerror.c
@@ -243,7 +243,7 @@ static const QErrorStringTable qerror_table[] = {
     {
         .error_fmt = QERR_PROPERTY_VALUE_OUT_OF_RANGE,
         .desc      = "Property '%(device).%(property)' doesn't take "
-                     "value %(value) (minimum: %(min), maximum: %(max)'",
+                     "value %(value) (minimum: %(min), maximum: %(max))",
     },
     {
         .error_fmt = QERR_QGA_COMMAND_FAILED,
commit c088b691363070d151f80cc1fde4b7c151bdfe8f
Author: Zhang Shengju <zhangsju at gmail.com>
Date:   Tue Mar 13 22:38:13 2012 +0800

    block/vpc: write checksum back to footer after check
    
    After validation check, the 'checksum' is not written back
    to footer, which leave it with zero.
    
    This results in errors while loadding it under Microsoft's
    Hyper-V environment, and also errors from utilities like
    Citrix's vhd-util.
    
    Signed-off-by: Zhang Shengju <sean_zhang at trendmicro.com.cn>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vpc.c b/block/vpc.c
index 706faf3..5cd13d1 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -189,6 +189,9 @@ static int vpc_open(BlockDriverState *bs, int flags)
         fprintf(stderr, "block-vpc: The header checksum of '%s' is "
             "incorrect.\n", bs->filename);
 
+    /* Write 'checksum' back to footer, or else will leave it with zero. */
+    footer->checksum = be32_to_cpu(checksum);
+
     // The visible size of a image in Virtual PC depends on the geometry
     // rather than on the size stored in the footer (the size in the footer
     // is too large usually)
commit 95ebda85e09ed2b7f00deb2adbdafa5ccf5db948
Author: Floris Bos <bos at je-eigen-domein.nl>
Date:   Tue Mar 13 13:31:47 2012 +0100

    ide: Adds wwn=hex qdev option
    
    Allow the user to specify a disk's World Wide Name.
    
    Linux guests can address disks by their unique World Wide Name number
    (e.g. /dev/disk/by-id/wwn-0x5001517959123522). This patch adds support
    for assigning a World Wide Name number to a virtual IDE disk.
    
    Cc: kwolf at redhat.com
    Signed-off-by: Floris Bos <dev at noc-ps.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 5647694..6e25338 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -142,8 +142,12 @@ static void ide_identify(IDEState *s)
     put_le16(p + 82, (1 << 14) | (1 << 5) | 1);
     /* 13=flush_cache_ext,12=flush_cache,10=lba48 */
     put_le16(p + 83, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10));
-    /* 14=set to 1, 1=SMART self test, 0=SMART error logging */
-    put_le16(p + 84, (1 << 14) | 0);
+    /* 14=set to 1, 8=has WWN, 1=SMART self test, 0=SMART error logging */
+    if (s->wwn) {
+        put_le16(p + 84, (1 << 14) | (1 << 8) | 0);
+    } else {
+        put_le16(p + 84, (1 << 14) | 0);
+    }
     /* 14 = NOP supported, 5=WCACHE enabled, 0=SMART feature set enabled */
     if (bdrv_enable_write_cache(s->bs))
          put_le16(p + 85, (1 << 14) | (1 << 5) | 1);
@@ -151,8 +155,12 @@ static void ide_identify(IDEState *s)
          put_le16(p + 85, (1 << 14) | 1);
     /* 13=flush_cache_ext,12=flush_cache,10=lba48 */
     put_le16(p + 86, (1 << 13) | (1 <<12) | (1 << 10));
-    /* 14=set to 1, 1=smart self test, 0=smart error logging */
-    put_le16(p + 87, (1 << 14) | 0);
+    /* 14=set to 1, 8=has WWN, 1=SMART self test, 0=SMART error logging */
+    if (s->wwn) {
+        put_le16(p + 87, (1 << 14) | (1 << 8) | 0);
+    } else {
+        put_le16(p + 87, (1 << 14) | 0);
+    }
     put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */
     put_le16(p + 93, 1 | (1 << 14) | 0x2000);
     put_le16(p + 100, s->nb_sectors);
@@ -162,6 +170,13 @@ static void ide_identify(IDEState *s)
 
     if (dev && dev->conf.physical_block_size)
         put_le16(p + 106, 0x6000 | get_physical_block_exp(&dev->conf));
+    if (s->wwn) {
+        /* LE 16-bit words 111-108 contain 64-bit World Wide Name */
+        put_le16(p + 108, s->wwn >> 48);
+        put_le16(p + 109, s->wwn >> 32);
+        put_le16(p + 110, s->wwn >> 16);
+        put_le16(p + 111, s->wwn);
+    }
     if (dev && dev->conf.discard_granularity) {
         put_le16(p + 169, 1); /* TRIM support */
     }
@@ -1833,7 +1848,8 @@ static const BlockDevOps ide_cd_block_ops = {
 };
 
 int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
-                   const char *version, const char *serial, const char *model)
+                   const char *version, const char *serial, const char *model,
+                   uint64_t wwn)
 {
     int cylinders, heads, secs;
     uint64_t nb_sectors;
@@ -1859,6 +1875,7 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
     s->heads = heads;
     s->sectors = secs;
     s->nb_sectors = nb_sectors;
+    s->wwn = wwn;
     /* The SMART values should be preserved across power cycles
        but they aren't.  */
     s->smart_enabled = 1;
@@ -1993,7 +2010,7 @@ void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
             if (ide_init_drive(&bus->ifs[i], dinfo->bdrv,
                                dinfo->media_cd ? IDE_CD : IDE_HD, NULL,
                                *dinfo->serial ? dinfo->serial : NULL,
-                               NULL) < 0) {
+                               NULL, 0) < 0) {
                 error_report("Can't set up IDE drive %s", dinfo->id);
                 exit(1);
             }
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index b1319dc..100efd3 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -349,6 +349,7 @@ struct IDEState {
     int drive_serial;
     char drive_serial_str[21];
     char drive_model_str[41];
+    uint64_t wwn;
     /* ide regs */
     uint8_t feature;
     uint8_t error;
@@ -470,6 +471,7 @@ struct IDEDevice {
     char *version;
     char *serial;
     char *model;
+    uint64_t wwn;
 };
 
 #define BM_STATUS_DMAING 0x01
@@ -536,7 +538,8 @@ void ide_data_writel(void *opaque, uint32_t addr, uint32_t val);
 uint32_t ide_data_readl(void *opaque, uint32_t addr);
 
 int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
-                   const char *version, const char *serial, const char *model);
+                   const char *version, const char *serial, const char *model,
+                   uint64_t wwn);
 void ide_init2(IDEBus *bus, qemu_irq irq);
 void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
                                     DriveInfo *hd1, qemu_irq irq);
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index 07227c7..a46578d 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -137,7 +137,7 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
     }
 
     if (ide_init_drive(s, dev->conf.bs, kind,
-                       dev->version, serial, dev->model) < 0) {
+                       dev->version, serial, dev->model, dev->wwn) < 0) {
         return -1;
     }
 
@@ -174,6 +174,7 @@ static int ide_drive_initfn(IDEDevice *dev)
 #define DEFINE_IDE_DEV_PROPERTIES()                     \
     DEFINE_BLOCK_PROPERTIES(IDEDrive, dev.conf),        \
     DEFINE_PROP_STRING("ver",  IDEDrive, dev.version),  \
+    DEFINE_PROP_HEX64("wwn",  IDEDrive, dev.wwn, 0),    \
     DEFINE_PROP_STRING("serial",  IDEDrive, dev.serial),\
     DEFINE_PROP_STRING("model", IDEDrive, dev.model)
 
commit aa2c91bdfebbfa314e9522573a9656626e21ac67
Author: Floris Bos <bos at je-eigen-domein.nl>
Date:   Mon Mar 12 21:05:10 2012 +0100

    ide: Change serial number strncpy() to pstrcpy()
    
    strncpy may not null-terminate the destination string.
    
    Cc: kwolf at redhat.com
    Signed-off-by: Floris Bos <dev at noc-ps.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 1a500b8..f5e7dba 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -532,8 +532,9 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
     dinfo->unit = unit_id;
     dinfo->opts = opts;
     dinfo->refcount = 1;
-    if (serial)
-        strncpy(dinfo->serial, serial, sizeof(dinfo->serial) - 1);
+    if (serial) {
+        pstrcpy(dinfo->serial, sizeof(dinfo->serial), serial);
+    }
     QTAILQ_INSERT_TAIL(&drives, dinfo, next);
 
     bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_error);
diff --git a/hw/ide/core.c b/hw/ide/core.c
index e38cace..5647694 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1879,7 +1879,7 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
         }
     }
     if (serial) {
-        strncpy(s->drive_serial_str, serial, sizeof(s->drive_serial_str));
+        pstrcpy(s->drive_serial_str, sizeof(s->drive_serial_str), serial);
     } else {
         snprintf(s->drive_serial_str, sizeof(s->drive_serial_str),
                  "QM%05d", s->drive_serial);
commit 27e0c9a1bbd166a67c16291016fba298a8e47140
Author: Floris Bos <bos at je-eigen-domein.nl>
Date:   Mon Mar 12 21:05:09 2012 +0100

    ide: Add "model=s" qdev option
    
    Allow the user to override the default disk model name "QEMU HARDDISK".
    
    Some Linux distributions use the /dev/disk/by-id/scsi-SATA_name-of-disk-
    model_serial addressing scheme when refering to partitions in /etc/fstab
    and elsewhere. This causes problems when starting a disk image taken from
    an existing physical server under qemu, because when running under qemu
    name-of-disk-model is always "QEMU HARDDISK".
    
    This patch introduces a model=s option which in combination with the
    existing serial=s option can be used to fake the disk the operating
    system was previously on, allowing the OS to boot properly.
    
    Cc: kwolf at redhat.com
    Signed-off-by: Floris Bos <dev at noc-ps.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 771811c..e38cace 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -100,7 +100,7 @@ static void ide_identify(IDEState *s)
     put_le16(p + 21, 512); /* cache size in sectors */
     put_le16(p + 22, 4); /* ecc bytes */
     padstr((char *)(p + 23), s->version, 8); /* firmware version */
-    padstr((char *)(p + 27), "QEMU HARDDISK", 40); /* model */
+    padstr((char *)(p + 27), s->drive_model_str, 40); /* model */
 #if MAX_MULT_SECTORS > 1
     put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS);
 #endif
@@ -188,7 +188,7 @@ static void ide_atapi_identify(IDEState *s)
     put_le16(p + 21, 512); /* cache size in sectors */
     put_le16(p + 22, 4); /* ecc bytes */
     padstr((char *)(p + 23), s->version, 8); /* firmware version */
-    padstr((char *)(p + 27), "QEMU DVD-ROM", 40); /* model */
+    padstr((char *)(p + 27), s->drive_model_str, 40); /* model */
     put_le16(p + 48, 1); /* dword I/O (XXX: should not be set on CDROM) */
 #ifdef USE_DMA_CDROM
     put_le16(p + 49, 1 << 9 | 1 << 8); /* DMA and LBA supported */
@@ -245,7 +245,7 @@ static void ide_cfata_identify(IDEState *s)
     padstr((char *)(p + 10), s->drive_serial_str, 20); /* serial number */
     put_le16(p + 22, 0x0004);			/* ECC bytes */
     padstr((char *) (p + 23), s->version, 8);	/* Firmware Revision */
-    padstr((char *) (p + 27), "QEMU MICRODRIVE", 40);/* Model number */
+    padstr((char *) (p + 27), s->drive_model_str, 40);/* Model number */
 #if MAX_MULT_SECTORS > 1
     put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS);
 #else
@@ -1833,7 +1833,7 @@ static const BlockDevOps ide_cd_block_ops = {
 };
 
 int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
-                   const char *version, const char *serial)
+                   const char *version, const char *serial, const char *model)
 {
     int cylinders, heads, secs;
     uint64_t nb_sectors;
@@ -1884,6 +1884,22 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
         snprintf(s->drive_serial_str, sizeof(s->drive_serial_str),
                  "QM%05d", s->drive_serial);
     }
+    if (model) {
+        pstrcpy(s->drive_model_str, sizeof(s->drive_model_str), model);
+    } else {
+        switch (kind) {
+        case IDE_CD:
+            strcpy(s->drive_model_str, "QEMU DVD-ROM");
+            break;
+        case IDE_CFATA:
+            strcpy(s->drive_model_str, "QEMU MICRODRIVE");
+            break;
+        default:
+            strcpy(s->drive_model_str, "QEMU HARDDISK");
+            break;
+        }
+    }
+
     if (version) {
         pstrcpy(s->version, sizeof(s->version), version);
     } else {
@@ -1976,7 +1992,8 @@ void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
         if (dinfo) {
             if (ide_init_drive(&bus->ifs[i], dinfo->bdrv,
                                dinfo->media_cd ? IDE_CD : IDE_HD, NULL,
-                               *dinfo->serial ? dinfo->serial : NULL) < 0) {
+                               *dinfo->serial ? dinfo->serial : NULL,
+                               NULL) < 0) {
                 error_report("Can't set up IDE drive %s", dinfo->id);
                 exit(1);
             }
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index c808a0d..b1319dc 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -348,6 +348,7 @@ struct IDEState {
     uint8_t identify_data[512];
     int drive_serial;
     char drive_serial_str[21];
+    char drive_model_str[41];
     /* ide regs */
     uint8_t feature;
     uint8_t error;
@@ -468,6 +469,7 @@ struct IDEDevice {
     BlockConf conf;
     char *version;
     char *serial;
+    char *model;
 };
 
 #define BM_STATUS_DMAING 0x01
@@ -534,7 +536,7 @@ void ide_data_writel(void *opaque, uint32_t addr, uint32_t val);
 uint32_t ide_data_readl(void *opaque, uint32_t addr);
 
 int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
-                   const char *version, const char *serial);
+                   const char *version, const char *serial, const char *model);
 void ide_init2(IDEBus *bus, qemu_irq irq);
 void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
                                     DriveInfo *hd1, qemu_irq irq);
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index f6a4896..07227c7 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -136,7 +136,8 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
         }
     }
 
-    if (ide_init_drive(s, dev->conf.bs, kind, dev->version, serial) < 0) {
+    if (ide_init_drive(s, dev->conf.bs, kind,
+                       dev->version, serial, dev->model) < 0) {
         return -1;
     }
 
@@ -173,7 +174,8 @@ static int ide_drive_initfn(IDEDevice *dev)
 #define DEFINE_IDE_DEV_PROPERTIES()                     \
     DEFINE_BLOCK_PROPERTIES(IDEDrive, dev.conf),        \
     DEFINE_PROP_STRING("ver",  IDEDrive, dev.version),  \
-    DEFINE_PROP_STRING("serial",  IDEDrive, dev.serial)
+    DEFINE_PROP_STRING("serial",  IDEDrive, dev.serial),\
+    DEFINE_PROP_STRING("model", IDEDrive, dev.model)
 
 static Property ide_hd_properties[] = {
     DEFINE_IDE_DEV_PROPERTIES(),
commit 2844bdd99a96dc32a6ebf464f49e65be31da1c14
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 13 14:44:22 2012 +0100

    ide: IDENTIFY word 86 bit 14 is reserved
    
    Reserved bits should be cleared to zero.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 6f06d28..771811c 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -150,7 +150,7 @@ static void ide_identify(IDEState *s)
     else
          put_le16(p + 85, (1 << 14) | 1);
     /* 13=flush_cache_ext,12=flush_cache,10=lba48 */
-    put_le16(p + 86, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10));
+    put_le16(p + 86, (1 << 13) | (1 <<12) | (1 << 10));
     /* 14=set to 1, 1=smart self test, 0=smart error logging */
     put_le16(p + 87, (1 << 14) | 0);
     put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */
commit 85e8dab1efc7228bb674e72f6fb3be78c1e883bf
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Mar 12 17:01:48 2012 +0100

    aio: move BlockDriverAIOCB to qemu-aio.h
    
    And remove several block_int.h inclusions that should not be there.
    
    Signed-off-by: Paolo Bonzini <pbonzini 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/block.h b/block.h
index 415bb17..e670606 100644
--- a/block.h
+++ b/block.h
@@ -180,8 +180,6 @@ typedef struct BdrvCheckResult {
 int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res);
 
 /* async block I/O */
-typedef struct BlockDriverAIOCB BlockDriverAIOCB;
-typedef void BlockDriverCompletionFunc(void *opaque, int ret);
 typedef void BlockDriverDirtyHandler(BlockDriverState *bs, int64_t sector,
                                      int sector_num);
 BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
diff --git a/block_int.h b/block_int.h
index b460c36..22c86a5 100644
--- a/block_int.h
+++ b/block_int.h
@@ -53,12 +53,6 @@
 
 typedef struct BdrvTrackedRequest BdrvTrackedRequest;
 
-typedef struct AIOPool {
-    void (*cancel)(BlockDriverAIOCB *acb);
-    int aiocb_size;
-    BlockDriverAIOCB *free_aiocb;
-} AIOPool;
-
 typedef struct BlockIOLimit {
     int64_t bps[3];
     int64_t iops[3];
@@ -302,20 +296,8 @@ struct BlockDriverState {
     BlockJob *job;
 };
 
-struct BlockDriverAIOCB {
-    AIOPool *pool;
-    BlockDriverState *bs;
-    BlockDriverCompletionFunc *cb;
-    void *opaque;
-    BlockDriverAIOCB *next;
-};
-
 void get_tmp_filename(char *filename, int size);
 
-void *qemu_aio_get(AIOPool *pool, BlockDriverState *bs,
-                   BlockDriverCompletionFunc *cb, void *opaque);
-void qemu_aio_release(void *p);
-
 void bdrv_set_io_limits(BlockDriverState *bs,
                         BlockIOLimit *io_limits);
 
diff --git a/dma-helpers.c b/dma-helpers.c
index c29ea6d..7fcc86d 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -8,7 +8,6 @@
  */
 
 #include "dma.h"
-#include "block_int.h"
 #include "trace.h"
 
 void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint)
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 4d568ac..6f06d28 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -31,7 +31,6 @@
 #include "sysemu.h"
 #include "dma.h"
 #include "blockdev.h"
-#include "block_int.h"
 
 #include <hw/ide/internal.h>
 
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index edc09b7..f022a02 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -15,7 +15,6 @@
 #include "hw.h"
 #include "pci.h"
 #include "scsi.h"
-#include "block_int.h"
 #include "dma.h"
 
 //#define DEBUG_LSI
diff --git a/linux-aio.c b/linux-aio.c
index d2fc2e7..15261ec 100644
--- a/linux-aio.c
+++ b/linux-aio.c
@@ -9,7 +9,6 @@
  */
 #include "qemu-common.h"
 #include "qemu-aio.h"
-#include "block_int.h"
 #include "block/raw-posix-aio.h"
 
 #include <sys/eventfd.h>
diff --git a/qemu-aio.h b/qemu-aio.h
index 3bdd749..230c2f7 100644
--- a/qemu-aio.h
+++ b/qemu-aio.h
@@ -17,6 +17,27 @@
 #include "qemu-common.h"
 #include "qemu-char.h"
 
+typedef struct BlockDriverAIOCB BlockDriverAIOCB;
+typedef void BlockDriverCompletionFunc(void *opaque, int ret);
+
+typedef struct AIOPool {
+    void (*cancel)(BlockDriverAIOCB *acb);
+    int aiocb_size;
+    BlockDriverAIOCB *free_aiocb;
+} AIOPool;
+
+struct BlockDriverAIOCB {
+    AIOPool *pool;
+    BlockDriverState *bs;
+    BlockDriverCompletionFunc *cb;
+    void *opaque;
+    BlockDriverAIOCB *next;
+};
+
+void *qemu_aio_get(AIOPool *pool, BlockDriverState *bs,
+                   BlockDriverCompletionFunc *cb, void *opaque);
+void qemu_aio_release(void *p);
+
 /* Returns 1 if there are still outstanding AIO requests; 0 otherwise */
 typedef int (AioFlushHandler)(void *opaque);
 
commit 29cdb2513c3f22f51d6f3585b41009576485cb35
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Mar 12 18:26:01 2012 +0100

    block: push recursive flushing up from drivers
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index b88ee90..8858be0 100644
--- a/block.c
+++ b/block.c
@@ -2331,9 +2331,7 @@ void bdrv_flush_all(void)
     BlockDriverState *bs;
 
     QTAILQ_FOREACH(bs, &bdrv_states, list) {
-        if (!bdrv_is_read_only(bs) && bdrv_is_inserted(bs)) {
-            bdrv_flush(bs);
-        }
+        bdrv_flush(bs);
     }
 }
 
@@ -3520,7 +3518,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
 {
     int ret;
 
-    if (!bs->drv) {
+    if (!bs || !bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
         return 0;
     }
 
@@ -3538,7 +3536,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
     }
 
     if (bs->drv->bdrv_co_flush_to_disk) {
-        return bs->drv->bdrv_co_flush_to_disk(bs);
+        ret = bs->drv->bdrv_co_flush_to_disk(bs);
     } else if (bs->drv->bdrv_aio_flush) {
         BlockDriverAIOCB *acb;
         CoroutineIOCompletion co = {
@@ -3547,10 +3545,10 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
 
         acb = bs->drv->bdrv_aio_flush(bs, bdrv_co_io_em_complete, &co);
         if (acb == NULL) {
-            return -EIO;
+            ret = -EIO;
         } else {
             qemu_coroutine_yield();
-            return co.ret;
+            ret = co.ret;
         }
     } else {
         /*
@@ -3564,8 +3562,16 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
          *
          * Let's hope the user knows what he's doing.
          */
-        return 0;
+        ret = 0;
     }
+    if (ret < 0) {
+        return ret;
+    }
+
+    /* Now flush the underlying protocol.  It will also have BDRV_O_NO_FLUSH
+     * in the case of cache=unsafe, so there are no useless flushes.
+     */
+    return bdrv_co_flush(bs->file);
 }
 
 void bdrv_invalidate_cache(BlockDriverState *bs)
diff --git a/block/blkdebug.c b/block/blkdebug.c
index a251802..e56e37d 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -397,12 +397,6 @@ static void blkdebug_close(BlockDriverState *bs)
     }
 }
 
-static BlockDriverAIOCB *blkdebug_aio_flush(BlockDriverState *bs,
-    BlockDriverCompletionFunc *cb, void *opaque)
-{
-    return bdrv_aio_flush(bs->file, cb, opaque);
-}
-
 static void process_rule(BlockDriverState *bs, struct BlkdebugRule *rule,
     BlkdebugVars *old_vars)
 {
@@ -452,7 +446,6 @@ static BlockDriver bdrv_blkdebug = {
 
     .bdrv_aio_readv     = blkdebug_aio_readv,
     .bdrv_aio_writev    = blkdebug_aio_writev,
-    .bdrv_aio_flush     = blkdebug_aio_flush,
 
     .bdrv_debug_event   = blkdebug_debug_event,
 };
diff --git a/block/cow.c b/block/cow.c
index bb5927c..8d3c9f8 100644
--- a/block/cow.c
+++ b/block/cow.c
@@ -318,11 +318,6 @@ exit:
     return ret;
 }
 
-static coroutine_fn int cow_co_flush(BlockDriverState *bs)
-{
-    return bdrv_co_flush(bs->file);
-}
-
 static QEMUOptionParameter cow_create_options[] = {
     {
         .name = BLOCK_OPT_SIZE,
@@ -348,7 +343,6 @@ static BlockDriver bdrv_cow = {
 
     .bdrv_read              = cow_co_read,
     .bdrv_write             = cow_co_write,
-    .bdrv_co_flush_to_disk  = cow_co_flush,
     .bdrv_co_is_allocated   = cow_co_is_allocated,
 
     .create_options = cow_create_options,
diff --git a/block/qcow.c b/block/qcow.c
index b1cfe1f..35dff49 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -835,11 +835,6 @@ fail:
     return ret;
 }
 
-static coroutine_fn int qcow_co_flush(BlockDriverState *bs)
-{
-    return bdrv_co_flush(bs->file);
-}
-
 static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
 {
     BDRVQcowState *s = bs->opaque;
@@ -877,7 +872,6 @@ static BlockDriver bdrv_qcow = {
 
     .bdrv_co_readv          = qcow_co_readv,
     .bdrv_co_writev         = qcow_co_writev,
-    .bdrv_co_flush_to_disk  = qcow_co_flush,
     .bdrv_co_is_allocated   = qcow_co_is_allocated,
 
     .bdrv_set_key           = qcow_set_key,
diff --git a/block/qcow2.c b/block/qcow2.c
index 7aece65..70d3141 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1253,11 +1253,6 @@ static coroutine_fn int qcow2_co_flush_to_os(BlockDriverState *bs)
     return 0;
 }
 
-static coroutine_fn int qcow2_co_flush_to_disk(BlockDriverState *bs)
-{
-    return bdrv_co_flush(bs->file);
-}
-
 static int64_t qcow2_vm_state_offset(BDRVQcowState *s)
 {
 	return (int64_t)s->l1_vm_state_index << (s->cluster_bits + s->l2_bits);
@@ -1377,7 +1372,6 @@ static BlockDriver bdrv_qcow2 = {
     .bdrv_co_readv          = qcow2_co_readv,
     .bdrv_co_writev         = qcow2_co_writev,
     .bdrv_co_flush_to_os    = qcow2_co_flush_to_os,
-    .bdrv_co_flush_to_disk  = qcow2_co_flush_to_disk,
 
     .bdrv_co_discard        = qcow2_co_discard,
     .bdrv_truncate          = qcow2_truncate,
diff --git a/block/qed.c b/block/qed.c
index a041d31..d6c1580 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -1350,13 +1350,6 @@ static BlockDriverAIOCB *bdrv_qed_aio_writev(BlockDriverState *bs,
                          opaque, QED_AIOCB_WRITE);
 }
 
-static BlockDriverAIOCB *bdrv_qed_aio_flush(BlockDriverState *bs,
-                                            BlockDriverCompletionFunc *cb,
-                                            void *opaque)
-{
-    return bdrv_aio_flush(bs->file, cb, opaque);
-}
-
 typedef struct {
     Coroutine *co;
     int ret;
@@ -1562,7 +1555,6 @@ static BlockDriver bdrv_qed = {
     .bdrv_make_empty          = bdrv_qed_make_empty,
     .bdrv_aio_readv           = bdrv_qed_aio_readv,
     .bdrv_aio_writev          = bdrv_qed_aio_writev,
-    .bdrv_aio_flush           = bdrv_qed_aio_flush,
     .bdrv_co_write_zeroes     = bdrv_qed_co_write_zeroes,
     .bdrv_truncate            = bdrv_qed_truncate,
     .bdrv_getlength           = bdrv_qed_getlength,
diff --git a/block/raw.c b/block/raw.c
index 1cdac0c..7086e31 100644
--- a/block/raw.c
+++ b/block/raw.c
@@ -25,11 +25,6 @@ static void raw_close(BlockDriverState *bs)
 {
 }
 
-static int coroutine_fn raw_co_flush(BlockDriverState *bs)
-{
-    return bdrv_co_flush(bs->file);
-}
-
 static int64_t raw_getlength(BlockDriverState *bs)
 {
     return bdrv_getlength(bs->file);
@@ -113,7 +108,6 @@ static BlockDriver bdrv_raw = {
 
     .bdrv_co_readv          = raw_co_readv,
     .bdrv_co_writev         = raw_co_writev,
-    .bdrv_co_flush_to_disk  = raw_co_flush,
     .bdrv_co_discard        = raw_co_discard,
 
     .bdrv_probe         = raw_probe,
diff --git a/block/vdi.c b/block/vdi.c
index 6a0011f..f8fa865 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -930,13 +930,6 @@ static void vdi_close(BlockDriverState *bs)
     error_free(s->migration_blocker);
 }
 
-static coroutine_fn int vdi_co_flush(BlockDriverState *bs)
-{
-    logout("\n");
-    return bdrv_co_flush(bs->file);
-}
-
-
 static QEMUOptionParameter vdi_create_options[] = {
     {
         .name = BLOCK_OPT_SIZE,
@@ -969,7 +962,6 @@ static BlockDriver bdrv_vdi = {
     .bdrv_open = vdi_open,
     .bdrv_close = vdi_close,
     .bdrv_create = vdi_create,
-    .bdrv_co_flush_to_disk = vdi_co_flush,
     .bdrv_co_is_allocated = vdi_co_is_allocated,
     .bdrv_make_empty = vdi_make_empty,
 
diff --git a/block/vmdk.c b/block/vmdk.c
index 45c003a..18e9b4c 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1525,10 +1525,10 @@ static void vmdk_close(BlockDriverState *bs)
 
 static coroutine_fn int vmdk_co_flush(BlockDriverState *bs)
 {
-    int i, ret, err;
     BDRVVmdkState *s = bs->opaque;
+    int i, err;
+    int ret = 0;
 
-    ret = bdrv_co_flush(bs->file);
     for (i = 0; i < s->num_extents; i++) {
         err = bdrv_co_flush(s->extents[i].file);
         if (err < 0) {
diff --git a/block/vpc.c b/block/vpc.c
index 6b4816f..706faf3 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -507,11 +507,6 @@ static coroutine_fn int vpc_co_write(BlockDriverState *bs, int64_t sector_num,
     return ret;
 }
 
-static coroutine_fn int vpc_co_flush(BlockDriverState *bs)
-{
-    return bdrv_co_flush(bs->file);
-}
-
 /*
  * Calculates the number of cylinders, heads and sectors per cylinder
  * based on a given number of sectors. This is the algorithm described
@@ -789,7 +784,6 @@ static BlockDriver bdrv_vpc = {
 
     .bdrv_read              = vpc_co_read,
     .bdrv_write             = vpc_co_write,
-    .bdrv_co_flush_to_disk  = vpc_co_flush,
 
     .create_options = vpc_create_options,
 };
commit d7bb72c83cfbcfd0563e158800e4052819223524
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Mar 12 16:36:07 2012 +0000

    qemu-io: add option to enable tracing
    
    It can be useful to enable QEMU tracing when trying out block layer
    interfaces via qemu-io.  Tracing can be enabled using the new -T FILE
    option where the given file contains a list of trace events to enable
    (just like the qemu --trace events=FILE option).
    
      $ echo qemu_vfree >my-events
      $ ./qemu-io -T my-events ...
    
    Remember to use ./configure --enable-trace-backend=BACKEND when building
    qemu-io.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-io.c b/qemu-io.c
index 3189530..e6fcd77 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -17,6 +17,7 @@
 #include "qemu-common.h"
 #include "block_int.h"
 #include "cmd.h"
+#include "trace/control.h"
 
 #define VERSION	"0.0.1"
 
@@ -1783,6 +1784,7 @@ static void usage(const char *name)
 "  -g, --growable       allow file to grow (only applies to protocols)\n"
 "  -m, --misalign       misalign allocations for O_DIRECT\n"
 "  -k, --native-aio     use kernel AIO implementation (on Linux only)\n"
+"  -T, --trace FILE     enable trace events listed in the given file\n"
 "  -h, --help           display this help and exit\n"
 "  -V, --version        output version information and exit\n"
 "\n",
@@ -1794,7 +1796,7 @@ int main(int argc, char **argv)
 {
     int readonly = 0;
     int growable = 0;
-    const char *sopt = "hVc:rsnmgk";
+    const char *sopt = "hVc:rsnmgkT:";
     const struct option lopt[] = {
         { "help", 0, NULL, 'h' },
         { "version", 0, NULL, 'V' },
@@ -1806,6 +1808,7 @@ int main(int argc, char **argv)
         { "misalign", 0, NULL, 'm' },
         { "growable", 0, NULL, 'g' },
         { "native-aio", 0, NULL, 'k' },
+        { "trace", 1, NULL, 'T' },
         { NULL, 0, NULL, 0 }
     };
     int c;
@@ -1837,6 +1840,11 @@ int main(int argc, char **argv)
         case 'k':
             flags |= BDRV_O_NATIVE_AIO;
             break;
+        case 'T':
+            if (!trace_backend_init(optarg, NULL)) {
+                exit(1); /* error message will have been printed */
+            }
+            break;
         case 'V':
             printf("%s version %s\n", progname, VERSION);
             exit(0);
commit 3948d1d4876065160583e79533bf604481063833
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Mar 12 17:46:51 2012 +0100

    qcow2: Remove unused parameter in get_cluster_table()
    
    Since everything goes through the cache, callers don't use the L2 table
    offset any more.
    
    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 e0fb907..cbd224d 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -466,7 +466,6 @@ out:
  */
 static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
                              uint64_t **new_l2_table,
-                             uint64_t *new_l2_offset,
                              int *new_l2_index)
 {
     BDRVQcowState *s = bs->opaque;
@@ -514,7 +513,6 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
     l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
 
     *new_l2_table = l2_table;
-    *new_l2_offset = l2_offset;
     *new_l2_index = l2_index;
 
     return 0;
@@ -539,11 +537,11 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
 {
     BDRVQcowState *s = bs->opaque;
     int l2_index, ret;
-    uint64_t l2_offset, *l2_table;
+    uint64_t *l2_table;
     int64_t cluster_offset;
     int nb_csectors;
 
-    ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index);
+    ret = get_cluster_table(bs, offset, &l2_table, &l2_index);
     if (ret < 0) {
         return 0;
     }
@@ -588,7 +586,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
 {
     BDRVQcowState *s = bs->opaque;
     int i, j = 0, l2_index, ret;
-    uint64_t *old_cluster, start_sect, l2_offset, *l2_table;
+    uint64_t *old_cluster, start_sect, *l2_table;
     uint64_t cluster_offset = m->alloc_offset;
     bool cow = false;
 
@@ -633,7 +631,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
     }
 
     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);
+    ret = get_cluster_table(bs, m->offset, &l2_table, &l2_index);
     if (ret < 0) {
         goto err;
     }
@@ -817,7 +815,7 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
 {
     BDRVQcowState *s = bs->opaque;
     int l2_index, ret, sectors;
-    uint64_t l2_offset, *l2_table;
+    uint64_t *l2_table;
     unsigned int nb_clusters, keep_clusters;
     uint64_t cluster_offset;
 
@@ -825,7 +823,7 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
                                       n_start, n_end);
 
     /* Find L2 entry for the first involved cluster */
-    ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index);
+    ret = get_cluster_table(bs, offset, &l2_table, &l2_index);
     if (ret < 0) {
         return ret;
     }
@@ -1000,12 +998,12 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
     unsigned int nb_clusters)
 {
     BDRVQcowState *s = bs->opaque;
-    uint64_t l2_offset, *l2_table;
+    uint64_t *l2_table;
     int l2_index;
     int ret;
     int i;
 
-    ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index);
+    ret = get_cluster_table(bs, offset, &l2_table, &l2_index);
     if (ret < 0) {
         return ret;
     }
commit fa6b8733c93107d7fcd7018d1822e93ba9edaa94
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Mar 12 10:30:02 2012 +0100

    tracetool: Forbid argument name 'next'
    
    It has happened more than once that patches that look perfectly sane
    and work with simpletrace broke systemtap because they use 'next' as an
    argument name for a tracing function. However, 'next' is a keyword for
    systemtap, so we shouldn't use it.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/scripts/tracetool b/scripts/tracetool
index 47389b6..7b1c142 100755
--- a/scripts/tracetool
+++ b/scripts/tracetool
@@ -81,6 +81,10 @@ get_args()
     args=${1#*\(}
     args=${args%%\)*}
     echo "$args"
+
+    if (echo "$args" | grep "[ *]next\($\|[, ]\)" > /dev/null 2>&1); then
+        echo -e "\n#error 'next' is a bad argument name (clash with systemtap keyword)\n "
+    fi
 }
 
 # Get the argument name list of a trace event
commit bfe24e1a26d33d57df3c75e7f44273f0b0ca5943
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Mar 12 10:28:34 2012 +0100

    trace-events: Rename 'next' argument
    
    'next' is a systemtap keyword, so it's a bad idea to use it as an
    argument name.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/trace-events b/trace-events
index db2cd39..a5f276d 100644
--- a/trace-events
+++ b/trace-events
@@ -562,7 +562,7 @@ qemu_coroutine_terminate(void *co) "self %p"
 
 # qemu-coroutine-lock.c
 qemu_co_queue_next_bh(void) ""
-qemu_co_queue_next(void *next) "next %p"
+qemu_co_queue_next(void *nxt) "next %p"
 qemu_co_mutex_lock_entry(void *mutex, void *self) "mutex %p self %p"
 qemu_co_mutex_lock_return(void *mutex, void *self) "mutex %p self %p"
 qemu_co_mutex_unlock_entry(void *mutex, void *self) "mutex %p self %p"
commit 221b3a3f1e5edb9e41a48bfa384803800184b397
Author: Julien Grall <julien.grall at citrix.com>
Date:   Wed Apr 4 15:15:41 2012 +0100

    memory: check address space when a listener is registered
    
    This patch resolves a bug in memory listener registration.
    "range_add" callback  was called on each section of the both
    address space (IO and memory space) even if it doesn't match
    the address space filter.
    
    Signed-off-by: Julien Grall <julien.grall at citrix.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/memory.c b/memory.c
index a3f5b59..aab4a31 100644
--- a/memory.c
+++ b/memory.c
@@ -1444,6 +1444,11 @@ static void listener_add_address_space(MemoryListener *listener,
 {
     FlatRange *fr;
 
+    if (listener->address_space_filter
+        && listener->address_space_filter != as->root) {
+        return;
+    }
+
     if (global_dirty_log) {
         listener->log_global_start(listener);
     }
commit 8f8d364f2447e58768132fc10f48a67af371ee38
Merge: a7be9ba... b8ba679...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Wed Apr 4 20:45:03 2012 +0000

    Merge branch 's390-for-upstream' of git://repo.or.cz/qemu/agraf
    
    * 's390-for-upstream' of git://repo.or.cz/qemu/agraf:
      target-s390x: Update s390x_{tod,cpu}_timer() to use S390CPU
      target-s390x: QOM'ify CPU init
      target-s390x: QOM'ify CPU reset
      target-s390x: QOM'ify CPU

commit a7be9bad33d81d4bab2a51935b5443d258e7d082
Author: Artyom Tarasenko <atar4qemu at gmail.com>
Date:   Tue Apr 3 17:49:05 2012 +0200

    Improve interrupt handling priority
    
    The vector interrupt has higher priority than interrupt_level_n.
    Also check only interrupt_level_n concurency when TL > 0, the traps of
    other types may be nested.
    
    Signed-off-by: Artyom Tarasenko <atar4qemu at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/sun4u.c b/hw/sun4u.c
index 50bc0d2..fe33138 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -248,6 +248,10 @@ void cpu_check_irqs(CPUSPARCState *env)
     uint32_t pil = env->pil_in |
                   (env->softint & ~(SOFTINT_TIMER | SOFTINT_STIMER));
 
+    /* TT_IVEC has a higher priority (16) than TT_EXTINT (31..17) */
+    if (env->ivec_status & 0x20) {
+        return;
+    }
     /* check if TM or SM in SOFTINT are set
        setting these also causes interrupt 14 */
     if (env->softint & (SOFTINT_TIMER | SOFTINT_STIMER)) {
@@ -275,7 +279,8 @@ void cpu_check_irqs(CPUSPARCState *env)
                 int old_interrupt = env->interrupt_index;
                 int new_interrupt = TT_EXTINT | i;
 
-                if (env->tl > 0 && cpu_tsptr(env)->tt > new_interrupt) {
+                if (unlikely(env->tl > 0 && cpu_tsptr(env)->tt > new_interrupt
+                  && ((cpu_tsptr(env)->tt & 0x1f0) == TT_EXTINT))) {
                     CPUIRQ_DPRINTF("Not setting CPU IRQ: TL=%d "
                                    "current %x >= pending %x\n",
                                    env->tl, cpu_tsptr(env)->tt, new_interrupt);
commit 23cf96e1971f04f21ec4bb048df4d9e2e9933018
Author: Artyom Tarasenko <atar4qemu at gmail.com>
Date:   Tue Apr 3 17:49:04 2012 +0200

    Fix vector interrupt handling
    
    Don't produce stray irq 5, don't overwrite ivec_data if still busy with
    processing of the previous interrupt.
    
    Signed-off-by: Artyom Tarasenko <atar4qemu at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/sun4u.c b/hw/sun4u.c
index 237e20c..50bc0d2 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -309,19 +309,22 @@ static void cpu_set_ivec_irq(void *opaque, int irq, int level)
     CPUSPARCState *env = opaque;
 
     if (level) {
-        CPUIRQ_DPRINTF("Raise IVEC IRQ %d\n", irq);
-        env->interrupt_index = TT_IVEC;
-        env->pil_in |= 1 << 5;
-        env->ivec_status |= 0x20;
-        env->ivec_data[0] = (0x1f << 6) | irq;
-        env->ivec_data[1] = 0;
-        env->ivec_data[2] = 0;
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
-      } else {
-        CPUIRQ_DPRINTF("Lower IVEC IRQ %d\n", irq);
-        env->pil_in &= ~(1 << 5);
-        env->ivec_status &= ~0x20;
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        if (!(env->ivec_status & 0x20)) {
+            CPUIRQ_DPRINTF("Raise IVEC IRQ %d\n", irq);
+            env->halted = 0;
+            env->interrupt_index = TT_IVEC;
+            env->ivec_status |= 0x20;
+            env->ivec_data[0] = (0x1f << 6) | irq;
+            env->ivec_data[1] = 0;
+            env->ivec_data[2] = 0;
+            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        }
+    } else {
+        if (env->ivec_status & 0x20) {
+            CPUIRQ_DPRINTF("Lower IVEC IRQ %d\n", irq);
+            env->ivec_status &= ~0x20;
+            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        }
     }
 }
 
commit b8ba6799f41cccd1e81ec2986f2f80fc916ef86f
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon Apr 2 14:00:43 2012 +0200

    target-s390x: Update s390x_{tod,cpu}_timer() to use S390CPU
    
    In place of CPUS390XState pass S390CPU as opaque from the new initfn.
    cpu_interrupt() is anticipated to take a CPUState in the future.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Tested-by: Christian Borntraeger <borntraeger at de.ibm.com>

diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
index 72ec349..f183213 100644
--- a/target-s390x/cpu.c
+++ b/target-s390x/cpu.c
@@ -60,8 +60,8 @@ static void s390_cpu_initfn(Object *obj)
     env->tod_offset = TOD_UNIX_EPOCH +
                       (time2tod(mktimegm(&tm)) * 1000000000ULL);
     env->tod_basetime = 0;
-    env->tod_timer = qemu_new_timer_ns(vm_clock, s390x_tod_timer, env);
-    env->cpu_timer = qemu_new_timer_ns(vm_clock, s390x_cpu_timer, env);
+    env->tod_timer = qemu_new_timer_ns(vm_clock, s390x_tod_timer, cpu);
+    env->cpu_timer = qemu_new_timer_ns(vm_clock, s390x_cpu_timer, cpu);
 #endif
     env->cpu_num = cpu_num++;
     env->ext_index = -1;
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 6233f9a..209a696 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -53,7 +53,8 @@
 #ifndef CONFIG_USER_ONLY
 void s390x_tod_timer(void *opaque)
 {
-    CPUS390XState *env = opaque;
+    S390CPU *cpu = opaque;
+    CPUS390XState *env = &cpu->env;
 
     env->pending_int |= INTERRUPT_TOD;
     cpu_interrupt(env, CPU_INTERRUPT_HARD);
@@ -61,7 +62,8 @@ void s390x_tod_timer(void *opaque)
 
 void s390x_cpu_timer(void *opaque)
 {
-    CPUS390XState *env = opaque;
+    S390CPU *cpu = opaque;
+    CPUS390XState *env = &cpu->env;
 
     env->pending_int |= INTERRUPT_CPUTIMER;
     cpu_interrupt(env, CPU_INTERRUPT_HARD);
commit 8f22e0df803697c11e8b10c90cc2e67df6e42884
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon Apr 2 13:56:29 2012 +0200

    target-s390x: QOM'ify CPU init
    
    Move code from cpu_s390x_init() into an initfn.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Tested-by: Christian Borntraeger <borntraeger at de.ibm.com>

diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
index cae0b18..72ec349 100644
--- a/target-s390x/cpu.c
+++ b/target-s390x/cpu.c
@@ -45,6 +45,30 @@ static void s390_cpu_reset(CPUState *s)
     s390_add_running_cpu(env);
 }
 
+static void s390_cpu_initfn(Object *obj)
+{
+    S390CPU *cpu = S390_CPU(obj);
+    CPUS390XState *env = &cpu->env;
+    static int cpu_num = 0;
+#if !defined(CONFIG_USER_ONLY)
+    struct tm tm;
+#endif
+
+    cpu_exec_init(env);
+#if !defined(CONFIG_USER_ONLY)
+    qemu_get_timedate(&tm, 0);
+    env->tod_offset = TOD_UNIX_EPOCH +
+                      (time2tod(mktimegm(&tm)) * 1000000000ULL);
+    env->tod_basetime = 0;
+    env->tod_timer = qemu_new_timer_ns(vm_clock, s390x_tod_timer, env);
+    env->cpu_timer = qemu_new_timer_ns(vm_clock, s390x_cpu_timer, env);
+#endif
+    env->cpu_num = cpu_num++;
+    env->ext_index = -1;
+
+    cpu_reset(CPU(cpu));
+}
+
 static void s390_cpu_class_init(ObjectClass *oc, void *data)
 {
     S390CPUClass *scc = S390_CPU_CLASS(oc);
@@ -58,6 +82,7 @@ static const TypeInfo s390_cpu_type_info = {
     .name = TYPE_S390_CPU,
     .parent = TYPE_CPU,
     .instance_size = sizeof(S390CPU),
+    .instance_init = s390_cpu_initfn,
     .abstract = false,
     .class_size = sizeof(S390CPUClass),
     .class_init = s390_cpu_class_init,
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index c6ee959..2f3f394 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -288,6 +288,9 @@ int cpu_s390x_handle_mmu_fault (CPUS390XState *env, target_ulong address, int rw
 
 
 #ifndef CONFIG_USER_ONLY
+void s390x_tod_timer(void *opaque);
+void s390x_cpu_timer(void *opaque);
+
 int s390_virtio_hypercall(CPUS390XState *env, uint64_t mem, uint64_t hypercall);
 
 #ifdef CONFIG_KVM
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index cd3e8f5..6233f9a 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -51,7 +51,7 @@
 #endif
 
 #ifndef CONFIG_USER_ONLY
-static void s390x_tod_timer(void *opaque)
+void s390x_tod_timer(void *opaque)
 {
     CPUS390XState *env = opaque;
 
@@ -59,7 +59,7 @@ static void s390x_tod_timer(void *opaque)
     cpu_interrupt(env, CPU_INTERRUPT_HARD);
 }
 
-static void s390x_cpu_timer(void *opaque)
+void s390x_cpu_timer(void *opaque)
 {
     CPUS390XState *env = opaque;
 
@@ -72,32 +72,17 @@ CPUS390XState *cpu_s390x_init(const char *cpu_model)
 {
     S390CPU *cpu;
     CPUS390XState *env;
-#if !defined (CONFIG_USER_ONLY)
-    struct tm tm;
-#endif
     static int inited = 0;
-    static int cpu_num = 0;
 
     cpu = S390_CPU(object_new(TYPE_S390_CPU));
     env = &cpu->env;
-    cpu_exec_init(env);
+
     if (tcg_enabled() && !inited) {
         inited = 1;
         s390x_translate_init();
     }
 
-#if !defined(CONFIG_USER_ONLY)
-    qemu_get_timedate(&tm, 0);
-    env->tod_offset = TOD_UNIX_EPOCH +
-                      (time2tod(mktimegm(&tm)) * 1000000000ULL);
-    env->tod_basetime = 0;
-    env->tod_timer = qemu_new_timer_ns(vm_clock, s390x_tod_timer, env);
-    env->cpu_timer = qemu_new_timer_ns(vm_clock, s390x_cpu_timer, env);
-#endif
     env->cpu_model_str = cpu_model;
-    env->cpu_num = cpu_num++;
-    env->ext_index = -1;
-    cpu_reset(CPU(cpu));
     qemu_init_vcpu(env);
     return env;
 }
commit 1ac1a7499bcb44174735780e0bd0421a1ac7a323
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon Apr 2 13:31:59 2012 +0200

    target-s390x: QOM'ify CPU reset
    
    Move code from cpu_state_reset() to s390_cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Tested-by: Christian Borntraeger <borntraeger at de.ibm.com>

diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
index 94320f2..cae0b18 100644
--- a/target-s390x/cpu.c
+++ b/target-s390x/cpu.c
@@ -1,6 +1,8 @@
 /*
  * QEMU S/390 CPU
  *
+ * Copyright (c) 2009 Ulrich Hecht
+ * Copyright (c) 2011 Alexander Graf
  * Copyright (c) 2012 SUSE LINUX Products GmbH
  *
  * This library is free software; you can redistribute it and/or
@@ -23,15 +25,24 @@
 #include "qemu-timer.h"
 
 
+/* CPUClass::reset() */
 static void s390_cpu_reset(CPUState *s)
 {
     S390CPU *cpu = S390_CPU(s);
     S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
     CPUS390XState *env = &cpu->env;
 
+    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+        log_cpu_state(env, 0);
+    }
+
     scc->parent_reset(s);
 
-    cpu_state_reset(env);
+    memset(env, 0, offsetof(CPUS390XState, breakpoints));
+    /* FIXME: reset vector? */
+    tlb_flush(env, 1);
+    s390_add_running_cpu(env);
 }
 
 static void s390_cpu_class_init(ObjectClass *oc, void *data)
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index ae57ab3..cd3e8f5 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -97,7 +97,7 @@ CPUS390XState *cpu_s390x_init(const char *cpu_model)
     env->cpu_model_str = cpu_model;
     env->cpu_num = cpu_num++;
     env->ext_index = -1;
-    cpu_state_reset(env);
+    cpu_reset(CPU(cpu));
     qemu_init_vcpu(env);
     return env;
 }
@@ -123,15 +123,7 @@ int cpu_s390x_handle_mmu_fault (CPUS390XState *env, target_ulong address, int rw
 
 void cpu_state_reset(CPUS390XState *env)
 {
-    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
-        log_cpu_state(env, 0);
-    }
-
-    memset(env, 0, offsetof(CPUS390XState, breakpoints));
-    /* FIXME: reset vector? */
-    tlb_flush(env, 1);
-    s390_add_running_cpu(env);
+    cpu_reset(ENV_GET_CPU(env));
 }
 
 #ifndef CONFIG_USER_ONLY
commit 29e4bcb26b80f975920508c83a9f24f29eb6bc1a
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon Apr 2 11:39:23 2012 +0200

    target-s390x: QOM'ify CPU
    
    Embed CPUS390XState as first member of S390CPU.
    Since -cpu is being ignored, make TYPE_S390_CPU non-abstract.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Tested-by: Christian Borntraeger <borntraeger at de.ibm.com>

diff --git a/Makefile.target b/Makefile.target
index cff15f0..999a968 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -93,6 +93,7 @@ libobj-$(TARGET_SPARC64) += vis_helper.o
 libobj-$(CONFIG_NEED_MMU) += mmu.o
 libobj-$(TARGET_ARM) += neon_helper.o iwmmxt_helper.o
 libobj-$(TARGET_ARM) += cpu.o
+libobj-$(TARGET_S390X) += cpu.o
 ifeq ($(TARGET_BASE_ARCH), sparc)
 libobj-y += fop_helper.o cc_helper.o win_helper.o mmu_helper.o ldst_helper.o
 libobj-y += cpu_init.o
diff --git a/target-s390x/cpu-qom.h b/target-s390x/cpu-qom.h
new file mode 100644
index 0000000..6fa55a8
--- /dev/null
+++ b/target-s390x/cpu-qom.h
@@ -0,0 +1,71 @@
+/*
+ * QEMU S/390 CPU
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * 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.1 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/lgpl-2.1.html>
+ */
+#ifndef QEMU_S390_CPU_QOM_H
+#define QEMU_S390_CPU_QOM_H
+
+#include "qemu/cpu.h"
+#include "cpu.h"
+
+#define TYPE_S390_CPU "s390-cpu"
+
+#define S390_CPU_CLASS(klass) \
+    OBJECT_CLASS_CHECK(S390CPUClass, (klass), TYPE_S390_CPU)
+#define S390_CPU(obj) \
+    OBJECT_CHECK(S390CPU, (obj), TYPE_S390_CPU)
+#define S390_CPU_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(S390CPUClass, (obj), TYPE_S390_CPU)
+
+/**
+ * S390CPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * An S/390 CPU model.
+ */
+typedef struct S390CPUClass {
+    /*< private >*/
+    CPUClass parent_class;
+    /*< public >*/
+
+    void (*parent_reset)(CPUState *cpu);
+} S390CPUClass;
+
+/**
+ * S390CPU:
+ * @env: #CPUS390XState.
+ *
+ * An S/390 CPU.
+ */
+typedef struct S390CPU {
+    /*< private >*/
+    CPUState parent_obj;
+    /*< public >*/
+
+    CPUS390XState env;
+} S390CPU;
+
+static inline S390CPU *s390_env_get_cpu(CPUS390XState *env)
+{
+    return S390_CPU(container_of(env, S390CPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(s390_env_get_cpu(e))
+
+
+#endif
diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
new file mode 100644
index 0000000..94320f2
--- /dev/null
+++ b/target-s390x/cpu.c
@@ -0,0 +1,60 @@
+/*
+ * QEMU S/390 CPU
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * 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.1 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/lgpl-2.1.html>
+ */
+
+#include "cpu-qom.h"
+#include "qemu-common.h"
+#include "qemu-timer.h"
+
+
+static void s390_cpu_reset(CPUState *s)
+{
+    S390CPU *cpu = S390_CPU(s);
+    S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
+    CPUS390XState *env = &cpu->env;
+
+    scc->parent_reset(s);
+
+    cpu_state_reset(env);
+}
+
+static void s390_cpu_class_init(ObjectClass *oc, void *data)
+{
+    S390CPUClass *scc = S390_CPU_CLASS(oc);
+    CPUClass *cc = CPU_CLASS(scc);
+
+    scc->parent_reset = cc->reset;
+    cc->reset = s390_cpu_reset;
+}
+
+static const TypeInfo s390_cpu_type_info = {
+    .name = TYPE_S390_CPU,
+    .parent = TYPE_CPU,
+    .instance_size = sizeof(S390CPU),
+    .abstract = false,
+    .class_size = sizeof(S390CPUClass),
+    .class_init = s390_cpu_class_init,
+};
+
+static void s390_cpu_register_types(void)
+{
+    type_register_static(&s390_cpu_type_info);
+}
+
+type_init(s390_cpu_register_types)
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index ea849fc..c6ee959 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -991,4 +991,6 @@ static inline void cpu_pc_from_tb(CPUS390XState *env, TranslationBlock* tb)
     env->psw.addr = tb->pc;
 }
 
+#include "cpu-qom.h"
+
 #endif
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 44d5048..ae57ab3 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -70,6 +70,7 @@ static void s390x_cpu_timer(void *opaque)
 
 CPUS390XState *cpu_s390x_init(const char *cpu_model)
 {
+    S390CPU *cpu;
     CPUS390XState *env;
 #if !defined (CONFIG_USER_ONLY)
     struct tm tm;
@@ -77,7 +78,8 @@ CPUS390XState *cpu_s390x_init(const char *cpu_model)
     static int inited = 0;
     static int cpu_num = 0;
 
-    env = g_malloc0(sizeof(CPUS390XState));
+    cpu = S390_CPU(object_new(TYPE_S390_CPU));
+    env = &cpu->env;
     cpu_exec_init(env);
     if (tcg_enabled() && !inited) {
         inited = 1;
commit 53fbf7b5391c76cc474d469bfed6a69a1243f4de
Author: Anthony PERARD <anthony.perard at citrix.com>
Date:   Mon Apr 2 16:10:39 2012 +0100

    make: fix clean rule by removing build file in qom/
    
    Make clean does not clean the 'qom' directory, leaving *.o and *.d files. This
    patch fixes this.
    
    Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/Makefile b/Makefile
index 35c7a2a..a78f53d 100644
--- a/Makefile
+++ b/Makefile
@@ -217,6 +217,7 @@ clean:
 	rm -f *.o *.d *.a *.lo $(TOOLS) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~
 	rm -Rf .libs
 	rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d block/*.o block/*.d net/*.o net/*.d fsdev/*.o fsdev/*.d ui/*.o ui/*.d qapi/*.o qapi/*.d qga/*.o qga/*.d
+	rm -f qom/*.o qom/*.d
 	rm -f qemu-img-cmds.h
 	rm -f trace/*.o trace/*.d
 	rm -f trace.c trace.h trace.c-timestamp trace.h-timestamp
commit c9a2e37c7d70e1b1f11997f7ecab202393bff9fc
Author: Lluís Vilanova <vilanova at ac.upc.edu>
Date:   Mon Apr 2 14:49:49 2012 +0200

    configure: Link qga against UST tracing related libraries
    
    Signed-off-by: Harsh Prateek Bora <harsh at linux.vnet.ibm.com>
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/configure b/configure
index 319355b..520bd93 100755
--- a/configure
+++ b/configure
@@ -2673,6 +2673,7 @@ int main(void) { return 0; }
 EOF
   if compile_prog "" "" ; then
     LIBS="-lust -lurcu-bp $LIBS"
+    libs_qga="-lust -lurcu-bp $libs_qga"
   else
     echo
     echo "Error: Trace backend 'ust' missing libust header files"
commit 94b4fefae6aa8ee7739b2b9ad6ef14a07baf78be
Author: Lluís Vilanova <vilanova at ac.upc.edu>
Date:   Mon Apr 2 14:49:44 2012 +0200

    configure: Link QEMU against 'liburcu-bp'
    
    This library is needed when using 'ust/tracepoint.h'.
    
    Signed-off-by: Harsh Prateek Bora <harsh at linux.vnet.ibm.com>
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/configure b/configure
index c0a542b..319355b 100755
--- a/configure
+++ b/configure
@@ -2672,7 +2672,7 @@ if test "$trace_backend" = "ust"; then
 int main(void) { return 0; }
 EOF
   if compile_prog "" "" ; then
-    LIBS="-lust $LIBS"
+    LIBS="-lust -lurcu-bp $LIBS"
   else
     echo
     echo "Error: Trace backend 'ust' missing libust header files"
commit a92433afcc1e48b0ba7a014bb6d2f0a7cd416a31
Author: Frediano Ziglio <freddy77 at gmail.com>
Date:   Sat Mar 31 19:32:14 2012 +0100

    main-loop: make qemu_event_handle static
    
    Signed-off-by: Frediano Ziglio <freddy77 at gmail.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/main-loop.c b/main-loop.c
index db23de0..fc738d1 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -164,7 +164,7 @@ static int qemu_signal_init(void)
 
 #else /* _WIN32 */
 
-HANDLE qemu_event_handle = NULL;
+static HANDLE qemu_event_handle = NULL;
 
 static void dummy_event_handler(void *opaque)
 {
commit fb7c8e8a2d3ac99c9310a01d17a2b46584320bc9
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Mar 31 17:34:41 2012 +0200

    block/curl: Replace usleep by g_usleep
    
    The function usleep is not available for all supported platforms:
    at least some versions of MinGW don't support it.
    
    usleep was also declared obsolete by POSIX.1-2001.
    
    The function g_usleep is part of glib2.0, so it is available for
    all supported platforms.
    
    Using nanosleep would also be possible but needs more code.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block/curl.c b/block/curl.c
index e9102e3..a909eca 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -282,7 +282,7 @@ static CURLState *curl_init_state(BDRVCURLState *s)
             break;
         }
         if (!state) {
-            usleep(100);
+            g_usleep(100);
             curl_multi_do(s);
         }
     } while(!state);
commit 3f97fd851cf7b16b822c2c366e02708070f713bb
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Mar 31 17:11:31 2012 +0200

    qtest: Add missing GCC_FMT_ATTR
    
    gcc reports an error when the code is compiled with -Wmissing-format-attribute.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/qtest.c b/qtest.c
index daeabb7..18afcd9 100644
--- a/qtest.c
+++ b/qtest.c
@@ -156,7 +156,8 @@ static void qtest_send_prefix(CharDriverState *chr)
             tv.tv_sec, tv.tv_usec);
 }
 
-static void qtest_send(CharDriverState *chr, const char *fmt, ...)
+static void GCC_FMT_ATTR(2, 3) qtest_send(CharDriverState *chr,
+                                          const char *fmt, ...)
 {
     va_list ap;
     char buffer[1024];
commit 6cec29c4a0338bfd96dec42cce51c9c447facb23
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Mar 28 20:56:38 2012 +0200

    w32: Undefine error constants before their redefinition
    
    Avoids lots of warnings.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/qemu_socket.h b/qemu_socket.h
index fe4cf6c..51ad210 100644
--- a/qemu_socket.h
+++ b/qemu_socket.h
@@ -8,7 +8,9 @@
 #include <ws2tcpip.h>
 
 #define socket_error() WSAGetLastError()
+#undef EWOULDBLOCK
 #undef EINTR
+#undef EINPROGRESS
 #define EWOULDBLOCK WSAEWOULDBLOCK
 #define EINTR       WSAEINTR
 #define EINPROGRESS WSAEINPROGRESS
commit 368542b8356038593c4d394d87ee086ef65a6da3
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Tue Mar 27 08:26:18 2012 +0100

    configure: fix mingw32 libs_qga typo
    
    It's typical to prepend or append parameters to an argument string so
    that other places in ./configure can add parameters without clobbering
    the string.  In the mingw32 libs_qga case there is a typo "$lib_qga"
    instead of "$libs_qga".
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>

diff --git a/configure b/configure
index 4b3adc9..c0a542b 100755
--- a/configure
+++ b/configure
@@ -526,7 +526,7 @@ EOF
   bindir="\${prefix}"
   sysconfdir="\${prefix}"
   confsuffix=""
-  libs_qga="-lws2_32 -lwinmm -lpowrprof $lib_qga"
+  libs_qga="-lws2_32 -lwinmm -lpowrprof $libs_qga"
 fi
 
 werror=""
commit f05f6b4adb4db3affb0cdd17383b0a7e905e66e1
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Mar 28 16:34:12 2012 +0200

    qdev: put all devices under /machine
    
    Avoid cluttering too much the QOM root.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 9017565..179d9a6 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -276,7 +276,7 @@ static PCIBus *i440fx_common_init(const char *device_name,
     b = pci_bus_new(&s->busdev.qdev, NULL, pci_address_space,
                     address_space_io, 0);
     s->bus = b;
-    object_property_add_child(object_get_root(), "i440fx", OBJECT(dev), NULL);
+    object_property_add_child(qdev_get_machine(), "i440fx", OBJECT(dev), NULL);
     qdev_init_nofail(dev);
 
     d = pci_create_simple(b, 0, device_name);
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 86c9336..9d8e659 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -615,7 +615,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
     sys = sysbus_from_qdev(dev);
     pcihost = DO_UPCAST(PCIHostState, busdev, sys);
     pcihost->address_space = get_system_memory();
-    object_property_add_child(object_get_root(), "raven", OBJECT(dev), NULL);
+    object_property_add_child(qdev_get_machine(), "raven", OBJECT(dev), NULL);
     qdev_init_nofail(dev);
     pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
     if (pci_bus == NULL) {
diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c
index 031cb83..4783366 100644
--- a/hw/qdev-monitor.c
+++ b/hw/qdev-monitor.c
@@ -180,7 +180,7 @@ static Object *qdev_get_peripheral(void)
     static Object *dev;
 
     if (dev == NULL) {
-        dev = container_get("/peripheral");
+        dev = container_get("/machine/peripheral");
     }
 
     return dev;
@@ -191,7 +191,7 @@ static Object *qdev_get_peripheral_anon(void)
     static Object *dev;
 
     if (dev == NULL) {
-        dev = container_get("/peripheral-anon");
+        dev = container_get("/machine/peripheral-anon");
     }
 
     return dev;
diff --git a/hw/qdev.c b/hw/qdev.c
index f5c716e..0d3c0fc 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -157,7 +157,7 @@ int qdev_init(DeviceState *dev)
         static int unattached_count = 0;
         gchar *name = g_strdup_printf("device[%d]", unattached_count++);
 
-        object_property_add_child(container_get("/unattached"), name,
+        object_property_add_child(container_get("/machine/unattached"), name,
                                   OBJECT(dev), NULL);
         g_free(name);
     }
@@ -668,6 +668,17 @@ void device_reset(DeviceState *dev)
     }
 }
 
+Object *qdev_get_machine(void)
+{
+    static Object *dev;
+
+    if (dev == NULL) {
+        dev = container_get("/machine");
+    }
+
+    return dev;
+}
+
 static TypeInfo device_type_info = {
     .name = TYPE_DEVICE,
     .parent = TYPE_OBJECT,
diff --git a/hw/qdev.h b/hw/qdev.h
index 9cc3f98..a8df42f 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -349,6 +349,8 @@ BusInfo *qdev_get_bus_info(DeviceState *dev);
 
 Property *qdev_get_props(DeviceState *dev);
 
+Object *qdev_get_machine(void);
+
 /* FIXME: make this a link<> */
 void qdev_set_parent_bus(DeviceState *dev, BusState *bus);
 
commit da57febfed7bad11be79f047b59719c38abd0712
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Mar 27 18:38:47 2012 +0200

    qdev: give all devices a canonical path
    
    A strong limitation of QOM right now is that unconverted ports
    (e.g. all...) do not give a canonical path to devices that are
    part of the board.  This in turn makes it impossible to replace
    PROP_PTR with a QOM link for example.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index ee21d90..f5c716e 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -113,14 +113,14 @@ DeviceState *qdev_create(BusState *bus, const char *name)
     return dev;
 }
 
-DeviceState *qdev_try_create(BusState *bus, const char *name)
+DeviceState *qdev_try_create(BusState *bus, const char *type)
 {
     DeviceState *dev;
 
-    if (object_class_by_name(name) == NULL) {
+    if (object_class_by_name(type) == NULL) {
         return NULL;
     }
-    dev = DEVICE(object_new(name));
+    dev = DEVICE(object_new(type));
     if (!dev) {
         return NULL;
     }
@@ -152,6 +152,16 @@ int qdev_init(DeviceState *dev)
         qdev_free(dev);
         return rc;
     }
+
+    if (!OBJECT(dev)->parent) {
+        static int unattached_count = 0;
+        gchar *name = g_strdup_printf("device[%d]", unattached_count++);
+
+        object_property_add_child(container_get("/unattached"), name,
+                                  OBJECT(dev), NULL);
+        g_free(name);
+    }
+
     if (qdev_get_vmsd(dev)) {
         vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
                                        dev->instance_id_alias,
commit f424d5c4c9de67b56594384eac3c08dc33de9344
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Mar 27 18:38:46 2012 +0200

    qdev: add children before qdev_init
    
    We want the composition tree to to be in order by the time we call
    qdev_init, so that a single set of the toplevel realize property can
    propagate all the way down the composition tree.
    
    This is not the case so far.  Unfortunately, this is incompatible
    with calling qdev_init in the constructor wrappers for devices,
    so for now we need to unattach some devices that are created through
    those wrappers.  This will be fixed by removing qdev_init and instead
    setting the toplevel realize property after machine init.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index ec5118f..fadca4c 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -149,7 +149,6 @@ static void pc_init1(MemoryRegion *system_memory,
     MemoryRegion *ram_memory;
     MemoryRegion *pci_memory;
     MemoryRegion *rom_memory;
-    DeviceState *dev;
 
     pc_cpus_init(cpu_model);
 
@@ -227,11 +226,7 @@ static void pc_init1(MemoryRegion *system_memory,
 
     pc_register_ferr_irq(gsi[13]);
 
-    dev = pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL);
-    if (dev) {
-        object_property_add_child(object_get_root(), "vga", OBJECT(dev), NULL);
-    }
-
+    pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL);
     if (xen_enabled()) {
         pci_create_simple(pci_bus, -1, "xen-platform");
     }
@@ -258,17 +253,6 @@ static void pc_init1(MemoryRegion *system_memory,
         }
         idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
         idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
-
-        /* FIXME there's some major spaghetti here.  Somehow we create the
-         * devices on the PIIX before we actually create it.  We create the
-         * PIIX3 deep in the recess of the i440fx creation too and then lose
-         * the DeviceState.
-         *
-         * For now, let's "fix" this by making judicious use of paths.  This
-         * is not generally the right way to do this.
-         */
-        object_property_add_child(object_resolve_path("/i440fx/piix3", NULL),
-                                  "rtc", (Object *)rtc_state, NULL);
     } else {
         for(i = 0; i < MAX_IDE_BUS; i++) {
             ISADevice *dev;
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index e0268fe..9017565 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -276,8 +276,8 @@ static PCIBus *i440fx_common_init(const char *device_name,
     b = pci_bus_new(&s->busdev.qdev, NULL, pci_address_space,
                     address_space_io, 0);
     s->bus = b;
-    qdev_init_nofail(dev);
     object_property_add_child(object_get_root(), "i440fx", OBJECT(dev), NULL);
+    qdev_init_nofail(dev);
 
     d = pci_create_simple(b, 0, device_name);
     *pi440fx_state = DO_UPCAST(PCII440FXState, dev, d);
@@ -316,7 +316,6 @@ static PCIBus *i440fx_common_init(const char *device_name,
         pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3,
                 PIIX_NUM_PIRQS);
     }
-    object_property_add_child(OBJECT(dev), "piix3", OBJECT(piix3), NULL);
     piix3->pic = pic;
     *isa_bus = DO_UPCAST(ISABus, qbus,
                          qdev_get_child_bus(&piix3->dev.qdev, "isa.0"));
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 06d589d..86c9336 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -615,8 +615,8 @@ static void ppc_prep_init (ram_addr_t ram_size,
     sys = sysbus_from_qdev(dev);
     pcihost = DO_UPCAST(PCIHostState, busdev, sys);
     pcihost->address_space = get_system_memory();
-    qdev_init_nofail(dev);
     object_property_add_child(object_get_root(), "raven", OBJECT(dev), NULL);
+    qdev_init_nofail(dev);
     pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
     if (pci_bus == NULL) {
         fprintf(stderr, "Couldn't create PCI host controller.\n");
diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c
index 2e82962..031cb83 100644
--- a/hw/qdev-monitor.c
+++ b/hw/qdev-monitor.c
@@ -458,10 +458,6 @@ DeviceState *qdev_device_add(QemuOpts *opts)
         qdev_free(qdev);
         return NULL;
     }
-    if (qdev_init(qdev) < 0) {
-        qerror_report(QERR_DEVICE_INIT_FAILED, driver);
-        return NULL;
-    }
     if (qdev->id) {
         object_property_add_child(qdev_get_peripheral(), qdev->id,
                                   OBJECT(qdev), NULL);
@@ -472,6 +468,10 @@ DeviceState *qdev_device_add(QemuOpts *opts)
                                   OBJECT(qdev), NULL);
         g_free(name);
     }        
+    if (qdev_init(qdev) < 0) {
+        qerror_report(QERR_DEVICE_INIT_FAILED, driver);
+        return NULL;
+    }
     qdev->opts = opts;
     return qdev;
 }
commit a612b2a6635fa1a3a29a8bcf41b31f1f3fae1110
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Mar 27 18:38:45 2012 +0200

    qom: add container_get
    
    This is QOM "mkdir -p".  It is useful when referring to
    container objects such as "/machine".
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c
index a310cc7..2e82962 100644
--- a/hw/qdev-monitor.c
+++ b/hw/qdev-monitor.c
@@ -180,9 +180,7 @@ static Object *qdev_get_peripheral(void)
     static Object *dev;
 
     if (dev == NULL) {
-        dev = object_new("container");
-        object_property_add_child(object_get_root(), "peripheral",
-                                  OBJECT(dev), NULL);
+        dev = container_get("/peripheral");
     }
 
     return dev;
@@ -193,9 +191,7 @@ static Object *qdev_get_peripheral_anon(void)
     static Object *dev;
 
     if (dev == NULL) {
-        dev = object_new("container");
-        object_property_add_child(object_get_root(), "peripheral-anon",
-                                  OBJECT(dev), NULL);
+        dev = container_get("/peripheral-anon");
     }
 
     return dev;
diff --git a/include/qemu/object.h b/include/qemu/object.h
index e8fc126..a675937 100644
--- a/include/qemu/object.h
+++ b/include/qemu/object.h
@@ -837,6 +837,18 @@ Object *object_resolve_path_type(const char *path, const char *typename,
                                  bool *ambiguous);
 
 /**
+ * object_resolve_path_component:
+ * @parent: the object in which to resolve the path
+ * @part: the component to resolve.
+ *
+ * This is similar to object_resolve_path with an absolute path, but it
+ * only resolves one element (@part) and takes the others from @parent.
+ *
+ * Returns: The resolved object or NULL on path lookup failure.
+ */
+Object *object_resolve_path_component(Object *parent, gchar *part);
+
+/**
  * object_property_add_child:
  * @obj: the object to add a property to
  * @name: the name of the property
@@ -891,4 +903,16 @@ void object_property_add_str(Object *obj, const char *name,
                              void (*set)(Object *, const char *, struct Error **),
                              struct Error **errp);
 
+/**
+ * container_get:
+ * @path: path to the container
+ *
+ * Return a container object whose path is @path.  Create more containers
+ * along the path if necessary.
+ *
+ * Returns: the container object.
+ */
+Object *container_get(const char *path);
+
+
 #endif
diff --git a/qom/container.c b/qom/container.c
index f107208..67e9e8a 100644
--- a/qom/container.c
+++ b/qom/container.c
@@ -12,6 +12,7 @@
 
 #include "qemu/object.h"
 #include "module.h"
+#include <assert.h>
 
 static TypeInfo container_info = {
     .name          = "container",
@@ -24,4 +25,26 @@ static void container_register_types(void)
     type_register_static(&container_info);
 }
 
+Object *container_get(const char *path)
+{
+    Object *obj, *child;
+    gchar **parts;
+    int i;
+
+    parts = g_strsplit(path, "/", 0);
+    assert(parts != NULL && parts[0] != NULL && !parts[0][0]);
+    obj = object_get_root();
+
+    for (i = 1; parts[i] != NULL; i++, obj = child) {
+        child = object_resolve_path_component(obj, parts[i]);
+        if (!child) {
+            child = object_new("container");
+            object_property_add_child(obj, parts[i], child, NULL);
+        }
+    }
+
+    return obj;
+}
+
+
 type_init(container_register_types)
diff --git a/qom/object.c b/qom/object.c
index 9cd9506..e721fc2 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1022,12 +1022,27 @@ gchar *object_get_canonical_path(Object *obj)
     return newpath;
 }
 
+Object *object_resolve_path_component(Object *parent, gchar *part)
+{
+    ObjectProperty *prop = object_property_find(parent, part);
+    if (prop == NULL) {
+        return NULL;
+    }
+
+    if (strstart(prop->type, "link<", NULL)) {
+        return *(Object **)prop->opaque;
+    } else if (strstart(prop->type, "child<", NULL)) {
+        return prop->opaque;
+    } else {
+        return NULL;
+    }
+}
+
 static Object *object_resolve_abs_path(Object *parent,
                                           gchar **parts,
                                           const char *typename,
                                           int index)
 {
-    ObjectProperty *prop;
     Object *child;
 
     if (parts[index] == NULL) {
@@ -1038,21 +1053,7 @@ static Object *object_resolve_abs_path(Object *parent,
         return object_resolve_abs_path(parent, parts, typename, index + 1);
     }
 
-    prop = object_property_find(parent, parts[index]);
-    if (prop == NULL) {
-        return NULL;
-    }
-
-    child = NULL;
-    if (strstart(prop->type, "link<", NULL)) {
-        Object **pchild = prop->opaque;
-        if (*pchild) {
-            child = *pchild;
-        }
-    } else if (strstart(prop->type, "child<", NULL)) {
-        child = prop->opaque;
-    }
-
+    child = object_resolve_path_component(parent, parts[index]);
     if (!child) {
         return NULL;
     }
commit cefc898806e0346eef87d15ddaac9475b57b7d84
Merge: aba8e41... 8607301...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Apr 2 09:46:45 2012 -0500

    Merge remote-tracking branch 'kiszka/queues/slirp' into staging
    
    * kiszka/queues/slirp:
      slirp: Signal free input buffer space to io-thread
      w32/slirp: Undefine error constants before their redefinition
      slirp: use socket_set_nonblock
      slirp: clean up conflicts with system headers

commit aba8e41e8666e4c0287cef1f6298985d4e03211d
Merge: dfe844c... 703e01e...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Apr 2 09:44:35 2012 -0500

    Merge remote-tracking branch 'stefanha/tracing' into staging
    
    * stefanha/tracing:
      tracetool: dtrace: handle in and next reserved words
      tracetool: dtrace disabled-events fix
      Makefile.target: code stp dependency on trace-events

commit dfe844c9043815497b6472bfaf470b0f8d2e7312
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Sun Apr 1 14:18:30 2012 -0500

    serial: clear LSR.TEMT when populating the TSR
    
    We never actually clear the TEMT (transmit sending register empty) flag when
    populating the TSR.  We set the flag, but since it's never cleared, setting it
    is sort of pointless..
    
    I found this with a unit test case.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/serial.c b/hw/serial.c
index b499bca..a421d1e 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -332,6 +332,7 @@ static void serial_xmit(void *opaque)
         } else {
             s->tsr = s->thr;
             s->lsr |= UART_LSR_THRE;
+            s->lsr &= ~UART_LSR_TEMT;
         }
     }
 
commit 67c5322d7000fd105a926eec44bc1765b7d70bdd
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Sun Apr 1 14:03:21 2012 -0500

    serial: fix retry logic
    
    I'm not sure if the retry logic has ever worked when not using FIFO mode.  I
    found this while writing a test case although code inspection confirms it is
    definitely broken.
    
    The TSR retry logic will never actually happen because it is guarded by an
    'if (s->tsr_rety > 0)' but this is the only place that can ever make the
    variable greater than zero.  That effectively makes the retry logic an 'if (0)'.
    
    I believe this is a typo and the intention was >= 0.  Once this is fixed though,
    I see double transmits with my test case.  This is because in the non FIFO
    case, serial_xmit may get invoked while LSR.THRE is still high because the
    character was processed but the retransmit timer was still active.
    
    We can handle this by simply checking for LSR.THRE and returning early.  It's
    possible that the FIFO paths also need some attention.
    
    Cc: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/serial.c b/hw/serial.c
index c0ee55d..b499bca 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -327,6 +327,8 @@ static void serial_xmit(void *opaque)
             s->tsr = fifo_get(s,XMIT_FIFO);
             if (!s->xmit_fifo.count)
                 s->lsr |= UART_LSR_THRE;
+        } else if ((s->lsr & UART_LSR_THRE)) {
+            return;
         } else {
             s->tsr = s->thr;
             s->lsr |= UART_LSR_THRE;
@@ -337,7 +339,7 @@ static void serial_xmit(void *opaque)
         /* in loopback mode, say that we just received a char */
         serial_receive1(s, &s->tsr, 1);
     } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1) {
-        if ((s->tsr_retry > 0) && (s->tsr_retry <= MAX_XMIT_RETRY)) {
+        if ((s->tsr_retry >= 0) && (s->tsr_retry <= MAX_XMIT_RETRY)) {
             s->tsr_retry++;
             qemu_mod_timer(s->transmit_timer,  new_xmit_ts + s->char_transmit_time);
             return;
commit 6e92466a7c16bc5a33a674b76964f4b1ac7fa44d
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Mar 30 14:04:04 2012 -0500

    qtest: use qemu_gettimeofday()
    
    On linux, qemu_timeval will always be two long ints.  On windows, we use our
    own struct definition.  This should fix win64.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qtest.c b/qtest.c
index cd7186c..daeabb7 100644
--- a/qtest.c
+++ b/qtest.c
@@ -31,7 +31,7 @@ static FILE *qtest_log_fp;
 static CharDriverState *qtest_chr;
 static GString *inbuf;
 static int irq_levels[MAX_IRQ];
-static struct timeval start_time;
+static qemu_timeval start_time;
 static bool qtest_opened;
 
 #define FMT_timeval "%ld.%06ld"
@@ -132,9 +132,9 @@ static int hex2nib(char ch)
     }
 }
 
-static void qtest_get_time(struct timeval *tv)
+static void qtest_get_time(qemu_timeval *tv)
 {
-    gettimeofday(tv, NULL);
+    qemu_gettimeofday(tv);
     tv->tv_sec -= start_time.tv_sec;
     tv->tv_usec -= start_time.tv_usec;
     if (tv->tv_usec < 0) {
@@ -145,7 +145,7 @@ static void qtest_get_time(struct timeval *tv)
 
 static void qtest_send_prefix(CharDriverState *chr)
 {
-    struct timeval tv;
+    qemu_timeval tv;
 
     if (!qtest_log_fp || !qtest_opened) {
         return;
@@ -195,7 +195,7 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
     command = words[0];
 
     if (qtest_log_fp) {
-        struct timeval tv;
+        qemu_timeval tv;
         int i;
 
         qtest_get_time(&tv);
@@ -394,7 +394,7 @@ static void qtest_event(void *opaque, int event)
         for (i = 0; i < ARRAY_SIZE(irq_levels); i++) {
             irq_levels[i] = 0;
         }
-        gettimeofday(&start_time, NULL);
+        qemu_gettimeofday(&start_time);
         qtest_opened = true;
         if (qtest_log_fp) {
             fprintf(qtest_log_fp, "[I " FMT_timeval "] OPENED\n",
@@ -404,7 +404,7 @@ static void qtest_event(void *opaque, int event)
     case CHR_EVENT_CLOSED:
         qtest_opened = false;
         if (qtest_log_fp) {
-            struct timeval tv;
+            qemu_timeval tv;
             qtest_get_time(&tv);
             fprintf(qtest_log_fp, "[I +" FMT_timeval "] CLOSED\n",
                     tv.tv_sec, tv.tv_usec);
commit a3b6181e42ef5713c684283c0187abaa11ef1eaf
Author: Michael Walle <michael at walle.cc>
Date:   Sat Mar 31 19:55:25 2012 +0200

    milkymist-vgafb: add missing register
    
    This bug existed since the first commit. Fortunately, the affected
    registers have no functionality in qemu. This will only prevent the
    following warning:
      milkymist_vgafb: write access to unknown register 0x00000034
    
    Signed-off-by: Michael Walle <michael at walle.cc>

diff --git a/hw/milkymist-vgafb.c b/hw/milkymist-vgafb.c
index 69afd72..cd4365d 100644
--- a/hw/milkymist-vgafb.c
+++ b/hw/milkymist-vgafb.c
@@ -2,7 +2,7 @@
 /*
  *  QEMU model of the Milkymist VGA framebuffer.
  *
- *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *  Copyright (c) 2010-2012 Michael Walle <michael at walle.cc>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -54,6 +54,7 @@ enum {
     R_BASEADDRESS,
     R_BASEADDRESS_ACT,
     R_BURST_COUNT,
+    R_DDC,
     R_SOURCE_CLOCK,
     R_MAX
 };
@@ -173,6 +174,7 @@ static uint64_t vgafb_read(void *opaque, target_phys_addr_t addr,
     case R_VSCAN:
     case R_BASEADDRESS:
     case R_BURST_COUNT:
+    case R_DDC:
     case R_SOURCE_CLOCK:
         r = s->regs[addr];
     break;
@@ -211,6 +213,7 @@ static void vgafb_write(void *opaque, target_phys_addr_t addr, uint64_t value,
     case R_VSYNC_END:
     case R_VSCAN:
     case R_BURST_COUNT:
+    case R_DDC:
     case R_SOURCE_CLOCK:
         s->regs[addr] = value;
         break;
commit 79368f4984eefcbed5d714c6131e58fd71178030
Author: Michael Walle <michael at walle.cc>
Date:   Sat Mar 31 19:54:20 2012 +0200

    target-lm32: add simple disassembler
    
    Because binutils disassembler is based on libopcode, this is a rewrite from
    scratch.
    
    Signed-off-by: Michael Walle <michael at walle.cc>

diff --git a/Makefile.objs b/Makefile.objs
index e9842b0..f308b57 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -365,6 +365,7 @@ libdis-$(CONFIG_PPC_DIS) += ppc-dis.o
 libdis-$(CONFIG_S390_DIS) += s390-dis.o
 libdis-$(CONFIG_SH4_DIS) += sh4-dis.o
 libdis-$(CONFIG_SPARC_DIS) += sparc-dis.o
+libdis-$(CONFIG_LM32_DIS) += lm32-dis.o
 
 ######################################################################
 # trace
diff --git a/configure b/configure
index 4ef5ec6..4b3adc9 100755
--- a/configure
+++ b/configure
@@ -3770,6 +3770,10 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
     echo "CONFIG_IA64_DIS=y"  >> $config_target_mak
     echo "CONFIG_IA64_DIS=y"  >> $libdis_config_mak
   ;;
+  lm32)
+    echo "CONFIG_LM32_DIS=y"  >> $config_target_mak
+    echo "CONFIG_LM32_DIS=y"  >> $libdis_config_mak
+  ;;
   m68k)
     echo "CONFIG_M68K_DIS=y"  >> $config_target_mak
     echo "CONFIG_M68K_DIS=y"  >> $libdis_config_mak
diff --git a/dis-asm.h b/dis-asm.h
index 4f15fad..3944b3c 100644
--- a/dis-asm.h
+++ b/dis-asm.h
@@ -221,6 +221,8 @@ enum bfd_architecture
   bfd_arch_ia64,      /* HP/Intel ia64 */
 #define bfd_mach_ia64_elf64    64
 #define bfd_mach_ia64_elf32    32
+  bfd_arch_lm32,       /* Lattice Mico32 */
+#define bfd_mach_lm32 1
   bfd_arch_last
   };
 #define bfd_mach_s390_31 31
@@ -404,6 +406,7 @@ 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*);
+int print_insn_lm32             (bfd_vma, disassemble_info*);
 
 #if 0
 /* Fetch the disassembler for a given BFD, if that support is available.  */
diff --git a/disas.c b/disas.c
index 4945c44..9485824 100644
--- a/disas.c
+++ b/disas.c
@@ -220,6 +220,9 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
 #elif defined(TARGET_MICROBLAZE)
     disasm_info.mach = bfd_arch_microblaze;
     print_insn = print_insn_microblaze;
+#elif defined(TARGET_LM32)
+    disasm_info.mach = bfd_mach_lm32;
+    print_insn = print_insn_lm32;
 #else
     fprintf(out, "0x" TARGET_FMT_lx
 	    ": Asm output not supported on this arch\n", code);
@@ -421,6 +424,9 @@ void monitor_disas(Monitor *mon, CPUArchState *env,
 #elif defined(TARGET_S390X)
     disasm_info.mach = bfd_mach_s390_64;
     print_insn = print_insn_s390;
+#elif defined(TARGET_LM32)
+    disasm_info.mach = bfd_mach_lm32;
+    print_insn = print_insn_lm32;
 #else
     monitor_printf(mon, "0x" TARGET_FMT_lx
                    ": Asm output not supported on this arch\n", pc);
diff --git a/lm32-dis.c b/lm32-dis.c
new file mode 100644
index 0000000..709ed32
--- /dev/null
+++ b/lm32-dis.c
@@ -0,0 +1,361 @@
+/*
+ *  Simple LatticeMico32 disassembler.
+ *
+ *  Copyright (c) 2012 Michael Walle <michael at walle.cc>
+ *
+ * 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/>.
+ *
+ */
+
+#include <stdio.h>
+#include "dis-asm.h"
+
+typedef enum {
+    LM32_OP_SRUI = 0, LM32_OP_NORI, LM32_OP_MULI, LM32_OP_SH, LM32_OP_LB,
+    LM32_OP_SRI, LM32_OP_XORI, LM32_OP_LH, LM32_OP_ANDI, LM32_OP_XNORI,
+    LM32_OP_LW, LM32_OP_LHU, LM32_OP_SB, LM32_OP_ADDI, LM32_OP_ORI,
+    LM32_OP_SLI, LM32_OP_LBU, LM32_OP_BE, LM32_OP_BG, LM32_OP_BGE,
+    LM32_OP_BGEU, LM32_OP_BGU, LM32_OP_SW, LM32_OP_BNE, LM32_OP_ANDHI,
+    LM32_OP_CMPEI, LM32_OP_CMPGI, LM32_OP_CMPGEI, LM32_OP_CMPGEUI,
+    LM32_OP_CMPGUI, LM32_OP_ORHI, LM32_OP_CMPNEI, LM32_OP_SRU, LM32_OP_NOR,
+    LM32_OP_MUL, LM32_OP_DIVU, LM32_OP_RCSR, LM32_OP_SR, LM32_OP_XOR,
+    LM32_OP_ILL0, LM32_OP_AND, LM32_OP_XNOR, LM32_OP_ILL1, LM32_OP_SCALL,
+    LM32_OP_SEXTB, LM32_OP_ADD, LM32_OP_OR, LM32_OP_SL, LM32_OP_B,
+    LM32_OP_MODU, LM32_OP_SUB, LM32_OP_ILL2, LM32_OP_WCSR, LM32_OP_ILL3,
+    LM32_OP_CALL, LM32_OP_SEXTH, LM32_OP_BI, LM32_OP_CMPE, LM32_OP_CMPG,
+    LM32_OP_CMPGE, LM32_OP_CMPGEU, LM32_OP_CMPGU, LM32_OP_CALLI, LM32_OP_CMPNE,
+} Lm32Opcode;
+
+typedef enum {
+    FMT_INVALID = 0, FMT_RRI5, FMT_RRI16, FMT_IMM26, FMT_LOAD, FMT_STORE,
+    FMT_RRR, FMT_R, FMT_RNR, FMT_CRN, FMT_CNR, FMT_BREAK,
+} Lm32OpcodeFmt;
+
+typedef enum {
+    LM32_CSR_IE = 0, LM32_CSR_IM, LM32_CSR_IP, LM32_CSR_ICC, LM32_CSR_DCC,
+    LM32_CSR_CC, LM32_CSR_CFG, LM32_CSR_EBA, LM32_CSR_DC, LM32_CSR_DEBA,
+    LM32_CSR_CFG2, LM32_CSR_JTX = 0xe, LM32_CSR_JRX, LM32_CSR_BP0,
+    LM32_CSR_BP1, LM32_CSR_BP2, LM32_CSR_BP3, LM32_CSR_WP0 = 0x18,
+    LM32_CSR_WP1, LM32_CSR_WP2, LM32_CSR_WP3,
+} Lm32CsrNum;
+
+typedef struct {
+    int csr;
+    const char *name;
+} Lm32CsrInfo;
+
+static const Lm32CsrInfo lm32_csr_info[] = {
+    {LM32_CSR_IE,   "ie", },
+    {LM32_CSR_IM,   "im", },
+    {LM32_CSR_IP,   "ip", },
+    {LM32_CSR_ICC,  "icc", },
+    {LM32_CSR_DCC,  "dcc", },
+    {LM32_CSR_CC,   "cc", },
+    {LM32_CSR_CFG,  "cfg", },
+    {LM32_CSR_EBA,  "eba", },
+    {LM32_CSR_DC,   "dc", },
+    {LM32_CSR_DEBA, "deba", },
+    {LM32_CSR_CFG2, "cfg2", },
+    {LM32_CSR_JTX,  "jtx", },
+    {LM32_CSR_JRX,  "jrx", },
+    {LM32_CSR_BP0,  "bp0", },
+    {LM32_CSR_BP1,  "bp1", },
+    {LM32_CSR_BP2,  "bp2", },
+    {LM32_CSR_BP3,  "bp3", },
+    {LM32_CSR_WP0,  "wp0", },
+    {LM32_CSR_WP1,  "wp1", },
+    {LM32_CSR_WP2,  "wp2", },
+    {LM32_CSR_WP3,  "wp3", },
+};
+
+static const Lm32CsrInfo *find_csr_info(int csr)
+{
+    const Lm32CsrInfo *info;
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(lm32_csr_info); i++) {
+        info = &lm32_csr_info[i];
+        if (csr == info->csr) {
+            return info;
+        }
+    }
+
+    return NULL;
+}
+
+typedef struct {
+    int reg;
+    const char *name;
+} Lm32RegInfo;
+
+typedef enum {
+    LM32_REG_R0 = 0, LM32_REG_R1, LM32_REG_R2, LM32_REG_R3, LM32_REG_R4,
+    LM32_REG_R5, LM32_REG_R6, LM32_REG_R7, LM32_REG_R8, LM32_REG_R9,
+    LM32_REG_R10, LM32_REG_R11, LM32_REG_R12, LM32_REG_R13, LM32_REG_R14,
+    LM32_REG_R15, LM32_REG_R16, LM32_REG_R17, LM32_REG_R18, LM32_REG_R19,
+    LM32_REG_R20, LM32_REG_R21, LM32_REG_R22, LM32_REG_R23, LM32_REG_R24,
+    LM32_REG_R25, LM32_REG_GP, LM32_REG_FP, LM32_REG_SP, LM32_REG_RA,
+    LM32_REG_EA, LM32_REG_BA,
+} Lm32RegNum;
+
+static const Lm32RegInfo lm32_reg_info[] = {
+    {LM32_REG_R0,  "r0", },
+    {LM32_REG_R1,  "r1", },
+    {LM32_REG_R2,  "r2", },
+    {LM32_REG_R3,  "r3", },
+    {LM32_REG_R4,  "r4", },
+    {LM32_REG_R5,  "r5", },
+    {LM32_REG_R6,  "r6", },
+    {LM32_REG_R7,  "r7", },
+    {LM32_REG_R8,  "r8", },
+    {LM32_REG_R9,  "r9", },
+    {LM32_REG_R10, "r10", },
+    {LM32_REG_R11, "r11", },
+    {LM32_REG_R12, "r12", },
+    {LM32_REG_R13, "r13", },
+    {LM32_REG_R14, "r14", },
+    {LM32_REG_R15, "r15", },
+    {LM32_REG_R16, "r16", },
+    {LM32_REG_R17, "r17", },
+    {LM32_REG_R18, "r18", },
+    {LM32_REG_R19, "r19", },
+    {LM32_REG_R20, "r20", },
+    {LM32_REG_R21, "r21", },
+    {LM32_REG_R22, "r22", },
+    {LM32_REG_R23, "r23", },
+    {LM32_REG_R24, "r24", },
+    {LM32_REG_R25, "r25", },
+    {LM32_REG_GP,  "gp", },
+    {LM32_REG_FP,  "fp", },
+    {LM32_REG_SP,  "sp", },
+    {LM32_REG_RA,  "ra", },
+    {LM32_REG_EA,  "ea", },
+    {LM32_REG_BA,  "ba", },
+};
+
+static const Lm32RegInfo *find_reg_info(int reg)
+{
+    assert(ARRAY_SIZE(lm32_reg_info) == 32);
+    return &lm32_reg_info[reg & 0x1f];
+}
+
+typedef struct {
+    struct {
+        uint32_t code;
+        uint32_t mask;
+    } op;
+    const char *name;
+    const char *args_fmt;
+} Lm32OpcodeInfo;
+
+static const Lm32OpcodeInfo lm32_opcode_info[] = {
+    /* pseudo instructions */
+    {{0x34000000, 0xffffffff}, "nop",   NULL},
+    {{0xac000002, 0xffffffff}, "break", NULL},
+    {{0xac000003, 0xffffffff}, "scall", NULL},
+    {{0xc3e00000, 0xffffffff}, "bret",  NULL},
+    {{0xc3c00000, 0xffffffff}, "eret",  NULL},
+    {{0xc3a00000, 0xffffffff}, "ret",   NULL},
+    {{0xa4000000, 0xfc1f07ff}, "not",   "%2, %0"},
+    {{0xb8000000, 0xfc1f07ff}, "mv",    "%2, %0"},
+    {{0x71e00000, 0xffe00000}, "mvhi",  "%1, %u"},
+    {{0x34000000, 0xffe00000}, "mvi",   "%1, %s"},
+
+#define _O(op) {op << 26, 0x3f << 26}
+    /* regular opcodes */
+    {_O(LM32_OP_ADD),     "add",     "%2, %0, %1"  },
+    {_O(LM32_OP_ADDI),    "addi",    "%1, %0, %s"  },
+    {_O(LM32_OP_AND),     "and",     "%2, %0, %1"  },
+    {_O(LM32_OP_ANDHI),   "andhi",   "%1, %0, %u"  },
+    {_O(LM32_OP_ANDI),    "andi",    "%1, %0, %u"  },
+    {_O(LM32_OP_B),       "b",       "%0",         },
+    {_O(LM32_OP_BE),      "be",      "%1, %0, %r"  },
+    {_O(LM32_OP_BG),      "bg",      "%1, %0, %r"  },
+    {_O(LM32_OP_BGE),     "bge",     "%1, %0, %r"  },
+    {_O(LM32_OP_BGEU),    "bgeu",    "%1, %0, %r"  },
+    {_O(LM32_OP_BGU),     "bgu",     "%1, %0, %r"  },
+    {_O(LM32_OP_BI),      "bi",      "%R",         },
+    {_O(LM32_OP_BNE),     "bne",     "%1, %0, %r"  },
+    {_O(LM32_OP_CALL),    "call",    "%0",         },
+    {_O(LM32_OP_CALLI),   "calli",   "%R",         },
+    {_O(LM32_OP_CMPE),    "cmpe",    "%2, %0, %1"  },
+    {_O(LM32_OP_CMPEI),   "cmpei",   "%1, %0, %s"  },
+    {_O(LM32_OP_CMPG),    "cmpg",    "%2, %0, %1"  },
+    {_O(LM32_OP_CMPGE),   "cmpge",   "%2, %0, %1"  },
+    {_O(LM32_OP_CMPGEI),  "cmpgei",  "%1, %0, %s"  },
+    {_O(LM32_OP_CMPGEU),  "cmpgeu",  "%2, %0, %1"  },
+    {_O(LM32_OP_CMPGEUI), "cmpgeui", "%1, %0, %s"  },
+    {_O(LM32_OP_CMPGI),   "cmpgi",   "%1, %0, %s"  },
+    {_O(LM32_OP_CMPGU),   "cmpgu",   "%2, %0, %1"  },
+    {_O(LM32_OP_CMPGUI),  "cmpgui",  "%1, %0, %s"  },
+    {_O(LM32_OP_CMPNE),   "cmpne",   "%2, %0, %1"  },
+    {_O(LM32_OP_CMPNEI),  "cmpnei",  "%1, %0, %s"  },
+    {_O(LM32_OP_DIVU),    "divu",    "%2, %0, %1"  },
+    {_O(LM32_OP_LB),      "lb",      "%1, (%0+%s)" },
+    {_O(LM32_OP_LBU),     "lbu",     "%1, (%0+%s)" },
+    {_O(LM32_OP_LH),      "lh",      "%1, (%0+%s)" },
+    {_O(LM32_OP_LHU),     "lhu",     "%1, (%0+%s)" },
+    {_O(LM32_OP_LW),      "lw",      "%1, (%0+%s)" },
+    {_O(LM32_OP_MODU),    "modu",    "%2, %0, %1"  },
+    {_O(LM32_OP_MULI),    "muli",    "%1, %0, %s"  },
+    {_O(LM32_OP_MUL),     "mul",     "%2, %0, %1"  },
+    {_O(LM32_OP_NORI),    "nori",    "%1, %0, %u"  },
+    {_O(LM32_OP_NOR),     "nor",     "%2, %0, %1"  },
+    {_O(LM32_OP_ORHI),    "orhi",    "%1, %0, %u"  },
+    {_O(LM32_OP_ORI),     "ori",     "%1, %0, %u"  },
+    {_O(LM32_OP_OR),      "or",      "%2, %0, %1"  },
+    {_O(LM32_OP_RCSR),    "rcsr",    "%2, %c",     },
+    {_O(LM32_OP_SB),      "sb",      "(%0+%s), %1" },
+    {_O(LM32_OP_SEXTB),   "sextb",   "%2, %0",     },
+    {_O(LM32_OP_SEXTH),   "sexth",   "%2, %0",     },
+    {_O(LM32_OP_SH),      "sh",      "(%0+%s), %1" },
+    {_O(LM32_OP_SLI),     "sli",     "%1, %0, %h"  },
+    {_O(LM32_OP_SL),      "sl",      "%2, %0, %1"  },
+    {_O(LM32_OP_SRI),     "sri",     "%1, %0, %h"  },
+    {_O(LM32_OP_SR),      "sr",      "%2, %0, %1"  },
+    {_O(LM32_OP_SRUI),    "srui",    "%1, %0, %d"  },
+    {_O(LM32_OP_SRU),     "sru",     "%2, %0, %s"  },
+    {_O(LM32_OP_SUB),     "sub",     "%2, %0, %s"  },
+    {_O(LM32_OP_SW),      "sw",      "(%0+%s), %1" },
+    {_O(LM32_OP_WCSR),    "wcsr",    "%c, %1",     },
+    {_O(LM32_OP_XNORI),   "xnori",   "%1, %0, %u"  },
+    {_O(LM32_OP_XNOR),    "xnor",    "%2, %0, %1"  },
+    {_O(LM32_OP_XORI),    "xori",    "%1, %0, %u"  },
+    {_O(LM32_OP_XOR),     "xor",     "%2, %0, %1"  },
+#undef _O
+};
+
+static const Lm32OpcodeInfo *find_opcode_info(uint32_t opcode)
+{
+    const Lm32OpcodeInfo *info;
+    int i;
+    for (i = 0; i < ARRAY_SIZE(lm32_opcode_info); i++) {
+        info = &lm32_opcode_info[i];
+        if ((opcode & info->op.mask) == info->op.code) {
+            return info;
+        }
+    }
+
+    return NULL;
+}
+
+int print_insn_lm32(bfd_vma memaddr, struct disassemble_info *info)
+{
+    fprintf_function fprintf_fn = info->fprintf_func;
+    void *stream = info->stream;
+    int rc;
+    uint8_t insn[4];
+    const Lm32OpcodeInfo *opc_info;
+    uint32_t op;
+    const char *args_fmt;
+
+    rc = info->read_memory_func(memaddr, insn, 4, info);
+    if (rc != 0) {
+        info->memory_error_func(rc, memaddr, info);
+        return -1;
+    }
+
+    fprintf_fn(stream, "%02x %02x %02x %02x    ",
+            insn[0], insn[1], insn[2], insn[3]);
+
+    op = bfd_getb32(insn);
+    opc_info = find_opcode_info(op);
+    if (opc_info) {
+        fprintf_fn(stream, "%-8s ", opc_info->name);
+        args_fmt = opc_info->args_fmt;
+        while (args_fmt && *args_fmt) {
+            if (*args_fmt == '%') {
+                switch (*(++args_fmt)) {
+                case '0': {
+                    uint8_t r0;
+                    const char *r0_name;
+                    r0 = (op >> 21) & 0x1f;
+                    r0_name = find_reg_info(r0)->name;
+                    fprintf_fn(stream, "%s", r0_name);
+                    break;
+                }
+                case '1': {
+                    uint8_t r1;
+                    const char *r1_name;
+                    r1 = (op >> 16) & 0x1f;
+                    r1_name = find_reg_info(r1)->name;
+                    fprintf_fn(stream, "%s", r1_name);
+                    break;
+                }
+                case '2': {
+                    uint8_t r2;
+                    const char *r2_name;
+                    r2 = (op >> 11) & 0x1f;
+                    r2_name = find_reg_info(r2)->name;
+                    fprintf_fn(stream, "%s", r2_name);
+                    break;
+                }
+                case 'c': {
+                    uint8_t csr;
+                    const char *csr_name;
+                    csr = (op >> 21) & 0x1f;
+                    csr_name = find_csr_info(csr)->name;
+                    if (csr_name) {
+                        fprintf_fn(stream, "%s", csr_name);
+                    } else {
+                        fprintf_fn(stream, "0x%x", csr);
+                    }
+                    break;
+                }
+                case 'u': {
+                    uint16_t u16;
+                    u16 = op & 0xffff;
+                    fprintf_fn(stream, "0x%x", u16);
+                    break;
+                }
+                case 's': {
+                    int16_t s16;
+                    s16 = (int16_t)(op & 0xffff);
+                    fprintf_fn(stream, "%d", s16);
+                    break;
+                }
+                case 'r': {
+                    uint32_t rela;
+                    rela = memaddr + (((int16_t)(op & 0xffff)) << 2);
+                    fprintf_fn(stream, "%x", rela);
+                    break;
+                }
+                case 'R': {
+                    uint32_t rela;
+                    int32_t imm26;
+                    imm26 = (int32_t)((op & 0x3ffffff) << 6) >> 4;
+                    rela = memaddr + imm26;
+                    fprintf_fn(stream, "%x", rela);
+                    break;
+                }
+                case 'h': {
+                    uint8_t u5;
+                    u5 = (op & 0x1f);
+                    fprintf_fn(stream, "%d", u5);
+                    break;
+                }
+                default:
+                    break;
+                }
+            } else {
+                fprintf_fn(stream, "%c", *args_fmt);
+            }
+            args_fmt++;
+        }
+    } else {
+        fprintf_fn(stream, ".word 0x%x", op);
+    }
+
+    return 4;
+}
commit 060544d30f4cc94bced1186e1b042960aebcdfea
Author: Michael Walle <michael at walle.cc>
Date:   Sat Mar 31 19:54:09 2012 +0200

    milkymist-sysctl: support for new core version
    
    The new version introduces the following new registers:
     - SoC clock frequency: read-only of system clock used on the SoC
     - debug scratchpad: 8 bit scratchpad register
     - debug write lock: write once register, without any function on QEMU
    
    Signed-off-by: Michael Walle <michael at walle.cc>

diff --git a/hw/milkymist-sysctl.c b/hw/milkymist-sysctl.c
index a88548e..8878d2b 100644
--- a/hw/milkymist-sysctl.c
+++ b/hw/milkymist-sysctl.c
@@ -1,7 +1,7 @@
 /*
  *  QEMU model of the Milkymist System Controller.
  *
- *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *  Copyright (c) 2010-2012 Michael Walle <michael at walle.cc>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -39,20 +39,19 @@ enum {
 };
 
 enum {
-    R_GPIO_IN = 0,
+    R_GPIO_IN         = 0,
     R_GPIO_OUT,
     R_GPIO_INTEN,
-    R_RESERVED0,
-    R_TIMER0_CONTROL,
+    R_TIMER0_CONTROL  = 4,
     R_TIMER0_COMPARE,
     R_TIMER0_COUNTER,
-    R_RESERVED1,
-    R_TIMER1_CONTROL,
+    R_TIMER1_CONTROL  = 8,
     R_TIMER1_COMPARE,
     R_TIMER1_COUNTER,
-    R_RESERVED2,
-    R_RESERVED3,
-    R_ICAP,
+    R_ICAP = 16,
+    R_DBG_SCRATCHPAD  = 20,
+    R_DBG_WRITE_LOCK,
+    R_CLK_FREQUENCY   = 29,
     R_CAPABILITIES,
     R_SYSTEM_ID,
     R_MAX
@@ -116,6 +115,9 @@ static uint64_t sysctl_read(void *opaque, target_phys_addr_t addr,
     case R_TIMER1_CONTROL:
     case R_TIMER1_COMPARE:
     case R_ICAP:
+    case R_DBG_SCRATCHPAD:
+    case R_DBG_WRITE_LOCK:
+    case R_CLK_FREQUENCY:
     case R_CAPABILITIES:
     case R_SYSTEM_ID:
         r = s->regs[addr];
@@ -145,6 +147,7 @@ static void sysctl_write(void *opaque, target_phys_addr_t addr, uint64_t value,
     case R_GPIO_INTEN:
     case R_TIMER0_COUNTER:
     case R_TIMER1_COUNTER:
+    case R_DBG_SCRATCHPAD:
         s->regs[addr] = value;
         break;
     case R_TIMER0_COMPARE:
@@ -182,11 +185,15 @@ static void sysctl_write(void *opaque, target_phys_addr_t addr, uint64_t value,
     case R_ICAP:
         sysctl_icap_write(s, value);
         break;
+    case R_DBG_WRITE_LOCK:
+        s->regs[addr] = 1;
+        break;
     case R_SYSTEM_ID:
         qemu_system_reset_request();
         break;
 
     case R_GPIO_IN:
+    case R_CLK_FREQUENCY:
     case R_CAPABILITIES:
         error_report("milkymist_sysctl: write to read-only register 0x"
                 TARGET_FMT_plx, addr << 2);
@@ -253,6 +260,7 @@ static void milkymist_sysctl_reset(DeviceState *d)
     /* defaults */
     s->regs[R_ICAP] = ICAP_READY;
     s->regs[R_SYSTEM_ID] = s->systemid;
+    s->regs[R_CLK_FREQUENCY] = s->freq_hz;
     s->regs[R_CAPABILITIES] = s->capabilities;
     s->regs[R_GPIO_IN] = s->strappings;
 }
commit de89fd2b885358e649dc38e293d18eecdb78e1ab
Author: Michael Walle <michael at walle.cc>
Date:   Sat Mar 31 19:54:05 2012 +0200

    target-lm32: init tcg only if available
    
    Once qtest support for target-lm32 arrives, tcg may be disabled.
    
    Signed-off-by: Michael Walle <michael at walle.cc>

diff --git a/target-lm32/helper.c b/target-lm32/helper.c
index 5db8f8d..78076e4 100644
--- a/target-lm32/helper.c
+++ b/target-lm32/helper.c
@@ -215,7 +215,7 @@ CPULM32State *cpu_lm32_init(const char *cpu_model)
     cpu_state_reset(env);
     qemu_init_vcpu(env);
 
-    if (!tcg_initialized) {
+    if (tcg_enabled() && !tcg_initialized) {
         tcg_initialized = 1;
         lm32_translate_init();
     }
commit 927b241d66c17501013ccea9f1b56a3d9c7ebb79
Author: Michael Walle <michael at walle.cc>
Date:   Sat Mar 31 19:53:51 2012 +0200

    tests: fix out-of-tree building for lm32 target
    
    Signed-off-by: Michael Walle <michael at walle.cc>

diff --git a/configure b/configure
index b51a749..4ef5ec6 100755
--- a/configure
+++ b/configure
@@ -3876,7 +3876,8 @@ echo "QEMU_INCLUDES+=$includes" >> $config_target_mak
 done # for target in $targets
 
 # build tree in object directory in case the source is not in the current directory
-DIRS="tests tests/tcg tests/tcg/cris slirp audio block net pc-bios/optionrom"
+DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32"
+DIRS="$DIRS slirp audio block net pc-bios/optionrom"
 DIRS="$DIRS pc-bios/spapr-rtas"
 DIRS="$DIRS roms/seabios roms/vgabios"
 DIRS="$DIRS fsdev ui usb"
@@ -3884,6 +3885,7 @@ DIRS="$DIRS qapi qapi-generated"
 DIRS="$DIRS qga trace qom"
 FILES="Makefile tests/tcg/Makefile qdict-test-data.txt"
 FILES="$FILES tests/tcg/cris/Makefile tests/tcg/cris/.gdbinit"
+FILES="$FILES tests/tcg/lm32/Makefile"
 FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
 FILES="$FILES pc-bios/spapr-rtas/Makefile"
 FILES="$FILES roms/seabios/Makefile roms/vgabios/Makefile"
diff --git a/tests/tcg/lm32/Makefile b/tests/tcg/lm32/Makefile
index 03a1abb..9a00ef7 100644
--- a/tests/tcg/lm32/Makefile
+++ b/tests/tcg/lm32/Makefile
@@ -1,4 +1,4 @@
--include ../../config-host.mak
+-include ../../../config-host.mak
 
 CROSS=lm32-elf-
 
@@ -12,7 +12,10 @@ SIZE    = $(CROSS)size
 LD      = $(CC)
 OBJCOPY = $(CROSS)objcopy
 
-LDFLAGS = -Tlinker.ld
+TSRC_PATH = $(SRC_PATH)/tests/tcg/lm32
+
+LDFLAGS = -T$(TSRC_PATH)/linker.ld
+ASFLAGS += -Wa,-I,$(TSRC_PATH)/
 
 CRT        = crt.o
 TESTCASES += test_add.tst
@@ -82,13 +85,13 @@ TESTCASES += test_xori.tst
 
 all: build
 
-%.o: $(SRC_PATH)/tests/lm32/%.c
+%.o: $(TSRC_PATH)/%.c
 	$(CC) $(CFLAGS) -c $< -o $@
 
-%.o: $(SRC_PATH)/tests/lm32/%.S
+%.o: $(TSRC_PATH)/%.S
 	$(AS) $(ASFLAGS) -c $< -o $@
 
-%.tst: %.o macros.inc $(CRT)
+%.tst: %.o $(TSRC_PATH)/macros.inc $(CRT)
 	$(LD) $(LDFLAGS) $(NOSTDFLAGS) $(CRT) $< -o $@
 
 build: $(CRT) $(TESTCASES)
commit b7c8e15a146a7b20021b524f41d6b8072ee093b5
Merge: 4dec465... b0f2663...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Mar 31 12:10:07 2012 +0000

    Merge branch 'arm-devs.for-upstream' of git://git.linaro.org/people/pmaydell/qemu-arm
    
    * 'arm-devs.for-upstream' of git://git.linaro.org/people/pmaydell/qemu-arm:
      pl031: switch clock base to rtc_clock
      pl031: rearm alarm timer upon load
      arm: switch real-time clocks to rtc_clock
      omap: switch omap_lpg to vm_clock
      rtc: add -rtc clock=rt

commit 4dec4654604e7e52964ff0201c46d85d179ed35f
Merge: e7c5601... 8df9082...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Mar 31 12:09:06 2012 +0000

    Merge branch 'qom-cpu-unicore32.v3' of git://github.com/afaerber/qemu-cpu
    
    * 'qom-cpu-unicore32.v3' of git://github.com/afaerber/qemu-cpu:
      target-unicore32: Move CPU-dependent init into initfn
      target-unicore32: QOM'ify CPU
      target-unicore32: License future contributions under GPLv2+
      target-unicore32: Relicense to GPLv2+
      MAINTAINERS: Add entry for UniCore32

commit e7c56016f998f9a55012c71e0168c406b50589e6
Merge: 94dd53c... 06ed5d6...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Mar 31 12:06:10 2012 +0000

    Merge branch 'target-arm.for-upstream' of git://git.linaro.org/people/pmaydell/qemu-arm
    
    * 'target-arm.for-upstream' of git://git.linaro.org/people/pmaydell/qemu-arm:
      ARM: Permit any ARMv6K CPU to read the MVFR0 and MVFR1 VFP registers.
      target-arm: Minimalistic CPU QOM'ification
      target-arm: Drop cpu_arm_close()

commit 94dd53c5b6c7b6cfc496a9a49cb73630ce0d6dd1
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Mar 29 10:55:18 2012 +0200

    buildfix: check for old pod2man versions
    
    Older pod2man don't have a --utf8 switch, check for this in conffigure
    and use it only when present.  Fixes build on RHEL-5.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile b/Makefile
index d8e1f36..35c7a2a 100644
--- a/Makefile
+++ b/Makefile
@@ -348,7 +348,6 @@ QMP/qmp-commands.txt: $(SRC_PATH)/qmp-commands.hx
 qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx
 	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"  GEN   $@")
 
-POD2MAN = pod2man --utf8
 qemu.1: qemu-doc.texi qemu-options.texi qemu-monitor.texi
 	$(call quiet-command, \
 	  perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< qemu.pod && \
diff --git a/configure b/configure
index dd01911..b51a749 100755
--- a/configure
+++ b/configure
@@ -2821,6 +2821,13 @@ if test "$solaris" = "no" ; then
     fi
 fi
 
+# test if pod2man has --utf8 option
+if pod2man --help | grep -q utf8; then
+    POD2MAN="pod2man --utf8"
+else
+    POD2MAN="pod2man"
+fi
+
 # Use ASLR, no-SEH and DEP if available
 if test "$mingw32" = "yes" ; then
     for flag in --dynamicbase --no-seh --nxcompat; do
@@ -3358,6 +3365,7 @@ echo "LIBS+=$LIBS" >> $config_host_mak
 echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak
 echo "EXESUF=$EXESUF" >> $config_host_mak
 echo "LIBS_QGA+=$libs_qga" >> $config_host_mak
+echo "POD2MAN=$POD2MAN" >> $config_host_mak
 
 # generate list of library paths for linker script
 
commit bb55b712e8dc4d4eb515144d5c26798fea178cba
Author: Stefan Weil <sw at weilnetz.de>
Date:   Tue Mar 27 19:23:53 2012 +0200

    Fix conversion from lower to upper case with Turkish locale
    
    Some locale settings let make fail or create wrong results
    because tr '[:lower:]' '[:upper:]' which is used to convert
    from lower to upper case depends on the locale.
    
    With locale tr_TR.UTF-8, lower case 'i' is not converted to 'I'.
    This results in wrong entries in config-host.h like these ones:
    
      #define CONFIG_QEMU_PREFiX "/usr/local"
      #define CONFIG_QEMU_BiNDiR "/usr/local/bin"
    
    This problem was reported by Emre Ersin.
    
    The same problem occurs when configure creates the target specific
    files config-target.mak. They get wrong declarations:
    
    TARGET_CRiS=y
    TARGET_i386=y
    TARGET_MiCROBLAZE=y
    TARGET_MiPS64=y
    TARGET_MiPS=y
    TARGET_UNiCORE32=y
    
    It is sufficient to restrict the conversion to the characters a-z.
    
    Using this explicit range avoids the dependency on the locale
    settings and is also shorter.
    
    v2:
    POSIX says that 'tr a-z' is unspecified outside of the POSIX
    locale, so we must set LC_ALL=C to make sure that we are using
    POSIX (hint from Eric Blake, thanks).
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/configure b/configure
index 14ef738..dd01911 100755
--- a/configure
+++ b/configure
@@ -3052,12 +3052,12 @@ if test "$cap_ng" = "yes" ; then
   echo "CONFIG_LIBCAP=y" >> $config_host_mak
 fi
 for card in $audio_card_list; do
-    def=CONFIG_`echo $card | tr '[:lower:]' '[:upper:]'`
+    def=CONFIG_`echo $card | LC_ALL=C tr '[a-z]' '[A-Z]'`
     echo "$def=y" >> $config_host_mak
 done
 echo "CONFIG_AUDIO_DRIVERS=$audio_drv_list" >> $config_host_mak
 for drv in $audio_drv_list; do
-    def=CONFIG_`echo $drv | tr '[:lower:]' '[:upper:]'`
+    def=CONFIG_`echo $drv | LC_ALL=C tr '[a-z]' '[A-Z]'`
     echo "$def=y" >> $config_host_mak
     if test "$drv" = "fmod"; then
         echo "FMOD_CFLAGS=-I$fmod_inc" >> $config_host_mak
@@ -3618,7 +3618,7 @@ echo "TARGET_INT_ALIGNMENT=$target_int_alignment" >> $config_target_mak
 echo "TARGET_LONG_ALIGNMENT=$target_long_alignment" >> $config_target_mak
 echo "TARGET_LLONG_ALIGNMENT=$target_llong_alignment" >> $config_target_mak
 echo "TARGET_ARCH=$TARGET_ARCH" >> $config_target_mak
-target_arch_name="`echo $TARGET_ARCH | tr '[:lower:]' '[:upper:]'`"
+target_arch_name="`echo $TARGET_ARCH | LC_ALL=C tr '[a-z]' '[A-Z]'`"
 echo "TARGET_$target_arch_name=y" >> $config_target_mak
 echo "TARGET_ARCH2=$target_arch2" >> $config_target_mak
 # TARGET_BASE_ARCH needs to be defined after TARGET_ARCH
diff --git a/scripts/create_config b/scripts/create_config
index 0098e68..470e05e 100755
--- a/scripts/create_config
+++ b/scripts/create_config
@@ -16,7 +16,7 @@ case $line in
  prefix=* | [a-z]*dir=*) # directory configuration
     name=${line%=*}
     value=${line#*=}
-    define_name=`echo $name | tr '[:lower:]' '[:upper:]'`
+    define_name=`echo $name | LC_ALL=C tr '[a-z]' '[A-Z]'`
     eval "define_value=\"$value\""
     echo "#define CONFIG_QEMU_$define_name \"$define_value\""
     # save for the next definitions
@@ -48,7 +48,7 @@ case $line in
     ;;
  ARCH=*) # configuration
     arch=${line#*=}
-    arch_name=`echo $arch | tr '[:lower:]' '[:upper:]'`
+    arch_name=`echo $arch | LC_ALL=C tr '[a-z]' '[A-Z]'`
     echo "#define HOST_$arch_name 1"
     ;;
  HOST_USB=*)
@@ -73,7 +73,7 @@ case $line in
  TARGET_BASE_ARCH=*) # configuration
     target_base_arch=${line#*=}
     if [ "$target_base_arch" != "$target_arch" ]; then
-      base_arch_name=`echo $target_base_arch | tr '[:lower:]' '[:upper:]'`
+      base_arch_name=`echo $target_base_arch | LC_ALL=C tr '[a-z]' '[A-Z]'`
       echo "#define TARGET_$base_arch_name 1"
     fi
     ;;
diff --git a/scripts/tracetool b/scripts/tracetool
index 65bd0a1..d675dab 100755
--- a/scripts/tracetool
+++ b/scripts/tracetool
@@ -410,7 +410,7 @@ linetoh_dtrace()
     args=$(get_args "$1")
     argnames=$(get_argnames "$1", ",")
 
-    nameupper=`echo $name | tr '[:lower:]' '[:upper:]'`
+    nameupper=`echo $name | LC_ALL=C tr '[a-z]' '[A-Z]'`
 
     # Define an empty function for the trace event
     cat <<EOF
@@ -539,7 +539,7 @@ convert()
         fi
         if [ "$1" = "h" ]; then
             name=$(get_name "$str")
-            NAME=$(echo $name | tr '[:lower:]' '[:upper:]')
+            NAME=$(echo $name | LC_ALL=C tr '[a-z]' '[A-Z]')
             echo "#define TRACE_${NAME}_ENABLED ${enabled}"
         fi
     done
commit 02b3efcb7509841871038d89406225d1aaf41684
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Fri Mar 30 17:42:27 2012 +0000

    qtest: avoid a warning with RTC test
    
    Avoid this warning on OpenBSD:
      CC    tests/rtc-test.o
    /src/qemu/tests/rtc-test.c: In function 'check_time':
    /src/qemu/tests/rtc-test.c:171: warning: format '%ld' expects type 'long int', but argument 2 has type 'time_t'
    /src/qemu/tests/rtc-test.c:173: warning: format '%ld' expects type 'long int', but argument 2 has type 'time_t'
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tests/rtc-test.c b/tests/rtc-test.c
index c32b36a..983a980 100644
--- a/tests/rtc-test.c
+++ b/tests/rtc-test.c
@@ -161,12 +161,12 @@ static void check_time(int wiggle)
     }
 
     if (!(tm_cmp(&start, datep) <= 0 && tm_cmp(datep, &end) <= 0)) {
-        time_t t, s;
+        long t, s;
 
         start.tm_isdst = datep->tm_isdst;
 
-        t = mktime(datep);
-        s = mktime(&start);
+        t = (long)mktime(datep);
+        s = (long)mktime(&start);
         if (t < s) {
             g_test_message("RTC is %ld second(s) behind wall-clock\n", (s - t));
         } else {
commit 6b7cff76e0545b831542bbbdcf3fa2e4f260fbfe
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Mar 30 12:53:54 2012 -0500

    qtest: fix 32-bit build
    
    time_t appears to be an unsigned long so use %ld.
    
    Reported-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qtest.c b/qtest.c
index 53e2b79..cd7186c 100644
--- a/qtest.c
+++ b/qtest.c
@@ -34,7 +34,7 @@ static int irq_levels[MAX_IRQ];
 static struct timeval start_time;
 static bool qtest_opened;
 
-#define FMT_timeval "%" PRId64 ".%06" PRId64
+#define FMT_timeval "%ld.%06ld"
 
 /**
  * QTest Protocol
commit 86073017e384b65a4b568da25e5873fd2e5e4db5
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Mar 30 19:29:08 2012 +0200

    slirp: Signal free input buffer space to io-thread
    
    This massively accelerates slirp reception speed: If data arrives
    faster than the guest can read it from the input buffer, the file
    descriptor for the corresponding socket was taken out of the fdset for
    select. However, the event of the guest reading enough data from the
    buffer was not signaled. Thus, the io-thread only noticed this change
    on the next time-driven poll. Fix this by kicking the io-thread as
    required.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>

diff --git a/slirp/sbuf.c b/slirp/sbuf.c
index 5a1ccbf..637f8fe 100644
--- a/slirp/sbuf.c
+++ b/slirp/sbuf.c
@@ -6,6 +6,7 @@
  */
 
 #include <slirp.h>
+#include <main-loop.h>
 
 static void sbappendsb(struct sbuf *sb, struct mbuf *m);
 
@@ -18,6 +19,8 @@ sbfree(struct sbuf *sb)
 void
 sbdrop(struct sbuf *sb, int num)
 {
+    int limit = sb->sb_datalen / 2;
+
 	/*
 	 * We can only drop how much we have
 	 * This should never succeed
@@ -29,6 +32,9 @@ sbdrop(struct sbuf *sb, int num)
 	if(sb->sb_rptr >= sb->sb_data + sb->sb_datalen)
 		sb->sb_rptr -= sb->sb_datalen;
 
+    if (sb->sb_cc < limit && sb->sb_cc + num >= limit) {
+        qemu_notify_event();
+    }
 }
 
 void
commit d2a16f74f22b4a8d5f8a66d568e729a943136872
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Fri Mar 30 17:39:33 2012 +0000

    qtest: fix out of tree build
    
    Trace objects are also needed if tracing is enabled.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tests/Makefile b/tests/Makefile
index 29c1e51..a98a848 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -63,6 +63,8 @@ tests/test-qmp-input-visitor$(EXESUF): tests/test-qmp-input-visitor.o $(test-qap
 tests/test-qmp-input-strict$(EXESUF): tests/test-qmp-input-strict.o $(test-qapi-obj-y)
 tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp-marshal.o $(test-qapi-obj-y)
 
+tests/rtc-test$(EXESUF): tests/rtc-test.o $(trace-obj-y)
+
 # QTest rules
 
 TARGETS=$(patsubst %-softmmu,%, $(filter %-softmmu,$(TARGET_DIRS)))
commit d1aaf543a73c33025cf1fcd30b363aadd150cac3
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Mar 28 15:42:07 2012 +0200

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

diff --git a/tests/Makefile b/tests/Makefile
index c6fb587..29c1e51 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -16,6 +16,11 @@ check-unit-y += tests/test-coroutine$(EXESUF)
 
 check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
 
+# All QTests for now are POSIX-only, but the dependencies are
+# really in libqtest, not in the testcases themselves.
+check-qtest-i386-y = tests/rtc-test
+check-qtest-x86_64-y = $(check-qtest-i386-y)
+
 GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h tests/test-qmp-commands.h
 
 test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
diff --git a/tests/rtc-test.c b/tests/rtc-test.c
new file mode 100644
index 0000000..c32b36a
--- /dev/null
+++ b/tests/rtc-test.c
@@ -0,0 +1,263 @@
+/*
+ * QTest testcase for the MC146818 real-time clock
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+#include "libqtest.h"
+#include "hw/mc146818rtc_regs.h"
+
+#include <glib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static uint8_t base = 0x70;
+
+static int bcd2dec(int value)
+{
+    return (((value >> 4) & 0x0F) * 10) + (value & 0x0F);
+}
+
+static int dec2bcd(int value)
+{
+    return ((value / 10) << 4) | (value % 10);
+}
+
+static uint8_t cmos_read(uint8_t reg)
+{
+    outb(base + 0, reg);
+    return inb(base + 1);
+}
+
+static void cmos_write(uint8_t reg, uint8_t val)
+{
+    outb(base + 0, reg);
+    outb(base + 1, val);
+}
+
+static int tm_cmp(struct tm *lhs, struct tm *rhs)
+{
+    time_t a, b;
+    struct tm d1, d2;
+
+    memcpy(&d1, lhs, sizeof(d1));
+    memcpy(&d2, rhs, sizeof(d2));
+
+    a = mktime(&d1);
+    b = mktime(&d2);
+
+    if (a < b) {
+        return -1;
+    } else if (a > b) {
+        return 1;
+    }
+
+    return 0;
+}
+
+#if 0
+static void print_tm(struct tm *tm)
+{
+    printf("%04d-%02d-%02d %02d:%02d:%02d\n",
+           tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+           tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_gmtoff);
+}
+#endif
+
+static void cmos_get_date_time(struct tm *date)
+{
+    int base_year = 2000, hour_offset;
+    int sec, min, hour, mday, mon, year;
+    time_t ts;
+    struct tm dummy;
+
+    sec = cmos_read(RTC_SECONDS);
+    min = cmos_read(RTC_MINUTES);
+    hour = cmos_read(RTC_HOURS);
+    mday = cmos_read(RTC_DAY_OF_MONTH);
+    mon = cmos_read(RTC_MONTH);
+    year = cmos_read(RTC_YEAR);
+
+    if ((cmos_read(RTC_REG_B) & REG_B_DM) == 0) {
+        sec = bcd2dec(sec);
+        min = bcd2dec(min);
+        hour = bcd2dec(hour);
+        mday = bcd2dec(mday);
+        mon = bcd2dec(mon);
+        year = bcd2dec(year);
+        hour_offset = 80;
+    } else {
+        hour_offset = 0x80;
+    }
+
+    if ((cmos_read(0x0B) & REG_B_24H) == 0) {
+        if (hour >= hour_offset) {
+            hour -= hour_offset;
+            hour += 12;
+        }
+    }
+
+    ts = time(NULL);
+    localtime_r(&ts, &dummy);
+
+    date->tm_isdst = dummy.tm_isdst;
+    date->tm_sec = sec;
+    date->tm_min = min;
+    date->tm_hour = hour;
+    date->tm_mday = mday;
+    date->tm_mon = mon - 1;
+    date->tm_year = base_year + year - 1900;
+    date->tm_gmtoff = 0;
+
+    ts = mktime(date);
+}
+
+static void check_time(int wiggle)
+{
+    struct tm start, date[4], end;
+    struct tm *datep;
+    time_t ts;
+
+    /*
+     * This check assumes a few things.  First, we cannot guarantee that we get
+     * a consistent reading from the wall clock because we may hit an edge of
+     * the clock while reading.  To work around this, we read four clock readings
+     * such that at least two of them should match.  We need to assume that one
+     * reading is corrupt so we need four readings to ensure that we have at
+     * least two consecutive identical readings
+     *
+     * It's also possible that we'll cross an edge reading the host clock so
+     * simply check to make sure that the clock reading is within the period of
+     * when we expect it to be.
+     */
+
+    ts = time(NULL);
+    gmtime_r(&ts, &start);
+
+    cmos_get_date_time(&date[0]);
+    cmos_get_date_time(&date[1]);
+    cmos_get_date_time(&date[2]);
+    cmos_get_date_time(&date[3]);
+
+    ts = time(NULL);
+    gmtime_r(&ts, &end);
+
+    if (tm_cmp(&date[0], &date[1]) == 0) {
+        datep = &date[0];
+    } else if (tm_cmp(&date[1], &date[2]) == 0) {
+        datep = &date[1];
+    } else if (tm_cmp(&date[2], &date[3]) == 0) {
+        datep = &date[2];
+    } else {
+        g_assert_not_reached();
+    }
+
+    if (!(tm_cmp(&start, datep) <= 0 && tm_cmp(datep, &end) <= 0)) {
+        time_t t, s;
+
+        start.tm_isdst = datep->tm_isdst;
+
+        t = mktime(datep);
+        s = mktime(&start);
+        if (t < s) {
+            g_test_message("RTC is %ld second(s) behind wall-clock\n", (s - t));
+        } else {
+            g_test_message("RTC is %ld second(s) ahead of wall-clock\n", (t - s));
+        }
+
+        g_assert_cmpint(ABS(t - s), <=, wiggle);
+    }
+}
+
+static int wiggle = 2;
+
+static void bcd_check_time(void)
+{
+    /* Set BCD mode */
+    cmos_write(RTC_REG_B, cmos_read(RTC_REG_B) & ~REG_B_DM);
+    check_time(wiggle);
+}
+
+static void dec_check_time(void)
+{
+    /* Set DEC mode */
+    cmos_write(RTC_REG_B, cmos_read(RTC_REG_B) | REG_B_DM);
+    check_time(wiggle);
+}
+
+static void set_alarm_time(struct tm *tm)
+{
+    int sec;
+
+    sec = tm->tm_sec;
+
+    if ((cmos_read(RTC_REG_B) & REG_B_DM) == 0) {
+        sec = dec2bcd(sec);
+    }
+
+    cmos_write(RTC_SECONDS_ALARM, sec);
+    cmos_write(RTC_MINUTES_ALARM, RTC_ALARM_DONT_CARE);
+    cmos_write(RTC_HOURS_ALARM, RTC_ALARM_DONT_CARE);
+}
+
+static void alarm_time(void)
+{
+    struct tm now;
+    time_t ts;
+    int i;
+
+    ts = time(NULL);
+    gmtime_r(&ts, &now);
+
+    /* set DEC mode */
+    cmos_write(RTC_REG_B, cmos_read(RTC_REG_B) | REG_B_DM);
+
+    g_assert(!get_irq(RTC_ISA_IRQ));
+    cmos_read(RTC_REG_C);
+
+    now.tm_sec = (now.tm_sec + 2) % 60;
+    set_alarm_time(&now);
+    cmos_write(RTC_REG_B, cmos_read(RTC_REG_B) | REG_B_AIE);
+
+    for (i = 0; i < 2 + wiggle; i++) {
+        if (get_irq(RTC_ISA_IRQ)) {
+            break;
+        }
+
+        clock_step(1000000000);
+    }
+
+    g_assert(get_irq(RTC_ISA_IRQ));
+    g_assert((cmos_read(RTC_REG_C) & REG_C_AF) != 0);
+    g_assert(cmos_read(RTC_REG_C) == 0);
+}
+
+int main(int argc, char **argv)
+{
+    QTestState *s = NULL;
+    int ret;
+
+    g_test_init(&argc, &argv, NULL);
+
+    s = qtest_start("-display none -rtc clock=vm");
+    qtest_irq_intercept_in(s, "ioapic");
+
+    qtest_add_func("/rtc/bcd/check-time", bcd_check_time);
+    qtest_add_func("/rtc/dec/check-time", dec_check_time);
+    qtest_add_func("/rtc/alarm-time", alarm_time);
+    ret = g_test_run();
+
+    if (s) {
+        qtest_quit(s);
+    }
+
+    return ret;
+}
commit fd94be7ae65195c1fad2b740e0cd4620b25cc5b5
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Mar 28 15:42:06 2012 +0200

    rtc: split out macros into a header file and use in test case
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 2b59c36..9c64e0a 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -47,39 +47,6 @@
 
 #define RTC_REINJECT_ON_ACK_COUNT 20
 
-#define RTC_SECONDS             0
-#define RTC_SECONDS_ALARM       1
-#define RTC_MINUTES             2
-#define RTC_MINUTES_ALARM       3
-#define RTC_HOURS               4
-#define RTC_HOURS_ALARM         5
-#define RTC_ALARM_DONT_CARE    0xC0
-
-#define RTC_DAY_OF_WEEK         6
-#define RTC_DAY_OF_MONTH        7
-#define RTC_MONTH               8
-#define RTC_YEAR                9
-
-#define RTC_REG_A               10
-#define RTC_REG_B               11
-#define RTC_REG_C               12
-#define RTC_REG_D               13
-
-#define REG_A_UIP 0x80
-
-#define REG_B_SET  0x80
-#define REG_B_PIE  0x40
-#define REG_B_AIE  0x20
-#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
-#define REG_C_PF   0x40
-#define REG_C_AF   0x20
-
 typedef struct RTCState {
     ISADevice dev;
     MemoryRegion io;
diff --git a/hw/mc146818rtc.h b/hw/mc146818rtc.h
index f119930..f286b6a 100644
--- a/hw/mc146818rtc.h
+++ b/hw/mc146818rtc.h
@@ -2,8 +2,7 @@
 #define MC146818RTC_H
 
 #include "isa.h"
-
-#define RTC_ISA_IRQ 8
+#include "mc146818rtc_regs.h"
 
 ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq);
 void rtc_set_memory(ISADevice *dev, int addr, int val);
diff --git a/hw/mc146818rtc_regs.h b/hw/mc146818rtc_regs.h
new file mode 100644
index 0000000..3ab3770
--- /dev/null
+++ b/hw/mc146818rtc_regs.h
@@ -0,0 +1,62 @@
+/*
+ * QEMU MC146818 RTC emulation
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * 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 RTC_REGS_H
+#define RTC_REGS_H
+
+#define RTC_ISA_IRQ 8
+
+#define RTC_SECONDS             0
+#define RTC_SECONDS_ALARM       1
+#define RTC_MINUTES             2
+#define RTC_MINUTES_ALARM       3
+#define RTC_HOURS               4
+#define RTC_HOURS_ALARM         5
+#define RTC_ALARM_DONT_CARE    0xC0
+
+#define RTC_DAY_OF_WEEK         6
+#define RTC_DAY_OF_MONTH        7
+#define RTC_MONTH               8
+#define RTC_YEAR                9
+
+#define RTC_REG_A               10
+#define RTC_REG_B               11
+#define RTC_REG_C               12
+#define RTC_REG_D               13
+
+#define REG_A_UIP 0x80
+
+#define REG_B_SET  0x80
+#define REG_B_PIE  0x40
+#define REG_B_AIE  0x20
+#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
+#define REG_C_PF   0x40
+#define REG_C_AF   0x20
+
+#endif
commit 49ee35907723a28e91da27537f48c9d8696c427e
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Mar 28 15:42:05 2012 +0200

    qtest: add C version of test infrastructure
    
    This also includes a qtest wrapper script to make it easier to launch qtest
    tests directly.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/osdep.h b/osdep.h
index 156666e..428285c 100644
--- a/osdep.h
+++ b/osdep.h
@@ -140,4 +140,6 @@ static inline void qemu_timersub(const struct timeval *val1,
 #define qemu_timersub timersub
 #endif
 
+void qemu_set_cloexec(int fd);
+
 #endif
diff --git a/qemu-common.h b/qemu-common.h
index c9e96a8..4647dd9 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -190,7 +190,6 @@ ssize_t qemu_send_full(int fd, const void *buf, size_t count, int flags)
     QEMU_WARN_UNUSED_RESULT;
 ssize_t qemu_recv_full(int fd, void *buf, size_t count, int flags)
     QEMU_WARN_UNUSED_RESULT;
-void qemu_set_cloexec(int fd);
 
 #ifndef _WIN32
 int qemu_eventfd(int pipefd[2]);
diff --git a/tests/Makefile b/tests/Makefile
index 17f6ece..c6fb587 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -58,11 +58,22 @@ tests/test-qmp-input-visitor$(EXESUF): tests/test-qmp-input-visitor.o $(test-qap
 tests/test-qmp-input-strict$(EXESUF): tests/test-qmp-input-strict.o $(test-qapi-obj-y)
 tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp-marshal.o $(test-qapi-obj-y)
 
+# QTest rules
+
+TARGETS=$(patsubst %-softmmu,%, $(filter %-softmmu,$(TARGET_DIRS)))
+QTEST_TARGETS=$(foreach TARGET,$(TARGETS), $(if $(check-qtest-$(TARGET)-y), $(TARGET),))
+check-qtest-$(CONFIG_POSIX)=$(foreach TARGET,$(TARGETS), $(check-qtest-$(TARGET)-y))
+
+qtest-obj-y = tests/libqtest.o $(oslib-obj-y)
+$(check-qtest-y): $(qtest-obj-y)
+
 .PHONY: check-help
 check-help:
 	@echo "Regression testing targets:"
 	@echo
 	@echo " make check                Run all tests"
+	@echo " make check-qtest-TARGET   Run qtest tests for given target"
+	@echo " make check-qtest          Run qtest tests"
 	@echo " make check-unit           Run qobject tests"
 	@echo " make check-block          Run block tests"
 	@echo " make check-report.html    Generates an HTML test report"
@@ -81,18 +92,27 @@ GTESTER_OPTIONS = -k $(if $(V),--verbose,-q)
 
 # gtester tests, possibly with verbose output
 
+.PHONY: $(patsubst %, check-qtest-%, $(QTEST_TARGETS))
+$(patsubst %, check-qtest-%, $(QTEST_TARGETS)): check-qtest-%: $(check-qtest-y)
+	$(call quiet-command,QTEST_QEMU_BINARY=$*-softmmu/qemu-system-$* \
+		gtester $(GTESTER_OPTIONS) -m=$(SPEED) $(check-qtest-$*-y),"GTESTER $@")
+
 .PHONY: $(patsubst %, check-%, $(check-unit-y))
 $(patsubst %, check-%, $(check-unit-y)): check-%: %
 	$(call quiet-command,gtester $(GTESTER_OPTIONS) -m=$(SPEED) $*,"GTESTER $*")
 
 # gtester tests with XML output
 
+$(patsubst %, check-report-qtest-%.xml, $(QTEST_TARGETS)): check-report-qtest-%.xml: $(check-qtest-y)
+	$(call quiet-command,QTEST_QEMU_BINARY=$*-softmmu/qemu-system-$* \
+	  gtester -q $(GTESTER_OPTIONS) -o $@ -m=$(SPEED) $(check-qtest-$*-y),"GTESTER $@")
+
 check-report-unit.xml: $(check-unit-y)
 	$(call quiet-command,gtester -q $(GTESTER_OPTIONS) -o $@ -m=$(SPEED) $^, "GTESTER $@")
 
 # Reports and overall runs
 
-check-report.xml: check-report-unit.xml
+check-report.xml: $(patsubst %,check-report-qtest-%.xml, $(QTEST_TARGETS)) check-report-unit.xml
 	$(call quiet-command,$(SRC_PATH)/scripts/gtester-cat $^ > $@, "  GEN    $@")
 
 check-report.html: check-report.xml
@@ -107,7 +127,8 @@ check-tests/qemu-iotests-quick.sh: tests/qemu-iotests-quick.sh qemu-img$(EXESUF)
 
 # Consolidated targets
 
-.PHONY: check-unit check
+.PHONY: check-qtest check-unit check
+check-qtest: $(patsubst %,check-qtest-%, $(QTEST_TARGETS))
 check-unit: $(patsubst %,check-%, $(check-unit-y))
 check-block: $(patsubst %,check-%, $(check-block-y))
-check: check-unit
+check: check-unit check-qtest
diff --git a/tests/libqtest.c b/tests/libqtest.c
new file mode 100644
index 0000000..d47969e
--- /dev/null
+++ b/tests/libqtest.c
@@ -0,0 +1,387 @@
+/*
+ * QTest
+ *
+ * Copyright IBM, Corp. 2012
+ * Copyright Red Hat, Inc. 2012
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *  Paolo Bonzini     <pbonzini at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+#include "libqtest.h"
+
+#include <glib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <sys/un.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "osdep.h"
+
+#define MAX_IRQ 256
+
+QTestState *global_qtest;
+
+struct QTestState
+{
+    int fd;
+    bool irq_level[MAX_IRQ];
+    GString *rx;
+    gchar *pid_file;
+};
+
+#define g_assert_no_errno(ret) do { \
+    g_assert_cmpint(ret, !=, -1); \
+} while (0)
+
+QTestState *qtest_init(const char *extra_args)
+{
+    QTestState *s;
+    struct sockaddr_un addr;
+    int sock, ret, i;
+    gchar *socket_path;
+    gchar *pid_file;
+    gchar *command;
+    const char *qemu_binary;
+    pid_t pid;
+    socklen_t addrlen;
+
+    qemu_binary = getenv("QTEST_QEMU_BINARY");
+    g_assert(qemu_binary != NULL);
+
+    socket_path = g_strdup_printf("/tmp/qtest-%d.sock", getpid());
+    pid_file = g_strdup_printf("/tmp/qtest-%d.pid", getpid());
+
+    s = g_malloc(sizeof(*s));
+
+    sock = socket(PF_UNIX, SOCK_STREAM, 0);
+    g_assert_no_errno(sock);
+
+    addr.sun_family = AF_UNIX;
+    snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", socket_path);
+    qemu_set_cloexec(sock);
+
+    do {
+        ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
+    } while (ret == -1 && errno == EINTR);
+    g_assert_no_errno(ret);
+    listen(sock, 1);
+
+    pid = fork();
+    if (pid == 0) {
+        command = g_strdup_printf("%s "
+                                  "-qtest unix:%s,nowait "
+                                  "-qtest-log /dev/null "
+                                  "-pidfile %s "
+                                  "-machine accel=qtest "
+                                  "%s", qemu_binary, socket_path,
+                                  pid_file,
+                                  extra_args ?: "");
+
+        ret = system(command);
+        exit(ret);
+        g_free(command);
+    }
+
+    do {
+        ret = accept(sock, (struct sockaddr *)&addr, &addrlen);
+    } while (ret == -1 && errno == EINTR);
+    g_assert_no_errno(ret);
+    close(sock);
+
+    s->fd = ret;
+    s->rx = g_string_new("");
+    s->pid_file = pid_file;
+    for (i = 0; i < MAX_IRQ; i++) {
+        s->irq_level[i] = false;
+    }
+
+    g_free(socket_path);
+
+    return s;
+}
+
+void qtest_quit(QTestState *s)
+{
+    FILE *f;
+    char buffer[1024];
+
+    f = fopen(s->pid_file, "r");
+    if (f) {
+        if (fgets(buffer, sizeof(buffer), f)) {
+            pid_t pid = atoi(buffer);
+            int status = 0;
+
+            kill(pid, SIGTERM);
+            waitpid(pid, &status, 0);
+        }
+
+        fclose(f);
+    }
+}
+
+static void qtest_sendf(QTestState *s, const char *fmt, ...)
+{
+    va_list ap;
+    gchar *str;
+    size_t size, offset;
+
+    va_start(ap, fmt);
+    str = g_strdup_vprintf(fmt, ap);
+    va_end(ap);
+    size = strlen(str);
+
+    offset = 0;
+    while (offset < size) {
+        ssize_t len;
+
+        len = write(s->fd, str + offset, size - offset);
+        if (len == -1 && errno == EINTR) {
+            continue;
+        }
+
+        g_assert_no_errno(len);
+        g_assert_cmpint(len, >, 0);
+
+        offset += len;
+    }
+}
+
+static GString *qtest_recv_line(QTestState *s)
+{
+    GString *line;
+    size_t offset;
+    char *eol;
+
+    while ((eol = strchr(s->rx->str, '\n')) == NULL) {
+        ssize_t len;
+        char buffer[1024];
+
+        len = read(s->fd, buffer, sizeof(buffer));
+        if (len == -1 && errno == EINTR) {
+            continue;
+        }
+
+        if (len == -1 || len == 0) {
+            fprintf(stderr, "Broken pipe\n");
+            exit(1);
+        }
+
+        g_string_append_len(s->rx, buffer, len);
+    }
+
+    offset = eol - s->rx->str;
+    line = g_string_new_len(s->rx->str, offset);
+    g_string_erase(s->rx, 0, offset + 1);
+
+    return line;
+}
+
+static gchar **qtest_rsp(QTestState *s, int expected_args)
+{
+    GString *line;
+    gchar **words;
+    int i;
+
+redo:
+    line = qtest_recv_line(s);
+    words = g_strsplit(line->str, " ", 0);
+    g_string_free(line, TRUE);
+
+    if (strcmp(words[0], "IRQ") == 0) {
+        int irq;
+
+        g_assert(words[1] != NULL);
+        g_assert(words[2] != NULL);
+
+        irq = strtoul(words[2], NULL, 0);
+        g_assert_cmpint(irq, >=, 0);
+        g_assert_cmpint(irq, <, MAX_IRQ);
+
+        if (strcmp(words[1], "raise") == 0) {
+            s->irq_level[irq] = true;
+        } else {
+            s->irq_level[irq] = false;
+        }
+
+        g_strfreev(words);
+        goto redo;
+    }
+
+    g_assert(words[0] != NULL);
+    g_assert_cmpstr(words[0], ==, "OK");
+
+    if (expected_args) {
+        for (i = 0; i < expected_args; i++) {
+            g_assert(words[i] != NULL);
+        }
+    } else {
+        g_strfreev(words);
+    }
+
+    return words;
+}
+
+const char *qtest_get_arch(void)
+{
+    const char *qemu = getenv("QTEST_QEMU_BINARY");
+    const char *end = strrchr(qemu, '/');
+
+    return end + strlen("/qemu-system-");
+}
+
+bool qtest_get_irq(QTestState *s, int num)
+{
+    /* dummy operation in order to make sure irq is up to date */
+    qtest_inb(s, 0);
+
+    return s->irq_level[num];
+}
+
+static int64_t qtest_clock_rsp(QTestState *s)
+{
+    gchar **words;
+    int64_t clock;
+    words = qtest_rsp(s, 2);
+    clock = g_ascii_strtoll(words[1], NULL, 0);
+    g_strfreev(words);
+    return clock;
+}
+
+int64_t qtest_clock_step_next(QTestState *s)
+{
+    qtest_sendf(s, "clock_step\n");
+    return qtest_clock_rsp(s);
+}
+
+int64_t qtest_clock_step(QTestState *s, int64_t step)
+{
+    qtest_sendf(s, "clock_step %"PRIi64"\n", step);
+    return qtest_clock_rsp(s);
+}
+
+int64_t qtest_clock_set(QTestState *s, int64_t val)
+{
+    qtest_sendf(s, "clock_set %"PRIi64"\n", val);
+    return qtest_clock_rsp(s);
+}
+
+void qtest_irq_intercept_out(QTestState *s, const char *qom_path)
+{
+    qtest_sendf(s, "irq_intercept_out %s\n", qom_path);
+    qtest_rsp(s, 0);
+}
+
+void qtest_irq_intercept_in(QTestState *s, const char *qom_path)
+{
+    qtest_sendf(s, "irq_intercept_in %s\n", qom_path);
+    qtest_rsp(s, 0);
+}
+
+static void qtest_out(QTestState *s, const char *cmd, uint16_t addr, uint32_t value)
+{
+    qtest_sendf(s, "%s 0x%x 0x%x\n", cmd, addr, value);
+    qtest_rsp(s, 0);
+}
+
+void qtest_outb(QTestState *s, uint16_t addr, uint8_t value)
+{
+    qtest_out(s, "outb", addr, value);
+}
+
+void qtest_outw(QTestState *s, uint16_t addr, uint16_t value)
+{
+    qtest_out(s, "outw", addr, value);
+}
+
+void qtest_outl(QTestState *s, uint16_t addr, uint32_t value)
+{
+    qtest_out(s, "outl", addr, value);
+}
+
+static uint32_t qtest_in(QTestState *s, const char *cmd, uint16_t addr)
+{
+    gchar **args;
+    uint32_t value;
+
+    qtest_sendf(s, "%s 0x%x\n", cmd, addr);
+    args = qtest_rsp(s, 2);
+    value = strtoul(args[1], NULL, 0);
+    g_strfreev(args);
+
+    return value;
+}
+
+uint8_t qtest_inb(QTestState *s, uint16_t addr)
+{
+    return qtest_in(s, "inb", addr);
+}
+
+uint16_t qtest_inw(QTestState *s, uint16_t addr)
+{
+    return qtest_in(s, "inw", addr);
+}
+
+uint32_t qtest_inl(QTestState *s, uint16_t addr)
+{
+    return qtest_in(s, "inl", addr);
+}
+
+static int hex2nib(char ch)
+{
+    if (ch >= '0' && ch <= '9') {
+        return ch - '0';
+    } else if (ch >= 'a' && ch <= 'f') {
+        return 10 + (ch - 'a');
+    } else if (ch >= 'A' && ch <= 'F') {
+        return 10 + (ch - 'a');
+    } else {
+        return -1;
+    }
+}
+
+void qtest_memread(QTestState *s, uint64_t addr, void *data, size_t size)
+{
+    uint8_t *ptr = data;
+    gchar **args;
+    size_t i;
+
+    qtest_sendf(s, "read 0x%x 0x%x\n", addr, size);
+    args = qtest_rsp(s, 2);
+
+    for (i = 0; i < size; i++) {
+        ptr[i] = hex2nib(args[1][2 + (i * 2)]) << 4;
+        ptr[i] |= hex2nib(args[1][2 + (i * 2) + 1]);
+    }
+
+    g_strfreev(args);
+}
+
+void qtest_add_func(const char *str, void (*fn))
+{
+    gchar *path = g_strdup_printf("/%s/%s", qtest_get_arch(), str);
+    g_test_add_func(path, fn);
+}
+
+void qtest_memwrite(QTestState *s, uint64_t addr, const void *data, size_t size)
+{
+    const uint8_t *ptr = data;
+    size_t i;
+
+    qtest_sendf(s, "write 0x%x 0x%x 0x", addr, size);
+    for (i = 0; i < size; i++) {
+        qtest_sendf(s, "%02x", ptr[i]);
+    }
+    qtest_sendf(s, "\n");
+    qtest_rsp(s, 0);
+}
diff --git a/tests/libqtest.h b/tests/libqtest.h
new file mode 100644
index 0000000..2ca85a9
--- /dev/null
+++ b/tests/libqtest.h
@@ -0,0 +1,335 @@
+/*
+ * QTest
+ *
+ * Copyright IBM, Corp. 2012
+ * Copyright Red Hat, Inc. 2012
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *  Paolo Bonzini     <pbonzini at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+#ifndef LIBQTEST_H
+#define LIBQTEST_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <sys/types.h>
+
+typedef struct QTestState QTestState;
+
+extern QTestState *global_qtest;
+
+/**
+ * qtest_init:
+ * @extra_args: other arguments to pass to QEMU.
+ */
+QTestState *qtest_init(const char *extra_args);
+
+/**
+ * qtest_quit:
+ * @s: QTestState instance to operate on.
+ *
+ * Shut down the QEMU process associated to @s.
+ */
+void qtest_quit(QTestState *s);
+
+/**
+ * qtest_get_irq:
+ * @s: QTestState instance to operate on.
+ * @num: Interrupt to observe.
+ *
+ * Return the level of the @num interrupt.
+ */
+bool qtest_get_irq(QTestState *s, int num);
+
+/**
+ * qtest_irq_intercept_in:
+ * @s: QTestState instance to operate on.
+ * @string: QOM path of a device.
+ *
+ * Associate qtest irqs with the GPIO-in pins of the device
+ * whose path is specified by @string.
+ */
+void qtest_irq_intercept_in(QTestState *s, const char *string);
+
+/**
+ * qtest_irq_intercept_out:
+ * @s: QTestState instance to operate on.
+ * @string: QOM path of a device.
+ *
+ * Associate qtest irqs with the GPIO-out pins of the device
+ * whose path is specified by @string.
+ */
+void qtest_irq_intercept_out(QTestState *s, const char *string);
+
+/**
+ * qtest_outb:
+ * @s: QTestState instance to operate on.
+ * @addr: I/O port to write to.
+ * @value: Value being written.
+ *
+ * Write an 8-bit value to an I/O port.
+ */
+void qtest_outb(QTestState *s, uint16_t addr, uint8_t value);
+
+/**
+ * qtest_outw:
+ * @s: QTestState instance to operate on.
+ * @addr: I/O port to write to.
+ * @value: Value being written.
+ *
+ * Write a 16-bit value to an I/O port.
+ */
+void qtest_outw(QTestState *s, uint16_t addr, uint16_t value);
+
+/**
+ * qtest_outl:
+ * @s: QTestState instance to operate on.
+ * @addr: I/O port to write to.
+ * @value: Value being written.
+ *
+ * Write a 32-bit value to an I/O port.
+ */
+void qtest_outl(QTestState *s, uint16_t addr, uint32_t value);
+
+/**
+ * qtest_inb:
+ * @s: QTestState instance to operate on.
+ * @addr: I/O port to read from.
+ * @value: Value being written.
+ *
+ * Returns an 8-bit value from an I/O port.
+ */
+uint8_t qtest_inb(QTestState *s, uint16_t addr);
+
+/**
+ * qtest_inw:
+ * @s: QTestState instance to operate on.
+ * @addr: I/O port to read from.
+ * @value: Value being written.
+ *
+ * Returns a 16-bit value from an I/O port.
+ */
+uint16_t qtest_inw(QTestState *s, uint16_t addr);
+
+/**
+ * qtest_inl:
+ * @s: QTestState instance to operate on.
+ * @addr: I/O port to read from.
+ * @value: Value being written.
+ *
+ * Returns a 32-bit value from an I/O port.
+ */
+uint32_t qtest_inl(QTestState *s, uint16_t addr);
+
+/**
+ * qtest_memread:
+ * @s: QTestState instance to operate on.
+ * @addr: Guest address to read from.
+ * @data: Pointer to where memory contents will be stored.
+ * @size: Number of bytes to read.
+ *
+ * Read guest memory into a buffer.
+ */
+void qtest_memread(QTestState *s, uint64_t addr, void *data, size_t size);
+
+/**
+ * qtest_memwrite:
+ * @s: QTestState instance to operate on.
+ * @addr: Guest address to write to.
+ * @data: Pointer to the bytes that will be written to guest memory.
+ * @size: Number of bytes to write.
+ *
+ * Write a buffer to guest memory.
+ */
+void qtest_memwrite(QTestState *s, uint64_t addr, const void *data, size_t size);
+
+/**
+ * qtest_clock_step_next:
+ * @s: QTestState instance to operate on.
+ *
+ * Advance the vm_clock to the next deadline.  Return the current
+ * value of the vm_clock in nanoseconds.
+ */
+int64_t qtest_clock_step_next(QTestState *s);
+
+/**
+ * qtest_clock_step:
+ * @s: QTestState instance to operate on.
+ * @step: Number of nanoseconds to advance the clock by.
+ *
+ * Advance the vm_clock by @step nanoseconds.  Return the current
+ * value of the vm_clock in nanoseconds.
+ */
+int64_t qtest_clock_step(QTestState *s, int64_t step);
+
+/**
+ * qtest_clock_set:
+ * @s: QTestState instance to operate on.
+ * @val: Nanoseconds value to advance the clock to.
+ *
+ * Advance the vm_clock to @val nanoseconds since the VM was launched.
+ * Return the current value of the vm_clock in nanoseconds.
+ */
+int64_t qtest_clock_set(QTestState *s, int64_t val);
+
+/**
+ * qtest_get_arch:
+ *
+ * Returns the architecture for the QEMU executable under test.
+ */
+const char *qtest_get_arch(void);
+
+/**
+ * qtest_add_func:
+ * @str: Test case path.
+ * @fn: Test case function
+ *
+ * Add a GTester testcase with the given name and function.
+ * The path is prefixed with the architecture under test, as
+ * returned by qtest_get_arch.
+ */
+void qtest_add_func(const char *str, void (*fn));
+
+/**
+ * qtest_start:
+ * @args: other arguments to pass to QEMU
+ *
+ * Start QEMU and assign the resulting QTestState to a global variable.
+ * The global variable is used by "shortcut" macros documented below.
+ */
+#define qtest_start(args) (            \
+    global_qtest = qtest_init((args)) \
+        )
+
+/**
+ * get_irq:
+ * @num: Interrupt to observe.
+ *
+ * Return the level of the @num interrupt.
+ */
+#define get_irq(num) qtest_get_irq(global_qtest, num)
+
+/**
+ * irq_intercept_in:
+ * @string: QOM path of a device.
+ *
+ * Associate qtest irqs with the GPIO-in pins of the device
+ * whose path is specified by @string.
+ */
+#define irq_intercept_in(string) qtest_irq_intercept_in(global_qtest, string)
+
+/**
+ * qtest_irq_intercept_out:
+ * @string: QOM path of a device.
+ *
+ * Associate qtest irqs with the GPIO-out pins of the device
+ * whose path is specified by @string.
+ */
+#define irq_intercept_out(string) qtest_irq_intercept_out(global_qtest, string)
+
+/**
+ * outb:
+ * @addr: I/O port to write to.
+ * @value: Value being written.
+ *
+ * Write an 8-bit value to an I/O port.
+ */
+#define outb(addr, val) qtest_outb(global_qtest, addr, val)
+
+/**
+ * outw:
+ * @addr: I/O port to write to.
+ * @value: Value being written.
+ *
+ * Write a 16-bit value to an I/O port.
+ */
+#define outw(addr, val) qtest_outw(global_qtest, addr, val)
+
+/**
+ * outl:
+ * @addr: I/O port to write to.
+ * @value: Value being written.
+ *
+ * Write a 32-bit value to an I/O port.
+ */
+#define outl(addr, val) qtest_outl(global_qtest, addr, val)
+
+/**
+ * inb:
+ * @addr: I/O port to read from.
+ * @value: Value being written.
+ *
+ * Returns an 8-bit value from an I/O port.
+ */
+#define inb(addr) qtest_inb(global_qtest, addr)
+
+/**
+ * inw:
+ * @addr: I/O port to read from.
+ * @value: Value being written.
+ *
+ * Returns a 16-bit value from an I/O port.
+ */
+#define inw(addr) qtest_inw(global_qtest, addr)
+
+/**
+ * inl:
+ * @addr: I/O port to read from.
+ * @value: Value being written.
+ *
+ * Returns a 32-bit value from an I/O port.
+ */
+#define inl(addr) qtest_inl(global_qtest, addr)
+
+/**
+ * memread:
+ * @addr: Guest address to read from.
+ * @data: Pointer to where memory contents will be stored.
+ * @size: Number of bytes to read.
+ *
+ * Read guest memory into a buffer.
+ */
+#define memread(addr, data, size) qtest_memread(global_qtest, addr, data, size)
+
+/**
+ * memwrite:
+ * @addr: Guest address to write to.
+ * @data: Pointer to the bytes that will be written to guest memory.
+ * @size: Number of bytes to write.
+ *
+ * Write a buffer to guest memory.
+ */
+#define memwrite(addr, data, size) qtest_memwrite(global_qtest, addr, data, size)
+
+/**
+ * clock_step_next:
+ *
+ * Advance the vm_clock to the next deadline.  Return the current
+ * value of the vm_clock in nanoseconds.
+ */
+#define clock_step_next() qtest_clock_step_next(global_qtest)
+
+/**
+ * clock_step:
+ * @step: Number of nanoseconds to advance the clock by.
+ *
+ * Advance the vm_clock by @step nanoseconds.  Return the current
+ * value of the vm_clock in nanoseconds.
+ */
+#define clock_step(step) qtest_clock_step(global_qtest, step)
+
+/**
+ * clock_set:
+ * @val: Nanoseconds value to advance the clock to.
+ *
+ * Advance the vm_clock to @val nanoseconds since the VM was launched.
+ * Return the current value of the vm_clock in nanoseconds.
+ */
+#define clock_set(val) qtest_clock_set(global_qtest, val)
+
+#endif
commit 8156be561019bd0fc17729e9a528f6c81eea9186
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Mar 28 15:42:04 2012 +0200

    qtest: add clock management
    
    This patch combines qtest and -icount together to turn the vm_clock
    into a source that can be fully managed by the client.  To this end new
    commands clock_step and clock_set are added.  Hooking them with libqtest
    is left as an exercise to the reader.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/cpus.c b/cpus.c
index ab8d67b..eb22bd5 100644
--- a/cpus.c
+++ b/cpus.c
@@ -34,6 +34,7 @@
 
 #include "qemu-thread.h"
 #include "cpus.h"
+#include "qtest.h"
 #include "main-loop.h"
 
 #ifndef _WIN32
@@ -238,6 +239,20 @@ static void icount_warp_rt(void *opaque)
     vm_clock_warp_start = -1;
 }
 
+void qtest_clock_warp(int64_t dest)
+{
+    int64_t clock = qemu_get_clock_ns(vm_clock);
+    assert(qtest_enabled());
+    while (clock < dest) {
+        int64_t deadline = qemu_clock_deadline(vm_clock);
+        int64_t warp = MIN(dest - clock, deadline);
+        qemu_icount_bias += warp;
+        qemu_run_timers(vm_clock);
+        clock = qemu_get_clock_ns(vm_clock);
+    }
+    qemu_notify_event();
+}
+
 void qemu_clock_warp(QEMUClock *clock)
 {
     int64_t deadline;
@@ -264,6 +279,11 @@ void qemu_clock_warp(QEMUClock *clock)
         return;
     }
 
+    if (qtest_enabled()) {
+        /* When testing, qtest commands advance icount.  */
+	return;
+    }
+
     vm_clock_warp_start = qemu_get_clock_ns(rt_clock);
     deadline = qemu_clock_deadline(vm_clock);
     if (deadline > 0) {
diff --git a/cpus.h b/cpus.h
index 4ea2fe2..81bd817 100644
--- a/cpus.h
+++ b/cpus.h
@@ -11,6 +11,8 @@ void cpu_synchronize_all_states(void);
 void cpu_synchronize_all_post_reset(void);
 void cpu_synchronize_all_post_init(void);
 
+void qtest_clock_warp(int64_t dest);
+
 /* vl.c */
 extern int smp_cores;
 extern int smp_threads;
diff --git a/qemu-timer.c b/qemu-timer.c
index d7f56e5..80bcc56 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -397,7 +397,7 @@ int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)
     return qemu_timer_expired_ns(timer_head, current_time * timer_head->scale);
 }
 
-static void qemu_run_timers(QEMUClock *clock)
+void qemu_run_timers(QEMUClock *clock)
 {
     QEMUTimer **ptimer_head, *ts;
     int64_t current_time;
diff --git a/qemu-timer.h b/qemu-timer.h
index de17f3b..661bbe7 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -59,6 +59,7 @@ int qemu_timer_pending(QEMUTimer *ts);
 int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time);
 uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts);
 
+void qemu_run_timers(QEMUClock *clock);
 void qemu_run_all_timers(void);
 int qemu_alarm_pending(void);
 void configure_alarms(char const *opt);
diff --git a/qtest.c b/qtest.c
index a1eca49..53e2b79 100644
--- a/qtest.c
+++ b/qtest.c
@@ -18,6 +18,7 @@
 #include "memory.h"
 #include "hw/irq.h"
 #include "sysemu.h"
+#include "cpus.h"
 
 #define MAX_IRQ 256
 
@@ -44,6 +45,30 @@ static bool qtest_opened;
  *
  * Valid requests
  *
+ * Clock management:
+ *
+ * The qtest client is completely in charge of the vm_clock.  qtest commands
+ * let you adjust the value of the clock (monotonically).  All the commands
+ * return the current value of the clock in nanoseconds.
+ *
+ *  > clock_step
+ *  < OK VALUE
+ *
+ *     Advance the clock to the next deadline.  Useful when waiting for
+ *     asynchronous events.
+ *
+ *  > clock_step NS
+ *  < OK VALUE
+ *
+ *     Advance the clock by NS nanoseconds.
+ *
+ *  > clock_set NS
+ *  < OK VALUE
+ *
+ *     Advance the clock to NS nanoseconds (do nothing if it's already past).
+ *
+ * PIO and memory access:
+ *
  *  > outb ADDR VALUE
  *  < OK
  *
@@ -299,6 +324,25 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
 
         qtest_send_prefix(chr);
         qtest_send(chr, "OK\n");
+    } else if (strcmp(words[0], "clock_step") == 0) {
+        int64_t ns;
+
+        if (words[1]) {
+            ns = strtoll(words[1], NULL, 0);
+        } else {
+            ns = qemu_clock_deadline(vm_clock);
+        }
+        qtest_clock_warp(qemu_get_clock_ns(vm_clock) + ns);
+        qtest_send_prefix(chr);
+        qtest_send(chr, "OK %"PRIi64"\n", (int64_t)qemu_get_clock_ns(vm_clock));
+    } else if (strcmp(words[0], "clock_set") == 0) {
+        int64_t ns;
+
+        g_assert(words[1]);
+        ns = strtoll(words[1], NULL, 0);
+        qtest_clock_warp(ns);
+        qtest_send_prefix(chr);
+        qtest_send(chr, "OK %"PRIi64"\n", (int64_t)qemu_get_clock_ns(vm_clock));
     } else {
         qtest_send_prefix(chr);
         qtest_send(chr, "FAIL Unknown command `%s'\n", words[0]);
@@ -377,6 +421,7 @@ int qtest_init(void)
 
     g_assert(qtest_chrdev != NULL);
 
+    configure_icount("0");
     chr = qemu_chr_new("qtest", qtest_chrdev, NULL);
 
     qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event, chr);
commit 2028834574e75de9d34995fbaf09a8b35cb9daa0
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Mar 28 15:42:03 2012 +0200

    qtest: IRQ interception infrastructure
    
    Since /i440fx/piix3 is being removed from the composition tree, the
    IO-APIC is placed under /i440fx.  This is wrong and should be changed
    as soon as the /i440fx/piix3 path is put back.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/irq.c b/hw/irq.c
index 62f766e..d413a0b 100644
--- a/hw/irq.c
+++ b/hw/irq.c
@@ -104,3 +104,20 @@ qemu_irq *qemu_irq_proxy(qemu_irq **target, int n)
 {
     return qemu_allocate_irqs(proxy_irq_handler, target, n);
 }
+
+void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n)
+{
+    int i;
+    qemu_irq *old_irqs = qemu_allocate_irqs(NULL, NULL, n);
+    for (i = 0; i < n; i++) {
+        *old_irqs[i] = *gpio_in[i];
+        gpio_in[i]->handler = handler;
+        gpio_in[i]->opaque = old_irqs;
+    }
+}
+
+void qemu_irq_intercept_out(qemu_irq **gpio_out, qemu_irq_handler handler, int n)
+{
+    qemu_irq *old_irqs = *gpio_out;
+    *gpio_out = qemu_allocate_irqs(handler, old_irqs, n);
+}
diff --git a/hw/irq.h b/hw/irq.h
index 64da2fd..56c55f0 100644
--- a/hw/irq.h
+++ b/hw/irq.h
@@ -38,4 +38,9 @@ qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2);
  */
 qemu_irq *qemu_irq_proxy(qemu_irq **target, int n);
 
+/* For internal use in qtest.  Similar to qemu_irq_split, but operating
+   on an existing vector of qemu_irq.  */
+void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n);
+void qemu_irq_intercept_out(qemu_irq **gpio_out, qemu_irq_handler handler, int n);
+
 #endif
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 3f99f9a..ec5118f 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -107,6 +107,9 @@ static void ioapic_init(GSIState *gsi_state)
     } else {
         dev = qdev_create(NULL, "ioapic");
     }
+    /* FIXME: this should be under the piix3.  */
+    object_property_add_child(object_resolve_path("i440fx", NULL),
+                              "ioapic", OBJECT(dev), NULL);
     qdev_init_nofail(dev);
     d = sysbus_from_qdev(dev);
     sysbus_mmio_map(d, 0, 0xfec00000);
diff --git a/qtest.c b/qtest.c
index 46ebda1..a1eca49 100644
--- a/qtest.c
+++ b/qtest.c
@@ -12,6 +12,7 @@
  */
 
 #include "qtest.h"
+#include "hw/qdev.h"
 #include "qemu-char.h"
 #include "ioport.h"
 #include "memory.h"
@@ -24,6 +25,7 @@ const char *qtest_chrdev;
 const char *qtest_log;
 int qtest_allowed = 0;
 
+static DeviceState *irq_intercept_dev;
 static FILE *qtest_log_fp;
 static CharDriverState *qtest_chr;
 static GString *inbuf;
@@ -66,18 +68,30 @@ static bool qtest_opened;
  *  > write ADDR SIZE DATA
  *  < OK
  *
- * Valid async messages:
- *
- *  IRQ raise NUM
- *  IRQ lower NUM
- *
  * ADDR, SIZE, VALUE are all integers parsed with strtoul() with a base of 0.
  *
  * DATA is an arbitrarily long hex number prefixed with '0x'.  If it's smaller
  * than the expected size, the value will be zero filled at the end of the data
  * sequence.
  *
- * NUM is an IRQ number.
+ * IRQ management:
+ *
+ *  > irq_intercept_in QOM-PATH
+ *  < OK
+ *
+ *  > irq_intercept_out QOM-PATH
+ *  < OK
+ *
+ * Attach to the gpio-in (resp. gpio-out) pins exported by the device at
+ * QOM-PATH.  When the pin is triggered, one of the following async messages
+ * will be printed to the qtest stream:
+ *
+ *  IRQ raise NUM
+ *  IRQ lower NUM
+ *
+ * where NUM is an IRQ number.  For the PC, interrupts can be intercepted
+ * simply with "irq_intercept_in ioapic" (note that IRQ0 comes out with
+ * NUM=0 even though it is remapped to GSI 2).
  */
 
 static int hex2nib(char ch)
@@ -133,6 +147,20 @@ static void qtest_send(CharDriverState *chr, const char *fmt, ...)
     }
 }
 
+static void qtest_irq_handler(void *opaque, int n, int level)
+{
+    qemu_irq *old_irqs = opaque;
+    qemu_set_irq(old_irqs[n], level);
+
+    if (irq_levels[n] != level) {
+        CharDriverState *chr = qtest_chr;
+        irq_levels[n] = level;
+        qtest_send_prefix(chr);
+        qtest_send(chr, "IRQ %s %d\n",
+                   level ? "raise" : "lower", n);
+    }
+}
+
 static void qtest_process_command(CharDriverState *chr, gchar **words)
 {
     const gchar *command;
@@ -155,9 +183,40 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
     }
 
     g_assert(command);
-    if (strcmp(words[0], "outb") == 0 ||
-        strcmp(words[0], "outw") == 0 ||
-        strcmp(words[0], "outl") == 0) {
+    if (strcmp(words[0], "irq_intercept_out") == 0
+        || strcmp(words[0], "irq_intercept_in") == 0) {
+	DeviceState *dev;
+
+        g_assert(words[1]);
+        dev = DEVICE(object_resolve_path(words[1], NULL));
+        if (!dev) {
+            qtest_send_prefix(chr);
+            qtest_send(chr, "FAIL Unknown device\n");
+	    return;
+        }
+
+        if (irq_intercept_dev) {
+            qtest_send_prefix(chr);
+            if (irq_intercept_dev != dev) {
+                qtest_send(chr, "FAIL IRQ intercept already enabled\n");
+            } else {
+                qtest_send(chr, "OK\n");
+            }
+	    return;
+        }
+
+        if (words[0][14] == 'o') {
+            qemu_irq_intercept_out(&dev->gpio_out, qtest_irq_handler, dev->num_gpio_out);
+        } else {
+            qemu_irq_intercept_in(dev->gpio_in, qtest_irq_handler, dev->num_gpio_in);
+        }
+        irq_intercept_dev = dev;
+        qtest_send_prefix(chr);
+        qtest_send(chr, "OK\n");
+
+    } else if (strcmp(words[0], "outb") == 0 ||
+               strcmp(words[0], "outw") == 0 ||
+               strcmp(words[0], "outl") == 0) {
         uint16_t addr;
         uint32_t value;
 
@@ -312,21 +371,6 @@ static void qtest_event(void *opaque, int event)
     }
 }
 
-static void qtest_set_irq(void *opaque, int irq, int level)
-{
-    CharDriverState *chr = qtest_chr;
-    bool changed;
-
-    changed = (irq_levels[irq] != level);
-    irq_levels[irq] = level;
-
-    if (changed) {
-        qtest_send_prefix(chr);
-        qtest_send(chr, "IRQ %s %d\n",
-                   level ? "raise" : "lower", irq);
-    }
-}
-
 int qtest_init(void)
 {
     CharDriverState *chr;
commit c7f0f3b1c826901358a0656f80a5fabb88f73c61
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Mar 28 15:42:02 2012 +0200

    qtest: add test framework
    
    The idea behind qtest is pretty simple.  Instead of executing a CPU via TCG or
    KVM, rely on an external process to send events to the device model that the CPU
    would normally generate.
    
    qtest presents itself as an accelerator.  In addition, a new option is added to
    establish a qtest server (-qtest) that takes a character device.  This is what
    allows the external process to send CPU events to the device model.
    
    qtest uses a simple line based protocol to send the events.  Documentation of
    that protocol is in qtest.c.
    
    I considered reusing the monitor for this job.  Adding interrupts would be a bit
    difficult.  In addition, logging would also be difficult.
    
    qtest has extensive logging support.  All protocol commands are logged with
    time stamps using a new command line option (-qtest-log).  Logging is important
    since ultimately, this is a feature for debugging.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile.objs b/Makefile.objs
index 226b01d..e9842b0 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -322,6 +322,8 @@ hw-obj-$(CONFIG_DP8393X) += dp8393x.o
 hw-obj-$(CONFIG_DS1225Y) += ds1225y.o
 hw-obj-$(CONFIG_MIPSNET) += mipsnet.o
 
+hw-obj-y += qtest.o
+
 # Sound
 sound-obj-y =
 sound-obj-$(CONFIG_SB16) += sb16.o
diff --git a/cpu-exec.c b/cpu-exec.c
index 0fa8325..d153f97 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -21,6 +21,7 @@
 #include "disas.h"
 #include "tcg.h"
 #include "qemu-barrier.h"
+#include "qtest.h"
 
 int tb_invalidated_flag;
 
diff --git a/cpus.c b/cpus.c
index 25ba621..ab8d67b 100644
--- a/cpus.c
+++ b/cpus.c
@@ -741,6 +741,48 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
     return NULL;
 }
 
+static void *qemu_dummy_cpu_thread_fn(void *arg)
+{
+#ifdef _WIN32
+    fprintf(stderr, "qtest is not supported under Windows\n");
+    exit(1);
+#else
+    CPUArchState *env = arg;
+    sigset_t waitset;
+    int r;
+
+    qemu_mutex_lock_iothread();
+    qemu_thread_get_self(env->thread);
+    env->thread_id = qemu_get_thread_id();
+
+    sigemptyset(&waitset);
+    sigaddset(&waitset, SIG_IPI);
+
+    /* signal CPU creation */
+    env->created = 1;
+    qemu_cond_signal(&qemu_cpu_cond);
+
+    cpu_single_env = env;
+    while (1) {
+        cpu_single_env = NULL;
+        qemu_mutex_unlock_iothread();
+        do {
+            int sig;
+            r = sigwait(&waitset, &sig);
+        } while (r == -1 && (errno == EAGAIN || errno == EINTR));
+        if (r == -1) {
+            perror("sigwait");
+            exit(1);
+        }
+        qemu_mutex_lock_iothread();
+        cpu_single_env = env;
+        qemu_wait_io_event_common(env);
+    }
+
+    return NULL;
+#endif
+}
+
 static void tcg_exec_all(void);
 
 static void *qemu_tcg_cpu_thread_fn(void *arg)
@@ -803,7 +845,7 @@ void qemu_cpu_kick(void *_env)
     CPUArchState *env = _env;
 
     qemu_cond_broadcast(env->halt_cond);
-    if (kvm_enabled() && !env->thread_kicked) {
+    if (!tcg_enabled() && !env->thread_kicked) {
         qemu_cpu_kick_thread(env);
         env->thread_kicked = true;
     }
@@ -832,7 +874,7 @@ int qemu_cpu_is_self(void *_env)
 
 void qemu_mutex_lock_iothread(void)
 {
-    if (kvm_enabled()) {
+    if (!tcg_enabled()) {
         qemu_mutex_lock(&qemu_global_mutex);
     } else {
         iothread_requesting_mutex = true;
@@ -947,6 +989,18 @@ static void qemu_kvm_start_vcpu(CPUArchState *env)
     }
 }
 
+static void qemu_dummy_start_vcpu(CPUArchState *env)
+{
+    env->thread = g_malloc0(sizeof(QemuThread));
+    env->halt_cond = g_malloc0(sizeof(QemuCond));
+    qemu_cond_init(env->halt_cond);
+    qemu_thread_create(env->thread, qemu_dummy_cpu_thread_fn, env,
+                       QEMU_THREAD_JOINABLE);
+    while (env->created == 0) {
+        qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
+    }
+}
+
 void qemu_init_vcpu(void *_env)
 {
     CPUArchState *env = _env;
@@ -956,8 +1010,10 @@ void qemu_init_vcpu(void *_env)
     env->stopped = 1;
     if (kvm_enabled()) {
         qemu_kvm_start_vcpu(env);
-    } else {
+    } else if (tcg_enabled()) {
         qemu_tcg_init_vcpu(env);
+    } else {
+        qemu_dummy_start_vcpu(env);
     }
 }
 
diff --git a/qemu-options.hx b/qemu-options.hx
index 662f571..fe88939 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2715,6 +2715,14 @@ the @var{simple} tracing backend.
 @end table
 ETEXI
 
+DEF("qtest", HAS_ARG, QEMU_OPTION_qtest,
+    "-qtest CHR      specify tracing options\n",
+    QEMU_ARCH_ALL)
+
+DEF("qtest-log", HAS_ARG, QEMU_OPTION_qtest_log,
+    "-qtest-log LOG  specify tracing options\n",
+    QEMU_ARCH_ALL)
+
 HXCOMM This is the last statement. Insert new options before this line!
 STEXI
 @end table
diff --git a/qtest.c b/qtest.c
new file mode 100644
index 0000000..46ebda1
--- /dev/null
+++ b/qtest.c
@@ -0,0 +1,354 @@
+/*
+ * Test Server
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qtest.h"
+#include "qemu-char.h"
+#include "ioport.h"
+#include "memory.h"
+#include "hw/irq.h"
+#include "sysemu.h"
+
+#define MAX_IRQ 256
+
+const char *qtest_chrdev;
+const char *qtest_log;
+int qtest_allowed = 0;
+
+static FILE *qtest_log_fp;
+static CharDriverState *qtest_chr;
+static GString *inbuf;
+static int irq_levels[MAX_IRQ];
+static struct timeval start_time;
+static bool qtest_opened;
+
+#define FMT_timeval "%" PRId64 ".%06" PRId64
+
+/**
+ * QTest Protocol
+ *
+ * Line based protocol, request/response based.  Server can send async messages
+ * so clients should always handle many async messages before the response
+ * comes in.
+ *
+ * Valid requests
+ *
+ *  > outb ADDR VALUE
+ *  < OK
+ *
+ *  > outw ADDR VALUE
+ *  < OK
+ *
+ *  > outl ADDR VALUE
+ *  < OK
+ *
+ *  > inb ADDR
+ *  < OK VALUE
+ *
+ *  > inw ADDR
+ *  < OK VALUE
+ *
+ *  > inl ADDR
+ *  < OK VALUE
+ *
+ *  > read ADDR SIZE
+ *  < OK DATA
+ *
+ *  > write ADDR SIZE DATA
+ *  < OK
+ *
+ * Valid async messages:
+ *
+ *  IRQ raise NUM
+ *  IRQ lower NUM
+ *
+ * ADDR, SIZE, VALUE are all integers parsed with strtoul() with a base of 0.
+ *
+ * DATA is an arbitrarily long hex number prefixed with '0x'.  If it's smaller
+ * than the expected size, the value will be zero filled at the end of the data
+ * sequence.
+ *
+ * NUM is an IRQ number.
+ */
+
+static int hex2nib(char ch)
+{
+    if (ch >= '0' && ch <= '9') {
+        return ch - '0';
+    } else if (ch >= 'a' && ch <= 'f') {
+        return 10 + (ch - 'a');
+    } else if (ch >= 'A' && ch <= 'F') {
+        return 10 + (ch - 'a');
+    } else {
+        return -1;
+    }
+}
+
+static void qtest_get_time(struct timeval *tv)
+{
+    gettimeofday(tv, NULL);
+    tv->tv_sec -= start_time.tv_sec;
+    tv->tv_usec -= start_time.tv_usec;
+    if (tv->tv_usec < 0) {
+        tv->tv_usec += 1000000;
+        tv->tv_sec -= 1;
+    }
+}
+
+static void qtest_send_prefix(CharDriverState *chr)
+{
+    struct timeval tv;
+
+    if (!qtest_log_fp || !qtest_opened) {
+        return;
+    }
+
+    qtest_get_time(&tv);
+    fprintf(qtest_log_fp, "[S +" FMT_timeval "] ",
+            tv.tv_sec, tv.tv_usec);
+}
+
+static void qtest_send(CharDriverState *chr, const char *fmt, ...)
+{
+    va_list ap;
+    char buffer[1024];
+    size_t len;
+
+    va_start(ap, fmt);
+    len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
+    va_end(ap);
+
+    qemu_chr_fe_write(chr, (uint8_t *)buffer, len);
+    if (qtest_log_fp && qtest_opened) {
+        fprintf(qtest_log_fp, "%s", buffer);
+    }
+}
+
+static void qtest_process_command(CharDriverState *chr, gchar **words)
+{
+    const gchar *command;
+
+    g_assert(words);
+
+    command = words[0];
+
+    if (qtest_log_fp) {
+        struct timeval tv;
+        int i;
+
+        qtest_get_time(&tv);
+        fprintf(qtest_log_fp, "[R +" FMT_timeval "]",
+                tv.tv_sec, tv.tv_usec);
+        for (i = 0; words[i]; i++) {
+            fprintf(qtest_log_fp, " %s", words[i]);
+        }
+        fprintf(qtest_log_fp, "\n");
+    }
+
+    g_assert(command);
+    if (strcmp(words[0], "outb") == 0 ||
+        strcmp(words[0], "outw") == 0 ||
+        strcmp(words[0], "outl") == 0) {
+        uint16_t addr;
+        uint32_t value;
+
+        g_assert(words[1] && words[2]);
+        addr = strtol(words[1], NULL, 0);
+        value = strtol(words[2], NULL, 0);
+
+        if (words[0][3] == 'b') {
+            cpu_outb(addr, value);
+        } else if (words[0][3] == 'w') {
+            cpu_outw(addr, value);
+        } else if (words[0][3] == 'l') {
+            cpu_outl(addr, value);
+        }
+        qtest_send_prefix(chr);
+        qtest_send(chr, "OK\n");
+    } else if (strcmp(words[0], "inb") == 0 ||
+        strcmp(words[0], "inw") == 0 ||
+        strcmp(words[0], "inl") == 0) {
+        uint16_t addr;
+        uint32_t value = -1U;
+
+        g_assert(words[1]);
+        addr = strtol(words[1], NULL, 0);
+
+        if (words[0][2] == 'b') {
+            value = cpu_inb(addr);
+        } else if (words[0][2] == 'w') {
+            value = cpu_inw(addr);
+        } else if (words[0][2] == 'l') {
+            value = cpu_inl(addr);
+        }
+        qtest_send_prefix(chr);
+        qtest_send(chr, "OK 0x%04x\n", value);
+    } else if (strcmp(words[0], "read") == 0) {
+        uint64_t addr, len, i;
+        uint8_t *data;
+
+        g_assert(words[1] && words[2]);
+        addr = strtoul(words[1], NULL, 0);
+        len = strtoul(words[2], NULL, 0);
+
+        data = g_malloc(len);
+        cpu_physical_memory_read(addr, data, len);
+
+        qtest_send_prefix(chr);
+        qtest_send(chr, "OK 0x");
+        for (i = 0; i < len; i++) {
+            qtest_send(chr, "%02x", data[i]);
+        }
+        qtest_send(chr, "\n");
+
+        g_free(data);
+    } else if (strcmp(words[0], "write") == 0) {
+        uint64_t addr, len, i;
+        uint8_t *data;
+        size_t data_len;
+
+        g_assert(words[1] && words[2] && words[3]);
+        addr = strtoul(words[1], NULL, 0);
+        len = strtoul(words[2], NULL, 0);
+
+        data_len = strlen(words[3]);
+        if (data_len < 3) {
+            qtest_send(chr, "ERR invalid argument size\n");
+            return;
+        }
+
+        data = g_malloc(len);
+        for (i = 0; i < len; i++) {
+            if ((i * 2 + 4) <= data_len) {
+                data[i] = hex2nib(words[3][i * 2 + 2]) << 4;
+                data[i] |= hex2nib(words[3][i * 2 + 3]);
+            } else {
+                data[i] = 0;
+            }
+        }
+        cpu_physical_memory_write(addr, data, len);
+        g_free(data);
+
+        qtest_send_prefix(chr);
+        qtest_send(chr, "OK\n");
+    } else {
+        qtest_send_prefix(chr);
+        qtest_send(chr, "FAIL Unknown command `%s'\n", words[0]);
+    }
+}
+
+static void qtest_process_inbuf(CharDriverState *chr, GString *inbuf)
+{
+    char *end;
+
+    while ((end = strchr(inbuf->str, '\n')) != NULL) {
+        size_t offset;
+        GString *cmd;
+        gchar **words;
+
+        offset = end - inbuf->str;
+
+        cmd = g_string_new_len(inbuf->str, offset);
+        g_string_erase(inbuf, 0, offset + 1);
+
+        words = g_strsplit(cmd->str, " ", 0);
+        qtest_process_command(chr, words);
+        g_strfreev(words);
+
+        g_string_free(cmd, TRUE);
+    }
+}
+
+static void qtest_read(void *opaque, const uint8_t *buf, int size)
+{
+    CharDriverState *chr = opaque;
+
+    g_string_append_len(inbuf, (const gchar *)buf, size);
+    qtest_process_inbuf(chr, inbuf);
+}
+
+static int qtest_can_read(void *opaque)
+{
+    return 1024;
+}
+
+static void qtest_event(void *opaque, int event)
+{
+    int i;
+
+    switch (event) {
+    case CHR_EVENT_OPENED:
+        qemu_system_reset(false);
+        for (i = 0; i < ARRAY_SIZE(irq_levels); i++) {
+            irq_levels[i] = 0;
+        }
+        gettimeofday(&start_time, NULL);
+        qtest_opened = true;
+        if (qtest_log_fp) {
+            fprintf(qtest_log_fp, "[I " FMT_timeval "] OPENED\n",
+                    start_time.tv_sec, start_time.tv_usec);
+        }
+        break;
+    case CHR_EVENT_CLOSED:
+        qtest_opened = false;
+        if (qtest_log_fp) {
+            struct timeval tv;
+            qtest_get_time(&tv);
+            fprintf(qtest_log_fp, "[I +" FMT_timeval "] CLOSED\n",
+                    tv.tv_sec, tv.tv_usec);
+        }
+        break;
+    default:
+        break;
+    }
+}
+
+static void qtest_set_irq(void *opaque, int irq, int level)
+{
+    CharDriverState *chr = qtest_chr;
+    bool changed;
+
+    changed = (irq_levels[irq] != level);
+    irq_levels[irq] = level;
+
+    if (changed) {
+        qtest_send_prefix(chr);
+        qtest_send(chr, "IRQ %s %d\n",
+                   level ? "raise" : "lower", irq);
+    }
+}
+
+int qtest_init(void)
+{
+    CharDriverState *chr;
+
+    g_assert(qtest_chrdev != NULL);
+
+    chr = qemu_chr_new("qtest", qtest_chrdev, NULL);
+
+    qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event, chr);
+    qemu_chr_fe_set_echo(chr, true);
+
+    inbuf = g_string_new("");
+
+    if (qtest_log) {
+        if (strcmp(qtest_log, "none") != 0) {
+            qtest_log_fp = fopen(qtest_log, "w+");
+        }
+    } else {
+        qtest_log_fp = stderr;
+    }
+
+    qtest_chr = chr;
+
+    return 0;
+}
diff --git a/qtest.h b/qtest.h
new file mode 100644
index 0000000..1478343
--- /dev/null
+++ b/qtest.h
@@ -0,0 +1,35 @@
+/*
+ * Test Server
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef QTEST_H
+#define QTEST_H
+
+#include "qemu-common.h"
+
+extern int qtest_allowed;
+extern const char *qtest_chrdev;
+extern const char *qtest_log;
+
+static inline bool qtest_enabled(void)
+{
+    return qtest_allowed;
+}
+
+static inline int qtest_available(void)
+{
+    return 1;
+}
+
+int qtest_init(void);
+
+#endif
diff --git a/scripts/qtest b/scripts/qtest
new file mode 100755
index 0000000..4ef6c1c
--- /dev/null
+++ b/scripts/qtest
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+export QTEST_QEMU_BINARY=$1
+shift
+"$@"
diff --git a/vl.c b/vl.c
index 0fccf50..e575401 100644
--- a/vl.c
+++ b/vl.c
@@ -152,6 +152,7 @@ int main(int argc, char **argv)
 #ifdef CONFIG_VIRTFS
 #include "fsdev/qemu-fsdev.h"
 #endif
+#include "qtest.h"
 
 #include "disas.h"
 
@@ -1312,7 +1313,7 @@ int qemu_shutdown_requested(void)
 
 void qemu_kill_report(void)
 {
-    if (shutdown_signal != -1) {
+    if (!qtest_enabled() && shutdown_signal != -1) {
         fprintf(stderr, "qemu: terminating on signal %d", shutdown_signal);
         if (shutdown_pid == 0) {
             /* This happens for eg ^C at the terminal, so it's worth
@@ -2098,6 +2099,7 @@ static struct {
     { "tcg", "tcg", tcg_available, tcg_init, &tcg_allowed },
     { "xen", "Xen", xen_available, xen_init, &xen_allowed },
     { "kvm", "KVM", kvm_available, kvm_init, &kvm_allowed },
+    { "qtest", "QTest", qtest_available, qtest_init, &qtest_allowed },
 };
 
 static int configure_accelerator(void)
@@ -3181,6 +3183,12 @@ int main(int argc, char **argv, char **envp)
                     fclose(fp);
                     break;
                 }
+            case QEMU_OPTION_qtest:
+                qtest_chrdev = optarg;
+                break;
+            case QEMU_OPTION_qtest_log:
+                qtest_log = optarg;
+                break;
             default:
                 os_parse_cmd_args(popt->index, optarg);
             }
commit b93b63f574ccb451e82f81c6da7c39b3ecb4f24c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Mar 28 15:42:01 2012 +0200

    test makefile overhaul
    
    This introduces new test reporting infrastructure based on
    gtester and gtester-report.
    
    Also, all existing tests are moved to tests/, and tests/Makefile
    is reorganized to factor out the commonalities in the rules.
    
    Signed-off-by: Anthony Liguori <aliguori at linux.vnet.ibm.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/check-qdict.c b/check-qdict.c
deleted file mode 100644
index fc0d276..0000000
--- a/check-qdict.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * QDict unit-tests.
- *
- * Copyright (C) 2009 Red Hat Inc.
- *
- * Authors:
- *  Luiz Capitulino <lcapitulino at redhat.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-#include <glib.h>
-
-#include "qint.h"
-#include "qdict.h"
-#include "qstring.h"
-#include "qemu-common.h"
-
-/*
- * Public Interface test-cases
- *
- * (with some violations to access 'private' data)
- */
-
-static void qdict_new_test(void)
-{
-    QDict *qdict;
-
-    qdict = qdict_new();
-    g_assert(qdict != NULL);
-    g_assert(qdict_size(qdict) == 0);
-    g_assert(qdict->base.refcnt == 1);
-    g_assert(qobject_type(QOBJECT(qdict)) == QTYPE_QDICT);
-
-    // destroy doesn't exit yet
-    g_free(qdict);
-}
-
-static void qdict_put_obj_test(void)
-{
-    QInt *qi;
-    QDict *qdict;
-    QDictEntry *ent;
-    const int num = 42;
-
-    qdict = qdict_new();
-
-    // key "" will have tdb hash 12345
-    qdict_put_obj(qdict, "", QOBJECT(qint_from_int(num)));
-
-    g_assert(qdict_size(qdict) == 1);
-    ent = QLIST_FIRST(&qdict->table[12345 % QDICT_BUCKET_MAX]);
-    qi = qobject_to_qint(ent->value);
-    g_assert(qint_get_int(qi) == num);
-
-    // destroy doesn't exit yet
-    QDECREF(qi);
-    g_free(ent->key);
-    g_free(ent);
-    g_free(qdict);
-}
-
-static void qdict_destroy_simple_test(void)
-{
-    QDict *qdict;
-
-    qdict = qdict_new();
-    qdict_put_obj(qdict, "num", QOBJECT(qint_from_int(0)));
-    qdict_put_obj(qdict, "str", QOBJECT(qstring_from_str("foo")));
-
-    QDECREF(qdict);
-}
-
-static void qdict_get_test(void)
-{
-    QInt *qi;
-    QObject *obj;
-    const int value = -42;
-    const char *key = "test";
-    QDict *tests_dict = qdict_new();
-
-    qdict_put(tests_dict, key, qint_from_int(value));
-
-    obj = qdict_get(tests_dict, key);
-    g_assert(obj != NULL);
-
-    qi = qobject_to_qint(obj);
-    g_assert(qint_get_int(qi) == value);
-
-    QDECREF(tests_dict);
-}
-
-static void qdict_get_int_test(void)
-{
-    int ret;
-    const int value = 100;
-    const char *key = "int";
-    QDict *tests_dict = qdict_new();
-
-    qdict_put(tests_dict, key, qint_from_int(value));
-
-    ret = qdict_get_int(tests_dict, key);
-    g_assert(ret == value);
-
-    QDECREF(tests_dict);
-}
-
-static void qdict_get_try_int_test(void)
-{
-    int ret;
-    const int value = 100;
-    const char *key = "int";
-    QDict *tests_dict = qdict_new();
-
-    qdict_put(tests_dict, key, qint_from_int(value));
-
-    ret = qdict_get_try_int(tests_dict, key, 0);
-    g_assert(ret == value);
-
-    QDECREF(tests_dict);
-}
-
-static void qdict_get_str_test(void)
-{
-    const char *p;
-    const char *key = "key";
-    const char *str = "string";
-    QDict *tests_dict = qdict_new();
-
-    qdict_put(tests_dict, key, qstring_from_str(str));
-
-    p = qdict_get_str(tests_dict, key);
-    g_assert(p != NULL);
-    g_assert(strcmp(p, str) == 0);
-
-    QDECREF(tests_dict);
-}
-
-static void qdict_get_try_str_test(void)
-{
-    const char *p;
-    const char *key = "key";
-    const char *str = "string";
-    QDict *tests_dict = qdict_new();
-
-    qdict_put(tests_dict, key, qstring_from_str(str));
-
-    p = qdict_get_try_str(tests_dict, key);
-    g_assert(p != NULL);
-    g_assert(strcmp(p, str) == 0);
-
-    QDECREF(tests_dict);
-}
-
-static void qdict_haskey_not_test(void)
-{
-    QDict *tests_dict = qdict_new();
-    g_assert(qdict_haskey(tests_dict, "test") == 0);
-
-    QDECREF(tests_dict);
-}
-
-static void qdict_haskey_test(void)
-{
-    const char *key = "test";
-    QDict *tests_dict = qdict_new();
-
-    qdict_put(tests_dict, key, qint_from_int(0));
-    g_assert(qdict_haskey(tests_dict, key) == 1);
-
-    QDECREF(tests_dict);
-}
-
-static void qdict_del_test(void)
-{
-    const char *key = "key test";
-    QDict *tests_dict = qdict_new();
-
-    qdict_put(tests_dict, key, qstring_from_str("foo"));
-    g_assert(qdict_size(tests_dict) == 1);
-
-    qdict_del(tests_dict, key);
-
-    g_assert(qdict_size(tests_dict) == 0);
-    g_assert(qdict_haskey(tests_dict, key) == 0);
-
-    QDECREF(tests_dict);
-}
-
-static void qobject_to_qdict_test(void)
-{
-    QDict *tests_dict = qdict_new();
-    g_assert(qobject_to_qdict(QOBJECT(tests_dict)) == tests_dict);
-
-    QDECREF(tests_dict);
-}
-
-static void qdict_iterapi_test(void)
-{
-    int count;
-    const QDictEntry *ent;
-    QDict *tests_dict = qdict_new();
-
-    g_assert(qdict_first(tests_dict) == NULL);
-
-    qdict_put(tests_dict, "key1", qint_from_int(1));
-    qdict_put(tests_dict, "key2", qint_from_int(2));
-    qdict_put(tests_dict, "key3", qint_from_int(3));
-
-    count = 0;
-    for (ent = qdict_first(tests_dict); ent; ent = qdict_next(tests_dict, ent)){
-        g_assert(qdict_haskey(tests_dict, qdict_entry_key(ent)) == 1);
-        count++;
-    }
-
-    g_assert(count == qdict_size(tests_dict));
-
-    /* Do it again to test restarting */
-    count = 0;
-    for (ent = qdict_first(tests_dict); ent; ent = qdict_next(tests_dict, ent)){
-        g_assert(qdict_haskey(tests_dict, qdict_entry_key(ent)) == 1);
-        count++;
-    }
-
-    g_assert(count == qdict_size(tests_dict));
-
-    QDECREF(tests_dict);
-}
-
-/*
- * Errors test-cases
- */
-
-static void qdict_put_exists_test(void)
-{
-    int value;
-    const char *key = "exists";
-    QDict *tests_dict = qdict_new();
-
-    qdict_put(tests_dict, key, qint_from_int(1));
-    qdict_put(tests_dict, key, qint_from_int(2));
-
-    value = qdict_get_int(tests_dict, key);
-    g_assert(value == 2);
-
-    g_assert(qdict_size(tests_dict) == 1);
-
-    QDECREF(tests_dict);
-}
-
-static void qdict_get_not_exists_test(void)
-{
-    QDict *tests_dict = qdict_new();
-    g_assert(qdict_get(tests_dict, "foo") == NULL);
-
-    QDECREF(tests_dict);
-}
-
-/*
- * Stress test-case
- *
- * This is a lot big for a unit-test, but there is no other place
- * to have it.
- */
-
-static void remove_dots(char *string)
-{
-    char *p = strchr(string, ':');
-    if (p)
-        *p = '\0';
-}
-
-static QString *read_line(FILE *file, char *key)
-{
-    char value[128];
-
-    if (fscanf(file, "%127s%127s", key, value) == EOF) {
-        return NULL;
-    }
-    remove_dots(key);
-    return qstring_from_str(value);
-}
-
-#define reset_file(file)    fseek(file, 0L, SEEK_SET)
-
-static void qdict_stress_test(void)
-{
-    size_t lines;
-    char key[128];
-    FILE *test_file;
-    QDict *qdict;
-    QString *value;
-    const char *test_file_path = "qdict-test-data.txt";
-
-    test_file = fopen(test_file_path, "r");
-    g_assert(test_file != NULL);
-
-    // Create the dict
-    qdict = qdict_new();
-    g_assert(qdict != NULL);
-
-    // Add everything from the test file
-    for (lines = 0;; lines++) {
-        value = read_line(test_file, key);
-        if (!value)
-            break;
-
-        qdict_put(qdict, key, value);
-    }
-    g_assert(qdict_size(qdict) == lines);
-
-    // Check if everything is really in there
-    reset_file(test_file);
-    for (;;) {
-        const char *str1, *str2;
-
-        value = read_line(test_file, key);
-        if (!value)
-            break;
-
-        str1 = qstring_get_str(value);
-
-        str2 = qdict_get_str(qdict, key);
-        g_assert(str2 != NULL);
-
-        g_assert(strcmp(str1, str2) == 0);
-
-        QDECREF(value);
-    }
-
-    // Delete everything
-    reset_file(test_file);
-    for (;;) {
-        value = read_line(test_file, key);
-        if (!value)
-            break;
-
-        qdict_del(qdict, key);
-        QDECREF(value);
-
-        g_assert(qdict_haskey(qdict, key) == 0);
-    }
-    fclose(test_file);
-
-    g_assert(qdict_size(qdict) == 0);
-    QDECREF(qdict);
-}
-
-int main(int argc, char **argv)
-{
-    g_test_init(&argc, &argv, NULL);
-
-    g_test_add_func("/public/new", qdict_new_test);
-    g_test_add_func("/public/put_obj", qdict_put_obj_test);
-    g_test_add_func("/public/destroy_simple", qdict_destroy_simple_test);
-
-    /* Continue, but now with fixtures */
-    g_test_add_func("/public/get", qdict_get_test);
-    g_test_add_func("/public/get_int", qdict_get_int_test);
-    g_test_add_func("/public/get_try_int", qdict_get_try_int_test);
-    g_test_add_func("/public/get_str", qdict_get_str_test);
-    g_test_add_func("/public/get_try_str", qdict_get_try_str_test);
-    g_test_add_func("/public/haskey_not", qdict_haskey_not_test);
-    g_test_add_func("/public/haskey", qdict_haskey_test);
-    g_test_add_func("/public/del", qdict_del_test);
-    g_test_add_func("/public/to_qdict", qobject_to_qdict_test);
-    g_test_add_func("/public/iterapi", qdict_iterapi_test);
-
-    g_test_add_func("/errors/put_exists", qdict_put_exists_test);
-    g_test_add_func("/errors/get_not_exists", qdict_get_not_exists_test);
-
-    /* The Big one */
-    if (g_test_slow()) {
-        g_test_add_func("/stress/test", qdict_stress_test);
-    }
-
-    return g_test_run();
-}
diff --git a/check-qfloat.c b/check-qfloat.c
deleted file mode 100644
index cdc66ea..0000000
--- a/check-qfloat.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * QFloat unit-tests.
- *
- * Copyright IBM, Corp. 2009
- *
- * Authors:
- *  Anthony Liguori   <aliguori at us.ibm.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- *
- */
-#include <glib.h>
-
-#include "qfloat.h"
-#include "qemu-common.h"
-
-/*
- * Public Interface test-cases
- *
- * (with some violations to access 'private' data)
- */
-
-static void qfloat_from_double_test(void)
-{
-    QFloat *qf;
-    const double value = -42.23423;
-
-    qf = qfloat_from_double(value);
-    g_assert(qf != NULL);
-    g_assert(qf->value == value);
-    g_assert(qf->base.refcnt == 1);
-    g_assert(qobject_type(QOBJECT(qf)) == QTYPE_QFLOAT);
-
-    // destroy doesn't exit yet
-    g_free(qf);
-}
-
-static void qfloat_destroy_test(void)
-{
-    QFloat *qf = qfloat_from_double(0.0);
-    QDECREF(qf);
-}
-
-int main(int argc, char **argv)
-{
-    g_test_init(&argc, &argv, NULL);
-
-    g_test_add_func("/public/from_double", qfloat_from_double_test);
-    g_test_add_func("/public/destroy", qfloat_destroy_test);
-
-    return g_test_run();
-}
diff --git a/check-qint.c b/check-qint.c
deleted file mode 100644
index 5a27119..0000000
--- a/check-qint.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * QInt unit-tests.
- *
- * Copyright (C) 2009 Red Hat Inc.
- *
- * Authors:
- *  Luiz Capitulino <lcapitulino at redhat.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-#include <glib.h>
-
-#include "qint.h"
-#include "qemu-common.h"
-
-/*
- * Public Interface test-cases
- *
- * (with some violations to access 'private' data)
- */
-
-static void qint_from_int_test(void)
-{
-    QInt *qi;
-    const int value = -42;
-
-    qi = qint_from_int(value);
-    g_assert(qi != NULL);
-    g_assert(qi->value == value);
-    g_assert(qi->base.refcnt == 1);
-    g_assert(qobject_type(QOBJECT(qi)) == QTYPE_QINT);
-
-    // destroy doesn't exit yet
-    g_free(qi);
-}
-
-static void qint_destroy_test(void)
-{
-    QInt *qi = qint_from_int(0);
-    QDECREF(qi);
-}
-
-static void qint_from_int64_test(void)
-{
-    QInt *qi;
-    const int64_t value = 0x1234567890abcdefLL;
-
-    qi = qint_from_int(value);
-    g_assert((int64_t) qi->value == value);
-
-    QDECREF(qi);
-}
-
-static void qint_get_int_test(void)
-{
-    QInt *qi;
-    const int value = 123456;
-
-    qi = qint_from_int(value);
-    g_assert(qint_get_int(qi) == value);
-
-    QDECREF(qi);
-}
-
-static void qobject_to_qint_test(void)
-{
-    QInt *qi;
-
-    qi = qint_from_int(0);
-    g_assert(qobject_to_qint(QOBJECT(qi)) == qi);
-
-    QDECREF(qi);
-}
-
-int main(int argc, char **argv)
-{
-    g_test_init(&argc, &argv, NULL);
-
-    g_test_add_func("/public/from_int", qint_from_int_test);
-    g_test_add_func("/public/destroy", qint_destroy_test);
-    g_test_add_func("/public/from_int64", qint_from_int64_test);
-    g_test_add_func("/public/get_int", qint_get_int_test);
-    g_test_add_func("/public/to_qint", qobject_to_qint_test);
-
-    return g_test_run();
-}
diff --git a/check-qjson.c b/check-qjson.c
deleted file mode 100644
index 526e25e..0000000
--- a/check-qjson.c
+++ /dev/null
@@ -1,728 +0,0 @@
-/*
- * Copyright IBM, Corp. 2009
- *
- * Authors:
- *  Anthony Liguori   <aliguori at us.ibm.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- *
- */
-#include <glib.h>
-
-#include "qstring.h"
-#include "qint.h"
-#include "qdict.h"
-#include "qlist.h"
-#include "qfloat.h"
-#include "qbool.h"
-#include "qjson.h"
-
-#include "qemu-common.h"
-
-static void escaped_string(void)
-{
-    int i;
-    struct {
-        const char *encoded;
-        const char *decoded;
-        int skip;
-    } test_cases[] = {
-        { "\"\\b\"", "\b" },
-        { "\"\\f\"", "\f" },
-        { "\"\\n\"", "\n" },
-        { "\"\\r\"", "\r" },
-        { "\"\\t\"", "\t" },
-        { "\"/\"", "/" },
-        { "\"\\/\"", "/", .skip = 1 },
-        { "\"\\\\\"", "\\" },
-        { "\"\\\"\"", "\"" },
-        { "\"hello world \\\"embedded string\\\"\"",
-          "hello world \"embedded string\"" },
-        { "\"hello world\\nwith new line\"", "hello world\nwith new line" },
-        { "\"single byte utf-8 \\u0020\"", "single byte utf-8  ", .skip = 1 },
-        { "\"double byte utf-8 \\u00A2\"", "double byte utf-8 \xc2\xa2" },
-        { "\"triple byte utf-8 \\u20AC\"", "triple byte utf-8 \xe2\x82\xac" },
-        {}
-    };
-
-    for (i = 0; test_cases[i].encoded; i++) {
-        QObject *obj;
-        QString *str;
-
-        obj = qobject_from_json(test_cases[i].encoded);
-
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QSTRING);
-        
-        str = qobject_to_qstring(obj);
-        g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].decoded);
-
-        if (test_cases[i].skip == 0) {
-            str = qobject_to_json(obj);
-            g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].encoded);
-            qobject_decref(obj);
-        }
-
-        QDECREF(str);
-    }
-}
-
-static void simple_string(void)
-{
-    int i;
-    struct {
-        const char *encoded;
-        const char *decoded;
-    } test_cases[] = {
-        { "\"hello world\"", "hello world" },
-        { "\"the quick brown fox jumped over the fence\"",
-          "the quick brown fox jumped over the fence" },
-        {}
-    };
-
-    for (i = 0; test_cases[i].encoded; i++) {
-        QObject *obj;
-        QString *str;
-
-        obj = qobject_from_json(test_cases[i].encoded);
-
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QSTRING);
-        
-        str = qobject_to_qstring(obj);
-        g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
-
-        str = qobject_to_json(obj);
-        g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
-
-        qobject_decref(obj);
-        
-        QDECREF(str);
-    }
-}
-
-static void single_quote_string(void)
-{
-    int i;
-    struct {
-        const char *encoded;
-        const char *decoded;
-    } test_cases[] = {
-        { "'hello world'", "hello world" },
-        { "'the quick brown fox \\' jumped over the fence'",
-          "the quick brown fox ' jumped over the fence" },
-        {}
-    };
-
-    for (i = 0; test_cases[i].encoded; i++) {
-        QObject *obj;
-        QString *str;
-
-        obj = qobject_from_json(test_cases[i].encoded);
-
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QSTRING);
-        
-        str = qobject_to_qstring(obj);
-        g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
-
-        QDECREF(str);
-    }
-}
-
-static void vararg_string(void)
-{
-    int i;
-    struct {
-        const char *decoded;
-    } test_cases[] = {
-        { "hello world" },
-        { "the quick brown fox jumped over the fence" },
-        {}
-    };
-
-    for (i = 0; test_cases[i].decoded; i++) {
-        QObject *obj;
-        QString *str;
-
-        obj = qobject_from_jsonf("%s", test_cases[i].decoded);
-
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QSTRING);
-        
-        str = qobject_to_qstring(obj);
-        g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
-
-        QDECREF(str);
-    }
-}
-
-static void simple_number(void)
-{
-    int i;
-    struct {
-        const char *encoded;
-        int64_t decoded;
-        int skip;
-    } test_cases[] = {
-        { "0", 0 },
-        { "1234", 1234 },
-        { "1", 1 },
-        { "-32", -32 },
-        { "-0", 0, .skip = 1 },
-        { },
-    };
-
-    for (i = 0; test_cases[i].encoded; i++) {
-        QObject *obj;
-        QInt *qint;
-
-        obj = qobject_from_json(test_cases[i].encoded);
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QINT);
-
-        qint = qobject_to_qint(obj);
-        g_assert(qint_get_int(qint) == test_cases[i].decoded);
-        if (test_cases[i].skip == 0) {
-            QString *str;
-
-            str = qobject_to_json(obj);
-            g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
-            QDECREF(str);
-        }
-
-        QDECREF(qint);
-    }
-}
-
-static void float_number(void)
-{
-    int i;
-    struct {
-        const char *encoded;
-        double decoded;
-        int skip;
-    } test_cases[] = {
-        { "32.43", 32.43 },
-        { "0.222", 0.222 },
-        { "-32.12313", -32.12313 },
-        { "-32.20e-10", -32.20e-10, .skip = 1 },
-        { },
-    };
-
-    for (i = 0; test_cases[i].encoded; i++) {
-        QObject *obj;
-        QFloat *qfloat;
-
-        obj = qobject_from_json(test_cases[i].encoded);
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QFLOAT);
-
-        qfloat = qobject_to_qfloat(obj);
-        g_assert(qfloat_get_double(qfloat) == test_cases[i].decoded);
-
-        if (test_cases[i].skip == 0) {
-            QString *str;
-
-            str = qobject_to_json(obj);
-            g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
-            QDECREF(str);
-        }
-
-        QDECREF(qfloat);
-    }
-}
-
-static void vararg_number(void)
-{
-    QObject *obj;
-    QInt *qint;
-    QFloat *qfloat;
-    int value = 0x2342;
-    int64_t value64 = 0x2342342343LL;
-    double valuef = 2.323423423;
-
-    obj = qobject_from_jsonf("%d", value);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QINT);
-
-    qint = qobject_to_qint(obj);
-    g_assert(qint_get_int(qint) == value);
-
-    QDECREF(qint);
-
-    obj = qobject_from_jsonf("%" PRId64, value64);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QINT);
-
-    qint = qobject_to_qint(obj);
-    g_assert(qint_get_int(qint) == value64);
-
-    QDECREF(qint);
-
-    obj = qobject_from_jsonf("%f", valuef);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QFLOAT);
-
-    qfloat = qobject_to_qfloat(obj);
-    g_assert(qfloat_get_double(qfloat) == valuef);
-
-    QDECREF(qfloat);
-}
-
-static void keyword_literal(void)
-{
-    QObject *obj;
-    QBool *qbool;
-    QString *str;
-
-    obj = qobject_from_json("true");
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QBOOL);
-
-    qbool = qobject_to_qbool(obj);
-    g_assert(qbool_get_int(qbool) != 0);
-
-    str = qobject_to_json(obj);
-    g_assert(strcmp(qstring_get_str(str), "true") == 0);
-    QDECREF(str);
-
-    QDECREF(qbool);
-
-    obj = qobject_from_json("false");
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QBOOL);
-
-    qbool = qobject_to_qbool(obj);
-    g_assert(qbool_get_int(qbool) == 0);
-
-    str = qobject_to_json(obj);
-    g_assert(strcmp(qstring_get_str(str), "false") == 0);
-    QDECREF(str);
-
-    QDECREF(qbool);
-
-    obj = qobject_from_jsonf("%i", false);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QBOOL);
-
-    qbool = qobject_to_qbool(obj);
-    g_assert(qbool_get_int(qbool) == 0);
-
-    QDECREF(qbool);
-    
-    obj = qobject_from_jsonf("%i", true);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QBOOL);
-
-    qbool = qobject_to_qbool(obj);
-    g_assert(qbool_get_int(qbool) != 0);
-
-    QDECREF(qbool);
-}
-
-typedef struct LiteralQDictEntry LiteralQDictEntry;
-typedef struct LiteralQObject LiteralQObject;
-
-struct LiteralQObject
-{
-    int type;
-    union {
-        int64_t qint;
-        const char *qstr;
-        LiteralQDictEntry *qdict;
-        LiteralQObject *qlist;
-    } value;
-};
-
-struct LiteralQDictEntry
-{
-    const char *key;
-    LiteralQObject value;
-};
-
-#define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
-#define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
-#define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
-#define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
-
-typedef struct QListCompareHelper
-{
-    int index;
-    LiteralQObject *objs;
-    int result;
-} QListCompareHelper;
-
-static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
-
-static void compare_helper(QObject *obj, void *opaque)
-{
-    QListCompareHelper *helper = opaque;
-
-    if (helper->result == 0) {
-        return;
-    }
-
-    if (helper->objs[helper->index].type == QTYPE_NONE) {
-        helper->result = 0;
-        return;
-    }
-
-    helper->result = compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
-}
-
-static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
-{
-    if (lhs->type != qobject_type(rhs)) {
-        return 0;
-    }
-
-    switch (lhs->type) {
-    case QTYPE_QINT:
-        return lhs->value.qint == qint_get_int(qobject_to_qint(rhs));
-    case QTYPE_QSTRING:
-        return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
-    case QTYPE_QDICT: {
-        int i;
-
-        for (i = 0; lhs->value.qdict[i].key; i++) {
-            QObject *obj = qdict_get(qobject_to_qdict(rhs), lhs->value.qdict[i].key);
-
-            if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
-                return 0;
-            }
-        }
-
-        return 1;
-    }
-    case QTYPE_QLIST: {
-        QListCompareHelper helper;
-
-        helper.index = 0;
-        helper.objs = lhs->value.qlist;
-        helper.result = 1;
-        
-        qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
-
-        return helper.result;
-    }
-    default:
-        break;
-    }
-
-    return 0;
-}
-
-static void simple_dict(void)
-{
-    int i;
-    struct {
-        const char *encoded;
-        LiteralQObject decoded;
-    } test_cases[] = {
-        {
-            .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
-            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
-                        { "foo", QLIT_QINT(42) },
-                        { "bar", QLIT_QSTR("hello world") },
-                        { }
-                    })),
-        }, {
-            .encoded = "{}",
-            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
-                        { }
-                    })),
-        }, {
-            .encoded = "{\"foo\": 43}",
-            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
-                        { "foo", QLIT_QINT(43) },
-                        { }
-                    })),
-        },
-        { }
-    };
-
-    for (i = 0; test_cases[i].encoded; i++) {
-        QObject *obj;
-        QString *str;
-
-        obj = qobject_from_json(test_cases[i].encoded);
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QDICT);
-
-        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
-
-        str = qobject_to_json(obj);
-        qobject_decref(obj);
-
-        obj = qobject_from_json(qstring_get_str(str));
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QDICT);
-
-        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
-        qobject_decref(obj);
-        QDECREF(str);
-    }
-}
-
-static void simple_list(void)
-{
-    int i;
-    struct {
-        const char *encoded;
-        LiteralQObject decoded;
-    } test_cases[] = {
-        {
-            .encoded = "[43,42]",
-            .decoded = QLIT_QLIST(((LiteralQObject[]){
-                        QLIT_QINT(43),
-                        QLIT_QINT(42),
-                        { }
-                    })),
-        },
-        {
-            .encoded = "[43]",
-            .decoded = QLIT_QLIST(((LiteralQObject[]){
-                        QLIT_QINT(43),
-                        { }
-                    })),
-        },
-        {
-            .encoded = "[]",
-            .decoded = QLIT_QLIST(((LiteralQObject[]){
-                        { }
-                    })),
-        },
-        {
-            .encoded = "[{}]",
-            .decoded = QLIT_QLIST(((LiteralQObject[]){
-                        QLIT_QDICT(((LiteralQDictEntry[]){
-                                    {},
-                                        })),
-                        {},
-                            })),
-        },
-        { }
-    };
-
-    for (i = 0; test_cases[i].encoded; i++) {
-        QObject *obj;
-        QString *str;
-
-        obj = qobject_from_json(test_cases[i].encoded);
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QLIST);
-
-        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
-
-        str = qobject_to_json(obj);
-        qobject_decref(obj);
-
-        obj = qobject_from_json(qstring_get_str(str));
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QLIST);
-
-        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
-        qobject_decref(obj);
-        QDECREF(str);
-    }
-}
-
-static void simple_whitespace(void)
-{
-    int i;
-    struct {
-        const char *encoded;
-        LiteralQObject decoded;
-    } test_cases[] = {
-        {
-            .encoded = " [ 43 , 42 ]",
-            .decoded = QLIT_QLIST(((LiteralQObject[]){
-                        QLIT_QINT(43),
-                        QLIT_QINT(42),
-                        { }
-                    })),
-        },
-        {
-            .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
-            .decoded = QLIT_QLIST(((LiteralQObject[]){
-                        QLIT_QINT(43),
-                        QLIT_QDICT(((LiteralQDictEntry[]){
-                                    { "h", QLIT_QSTR("b") },
-                                    { }})),
-                        QLIT_QLIST(((LiteralQObject[]){
-                                    { }})),
-                        QLIT_QINT(42),
-                        { }
-                    })),
-        },
-        {
-            .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
-            .decoded = QLIT_QLIST(((LiteralQObject[]){
-                        QLIT_QINT(43),
-                        QLIT_QDICT(((LiteralQDictEntry[]){
-                                    { "h", QLIT_QSTR("b") },
-                                    { "a", QLIT_QINT(32) },
-                                    { }})),
-                        QLIT_QLIST(((LiteralQObject[]){
-                                    { }})),
-                        QLIT_QINT(42),
-                        { }
-                    })),
-        },
-        { }
-    };
-
-    for (i = 0; test_cases[i].encoded; i++) {
-        QObject *obj;
-        QString *str;
-
-        obj = qobject_from_json(test_cases[i].encoded);
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QLIST);
-
-        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
-
-        str = qobject_to_json(obj);
-        qobject_decref(obj);
-
-        obj = qobject_from_json(qstring_get_str(str));
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QLIST);
-
-        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
-
-        qobject_decref(obj);
-        QDECREF(str);
-    }
-}
-
-static void simple_varargs(void)
-{
-    QObject *embedded_obj;
-    QObject *obj;
-    LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
-            QLIT_QINT(1),
-            QLIT_QINT(2),
-            QLIT_QLIST(((LiteralQObject[]){
-                        QLIT_QINT(32),
-                        QLIT_QINT(42),
-                        {}})),
-            {}}));
-
-    embedded_obj = qobject_from_json("[32, 42]");
-    g_assert(embedded_obj != NULL);
-
-    obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
-    g_assert(obj != NULL);
-
-    g_assert(compare_litqobj_to_qobj(&decoded, obj) == 1);
-
-    qobject_decref(obj);
-}
-
-static void empty_input(void)
-{
-    const char *empty = "";
-
-    QObject *obj = qobject_from_json(empty);
-    g_assert(obj == NULL);
-}
-
-static void unterminated_string(void)
-{
-    QObject *obj = qobject_from_json("\"abc");
-    g_assert(obj == NULL);
-}
-
-static void unterminated_sq_string(void)
-{
-    QObject *obj = qobject_from_json("'abc");
-    g_assert(obj == NULL);
-}
-
-static void unterminated_escape(void)
-{
-    QObject *obj = qobject_from_json("\"abc\\\"");
-    g_assert(obj == NULL);
-}
-
-static void unterminated_array(void)
-{
-    QObject *obj = qobject_from_json("[32");
-    g_assert(obj == NULL);
-}
-
-static void unterminated_array_comma(void)
-{
-    QObject *obj = qobject_from_json("[32,");
-    g_assert(obj == NULL);
-}
-
-static void invalid_array_comma(void)
-{
-    QObject *obj = qobject_from_json("[32,}");
-    g_assert(obj == NULL);
-}
-
-static void unterminated_dict(void)
-{
-    QObject *obj = qobject_from_json("{'abc':32");
-    g_assert(obj == NULL);
-}
-
-static void unterminated_dict_comma(void)
-{
-    QObject *obj = qobject_from_json("{'abc':32,");
-    g_assert(obj == NULL);
-}
-
-static void invalid_dict_comma(void)
-{
-    QObject *obj = qobject_from_json("{'abc':32,}");
-    g_assert(obj == NULL);
-}
-
-static void unterminated_literal(void)
-{
-    QObject *obj = qobject_from_json("nul");
-    g_assert(obj == NULL);
-}
-
-int main(int argc, char **argv)
-{
-    g_test_init(&argc, &argv, NULL);
-
-    g_test_add_func("/literals/string/simple", simple_string);
-    g_test_add_func("/literals/string/escaped", escaped_string);
-    g_test_add_func("/literals/string/single_quote", single_quote_string);
-    g_test_add_func("/literals/string/vararg", vararg_string);
-
-    g_test_add_func("/literals/number/simple", simple_number);
-    g_test_add_func("/literals/number/float", float_number);
-    g_test_add_func("/literals/number/vararg", vararg_number);
-
-    g_test_add_func("/literals/keyword", keyword_literal);
-
-    g_test_add_func("/dicts/simple_dict", simple_dict);
-    g_test_add_func("/lists/simple_list", simple_list);
-
-    g_test_add_func("/whitespace/simple_whitespace", simple_whitespace);
-
-    g_test_add_func("/varargs/simple_varargs", simple_varargs);
-
-    g_test_add_func("/errors/empty_input", empty_input);
-    g_test_add_func("/errors/unterminated/string", unterminated_string);
-    g_test_add_func("/errors/unterminated/escape", unterminated_escape);
-    g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string);
-    g_test_add_func("/errors/unterminated/array", unterminated_array);
-    g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma);
-    g_test_add_func("/errors/unterminated/dict", unterminated_dict);
-    g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma);
-    g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
-    g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
-    g_test_add_func("/errors/unterminated/literal", unterminated_literal);
-
-    return g_test_run();
-}
diff --git a/check-qlist.c b/check-qlist.c
deleted file mode 100644
index 501ba26..0000000
--- a/check-qlist.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * QList unit-tests.
- *
- * Copyright (C) 2009 Red Hat Inc.
- *
- * Authors:
- *  Luiz Capitulino <lcapitulino at redhat.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-#include <glib.h>
-
-#include "qint.h"
-#include "qlist.h"
-
-/*
- * Public Interface test-cases
- *
- * (with some violations to access 'private' data)
- */
-
-static void qlist_new_test(void)
-{
-    QList *qlist;
-
-    qlist = qlist_new();
-    g_assert(qlist != NULL);
-    g_assert(qlist->base.refcnt == 1);
-    g_assert(qobject_type(QOBJECT(qlist)) == QTYPE_QLIST);
-
-    // destroy doesn't exist yet
-    g_free(qlist);
-}
-
-static void qlist_append_test(void)
-{
-    QInt *qi;
-    QList *qlist;
-    QListEntry *entry;
-
-    qi = qint_from_int(42);
-
-    qlist = qlist_new();
-    qlist_append(qlist, qi);
-
-    entry = QTAILQ_FIRST(&qlist->head);
-    g_assert(entry != NULL);
-    g_assert(entry->value == QOBJECT(qi));
-
-    // destroy doesn't exist yet
-    QDECREF(qi);
-    g_free(entry);
-    g_free(qlist);
-}
-
-static void qobject_to_qlist_test(void)
-{
-    QList *qlist;
-
-    qlist = qlist_new();
-
-    g_assert(qobject_to_qlist(QOBJECT(qlist)) == qlist);
-
-    // destroy doesn't exist yet
-    g_free(qlist);
-}
-
-static void qlist_destroy_test(void)
-{
-    int i;
-    QList *qlist;
-
-    qlist = qlist_new();
-
-    for (i = 0; i < 42; i++)
-        qlist_append(qlist, qint_from_int(i));
-
-    QDECREF(qlist);
-}
-
-static int iter_called;
-static const int iter_max = 42;
-
-static void iter_func(QObject *obj, void *opaque)
-{
-    QInt *qi;
-
-    g_assert(opaque == NULL);
-
-    qi = qobject_to_qint(obj);
-    g_assert(qi != NULL);
-    g_assert((qint_get_int(qi) >= 0) && (qint_get_int(qi) <= iter_max));
-
-    iter_called++;
-}
-
-static void qlist_iter_test(void)
-{
-    int i;
-    QList *qlist;
-
-    qlist = qlist_new();
-
-    for (i = 0; i < iter_max; i++)
-        qlist_append(qlist, qint_from_int(i));
-
-    iter_called = 0;
-    qlist_iter(qlist, iter_func, NULL);
-
-    g_assert(iter_called == iter_max);
-
-    QDECREF(qlist);
-}
-
-int main(int argc, char **argv)
-{
-    g_test_init(&argc, &argv, NULL);
-
-    g_test_add_func("/public/new", qlist_new_test);
-    g_test_add_func("/public/append", qlist_append_test);
-    g_test_add_func("/public/to_qlist", qobject_to_qlist_test);
-    g_test_add_func("/public/destroy", qlist_destroy_test);
-    g_test_add_func("/public/iter", qlist_iter_test);
-
-    return g_test_run();
-}
diff --git a/check-qstring.c b/check-qstring.c
deleted file mode 100644
index addad6c..0000000
--- a/check-qstring.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * QString unit-tests.
- *
- * Copyright (C) 2009 Red Hat Inc.
- *
- * Authors:
- *  Luiz Capitulino <lcapitulino at redhat.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-#include <glib.h>
-
-#include "qstring.h"
-#include "qemu-common.h"
-
-/*
- * Public Interface test-cases
- *
- * (with some violations to access 'private' data)
- */
-
-static void qstring_from_str_test(void)
-{
-    QString *qstring;
-    const char *str = "QEMU";
-
-    qstring = qstring_from_str(str);
-    g_assert(qstring != NULL);
-    g_assert(qstring->base.refcnt == 1);
-    g_assert(strcmp(str, qstring->string) == 0);
-    g_assert(qobject_type(QOBJECT(qstring)) == QTYPE_QSTRING);
-
-    // destroy doesn't exit yet
-    g_free(qstring->string);
-    g_free(qstring);
-}
-
-static void qstring_destroy_test(void)
-{
-    QString *qstring = qstring_from_str("destroy test");
-    QDECREF(qstring);
-}
-
-static void qstring_get_str_test(void)
-{
-    QString *qstring;
-    const char *ret_str;
-    const char *str = "QEMU/KVM";
-
-    qstring = qstring_from_str(str);
-    ret_str = qstring_get_str(qstring);
-    g_assert(strcmp(ret_str, str) == 0);
-
-    QDECREF(qstring);
-}
-
-static void qstring_append_chr_test(void)
-{
-    int i;
-    QString *qstring;
-    const char *str = "qstring append char unit-test";
-
-    qstring = qstring_new();
-
-    for (i = 0; str[i]; i++)
-        qstring_append_chr(qstring, str[i]);
-
-    g_assert(strcmp(str, qstring_get_str(qstring)) == 0);
-    QDECREF(qstring);
-}
-
-static void qstring_from_substr_test(void)
-{
-    QString *qs;
-
-    qs = qstring_from_substr("virtualization", 3, 9);
-    g_assert(qs != NULL);
-    g_assert(strcmp(qstring_get_str(qs), "tualiza") == 0);
-
-    QDECREF(qs);
-}
-
-
-static void qobject_to_qstring_test(void)
-{
-    QString *qstring;
-
-    qstring = qstring_from_str("foo");
-    g_assert(qobject_to_qstring(QOBJECT(qstring)) == qstring);
-
-    QDECREF(qstring);
-}
-
-int main(int argc, char **argv)
-{
-    g_test_init(&argc, &argv, NULL);
-
-    g_test_add_func("/public/from_str", qstring_from_str_test);
-    g_test_add_func("/public/destroy", qstring_destroy_test);
-    g_test_add_func("/public/get_str", qstring_get_str_test);
-    g_test_add_func("/public/append_chr", qstring_append_chr_test);
-    g_test_add_func("/public/from_substr", qstring_from_substr_test);
-    g_test_add_func("/public/to_qstring", qobject_to_qstring_test);
-
-    return g_test_run();
-}
diff --git a/rules.mak b/rules.mak
index 04a9198..c30093c 100644
--- a/rules.mak
+++ b/rules.mak
@@ -47,7 +47,7 @@ quiet-command = $(if $(V),$1,$(if $(2), at echo $2 && $1, @$1))
 cc-option = $(if $(shell $(CC) $1 $2 -S -o /dev/null -xc /dev/null \
               >/dev/null 2>&1 && echo OK), $2, $3)
 
-VPATH_SUFFIXES = %.c %.h %.S %.m %.mak %.texi
+VPATH_SUFFIXES = %.c %.h %.S %.m %.mak %.texi %.sh
 set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath $(PATTERN) $1)))
 
 # find-in-path
diff --git a/scripts/gtester-cat b/scripts/gtester-cat
new file mode 100755
index 0000000..061a952
--- /dev/null
+++ b/scripts/gtester-cat
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# Copyright IBM, Corp. 2012
+#
+# Authors:
+#  Anthony Liguori <aliguori at us.ibm.com>
+#
+# This work is licensed under the terms of the GNU GPLv2 or later.
+# See the COPYING file in the top-level directory.
+
+cat <<EOF
+<?xml version="1.0"?>
+<gtester>
+ <info>
+  <package>qemu</package>
+  <version>0.0</version>
+  <revision>rev</revision>
+ </info>
+EOF
+
+sed \
+  -e '/<?xml/d' \
+  -e '/^<gtester>$/d' \
+  -e '/<info>/,/<\/info>/d' \
+  -e '$b' \
+  -e '/^<\/gtester>$/d' "$@"
diff --git a/test-coroutine.c b/test-coroutine.c
deleted file mode 100644
index e5d14eb..0000000
--- a/test-coroutine.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Coroutine tests
- *
- * Copyright IBM, Corp. 2011
- *
- * Authors:
- *  Stefan Hajnoczi    <stefanha at linux.vnet.ibm.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2 or later.
- * See the COPYING.LIB file in the top-level directory.
- *
- */
-
-#include <glib.h>
-#include "qemu-coroutine.h"
-
-/*
- * Check that qemu_in_coroutine() works
- */
-
-static void coroutine_fn verify_in_coroutine(void *opaque)
-{
-    g_assert(qemu_in_coroutine());
-}
-
-static void test_in_coroutine(void)
-{
-    Coroutine *coroutine;
-
-    g_assert(!qemu_in_coroutine());
-
-    coroutine = qemu_coroutine_create(verify_in_coroutine);
-    qemu_coroutine_enter(coroutine, NULL);
-}
-
-/*
- * Check that qemu_coroutine_self() works
- */
-
-static void coroutine_fn verify_self(void *opaque)
-{
-    g_assert(qemu_coroutine_self() == opaque);
-}
-
-static void test_self(void)
-{
-    Coroutine *coroutine;
-
-    coroutine = qemu_coroutine_create(verify_self);
-    qemu_coroutine_enter(coroutine, coroutine);
-}
-
-/*
- * Check that coroutines may nest multiple levels
- */
-
-typedef struct {
-    unsigned int n_enter;   /* num coroutines entered */
-    unsigned int n_return;  /* num coroutines returned */
-    unsigned int max;       /* maximum level of nesting */
-} NestData;
-
-static void coroutine_fn nest(void *opaque)
-{
-    NestData *nd = opaque;
-
-    nd->n_enter++;
-
-    if (nd->n_enter < nd->max) {
-        Coroutine *child;
-
-        child = qemu_coroutine_create(nest);
-        qemu_coroutine_enter(child, nd);
-    }
-
-    nd->n_return++;
-}
-
-static void test_nesting(void)
-{
-    Coroutine *root;
-    NestData nd = {
-        .n_enter  = 0,
-        .n_return = 0,
-        .max      = 128,
-    };
-
-    root = qemu_coroutine_create(nest);
-    qemu_coroutine_enter(root, &nd);
-
-    /* Must enter and return from max nesting level */
-    g_assert_cmpint(nd.n_enter, ==, nd.max);
-    g_assert_cmpint(nd.n_return, ==, nd.max);
-}
-
-/*
- * Check that yield/enter transfer control correctly
- */
-
-static void coroutine_fn yield_5_times(void *opaque)
-{
-    bool *done = opaque;
-    int i;
-
-    for (i = 0; i < 5; i++) {
-        qemu_coroutine_yield();
-    }
-    *done = true;
-}
-
-static void test_yield(void)
-{
-    Coroutine *coroutine;
-    bool done = false;
-    int i = -1; /* one extra time to return from coroutine */
-
-    coroutine = qemu_coroutine_create(yield_5_times);
-    while (!done) {
-        qemu_coroutine_enter(coroutine, &done);
-        i++;
-    }
-    g_assert_cmpint(i, ==, 5); /* coroutine must yield 5 times */
-}
-
-/*
- * Check that creation, enter, and return work
- */
-
-static void coroutine_fn set_and_exit(void *opaque)
-{
-    bool *done = opaque;
-
-    *done = true;
-}
-
-static void test_lifecycle(void)
-{
-    Coroutine *coroutine;
-    bool done = false;
-
-    /* Create, enter, and return from coroutine */
-    coroutine = qemu_coroutine_create(set_and_exit);
-    qemu_coroutine_enter(coroutine, &done);
-    g_assert(done); /* expect done to be true (first time) */
-
-    /* Repeat to check that no state affects this test */
-    done = false;
-    coroutine = qemu_coroutine_create(set_and_exit);
-    qemu_coroutine_enter(coroutine, &done);
-    g_assert(done); /* expect done to be true (second time) */
-}
-
-/*
- * Lifecycle benchmark
- */
-
-static void coroutine_fn empty_coroutine(void *opaque)
-{
-    /* Do nothing */
-}
-
-static void perf_lifecycle(void)
-{
-    Coroutine *coroutine;
-    unsigned int i, max;
-    double duration;
-
-    max = 1000000;
-
-    g_test_timer_start();
-    for (i = 0; i < max; i++) {
-        coroutine = qemu_coroutine_create(empty_coroutine);
-        qemu_coroutine_enter(coroutine, NULL);
-    }
-    duration = g_test_timer_elapsed();
-
-    g_test_message("Lifecycle %u iterations: %f s\n", max, duration);
-}
-
-static void perf_nesting(void)
-{
-    unsigned int i, maxcycles, maxnesting;
-    double duration;
-
-    maxcycles = 100000000;
-    maxnesting = 20000;
-    Coroutine *root;
-    NestData nd = {
-        .n_enter  = 0,
-        .n_return = 0,
-        .max      = maxnesting,
-    };
-
-    g_test_timer_start();
-    for (i = 0; i < maxcycles; i++) {
-        root = qemu_coroutine_create(nest);
-        qemu_coroutine_enter(root, &nd);
-    }
-    duration = g_test_timer_elapsed();
-
-    g_test_message("Nesting %u iterations of %u depth each: %f s\n",
-        maxcycles, maxnesting, duration);
-}
-
-
-int main(int argc, char **argv)
-{
-    g_test_init(&argc, &argv, NULL);
-    g_test_add_func("/basic/lifecycle", test_lifecycle);
-    g_test_add_func("/basic/yield", test_yield);
-    g_test_add_func("/basic/nesting", test_nesting);
-    g_test_add_func("/basic/self", test_self);
-    g_test_add_func("/basic/in_coroutine", test_in_coroutine);
-    if (g_test_perf()) {
-        g_test_add_func("/perf/lifecycle", perf_lifecycle);
-        g_test_add_func("/perf/nesting", perf_nesting);
-    }
-    return g_test_run();
-}
diff --git a/test-qmp-commands.c b/test-qmp-commands.c
deleted file mode 100644
index 60cbf01..0000000
--- a/test-qmp-commands.c
+++ /dev/null
@@ -1,139 +0,0 @@
-#include <glib.h>
-#include "qemu-objects.h"
-#include "test-qmp-commands.h"
-#include "qapi/qmp-core.h"
-#include "module.h"
-
-void qmp_user_def_cmd(Error **errp)
-{
-}
-
-void qmp_user_def_cmd1(UserDefOne * ud1, Error **errp)
-{
-}
-
-UserDefTwo * qmp_user_def_cmd2(UserDefOne * ud1a, UserDefOne * ud1b, Error **errp)
-{
-    UserDefTwo *ret;
-    UserDefOne *ud1c = g_malloc0(sizeof(UserDefOne));
-    UserDefOne *ud1d = g_malloc0(sizeof(UserDefOne));
-
-    ud1c->string = strdup(ud1a->string);
-    ud1c->integer = ud1a->integer;
-    ud1d->string = strdup(ud1b->string);
-    ud1d->integer = ud1b->integer;
-
-    ret = g_malloc0(sizeof(UserDefTwo));
-    ret->string = strdup("blah1");
-    ret->dict.string = strdup("blah2");
-    ret->dict.dict.userdef = ud1c;
-    ret->dict.dict.string = strdup("blah3");
-    ret->dict.has_dict2 = true;
-    ret->dict.dict2.userdef = ud1d;
-    ret->dict.dict2.string = strdup("blah4");
-
-    return ret;
-}
-
-/* test commands with no input and no return value */
-static void test_dispatch_cmd(void)
-{
-    QDict *req = qdict_new();
-    QObject *resp;
-
-    qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd")));
-
-    resp = qmp_dispatch(QOBJECT(req));
-    assert(resp != NULL);
-    assert(!qdict_haskey(qobject_to_qdict(resp), "error"));
-
-    qobject_decref(resp);
-    QDECREF(req);
-}
-
-/* test commands that return an error due to invalid parameters */
-static void test_dispatch_cmd_error(void)
-{
-    QDict *req = qdict_new();
-    QObject *resp;
-
-    qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd2")));
-
-    resp = qmp_dispatch(QOBJECT(req));
-    assert(resp != NULL);
-    assert(qdict_haskey(qobject_to_qdict(resp), "error"));
-
-    qobject_decref(resp);
-    QDECREF(req);
-}
-
-/* test commands that involve both input parameters and return values */
-static void test_dispatch_cmd_io(void)
-{
-    QDict *req = qdict_new();
-    QDict *args = qdict_new();
-    QDict *ud1a = qdict_new();
-    QDict *ud1b = qdict_new();
-    QObject *resp;
-
-    qdict_put_obj(ud1a, "integer", QOBJECT(qint_from_int(42)));
-    qdict_put_obj(ud1a, "string", QOBJECT(qstring_from_str("hello")));
-    qdict_put_obj(ud1b, "integer", QOBJECT(qint_from_int(422)));
-    qdict_put_obj(ud1b, "string", QOBJECT(qstring_from_str("hello2")));
-    qdict_put_obj(args, "ud1a", QOBJECT(ud1a));
-    qdict_put_obj(args, "ud1b", QOBJECT(ud1b));
-    qdict_put_obj(req, "arguments", QOBJECT(args));
-
-    qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd2")));
-
-    /* TODO: put in full payload and check for errors */
-    resp = qmp_dispatch(QOBJECT(req));
-    assert(resp != NULL);
-    assert(!qdict_haskey(qobject_to_qdict(resp), "error"));
-
-    qobject_decref(resp);
-    QDECREF(req);
-}
-
-/* test generated dealloc functions for generated types */
-static void test_dealloc_types(void)
-{
-    UserDefOne *ud1test, *ud1a, *ud1b;
-    UserDefOneList *ud1list;
-
-    ud1test = g_malloc0(sizeof(UserDefOne));
-    ud1test->integer = 42;
-    ud1test->string = g_strdup("hi there 42");
-
-    qapi_free_UserDefOne(ud1test);
-
-    ud1a = g_malloc0(sizeof(UserDefOne));
-    ud1a->integer = 43;
-    ud1a->string = g_strdup("hi there 43");
-
-    ud1b = g_malloc0(sizeof(UserDefOne));
-    ud1b->integer = 44;
-    ud1b->string = g_strdup("hi there 44");
-
-    ud1list = g_malloc0(sizeof(UserDefOneList));
-    ud1list->value = ud1a;
-    ud1list->next = g_malloc0(sizeof(UserDefOneList));
-    ud1list->next->value = ud1b;
-
-    qapi_free_UserDefOneList(ud1list);
-}
-
-int main(int argc, char **argv)
-{
-    g_test_init(&argc, &argv, NULL);
-
-    g_test_add_func("/0.15/dispatch_cmd", test_dispatch_cmd);
-    g_test_add_func("/0.15/dispatch_cmd_error", test_dispatch_cmd_error);
-    g_test_add_func("/0.15/dispatch_cmd_io", test_dispatch_cmd_io);
-    g_test_add_func("/0.15/dealloc_types", test_dealloc_types);
-
-    module_call_init(MODULE_INIT_QAPI);
-    g_test_run();
-
-    return 0;
-}
diff --git a/test-qmp-input-strict.c b/test-qmp-input-strict.c
deleted file mode 100644
index f6df8cb..0000000
--- a/test-qmp-input-strict.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * QMP Input Visitor unit-tests (strict mode).
- *
- * Copyright (C) 2011-2012 Red Hat Inc.
- *
- * Authors:
- *  Luiz Capitulino <lcapitulino at redhat.com>
- *  Paolo Bonzini <pbonzini at redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include <glib.h>
-#include <stdarg.h>
-
-#include "qapi/qmp-input-visitor.h"
-#include "test-qapi-types.h"
-#include "test-qapi-visit.h"
-#include "qemu-objects.h"
-
-typedef struct TestInputVisitorData {
-    QObject *obj;
-    QmpInputVisitor *qiv;
-} TestInputVisitorData;
-
-static void validate_teardown(TestInputVisitorData *data,
-                               const void *unused)
-{
-    qobject_decref(data->obj);
-    data->obj = NULL;
-
-    if (data->qiv) {
-        qmp_input_visitor_cleanup(data->qiv);
-        data->qiv = NULL;
-    }
-}
-
-/* This is provided instead of a test setup function so that the JSON
-   string used by the tests are kept in the test functions (and not
-   int main()) */
-static GCC_FMT_ATTR(2, 3)
-Visitor *validate_test_init(TestInputVisitorData *data,
-                             const char *json_string, ...)
-{
-    Visitor *v;
-    va_list ap;
-
-    va_start(ap, json_string);
-    data->obj = qobject_from_jsonv(json_string, &ap);
-    va_end(ap);
-
-    g_assert(data->obj != NULL);
-
-    data->qiv = qmp_input_visitor_new_strict(data->obj);
-    g_assert(data->qiv != NULL);
-
-    v = qmp_input_get_visitor(data->qiv);
-    g_assert(v != NULL);
-
-    return v;
-}
-
-typedef struct TestStruct
-{
-    int64_t integer;
-    bool boolean;
-    char *string;
-} TestStruct;
-
-static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
-                                  const char *name, Error **errp)
-{
-    visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
-                       errp);
-
-    visit_type_int(v, &(*obj)->integer, "integer", errp);
-    visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
-    visit_type_str(v, &(*obj)->string, "string", errp);
-
-    visit_end_struct(v, errp);
-}
-
-static void test_validate_struct(TestInputVisitorData *data,
-                                  const void *unused)
-{
-    TestStruct *p = NULL;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
-
-    visit_type_TestStruct(v, &p, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_free(p->string);
-    g_free(p);
-}
-
-static void test_validate_struct_nested(TestInputVisitorData *data,
-                                         const void *unused)
-{
-    UserDefNested *udp = NULL;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = validate_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string' }, 'string2': 'string2'}}}");
-
-    visit_type_UserDefNested(v, &udp, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    qapi_free_UserDefNested(udp);
-}
-
-static void test_validate_list(TestInputVisitorData *data,
-                                const void *unused)
-{
-    UserDefOneList *head = NULL;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
-
-    visit_type_UserDefOneList(v, &head, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    qapi_free_UserDefOneList(head);
-}
-
-static void test_validate_union(TestInputVisitorData *data,
-                                 const void *unused)
-{
-    UserDefUnion *tmp = NULL;
-    Visitor *v;
-    Error *errp = NULL;
-
-    v = validate_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 } }");
-
-    visit_type_UserDefUnion(v, &tmp, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    qapi_free_UserDefUnion(tmp);
-}
-
-static void test_validate_fail_struct(TestInputVisitorData *data,
-                                       const void *unused)
-{
-    TestStruct *p = NULL;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo', 'extra': 42 }");
-
-    visit_type_TestStruct(v, &p, NULL, &errp);
-    g_assert(error_is_set(&errp));
-    if (p) {
-        g_free(p->string);
-    }
-    g_free(p);
-}
-
-static void test_validate_fail_struct_nested(TestInputVisitorData *data,
-                                              const void *unused)
-{
-    UserDefNested *udp = NULL;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = validate_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string', 'extra': [42, 23, {'foo':'bar'}] }, 'string2': 'string2'}}}");
-
-    visit_type_UserDefNested(v, &udp, NULL, &errp);
-    g_assert(error_is_set(&errp));
-    qapi_free_UserDefNested(udp);
-}
-
-static void test_validate_fail_list(TestInputVisitorData *data,
-                                     const void *unused)
-{
-    UserDefOneList *head = NULL;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44, 'extra': 'ggg' } ]");
-
-    visit_type_UserDefOneList(v, &head, NULL, &errp);
-    g_assert(error_is_set(&errp));
-    qapi_free_UserDefOneList(head);
-}
-
-static void test_validate_fail_union(TestInputVisitorData *data,
-                                      const void *unused)
-{
-    UserDefUnion *tmp = NULL;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = validate_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 }, 'extra': 'yyy' }");
-
-    visit_type_UserDefUnion(v, &tmp, NULL, &errp);
-    g_assert(error_is_set(&errp));
-    qapi_free_UserDefUnion(tmp);
-}
-
-static void validate_test_add(const char *testpath,
-                               TestInputVisitorData *data,
-                               void (*test_func)(TestInputVisitorData *data, const void *user_data))
-{
-    g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
-               validate_teardown);
-}
-
-int main(int argc, char **argv)
-{
-    TestInputVisitorData testdata;
-
-    g_test_init(&argc, &argv, NULL);
-
-    validate_test_add("/visitor/input-strict/pass/struct",
-                       &testdata, test_validate_struct);
-    validate_test_add("/visitor/input-strict/pass/struct-nested",
-                       &testdata, test_validate_struct_nested);
-    validate_test_add("/visitor/input-strict/pass/list",
-                       &testdata, test_validate_list);
-    validate_test_add("/visitor/input-strict/pass/union",
-                       &testdata, test_validate_union);
-    validate_test_add("/visitor/input-strict/fail/struct",
-                       &testdata, test_validate_fail_struct);
-    validate_test_add("/visitor/input-strict/fail/struct-nested",
-                       &testdata, test_validate_fail_struct_nested);
-    validate_test_add("/visitor/input-strict/fail/list",
-                       &testdata, test_validate_fail_list);
-    validate_test_add("/visitor/input-strict/fail/union",
-                       &testdata, test_validate_fail_union);
-
-    g_test_run();
-
-    return 0;
-}
diff --git a/test-qmp-input-visitor.c b/test-qmp-input-visitor.c
deleted file mode 100644
index c30fdc4..0000000
--- a/test-qmp-input-visitor.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * QMP Input Visitor unit-tests.
- *
- * Copyright (C) 2011 Red Hat Inc.
- *
- * Authors:
- *  Luiz Capitulino <lcapitulino at redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include <glib.h>
-#include <stdarg.h>
-
-#include "qapi/qmp-input-visitor.h"
-#include "test-qapi-types.h"
-#include "test-qapi-visit.h"
-#include "qemu-objects.h"
-
-typedef struct TestInputVisitorData {
-    QObject *obj;
-    QmpInputVisitor *qiv;
-} TestInputVisitorData;
-
-static void visitor_input_teardown(TestInputVisitorData *data,
-                                   const void *unused)
-{
-    qobject_decref(data->obj);
-    data->obj = NULL;
-
-    if (data->qiv) {
-        qmp_input_visitor_cleanup(data->qiv);
-        data->qiv = NULL;
-    }
-}
-
-/* This is provided instead of a test setup function so that the JSON
-   string used by the tests are kept in the test functions (and not
-   int main()) */
-static GCC_FMT_ATTR(2, 3)
-Visitor *visitor_input_test_init(TestInputVisitorData *data,
-                                 const char *json_string, ...)
-{
-    Visitor *v;
-    va_list ap;
-
-    va_start(ap, json_string);
-    data->obj = qobject_from_jsonv(json_string, &ap);
-    va_end(ap);
-
-    g_assert(data->obj != NULL);
-
-    data->qiv = qmp_input_visitor_new(data->obj);
-    g_assert(data->qiv != NULL);
-
-    v = qmp_input_get_visitor(data->qiv);
-    g_assert(v != NULL);
-
-    return v;
-}
-
-static void test_visitor_in_int(TestInputVisitorData *data,
-                                const void *unused)
-{
-    int64_t res = 0, value = -42;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = visitor_input_test_init(data, "%" PRId64, value);
-
-    visit_type_int(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpint(res, ==, value);
-}
-
-static void test_visitor_in_bool(TestInputVisitorData *data,
-                                 const void *unused)
-{
-    Error *errp = NULL;
-    bool res = false;
-    Visitor *v;
-
-    v = visitor_input_test_init(data, "true");
-
-    visit_type_bool(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpint(res, ==, true);
-}
-
-static void test_visitor_in_number(TestInputVisitorData *data,
-                                   const void *unused)
-{
-    double res = 0, value = 3.14;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = visitor_input_test_init(data, "%f", value);
-
-    visit_type_number(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpfloat(res, ==, value);
-}
-
-static void test_visitor_in_string(TestInputVisitorData *data,
-                                   const void *unused)
-{
-    char *res = NULL, *value = (char *) "Q E M U";
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = visitor_input_test_init(data, "%s", value);
-
-    visit_type_str(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpstr(res, ==, value);
-
-    g_free(res);
-}
-
-static void test_visitor_in_enum(TestInputVisitorData *data,
-                                 const void *unused)
-{
-    Error *errp = NULL;
-    Visitor *v;
-    EnumOne i;
-
-    for (i = 0; EnumOne_lookup[i]; i++) {
-        EnumOne res = -1;
-
-        v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);
-
-        visit_type_EnumOne(v, &res, NULL, &errp);
-        g_assert(!error_is_set(&errp));
-        g_assert_cmpint(i, ==, res);
-
-        visitor_input_teardown(data, NULL);
-    }
-
-    data->obj = NULL;
-    data->qiv = NULL;
-}
-
-typedef struct TestStruct
-{
-    int64_t integer;
-    bool boolean;
-    char *string;
-} TestStruct;
-
-static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
-                                  const char *name, Error **errp)
-{
-    visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
-                       errp);
-
-    visit_type_int(v, &(*obj)->integer, "integer", errp);
-    visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
-    visit_type_str(v, &(*obj)->string, "string", errp);
-
-    visit_end_struct(v, errp);
-}
-
-static void test_visitor_in_struct(TestInputVisitorData *data,
-                                   const void *unused)
-{
-    TestStruct *p = NULL;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
-
-    visit_type_TestStruct(v, &p, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpint(p->integer, ==, -42);
-    g_assert(p->boolean == true);
-    g_assert_cmpstr(p->string, ==, "foo");
-
-    g_free(p->string);
-    g_free(p);
-}
-
-static void check_and_free_str(char *str, const char *cmp)
-{
-    g_assert_cmpstr(str, ==, cmp);
-    g_free(str);
-}
-
-static void test_visitor_in_struct_nested(TestInputVisitorData *data,
-                                          const void *unused)
-{
-    UserDefNested *udp = NULL;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = visitor_input_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string' }, 'string2': 'string2'}}}");
-
-    visit_type_UserDefNested(v, &udp, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-
-    check_and_free_str(udp->string0, "string0");
-    check_and_free_str(udp->dict1.string1, "string1");
-    g_assert_cmpint(udp->dict1.dict2.userdef1->integer, ==, 42);
-    check_and_free_str(udp->dict1.dict2.userdef1->string, "string");
-    check_and_free_str(udp->dict1.dict2.string2, "string2");
-    g_assert(udp->dict1.has_dict3 == false);
-
-    g_free(udp->dict1.dict2.userdef1);
-    g_free(udp);
-}
-
-static void test_visitor_in_list(TestInputVisitorData *data,
-                                 const void *unused)
-{
-    UserDefOneList *item, *head = NULL;
-    Error *errp = NULL;
-    Visitor *v;
-    int i;
-
-    v = visitor_input_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
-
-    visit_type_UserDefOneList(v, &head, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert(head != NULL);
-
-    for (i = 0, item = head; item; item = item->next, i++) {
-        char string[12];
-
-        snprintf(string, sizeof(string), "string%d", i);
-        g_assert_cmpstr(item->value->string, ==, string);
-        g_assert_cmpint(item->value->integer, ==, 42 + i);
-    }
-
-    qapi_free_UserDefOneList(head);
-}
-
-static void test_visitor_in_union(TestInputVisitorData *data,
-                                  const void *unused)
-{
-    Visitor *v;
-    Error *err = NULL;
-    UserDefUnion *tmp;
-
-    v = visitor_input_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 } }");
-
-    visit_type_UserDefUnion(v, &tmp, NULL, &err);
-    g_assert(err == NULL);
-    g_assert_cmpint(tmp->kind, ==, USER_DEF_UNION_KIND_B);
-    g_assert_cmpint(tmp->b->integer, ==, 42);
-    qapi_free_UserDefUnion(tmp);
-}
-
-static void input_visitor_test_add(const char *testpath,
-                                   TestInputVisitorData *data,
-                                   void (*test_func)(TestInputVisitorData *data, const void *user_data))
-{
-    g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
-               visitor_input_teardown);
-}
-
-static void test_visitor_in_errors(TestInputVisitorData *data,
-                                   const void *unused)
-{
-    TestStruct *p = NULL;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', 'string': -42 }");
-
-    visit_type_TestStruct(v, &p, NULL, &errp);
-    g_assert(error_is_set(&errp));
-    g_assert(p->string == NULL);
-
-    g_free(p->string);
-    g_free(p);
-}
-
-int main(int argc, char **argv)
-{
-    TestInputVisitorData in_visitor_data;
-
-    g_test_init(&argc, &argv, NULL);
-
-    input_visitor_test_add("/visitor/input/int",
-                           &in_visitor_data, test_visitor_in_int);
-    input_visitor_test_add("/visitor/input/bool",
-                           &in_visitor_data, test_visitor_in_bool);
-    input_visitor_test_add("/visitor/input/number",
-                           &in_visitor_data, test_visitor_in_number);
-    input_visitor_test_add("/visitor/input/string",
-                            &in_visitor_data, test_visitor_in_string);
-    input_visitor_test_add("/visitor/input/enum",
-                            &in_visitor_data, test_visitor_in_enum);
-    input_visitor_test_add("/visitor/input/struct",
-                            &in_visitor_data, test_visitor_in_struct);
-    input_visitor_test_add("/visitor/input/struct-nested",
-                            &in_visitor_data, test_visitor_in_struct_nested);
-    input_visitor_test_add("/visitor/input/list",
-                            &in_visitor_data, test_visitor_in_list);
-    input_visitor_test_add("/visitor/input/union",
-                            &in_visitor_data, test_visitor_in_union);
-    input_visitor_test_add("/visitor/input/errors",
-                            &in_visitor_data, test_visitor_in_errors);
-
-    g_test_run();
-
-    return 0;
-}
diff --git a/test-qmp-output-visitor.c b/test-qmp-output-visitor.c
deleted file mode 100644
index 24a6359..0000000
--- a/test-qmp-output-visitor.c
+++ /dev/null
@@ -1,477 +0,0 @@
-/*
- * QMP Output Visitor unit-tests.
- *
- * Copyright (C) 2011 Red Hat Inc.
- *
- * Authors:
- *  Luiz Capitulino <lcapitulino at redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include <glib.h>
-
-#include "qapi/qmp-output-visitor.h"
-#include "test-qapi-types.h"
-#include "test-qapi-visit.h"
-#include "qemu-objects.h"
-
-typedef struct TestOutputVisitorData {
-    QmpOutputVisitor *qov;
-    Visitor *ov;
-} TestOutputVisitorData;
-
-static void visitor_output_setup(TestOutputVisitorData *data,
-                                 const void *unused)
-{
-    data->qov = qmp_output_visitor_new();
-    g_assert(data->qov != NULL);
-
-    data->ov = qmp_output_get_visitor(data->qov);
-    g_assert(data->ov != NULL);
-}
-
-static void visitor_output_teardown(TestOutputVisitorData *data,
-                                    const void *unused)
-{
-    qmp_output_visitor_cleanup(data->qov);
-    data->qov = NULL;
-    data->ov = NULL;
-}
-
-static void test_visitor_out_int(TestOutputVisitorData *data,
-                                 const void *unused)
-{
-    int64_t value = -42;
-    Error *errp = NULL;
-    QObject *obj;
-
-    visit_type_int(data->ov, &value, NULL, &errp);
-    g_assert(error_is_set(&errp) == 0);
-
-    obj = qmp_output_get_qobject(data->qov);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QINT);
-    g_assert_cmpint(qint_get_int(qobject_to_qint(obj)), ==, value);
-
-    qobject_decref(obj);
-}
-
-static void test_visitor_out_bool(TestOutputVisitorData *data,
-                                  const void *unused)
-{
-    Error *errp = NULL;
-    bool value = true;
-    QObject *obj;
-
-    visit_type_bool(data->ov, &value, NULL, &errp);
-    g_assert(error_is_set(&errp) == 0);
-
-    obj = qmp_output_get_qobject(data->qov);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QBOOL);
-    g_assert(qbool_get_int(qobject_to_qbool(obj)) == value);
-
-    qobject_decref(obj);
-}
-
-static void test_visitor_out_number(TestOutputVisitorData *data,
-                                    const void *unused)
-{
-    double value = 3.14;
-    Error *errp = NULL;
-    QObject *obj;
-
-    visit_type_number(data->ov, &value, NULL, &errp);
-    g_assert(error_is_set(&errp) == 0);
-
-    obj = qmp_output_get_qobject(data->qov);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QFLOAT);
-    g_assert(qfloat_get_double(qobject_to_qfloat(obj)) == value);
-
-    qobject_decref(obj);
-}
-
-static void test_visitor_out_string(TestOutputVisitorData *data,
-                                    const void *unused)
-{
-    char *string = (char *) "Q E M U";
-    Error *errp = NULL;
-    QObject *obj;
-
-    visit_type_str(data->ov, &string, NULL, &errp);
-    g_assert(error_is_set(&errp) == 0);
-
-    obj = qmp_output_get_qobject(data->qov);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QSTRING);
-    g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, string);
-
-    qobject_decref(obj);
-}
-
-static void test_visitor_out_no_string(TestOutputVisitorData *data,
-                                       const void *unused)
-{
-    char *string = NULL;
-    Error *errp = NULL;
-    QObject *obj;
-
-    /* A null string should return "" */
-    visit_type_str(data->ov, &string, NULL, &errp);
-    g_assert(error_is_set(&errp) == 0);
-
-    obj = qmp_output_get_qobject(data->qov);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QSTRING);
-    g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, "");
-
-    qobject_decref(obj);
-}
-
-static void test_visitor_out_enum(TestOutputVisitorData *data,
-                                  const void *unused)
-{
-    Error *errp = NULL;
-    QObject *obj;
-    EnumOne i;
-
-    for (i = 0; i < ENUM_ONE_MAX; i++) {
-        visit_type_EnumOne(data->ov, &i, "unused", &errp);
-        g_assert(!error_is_set(&errp));
-
-        obj = qmp_output_get_qobject(data->qov);
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QSTRING);
-        g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==,
-                        EnumOne_lookup[i]);
-        qobject_decref(obj);
-    }
-}
-
-static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
-                                         const void *unused)
-{
-    EnumOne i, bad_values[] = { ENUM_ONE_MAX, -1 };
-    Error *errp;
-
-    for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
-        errp = NULL;
-        visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp);
-        g_assert(error_is_set(&errp) == true);
-        error_free(errp);
-    }
-}
-
-typedef struct TestStruct
-{
-    int64_t integer;
-    bool boolean;
-    char *string;
-} TestStruct;
-
-static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
-                                  const char *name, Error **errp)
-{
-    visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
-                       errp);
-
-    visit_type_int(v, &(*obj)->integer, "integer", errp);
-    visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
-    visit_type_str(v, &(*obj)->string, "string", errp);
-
-    visit_end_struct(v, errp);
-}
-
-static void test_visitor_out_struct(TestOutputVisitorData *data,
-                                    const void *unused)
-{
-    TestStruct test_struct = { .integer = 42,
-                               .boolean = false,
-                               .string = (char *) "foo"};
-    TestStruct *p = &test_struct;
-    Error *errp = NULL;
-    QObject *obj;
-    QDict *qdict;
-
-    visit_type_TestStruct(data->ov, &p, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-
-    obj = qmp_output_get_qobject(data->qov);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QDICT);
-
-    qdict = qobject_to_qdict(obj);
-    g_assert_cmpint(qdict_size(qdict), ==, 3);
-    g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 42);
-    g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, 0);
-    g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "foo");
-
-    QDECREF(qdict);
-}
-
-static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
-                                           const void *unused)
-{
-    int64_t value = 42;
-    Error *errp = NULL;
-    UserDefNested *ud2;
-    QObject *obj;
-    QDict *qdict, *dict1, *dict2, *dict3, *userdef;
-    const char *string = "user def string";
-    const char *strings[] = { "forty two", "forty three", "forty four",
-                              "forty five" };
-
-    ud2 = g_malloc0(sizeof(*ud2));
-    ud2->string0 = g_strdup(strings[0]);
-
-    ud2->dict1.string1 = g_strdup(strings[1]);
-    ud2->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
-    ud2->dict1.dict2.userdef1->string = g_strdup(string);
-    ud2->dict1.dict2.userdef1->integer = value;
-    ud2->dict1.dict2.string2 = g_strdup(strings[2]);
-
-    ud2->dict1.has_dict3 = true;
-    ud2->dict1.dict3.userdef2 = g_malloc0(sizeof(UserDefOne));
-    ud2->dict1.dict3.userdef2->string = g_strdup(string);
-    ud2->dict1.dict3.userdef2->integer = value;
-    ud2->dict1.dict3.string3 = g_strdup(strings[3]);
-
-    visit_type_UserDefNested(data->ov, &ud2, "unused", &errp);
-    g_assert(!error_is_set(&errp));
-
-    obj = qmp_output_get_qobject(data->qov);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QDICT);
-
-    qdict = qobject_to_qdict(obj);
-    g_assert_cmpint(qdict_size(qdict), ==, 2);
-    g_assert_cmpstr(qdict_get_str(qdict, "string0"), ==, strings[0]);
-
-    dict1 = qdict_get_qdict(qdict, "dict1");
-    g_assert_cmpint(qdict_size(dict1), ==, 3);
-    g_assert_cmpstr(qdict_get_str(dict1, "string1"), ==, strings[1]);
-
-    dict2 = qdict_get_qdict(dict1, "dict2");
-    g_assert_cmpint(qdict_size(dict2), ==, 2);
-    g_assert_cmpstr(qdict_get_str(dict2, "string2"), ==, strings[2]);
-    userdef = qdict_get_qdict(dict2, "userdef1");
-    g_assert_cmpint(qdict_size(userdef), ==, 2);
-    g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
-    g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
-
-    dict3 = qdict_get_qdict(dict1, "dict3");
-    g_assert_cmpint(qdict_size(dict3), ==, 2);
-    g_assert_cmpstr(qdict_get_str(dict3, "string3"), ==, strings[3]);
-    userdef = qdict_get_qdict(dict3, "userdef2");
-    g_assert_cmpint(qdict_size(userdef), ==, 2);
-    g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
-    g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
-
-    QDECREF(qdict);
-    qapi_free_UserDefNested(ud2);
-}
-
-static void test_visitor_out_struct_errors(TestOutputVisitorData *data,
-                                           const void *unused)
-{
-    EnumOne bad_values[] = { ENUM_ONE_MAX, -1 };
-    UserDefOne u = { 0 }, *pu = &u;
-    Error *errp;
-    int i;
-
-    for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
-        errp = NULL;
-        u.has_enum1 = true;
-        u.enum1 = bad_values[i];
-        visit_type_UserDefOne(data->ov, &pu, "unused", &errp);
-        g_assert(error_is_set(&errp) == true);
-        error_free(errp);
-    }
-}
-
-typedef struct TestStructList
-{
-    TestStruct *value;
-    struct TestStructList *next;
-} TestStructList;
-
-static void visit_type_TestStructList(Visitor *v, TestStructList **obj,
-                                      const char *name, Error **errp)
-{
-    GenericList *i, **head = (GenericList **)obj;
-
-    visit_start_list(v, name, errp);
-
-    for (*head = i = visit_next_list(v, head, errp); i; i = visit_next_list(v, &i, errp)) {
-        TestStructList *native_i = (TestStructList *)i;
-        visit_type_TestStruct(v, &native_i->value, NULL, errp);
-    }
-
-    visit_end_list(v, errp);
-}
-
-static void test_visitor_out_list(TestOutputVisitorData *data,
-                                  const void *unused)
-{
-    char *value_str = (char *) "list value";
-    TestStructList *p, *head = NULL;
-    const int max_items = 10;
-    bool value_bool = true;
-    int value_int = 10;
-    Error *errp = NULL;
-    QListEntry *entry;
-    QObject *obj;
-    QList *qlist;
-    int i;
-
-    for (i = 0; i < max_items; i++) {
-        p = g_malloc0(sizeof(*p));
-        p->value = g_malloc0(sizeof(*p->value));
-        p->value->integer = value_int;
-        p->value->boolean = value_bool;
-        p->value->string = value_str;
-
-        p->next = head;
-        head = p;
-    }
-
-    visit_type_TestStructList(data->ov, &head, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-
-    obj = qmp_output_get_qobject(data->qov);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QLIST);
-
-    qlist = qobject_to_qlist(obj);
-    g_assert(!qlist_empty(qlist));
-
-    i = 0;
-    QLIST_FOREACH_ENTRY(qlist, entry) {
-        QDict *qdict;
-
-        g_assert(qobject_type(entry->value) == QTYPE_QDICT);
-        qdict = qobject_to_qdict(entry->value);
-        g_assert_cmpint(qdict_size(qdict), ==, 3);
-        g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, value_int);
-        g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, value_bool);
-        g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, value_str);
-        i++;
-    }
-    g_assert_cmpint(i, ==, max_items);
-
-    QDECREF(qlist);
-
-    for (p = head; p;) {
-        TestStructList *tmp = p->next;
-        g_free(p->value);
-        g_free(p);
-        p = tmp;
-    }
-}
-
-static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
-                                            const void *unused)
-{
-    UserDefNestedList *p, *head = NULL;
-    const char string[] = "foo bar";
-    int i, max_count = 1024;
-
-    for (i = 0; i < max_count; i++) {
-        p = g_malloc0(sizeof(*p));
-        p->value = g_malloc0(sizeof(*p->value));
-
-        p->value->string0 = g_strdup(string);
-        p->value->dict1.string1 = g_strdup(string);
-        p->value->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
-        p->value->dict1.dict2.userdef1->string = g_strdup(string);
-        p->value->dict1.dict2.userdef1->integer = 42;
-        p->value->dict1.dict2.string2 = g_strdup(string);
-        p->value->dict1.has_dict3 = false;
-
-        p->next = head;
-        head = p;
-    }
-
-    qapi_free_UserDefNestedList(head);
-}
-
-static void test_visitor_out_union(TestOutputVisitorData *data,
-                                   const void *unused)
-{
-    QObject *arg, *qvalue;
-    QDict *qdict, *value;
-
-    Error *err = NULL;
-
-    UserDefUnion *tmp = g_malloc0(sizeof(UserDefUnion));
-    tmp->kind = USER_DEF_UNION_KIND_A;
-    tmp->a = g_malloc0(sizeof(UserDefA));
-    tmp->a->boolean = true;
-
-    visit_type_UserDefUnion(data->ov, &tmp, NULL, &err);
-    g_assert(err == NULL);
-    arg = qmp_output_get_qobject(data->qov);
-
-    g_assert(qobject_type(arg) == QTYPE_QDICT);
-    qdict = qobject_to_qdict(arg);
-
-    g_assert_cmpstr(qdict_get_str(qdict, "type"), ==, "a");
-
-    qvalue = qdict_get(qdict, "data");
-    g_assert(data != NULL);
-    g_assert(qobject_type(qvalue) == QTYPE_QDICT);
-    value = qobject_to_qdict(qvalue);
-    g_assert_cmpint(qdict_get_bool(value, "boolean"), ==, true);
-
-    qapi_free_UserDefUnion(tmp);
-    QDECREF(qdict);
-}
-
-static void output_visitor_test_add(const char *testpath,
-                                    TestOutputVisitorData *data,
-                                    void (*test_func)(TestOutputVisitorData *data, const void *user_data))
-{
-    g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup,
-               test_func, visitor_output_teardown);
-}
-
-int main(int argc, char **argv)
-{
-    TestOutputVisitorData out_visitor_data;
-
-    g_test_init(&argc, &argv, NULL);
-
-    output_visitor_test_add("/visitor/output/int",
-                            &out_visitor_data, test_visitor_out_int);
-    output_visitor_test_add("/visitor/output/bool",
-                            &out_visitor_data, test_visitor_out_bool);
-    output_visitor_test_add("/visitor/output/number",
-                            &out_visitor_data, test_visitor_out_number);
-    output_visitor_test_add("/visitor/output/string",
-                            &out_visitor_data, test_visitor_out_string);
-    output_visitor_test_add("/visitor/output/no-string",
-                            &out_visitor_data, test_visitor_out_no_string);
-    output_visitor_test_add("/visitor/output/enum",
-                            &out_visitor_data, test_visitor_out_enum);
-    output_visitor_test_add("/visitor/output/enum-errors",
-                            &out_visitor_data, test_visitor_out_enum_errors);
-    output_visitor_test_add("/visitor/output/struct",
-                            &out_visitor_data, test_visitor_out_struct);
-    output_visitor_test_add("/visitor/output/struct-nested",
-                            &out_visitor_data, test_visitor_out_struct_nested);
-    output_visitor_test_add("/visitor/output/struct-errors",
-                            &out_visitor_data, test_visitor_out_struct_errors);
-    output_visitor_test_add("/visitor/output/list",
-                            &out_visitor_data, test_visitor_out_list);
-    output_visitor_test_add("/visitor/output/list-qapi-free",
-                            &out_visitor_data, test_visitor_out_list_qapi_free);
-    output_visitor_test_add("/visitor/output/union",
-                            &out_visitor_data, test_visitor_out_union);
-
-    g_test_run();
-
-    return 0;
-}
diff --git a/test-string-input-visitor.c b/test-string-input-visitor.c
deleted file mode 100644
index 5370e32..0000000
--- a/test-string-input-visitor.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * String Input Visitor unit-tests.
- *
- * Copyright (C) 2012 Red Hat Inc.
- *
- * Authors:
- *  Paolo Bonzini <pbonzini at redhat.com> (based on test-qmp-input-visitor)
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include <glib.h>
-#include <stdarg.h>
-
-#include "qapi/string-input-visitor.h"
-#include "test-qapi-types.h"
-#include "test-qapi-visit.h"
-#include "qemu-objects.h"
-
-typedef struct TestInputVisitorData {
-    StringInputVisitor *siv;
-} TestInputVisitorData;
-
-static void visitor_input_teardown(TestInputVisitorData *data,
-                                   const void *unused)
-{
-    if (data->siv) {
-        string_input_visitor_cleanup(data->siv);
-        data->siv = NULL;
-    }
-}
-
-/* This is provided instead of a test setup function so that the JSON
-   string used by the tests are kept in the test functions (and not
-   int main()) */
-static
-Visitor *visitor_input_test_init(TestInputVisitorData *data,
-                                 const char *string)
-{
-    Visitor *v;
-
-    data->siv = string_input_visitor_new(string);
-    g_assert(data->siv != NULL);
-
-    v = string_input_get_visitor(data->siv);
-    g_assert(v != NULL);
-
-    return v;
-}
-
-static void test_visitor_in_int(TestInputVisitorData *data,
-                                const void *unused)
-{
-    int64_t res = 0, value = -42;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = visitor_input_test_init(data, "-42");
-
-    visit_type_int(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpint(res, ==, value);
-}
-
-static void test_visitor_in_bool(TestInputVisitorData *data,
-                                 const void *unused)
-{
-    Error *errp = NULL;
-    bool res = false;
-    Visitor *v;
-
-    v = visitor_input_test_init(data, "true");
-
-    visit_type_bool(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpint(res, ==, true);
-    visitor_input_teardown(data, unused);
-
-    v = visitor_input_test_init(data, "yes");
-
-    visit_type_bool(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpint(res, ==, true);
-    visitor_input_teardown(data, unused);
-
-    v = visitor_input_test_init(data, "on");
-
-    visit_type_bool(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpint(res, ==, true);
-    visitor_input_teardown(data, unused);
-
-    v = visitor_input_test_init(data, "false");
-
-    visit_type_bool(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpint(res, ==, false);
-    visitor_input_teardown(data, unused);
-
-    v = visitor_input_test_init(data, "no");
-
-    visit_type_bool(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpint(res, ==, false);
-    visitor_input_teardown(data, unused);
-
-    v = visitor_input_test_init(data, "off");
-
-    visit_type_bool(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpint(res, ==, false);
-}
-
-static void test_visitor_in_number(TestInputVisitorData *data,
-                                   const void *unused)
-{
-    double res = 0, value = 3.14;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = visitor_input_test_init(data, "3.14");
-
-    visit_type_number(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpfloat(res, ==, value);
-}
-
-static void test_visitor_in_string(TestInputVisitorData *data,
-                                   const void *unused)
-{
-    char *res = NULL, *value = (char *) "Q E M U";
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = visitor_input_test_init(data, value);
-
-    visit_type_str(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpstr(res, ==, value);
-
-    g_free(res);
-}
-
-static void test_visitor_in_enum(TestInputVisitorData *data,
-                                 const void *unused)
-{
-    Error *errp = NULL;
-    Visitor *v;
-    EnumOne i;
-
-    for (i = 0; EnumOne_lookup[i]; i++) {
-        EnumOne res = -1;
-
-        v = visitor_input_test_init(data, EnumOne_lookup[i]);
-
-        visit_type_EnumOne(v, &res, NULL, &errp);
-        g_assert(!error_is_set(&errp));
-        g_assert_cmpint(i, ==, res);
-
-        visitor_input_teardown(data, NULL);
-    }
-
-    data->siv = NULL;
-}
-
-static void input_visitor_test_add(const char *testpath,
-                                   TestInputVisitorData *data,
-                                   void (*test_func)(TestInputVisitorData *data, const void *user_data))
-{
-    g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
-               visitor_input_teardown);
-}
-
-int main(int argc, char **argv)
-{
-    TestInputVisitorData in_visitor_data;
-
-    g_test_init(&argc, &argv, NULL);
-
-    input_visitor_test_add("/string-visitor/input/int",
-                           &in_visitor_data, test_visitor_in_int);
-    input_visitor_test_add("/string-visitor/input/bool",
-                           &in_visitor_data, test_visitor_in_bool);
-    input_visitor_test_add("/string-visitor/input/number",
-                           &in_visitor_data, test_visitor_in_number);
-    input_visitor_test_add("/string-visitor/input/string",
-                            &in_visitor_data, test_visitor_in_string);
-    input_visitor_test_add("/string-visitor/input/enum",
-                            &in_visitor_data, test_visitor_in_enum);
-
-    g_test_run();
-
-    return 0;
-}
diff --git a/test-string-output-visitor.c b/test-string-output-visitor.c
deleted file mode 100644
index 22909b8..0000000
--- a/test-string-output-visitor.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * String Output Visitor unit-tests.
- *
- * Copyright (C) 2012 Red Hat Inc.
- *
- * Authors:
- *  Paolo Bonzini <pbonzini at redhat.com> (based on test-qmp-output-visitor)
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include <glib.h>
-
-#include "qapi/string-output-visitor.h"
-#include "test-qapi-types.h"
-#include "test-qapi-visit.h"
-#include "qemu-objects.h"
-
-typedef struct TestOutputVisitorData {
-    StringOutputVisitor *sov;
-    Visitor *ov;
-} TestOutputVisitorData;
-
-static void visitor_output_setup(TestOutputVisitorData *data,
-                                 const void *unused)
-{
-    data->sov = string_output_visitor_new();
-    g_assert(data->sov != NULL);
-
-    data->ov = string_output_get_visitor(data->sov);
-    g_assert(data->ov != NULL);
-}
-
-static void visitor_output_teardown(TestOutputVisitorData *data,
-                                    const void *unused)
-{
-    string_output_visitor_cleanup(data->sov);
-    data->sov = NULL;
-    data->ov = NULL;
-}
-
-static void test_visitor_out_int(TestOutputVisitorData *data,
-                                 const void *unused)
-{
-    int64_t value = -42;
-    Error *errp = NULL;
-    char *str;
-
-    visit_type_int(data->ov, &value, NULL, &errp);
-    g_assert(error_is_set(&errp) == 0);
-
-    str = string_output_get_string(data->sov);
-    g_assert(str != NULL);
-    g_assert_cmpstr(str, ==, "-42");
-    g_free(str);
-}
-
-static void test_visitor_out_bool(TestOutputVisitorData *data,
-                                  const void *unused)
-{
-    Error *errp = NULL;
-    bool value = true;
-    char *str;
-
-    visit_type_bool(data->ov, &value, NULL, &errp);
-    g_assert(error_is_set(&errp) == 0);
-
-    str = string_output_get_string(data->sov);
-    g_assert(str != NULL);
-    g_assert_cmpstr(str, ==, "true");
-    g_free(str);
-}
-
-static void test_visitor_out_number(TestOutputVisitorData *data,
-                                    const void *unused)
-{
-    double value = 3.14;
-    Error *errp = NULL;
-    char *str;
-
-    visit_type_number(data->ov, &value, NULL, &errp);
-    g_assert(error_is_set(&errp) == 0);
-
-    str = string_output_get_string(data->sov);
-    g_assert(str != NULL);
-    g_assert_cmpstr(str, ==, "3.14");
-    g_free(str);
-}
-
-static void test_visitor_out_string(TestOutputVisitorData *data,
-                                    const void *unused)
-{
-    char *string = (char *) "Q E M U";
-    Error *errp = NULL;
-    char *str;
-
-    visit_type_str(data->ov, &string, NULL, &errp);
-    g_assert(error_is_set(&errp) == 0);
-
-    str = string_output_get_string(data->sov);
-    g_assert(str != NULL);
-    g_assert_cmpstr(str, ==, string);
-    g_free(str);
-}
-
-static void test_visitor_out_no_string(TestOutputVisitorData *data,
-                                       const void *unused)
-{
-    char *string = NULL;
-    Error *errp = NULL;
-    char *str;
-
-    /* A null string should return "" */
-    visit_type_str(data->ov, &string, NULL, &errp);
-    g_assert(error_is_set(&errp) == 0);
-
-    str = string_output_get_string(data->sov);
-    g_assert(str != NULL);
-    g_assert_cmpstr(str, ==, "");
-    g_free(str);
-}
-
-static void test_visitor_out_enum(TestOutputVisitorData *data,
-                                  const void *unused)
-{
-    Error *errp = NULL;
-    char *str;
-    EnumOne i;
-
-    for (i = 0; i < ENUM_ONE_MAX; i++) {
-        visit_type_EnumOne(data->ov, &i, "unused", &errp);
-        g_assert(!error_is_set(&errp));
-
-        str = string_output_get_string(data->sov);
-        g_assert(str != NULL);
-        g_assert_cmpstr(str, ==, EnumOne_lookup[i]);
-	g_free(str);
-    }
-}
-
-static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
-                                         const void *unused)
-{
-    EnumOne i, bad_values[] = { ENUM_ONE_MAX, -1 };
-    Error *errp;
-
-    for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
-        errp = NULL;
-        visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp);
-        g_assert(error_is_set(&errp) == true);
-        error_free(errp);
-    }
-}
-
-static void output_visitor_test_add(const char *testpath,
-                                    TestOutputVisitorData *data,
-                                    void (*test_func)(TestOutputVisitorData *data, const void *user_data))
-{
-    g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup,
-               test_func, visitor_output_teardown);
-}
-
-int main(int argc, char **argv)
-{
-    TestOutputVisitorData out_visitor_data;
-
-    g_test_init(&argc, &argv, NULL);
-
-    output_visitor_test_add("/string-visitor/output/int",
-                            &out_visitor_data, test_visitor_out_int);
-    output_visitor_test_add("/string-visitor/output/bool",
-                            &out_visitor_data, test_visitor_out_bool);
-    output_visitor_test_add("/string-visitor/output/number",
-                            &out_visitor_data, test_visitor_out_number);
-    output_visitor_test_add("/string-visitor/output/string",
-                            &out_visitor_data, test_visitor_out_string);
-    output_visitor_test_add("/string-visitor/output/no-string",
-                            &out_visitor_data, test_visitor_out_no_string);
-    output_visitor_test_add("/string-visitor/output/enum",
-                            &out_visitor_data, test_visitor_out_enum);
-    output_visitor_test_add("/string-visitor/output/enum-errors",
-                            &out_visitor_data, test_visitor_out_enum_errors);
-
-    g_test_run();
-
-    return 0;
-}
diff --git a/tests/Makefile b/tests/Makefile
index 2a2fff7..17f6ece 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -1,61 +1,113 @@
 export SRC_PATH
 
-CHECKS = check-qdict check-qfloat check-qint check-qstring check-qlist
-CHECKS += check-qjson test-qmp-output-visitor test-qmp-input-visitor
-CHECKS += test-string-input-visitor test-string-output-visitor test-coroutine
-CHECKS += test-qmp-commands
-CHECKS += $(SRC_PATH)/tests/qemu-iotests-quick.sh
-
-check-qint.o check-qstring.o check-qdict.o check-qlist.o check-qfloat.o check-qjson.o test-coroutine.o: $(GENERATED_HEADERS)
-
-check-qint: check-qint.o qint.o $(tools-obj-y)
-check-qstring: check-qstring.o qstring.o $(tools-obj-y)
-check-qdict: check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qlist.o $(tools-obj-y)
-check-qlist: check-qlist.o qlist.o qint.o $(tools-obj-y)
-check-qfloat: check-qfloat.o qfloat.o $(tools-obj-y)
-check-qjson: check-qjson.o $(qobject-obj-y) $(tools-obj-y)
-test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y) $(tools-obj-y)
-
-test-qmp-input-visitor.o test-qmp-output-visitor.o test-qmp-input-strict.o \
-test-string-input-visitor.o test-string-output-visitor.o \
-	test-qmp-commands.o: QEMU_CFLAGS += -I $(qapi-dir)
-
-$(qapi-dir)/test-qapi-types.c $(qapi-dir)/test-qapi-types.h :\
+check-unit-y = tests/check-qdict$(EXESUF)
+check-unit-y += tests/check-qfloat$(EXESUF)
+check-unit-y += tests/check-qint$(EXESUF)
+check-unit-y += tests/check-qstring$(EXESUF)
+check-unit-y += tests/check-qlist$(EXESUF)
+check-unit-y += tests/check-qjson$(EXESUF)
+check-unit-y += tests/test-qmp-output-visitor$(EXESUF)
+check-unit-y += tests/test-qmp-input-visitor$(EXESUF)
+check-unit-y += tests/test-qmp-input-strict$(EXESUF)
+check-unit-y += tests/test-qmp-commands$(EXESUF)
+check-unit-y += tests/test-string-input-visitor$(EXESUF)
+check-unit-y += tests/test-string-output-visitor$(EXESUF)
+check-unit-y += tests/test-coroutine$(EXESUF)
+
+check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
+
+GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h tests/test-qmp-commands.h
+
+test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
+	tests/check-qlist.o tests/check-qfloat.o tests/check-qjson.o \
+	tests/test-coroutine.o tests/test-string-output-visitor.o \
+	tests/test-string-input-visitor.o tests/test-qmp-output-visitor.o \
+	tests/test-qmp-input-visitor.o tests/test-qmp-input-strict.o \
+	tests/test-qmp-commands.o
+
+test-qapi-obj-y =  $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y)
+test-qapi-obj-y += tests/test-qapi-visit.o tests/test-qapi-types.o
+test-qapi-obj-y += module.o
+
+$(test-obj-y): $(GENERATED_HEADERS)
+$(test-obj-y): QEMU_INCLUDES += -Itests
+
+tests/check-qint$(EXESUF): tests/check-qint.o qint.o $(tools-obj-y)
+tests/check-qstring$(EXESUF): tests/check-qstring.o qstring.o $(tools-obj-y)
+tests/check-qdict$(EXESUF): tests/check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qlist.o $(tools-obj-y)
+tests/check-qlist$(EXESUF): tests/check-qlist.o qlist.o qint.o $(tools-obj-y)
+tests/check-qfloat$(EXESUF): tests/check-qfloat.o qfloat.o $(tools-obj-y)
+tests/check-qjson$(EXESUF): tests/check-qjson.o $(qobject-obj-y) $(tools-obj-y)
+tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(coroutine-obj-y) $(tools-obj-y)
+
+tests/test-qapi-types.c tests/test-qapi-types.h :\
 $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
-	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "$(qapi-dir)" -p "test-" < $<, "  GEN   $@")
-$(qapi-dir)/test-qapi-visit.c $(qapi-dir)/test-qapi-visit.h :\
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o tests -p "test-" < $<, "  GEN   $@")
+tests/test-qapi-visit.c tests/test-qapi-visit.h :\
 $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-visit.py
-	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "$(qapi-dir)" -p "test-" < $<, "  GEN   $@")
-$(qapi-dir)/test-qmp-commands.h $(qapi-dir)/test-qmp-marshal.c :\
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o tests -p "test-" < $<, "  GEN   $@")
+tests/test-qmp-commands.h tests/test-qmp-marshal.c :\
 $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py
-	    $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -o "$(qapi-dir)" -p "test-" < $<, "  GEN   $@")
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -o tests -p "test-" < $<, "  GEN   $@")
 
 
-test-string-output-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
-test-string-output-visitor: test-string-output-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
+tests/test-string-output-visitor$(EXESUF): tests/test-string-output-visitor.o $(test-qapi-obj-y)
+tests/test-string-input-visitor$(EXESUF): tests/test-string-input-visitor.o $(test-qapi-obj-y)
+tests/test-qmp-output-visitor$(EXESUF): tests/test-qmp-output-visitor.o $(test-qapi-obj-y)
+tests/test-qmp-input-visitor$(EXESUF): tests/test-qmp-input-visitor.o $(test-qapi-obj-y)
+tests/test-qmp-input-strict$(EXESUF): tests/test-qmp-input-strict.o $(test-qapi-obj-y)
+tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp-marshal.o $(test-qapi-obj-y)
 
-test-string-input-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
-test-string-input-visitor: test-string-input-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
+.PHONY: check-help
+check-help:
+	@echo "Regression testing targets:"
+	@echo
+	@echo " make check                Run all tests"
+	@echo " make check-unit           Run qobject tests"
+	@echo " make check-block          Run block tests"
+	@echo " make check-report.html    Generates an HTML test report"
+	@echo
+	@echo "Please note that HTML reports do not regenerate if the unit tests"
+	@echo "has not changed."
+	@echo
+	@echo "The variable SPEED can be set to control the gtester speed setting."
+	@echo "Default options are -k and (for make V=1) --verbose; they can be"
+	@echo "changed with variable GTESTER_OPTIONS."
 
-test-qmp-input-strict.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
-test-qmp-input-strict: test-qmp-input-strict.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
+.SECONDARY:
 
-test-qmp-output-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
-test-qmp-output-visitor: test-qmp-output-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
+SPEED = quick
+GTESTER_OPTIONS = -k $(if $(V),--verbose,-q)
 
-test-qmp-input-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
-test-qmp-input-visitor: test-qmp-input-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
+# gtester tests, possibly with verbose output
 
-test-qmp-commands.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h test-qmp-marshal.c test-qmp-commands.h) $(qapi-obj-y)
-test-qmp-commands: test-qmp-commands.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o $(qapi-dir)/test-qmp-marshal.o module.o
+.PHONY: $(patsubst %, check-%, $(check-unit-y))
+$(patsubst %, check-%, $(check-unit-y)): check-%: %
+	$(call quiet-command,gtester $(GTESTER_OPTIONS) -m=$(SPEED) $*,"GTESTER $*")
 
-$(SRC_PATH)/tests/qemu-iotests-quick.sh: qemu-img qemu-io
+# gtester tests with XML output
 
+check-report-unit.xml: $(check-unit-y)
+	$(call quiet-command,gtester -q $(GTESTER_OPTIONS) -o $@ -m=$(SPEED) $^, "GTESTER $@")
 
-.PHONY: check check-block
+# Reports and overall runs
 
-check: $(CHECKS)
-	$(call quiet-command, gtester $(CHECKS), "  CHECK")
+check-report.xml: check-report-unit.xml
+	$(call quiet-command,$(SRC_PATH)/scripts/gtester-cat $^ > $@, "  GEN    $@")
 
-check-block:
-	$(call quiet-command, $(SHELL) $(SRC_PATH)/tests/check-block.sh , "  CHECK")
+check-report.html: check-report.xml
+	$(call quiet-command,gtester-report $< > $@, "  GEN    $@")
+
+
+# Other tests
+
+.PHONY: check-tests/qemu-iotests-quick.sh
+check-tests/qemu-iotests-quick.sh: tests/qemu-iotests-quick.sh qemu-img$(EXESUF) qemu-io$(EXESUF)
+	$<
+
+# Consolidated targets
+
+.PHONY: check-unit check
+check-unit: $(patsubst %,check-%, $(check-unit-y))
+check-block: $(patsubst %,check-%, $(check-block-y))
+check: check-unit
diff --git a/tests/check-qdict.c b/tests/check-qdict.c
new file mode 100644
index 0000000..fc0d276
--- /dev/null
+++ b/tests/check-qdict.c
@@ -0,0 +1,378 @@
+/*
+ * QDict unit-tests.
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+#include <glib.h>
+
+#include "qint.h"
+#include "qdict.h"
+#include "qstring.h"
+#include "qemu-common.h"
+
+/*
+ * Public Interface test-cases
+ *
+ * (with some violations to access 'private' data)
+ */
+
+static void qdict_new_test(void)
+{
+    QDict *qdict;
+
+    qdict = qdict_new();
+    g_assert(qdict != NULL);
+    g_assert(qdict_size(qdict) == 0);
+    g_assert(qdict->base.refcnt == 1);
+    g_assert(qobject_type(QOBJECT(qdict)) == QTYPE_QDICT);
+
+    // destroy doesn't exit yet
+    g_free(qdict);
+}
+
+static void qdict_put_obj_test(void)
+{
+    QInt *qi;
+    QDict *qdict;
+    QDictEntry *ent;
+    const int num = 42;
+
+    qdict = qdict_new();
+
+    // key "" will have tdb hash 12345
+    qdict_put_obj(qdict, "", QOBJECT(qint_from_int(num)));
+
+    g_assert(qdict_size(qdict) == 1);
+    ent = QLIST_FIRST(&qdict->table[12345 % QDICT_BUCKET_MAX]);
+    qi = qobject_to_qint(ent->value);
+    g_assert(qint_get_int(qi) == num);
+
+    // destroy doesn't exit yet
+    QDECREF(qi);
+    g_free(ent->key);
+    g_free(ent);
+    g_free(qdict);
+}
+
+static void qdict_destroy_simple_test(void)
+{
+    QDict *qdict;
+
+    qdict = qdict_new();
+    qdict_put_obj(qdict, "num", QOBJECT(qint_from_int(0)));
+    qdict_put_obj(qdict, "str", QOBJECT(qstring_from_str("foo")));
+
+    QDECREF(qdict);
+}
+
+static void qdict_get_test(void)
+{
+    QInt *qi;
+    QObject *obj;
+    const int value = -42;
+    const char *key = "test";
+    QDict *tests_dict = qdict_new();
+
+    qdict_put(tests_dict, key, qint_from_int(value));
+
+    obj = qdict_get(tests_dict, key);
+    g_assert(obj != NULL);
+
+    qi = qobject_to_qint(obj);
+    g_assert(qint_get_int(qi) == value);
+
+    QDECREF(tests_dict);
+}
+
+static void qdict_get_int_test(void)
+{
+    int ret;
+    const int value = 100;
+    const char *key = "int";
+    QDict *tests_dict = qdict_new();
+
+    qdict_put(tests_dict, key, qint_from_int(value));
+
+    ret = qdict_get_int(tests_dict, key);
+    g_assert(ret == value);
+
+    QDECREF(tests_dict);
+}
+
+static void qdict_get_try_int_test(void)
+{
+    int ret;
+    const int value = 100;
+    const char *key = "int";
+    QDict *tests_dict = qdict_new();
+
+    qdict_put(tests_dict, key, qint_from_int(value));
+
+    ret = qdict_get_try_int(tests_dict, key, 0);
+    g_assert(ret == value);
+
+    QDECREF(tests_dict);
+}
+
+static void qdict_get_str_test(void)
+{
+    const char *p;
+    const char *key = "key";
+    const char *str = "string";
+    QDict *tests_dict = qdict_new();
+
+    qdict_put(tests_dict, key, qstring_from_str(str));
+
+    p = qdict_get_str(tests_dict, key);
+    g_assert(p != NULL);
+    g_assert(strcmp(p, str) == 0);
+
+    QDECREF(tests_dict);
+}
+
+static void qdict_get_try_str_test(void)
+{
+    const char *p;
+    const char *key = "key";
+    const char *str = "string";
+    QDict *tests_dict = qdict_new();
+
+    qdict_put(tests_dict, key, qstring_from_str(str));
+
+    p = qdict_get_try_str(tests_dict, key);
+    g_assert(p != NULL);
+    g_assert(strcmp(p, str) == 0);
+
+    QDECREF(tests_dict);
+}
+
+static void qdict_haskey_not_test(void)
+{
+    QDict *tests_dict = qdict_new();
+    g_assert(qdict_haskey(tests_dict, "test") == 0);
+
+    QDECREF(tests_dict);
+}
+
+static void qdict_haskey_test(void)
+{
+    const char *key = "test";
+    QDict *tests_dict = qdict_new();
+
+    qdict_put(tests_dict, key, qint_from_int(0));
+    g_assert(qdict_haskey(tests_dict, key) == 1);
+
+    QDECREF(tests_dict);
+}
+
+static void qdict_del_test(void)
+{
+    const char *key = "key test";
+    QDict *tests_dict = qdict_new();
+
+    qdict_put(tests_dict, key, qstring_from_str("foo"));
+    g_assert(qdict_size(tests_dict) == 1);
+
+    qdict_del(tests_dict, key);
+
+    g_assert(qdict_size(tests_dict) == 0);
+    g_assert(qdict_haskey(tests_dict, key) == 0);
+
+    QDECREF(tests_dict);
+}
+
+static void qobject_to_qdict_test(void)
+{
+    QDict *tests_dict = qdict_new();
+    g_assert(qobject_to_qdict(QOBJECT(tests_dict)) == tests_dict);
+
+    QDECREF(tests_dict);
+}
+
+static void qdict_iterapi_test(void)
+{
+    int count;
+    const QDictEntry *ent;
+    QDict *tests_dict = qdict_new();
+
+    g_assert(qdict_first(tests_dict) == NULL);
+
+    qdict_put(tests_dict, "key1", qint_from_int(1));
+    qdict_put(tests_dict, "key2", qint_from_int(2));
+    qdict_put(tests_dict, "key3", qint_from_int(3));
+
+    count = 0;
+    for (ent = qdict_first(tests_dict); ent; ent = qdict_next(tests_dict, ent)){
+        g_assert(qdict_haskey(tests_dict, qdict_entry_key(ent)) == 1);
+        count++;
+    }
+
+    g_assert(count == qdict_size(tests_dict));
+
+    /* Do it again to test restarting */
+    count = 0;
+    for (ent = qdict_first(tests_dict); ent; ent = qdict_next(tests_dict, ent)){
+        g_assert(qdict_haskey(tests_dict, qdict_entry_key(ent)) == 1);
+        count++;
+    }
+
+    g_assert(count == qdict_size(tests_dict));
+
+    QDECREF(tests_dict);
+}
+
+/*
+ * Errors test-cases
+ */
+
+static void qdict_put_exists_test(void)
+{
+    int value;
+    const char *key = "exists";
+    QDict *tests_dict = qdict_new();
+
+    qdict_put(tests_dict, key, qint_from_int(1));
+    qdict_put(tests_dict, key, qint_from_int(2));
+
+    value = qdict_get_int(tests_dict, key);
+    g_assert(value == 2);
+
+    g_assert(qdict_size(tests_dict) == 1);
+
+    QDECREF(tests_dict);
+}
+
+static void qdict_get_not_exists_test(void)
+{
+    QDict *tests_dict = qdict_new();
+    g_assert(qdict_get(tests_dict, "foo") == NULL);
+
+    QDECREF(tests_dict);
+}
+
+/*
+ * Stress test-case
+ *
+ * This is a lot big for a unit-test, but there is no other place
+ * to have it.
+ */
+
+static void remove_dots(char *string)
+{
+    char *p = strchr(string, ':');
+    if (p)
+        *p = '\0';
+}
+
+static QString *read_line(FILE *file, char *key)
+{
+    char value[128];
+
+    if (fscanf(file, "%127s%127s", key, value) == EOF) {
+        return NULL;
+    }
+    remove_dots(key);
+    return qstring_from_str(value);
+}
+
+#define reset_file(file)    fseek(file, 0L, SEEK_SET)
+
+static void qdict_stress_test(void)
+{
+    size_t lines;
+    char key[128];
+    FILE *test_file;
+    QDict *qdict;
+    QString *value;
+    const char *test_file_path = "qdict-test-data.txt";
+
+    test_file = fopen(test_file_path, "r");
+    g_assert(test_file != NULL);
+
+    // Create the dict
+    qdict = qdict_new();
+    g_assert(qdict != NULL);
+
+    // Add everything from the test file
+    for (lines = 0;; lines++) {
+        value = read_line(test_file, key);
+        if (!value)
+            break;
+
+        qdict_put(qdict, key, value);
+    }
+    g_assert(qdict_size(qdict) == lines);
+
+    // Check if everything is really in there
+    reset_file(test_file);
+    for (;;) {
+        const char *str1, *str2;
+
+        value = read_line(test_file, key);
+        if (!value)
+            break;
+
+        str1 = qstring_get_str(value);
+
+        str2 = qdict_get_str(qdict, key);
+        g_assert(str2 != NULL);
+
+        g_assert(strcmp(str1, str2) == 0);
+
+        QDECREF(value);
+    }
+
+    // Delete everything
+    reset_file(test_file);
+    for (;;) {
+        value = read_line(test_file, key);
+        if (!value)
+            break;
+
+        qdict_del(qdict, key);
+        QDECREF(value);
+
+        g_assert(qdict_haskey(qdict, key) == 0);
+    }
+    fclose(test_file);
+
+    g_assert(qdict_size(qdict) == 0);
+    QDECREF(qdict);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    g_test_add_func("/public/new", qdict_new_test);
+    g_test_add_func("/public/put_obj", qdict_put_obj_test);
+    g_test_add_func("/public/destroy_simple", qdict_destroy_simple_test);
+
+    /* Continue, but now with fixtures */
+    g_test_add_func("/public/get", qdict_get_test);
+    g_test_add_func("/public/get_int", qdict_get_int_test);
+    g_test_add_func("/public/get_try_int", qdict_get_try_int_test);
+    g_test_add_func("/public/get_str", qdict_get_str_test);
+    g_test_add_func("/public/get_try_str", qdict_get_try_str_test);
+    g_test_add_func("/public/haskey_not", qdict_haskey_not_test);
+    g_test_add_func("/public/haskey", qdict_haskey_test);
+    g_test_add_func("/public/del", qdict_del_test);
+    g_test_add_func("/public/to_qdict", qobject_to_qdict_test);
+    g_test_add_func("/public/iterapi", qdict_iterapi_test);
+
+    g_test_add_func("/errors/put_exists", qdict_put_exists_test);
+    g_test_add_func("/errors/get_not_exists", qdict_get_not_exists_test);
+
+    /* The Big one */
+    if (g_test_slow()) {
+        g_test_add_func("/stress/test", qdict_stress_test);
+    }
+
+    return g_test_run();
+}
diff --git a/tests/check-qfloat.c b/tests/check-qfloat.c
new file mode 100644
index 0000000..cdc66ea
--- /dev/null
+++ b/tests/check-qfloat.c
@@ -0,0 +1,53 @@
+/*
+ * QFloat unit-tests.
+ *
+ * Copyright IBM, Corp. 2009
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+#include <glib.h>
+
+#include "qfloat.h"
+#include "qemu-common.h"
+
+/*
+ * Public Interface test-cases
+ *
+ * (with some violations to access 'private' data)
+ */
+
+static void qfloat_from_double_test(void)
+{
+    QFloat *qf;
+    const double value = -42.23423;
+
+    qf = qfloat_from_double(value);
+    g_assert(qf != NULL);
+    g_assert(qf->value == value);
+    g_assert(qf->base.refcnt == 1);
+    g_assert(qobject_type(QOBJECT(qf)) == QTYPE_QFLOAT);
+
+    // destroy doesn't exit yet
+    g_free(qf);
+}
+
+static void qfloat_destroy_test(void)
+{
+    QFloat *qf = qfloat_from_double(0.0);
+    QDECREF(qf);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    g_test_add_func("/public/from_double", qfloat_from_double_test);
+    g_test_add_func("/public/destroy", qfloat_destroy_test);
+
+    return g_test_run();
+}
diff --git a/tests/check-qint.c b/tests/check-qint.c
new file mode 100644
index 0000000..5a27119
--- /dev/null
+++ b/tests/check-qint.c
@@ -0,0 +1,87 @@
+/*
+ * QInt unit-tests.
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+#include <glib.h>
+
+#include "qint.h"
+#include "qemu-common.h"
+
+/*
+ * Public Interface test-cases
+ *
+ * (with some violations to access 'private' data)
+ */
+
+static void qint_from_int_test(void)
+{
+    QInt *qi;
+    const int value = -42;
+
+    qi = qint_from_int(value);
+    g_assert(qi != NULL);
+    g_assert(qi->value == value);
+    g_assert(qi->base.refcnt == 1);
+    g_assert(qobject_type(QOBJECT(qi)) == QTYPE_QINT);
+
+    // destroy doesn't exit yet
+    g_free(qi);
+}
+
+static void qint_destroy_test(void)
+{
+    QInt *qi = qint_from_int(0);
+    QDECREF(qi);
+}
+
+static void qint_from_int64_test(void)
+{
+    QInt *qi;
+    const int64_t value = 0x1234567890abcdefLL;
+
+    qi = qint_from_int(value);
+    g_assert((int64_t) qi->value == value);
+
+    QDECREF(qi);
+}
+
+static void qint_get_int_test(void)
+{
+    QInt *qi;
+    const int value = 123456;
+
+    qi = qint_from_int(value);
+    g_assert(qint_get_int(qi) == value);
+
+    QDECREF(qi);
+}
+
+static void qobject_to_qint_test(void)
+{
+    QInt *qi;
+
+    qi = qint_from_int(0);
+    g_assert(qobject_to_qint(QOBJECT(qi)) == qi);
+
+    QDECREF(qi);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    g_test_add_func("/public/from_int", qint_from_int_test);
+    g_test_add_func("/public/destroy", qint_destroy_test);
+    g_test_add_func("/public/from_int64", qint_from_int64_test);
+    g_test_add_func("/public/get_int", qint_get_int_test);
+    g_test_add_func("/public/to_qint", qobject_to_qint_test);
+
+    return g_test_run();
+}
diff --git a/tests/check-qjson.c b/tests/check-qjson.c
new file mode 100644
index 0000000..526e25e
--- /dev/null
+++ b/tests/check-qjson.c
@@ -0,0 +1,728 @@
+/*
+ * Copyright IBM, Corp. 2009
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+#include <glib.h>
+
+#include "qstring.h"
+#include "qint.h"
+#include "qdict.h"
+#include "qlist.h"
+#include "qfloat.h"
+#include "qbool.h"
+#include "qjson.h"
+
+#include "qemu-common.h"
+
+static void escaped_string(void)
+{
+    int i;
+    struct {
+        const char *encoded;
+        const char *decoded;
+        int skip;
+    } test_cases[] = {
+        { "\"\\b\"", "\b" },
+        { "\"\\f\"", "\f" },
+        { "\"\\n\"", "\n" },
+        { "\"\\r\"", "\r" },
+        { "\"\\t\"", "\t" },
+        { "\"/\"", "/" },
+        { "\"\\/\"", "/", .skip = 1 },
+        { "\"\\\\\"", "\\" },
+        { "\"\\\"\"", "\"" },
+        { "\"hello world \\\"embedded string\\\"\"",
+          "hello world \"embedded string\"" },
+        { "\"hello world\\nwith new line\"", "hello world\nwith new line" },
+        { "\"single byte utf-8 \\u0020\"", "single byte utf-8  ", .skip = 1 },
+        { "\"double byte utf-8 \\u00A2\"", "double byte utf-8 \xc2\xa2" },
+        { "\"triple byte utf-8 \\u20AC\"", "triple byte utf-8 \xe2\x82\xac" },
+        {}
+    };
+
+    for (i = 0; test_cases[i].encoded; i++) {
+        QObject *obj;
+        QString *str;
+
+        obj = qobject_from_json(test_cases[i].encoded);
+
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QSTRING);
+        
+        str = qobject_to_qstring(obj);
+        g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].decoded);
+
+        if (test_cases[i].skip == 0) {
+            str = qobject_to_json(obj);
+            g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].encoded);
+            qobject_decref(obj);
+        }
+
+        QDECREF(str);
+    }
+}
+
+static void simple_string(void)
+{
+    int i;
+    struct {
+        const char *encoded;
+        const char *decoded;
+    } test_cases[] = {
+        { "\"hello world\"", "hello world" },
+        { "\"the quick brown fox jumped over the fence\"",
+          "the quick brown fox jumped over the fence" },
+        {}
+    };
+
+    for (i = 0; test_cases[i].encoded; i++) {
+        QObject *obj;
+        QString *str;
+
+        obj = qobject_from_json(test_cases[i].encoded);
+
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QSTRING);
+        
+        str = qobject_to_qstring(obj);
+        g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
+
+        str = qobject_to_json(obj);
+        g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
+
+        qobject_decref(obj);
+        
+        QDECREF(str);
+    }
+}
+
+static void single_quote_string(void)
+{
+    int i;
+    struct {
+        const char *encoded;
+        const char *decoded;
+    } test_cases[] = {
+        { "'hello world'", "hello world" },
+        { "'the quick brown fox \\' jumped over the fence'",
+          "the quick brown fox ' jumped over the fence" },
+        {}
+    };
+
+    for (i = 0; test_cases[i].encoded; i++) {
+        QObject *obj;
+        QString *str;
+
+        obj = qobject_from_json(test_cases[i].encoded);
+
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QSTRING);
+        
+        str = qobject_to_qstring(obj);
+        g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
+
+        QDECREF(str);
+    }
+}
+
+static void vararg_string(void)
+{
+    int i;
+    struct {
+        const char *decoded;
+    } test_cases[] = {
+        { "hello world" },
+        { "the quick brown fox jumped over the fence" },
+        {}
+    };
+
+    for (i = 0; test_cases[i].decoded; i++) {
+        QObject *obj;
+        QString *str;
+
+        obj = qobject_from_jsonf("%s", test_cases[i].decoded);
+
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QSTRING);
+        
+        str = qobject_to_qstring(obj);
+        g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
+
+        QDECREF(str);
+    }
+}
+
+static void simple_number(void)
+{
+    int i;
+    struct {
+        const char *encoded;
+        int64_t decoded;
+        int skip;
+    } test_cases[] = {
+        { "0", 0 },
+        { "1234", 1234 },
+        { "1", 1 },
+        { "-32", -32 },
+        { "-0", 0, .skip = 1 },
+        { },
+    };
+
+    for (i = 0; test_cases[i].encoded; i++) {
+        QObject *obj;
+        QInt *qint;
+
+        obj = qobject_from_json(test_cases[i].encoded);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QINT);
+
+        qint = qobject_to_qint(obj);
+        g_assert(qint_get_int(qint) == test_cases[i].decoded);
+        if (test_cases[i].skip == 0) {
+            QString *str;
+
+            str = qobject_to_json(obj);
+            g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
+            QDECREF(str);
+        }
+
+        QDECREF(qint);
+    }
+}
+
+static void float_number(void)
+{
+    int i;
+    struct {
+        const char *encoded;
+        double decoded;
+        int skip;
+    } test_cases[] = {
+        { "32.43", 32.43 },
+        { "0.222", 0.222 },
+        { "-32.12313", -32.12313 },
+        { "-32.20e-10", -32.20e-10, .skip = 1 },
+        { },
+    };
+
+    for (i = 0; test_cases[i].encoded; i++) {
+        QObject *obj;
+        QFloat *qfloat;
+
+        obj = qobject_from_json(test_cases[i].encoded);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QFLOAT);
+
+        qfloat = qobject_to_qfloat(obj);
+        g_assert(qfloat_get_double(qfloat) == test_cases[i].decoded);
+
+        if (test_cases[i].skip == 0) {
+            QString *str;
+
+            str = qobject_to_json(obj);
+            g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
+            QDECREF(str);
+        }
+
+        QDECREF(qfloat);
+    }
+}
+
+static void vararg_number(void)
+{
+    QObject *obj;
+    QInt *qint;
+    QFloat *qfloat;
+    int value = 0x2342;
+    int64_t value64 = 0x2342342343LL;
+    double valuef = 2.323423423;
+
+    obj = qobject_from_jsonf("%d", value);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QINT);
+
+    qint = qobject_to_qint(obj);
+    g_assert(qint_get_int(qint) == value);
+
+    QDECREF(qint);
+
+    obj = qobject_from_jsonf("%" PRId64, value64);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QINT);
+
+    qint = qobject_to_qint(obj);
+    g_assert(qint_get_int(qint) == value64);
+
+    QDECREF(qint);
+
+    obj = qobject_from_jsonf("%f", valuef);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QFLOAT);
+
+    qfloat = qobject_to_qfloat(obj);
+    g_assert(qfloat_get_double(qfloat) == valuef);
+
+    QDECREF(qfloat);
+}
+
+static void keyword_literal(void)
+{
+    QObject *obj;
+    QBool *qbool;
+    QString *str;
+
+    obj = qobject_from_json("true");
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QBOOL);
+
+    qbool = qobject_to_qbool(obj);
+    g_assert(qbool_get_int(qbool) != 0);
+
+    str = qobject_to_json(obj);
+    g_assert(strcmp(qstring_get_str(str), "true") == 0);
+    QDECREF(str);
+
+    QDECREF(qbool);
+
+    obj = qobject_from_json("false");
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QBOOL);
+
+    qbool = qobject_to_qbool(obj);
+    g_assert(qbool_get_int(qbool) == 0);
+
+    str = qobject_to_json(obj);
+    g_assert(strcmp(qstring_get_str(str), "false") == 0);
+    QDECREF(str);
+
+    QDECREF(qbool);
+
+    obj = qobject_from_jsonf("%i", false);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QBOOL);
+
+    qbool = qobject_to_qbool(obj);
+    g_assert(qbool_get_int(qbool) == 0);
+
+    QDECREF(qbool);
+    
+    obj = qobject_from_jsonf("%i", true);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QBOOL);
+
+    qbool = qobject_to_qbool(obj);
+    g_assert(qbool_get_int(qbool) != 0);
+
+    QDECREF(qbool);
+}
+
+typedef struct LiteralQDictEntry LiteralQDictEntry;
+typedef struct LiteralQObject LiteralQObject;
+
+struct LiteralQObject
+{
+    int type;
+    union {
+        int64_t qint;
+        const char *qstr;
+        LiteralQDictEntry *qdict;
+        LiteralQObject *qlist;
+    } value;
+};
+
+struct LiteralQDictEntry
+{
+    const char *key;
+    LiteralQObject value;
+};
+
+#define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
+#define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
+#define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
+#define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
+
+typedef struct QListCompareHelper
+{
+    int index;
+    LiteralQObject *objs;
+    int result;
+} QListCompareHelper;
+
+static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
+
+static void compare_helper(QObject *obj, void *opaque)
+{
+    QListCompareHelper *helper = opaque;
+
+    if (helper->result == 0) {
+        return;
+    }
+
+    if (helper->objs[helper->index].type == QTYPE_NONE) {
+        helper->result = 0;
+        return;
+    }
+
+    helper->result = compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
+}
+
+static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
+{
+    if (lhs->type != qobject_type(rhs)) {
+        return 0;
+    }
+
+    switch (lhs->type) {
+    case QTYPE_QINT:
+        return lhs->value.qint == qint_get_int(qobject_to_qint(rhs));
+    case QTYPE_QSTRING:
+        return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
+    case QTYPE_QDICT: {
+        int i;
+
+        for (i = 0; lhs->value.qdict[i].key; i++) {
+            QObject *obj = qdict_get(qobject_to_qdict(rhs), lhs->value.qdict[i].key);
+
+            if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
+                return 0;
+            }
+        }
+
+        return 1;
+    }
+    case QTYPE_QLIST: {
+        QListCompareHelper helper;
+
+        helper.index = 0;
+        helper.objs = lhs->value.qlist;
+        helper.result = 1;
+        
+        qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
+
+        return helper.result;
+    }
+    default:
+        break;
+    }
+
+    return 0;
+}
+
+static void simple_dict(void)
+{
+    int i;
+    struct {
+        const char *encoded;
+        LiteralQObject decoded;
+    } test_cases[] = {
+        {
+            .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
+            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
+                        { "foo", QLIT_QINT(42) },
+                        { "bar", QLIT_QSTR("hello world") },
+                        { }
+                    })),
+        }, {
+            .encoded = "{}",
+            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
+                        { }
+                    })),
+        }, {
+            .encoded = "{\"foo\": 43}",
+            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
+                        { "foo", QLIT_QINT(43) },
+                        { }
+                    })),
+        },
+        { }
+    };
+
+    for (i = 0; test_cases[i].encoded; i++) {
+        QObject *obj;
+        QString *str;
+
+        obj = qobject_from_json(test_cases[i].encoded);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QDICT);
+
+        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+
+        str = qobject_to_json(obj);
+        qobject_decref(obj);
+
+        obj = qobject_from_json(qstring_get_str(str));
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QDICT);
+
+        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+        qobject_decref(obj);
+        QDECREF(str);
+    }
+}
+
+static void simple_list(void)
+{
+    int i;
+    struct {
+        const char *encoded;
+        LiteralQObject decoded;
+    } test_cases[] = {
+        {
+            .encoded = "[43,42]",
+            .decoded = QLIT_QLIST(((LiteralQObject[]){
+                        QLIT_QINT(43),
+                        QLIT_QINT(42),
+                        { }
+                    })),
+        },
+        {
+            .encoded = "[43]",
+            .decoded = QLIT_QLIST(((LiteralQObject[]){
+                        QLIT_QINT(43),
+                        { }
+                    })),
+        },
+        {
+            .encoded = "[]",
+            .decoded = QLIT_QLIST(((LiteralQObject[]){
+                        { }
+                    })),
+        },
+        {
+            .encoded = "[{}]",
+            .decoded = QLIT_QLIST(((LiteralQObject[]){
+                        QLIT_QDICT(((LiteralQDictEntry[]){
+                                    {},
+                                        })),
+                        {},
+                            })),
+        },
+        { }
+    };
+
+    for (i = 0; test_cases[i].encoded; i++) {
+        QObject *obj;
+        QString *str;
+
+        obj = qobject_from_json(test_cases[i].encoded);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QLIST);
+
+        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+
+        str = qobject_to_json(obj);
+        qobject_decref(obj);
+
+        obj = qobject_from_json(qstring_get_str(str));
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QLIST);
+
+        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+        qobject_decref(obj);
+        QDECREF(str);
+    }
+}
+
+static void simple_whitespace(void)
+{
+    int i;
+    struct {
+        const char *encoded;
+        LiteralQObject decoded;
+    } test_cases[] = {
+        {
+            .encoded = " [ 43 , 42 ]",
+            .decoded = QLIT_QLIST(((LiteralQObject[]){
+                        QLIT_QINT(43),
+                        QLIT_QINT(42),
+                        { }
+                    })),
+        },
+        {
+            .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
+            .decoded = QLIT_QLIST(((LiteralQObject[]){
+                        QLIT_QINT(43),
+                        QLIT_QDICT(((LiteralQDictEntry[]){
+                                    { "h", QLIT_QSTR("b") },
+                                    { }})),
+                        QLIT_QLIST(((LiteralQObject[]){
+                                    { }})),
+                        QLIT_QINT(42),
+                        { }
+                    })),
+        },
+        {
+            .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
+            .decoded = QLIT_QLIST(((LiteralQObject[]){
+                        QLIT_QINT(43),
+                        QLIT_QDICT(((LiteralQDictEntry[]){
+                                    { "h", QLIT_QSTR("b") },
+                                    { "a", QLIT_QINT(32) },
+                                    { }})),
+                        QLIT_QLIST(((LiteralQObject[]){
+                                    { }})),
+                        QLIT_QINT(42),
+                        { }
+                    })),
+        },
+        { }
+    };
+
+    for (i = 0; test_cases[i].encoded; i++) {
+        QObject *obj;
+        QString *str;
+
+        obj = qobject_from_json(test_cases[i].encoded);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QLIST);
+
+        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+
+        str = qobject_to_json(obj);
+        qobject_decref(obj);
+
+        obj = qobject_from_json(qstring_get_str(str));
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QLIST);
+
+        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+
+        qobject_decref(obj);
+        QDECREF(str);
+    }
+}
+
+static void simple_varargs(void)
+{
+    QObject *embedded_obj;
+    QObject *obj;
+    LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
+            QLIT_QINT(1),
+            QLIT_QINT(2),
+            QLIT_QLIST(((LiteralQObject[]){
+                        QLIT_QINT(32),
+                        QLIT_QINT(42),
+                        {}})),
+            {}}));
+
+    embedded_obj = qobject_from_json("[32, 42]");
+    g_assert(embedded_obj != NULL);
+
+    obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
+    g_assert(obj != NULL);
+
+    g_assert(compare_litqobj_to_qobj(&decoded, obj) == 1);
+
+    qobject_decref(obj);
+}
+
+static void empty_input(void)
+{
+    const char *empty = "";
+
+    QObject *obj = qobject_from_json(empty);
+    g_assert(obj == NULL);
+}
+
+static void unterminated_string(void)
+{
+    QObject *obj = qobject_from_json("\"abc");
+    g_assert(obj == NULL);
+}
+
+static void unterminated_sq_string(void)
+{
+    QObject *obj = qobject_from_json("'abc");
+    g_assert(obj == NULL);
+}
+
+static void unterminated_escape(void)
+{
+    QObject *obj = qobject_from_json("\"abc\\\"");
+    g_assert(obj == NULL);
+}
+
+static void unterminated_array(void)
+{
+    QObject *obj = qobject_from_json("[32");
+    g_assert(obj == NULL);
+}
+
+static void unterminated_array_comma(void)
+{
+    QObject *obj = qobject_from_json("[32,");
+    g_assert(obj == NULL);
+}
+
+static void invalid_array_comma(void)
+{
+    QObject *obj = qobject_from_json("[32,}");
+    g_assert(obj == NULL);
+}
+
+static void unterminated_dict(void)
+{
+    QObject *obj = qobject_from_json("{'abc':32");
+    g_assert(obj == NULL);
+}
+
+static void unterminated_dict_comma(void)
+{
+    QObject *obj = qobject_from_json("{'abc':32,");
+    g_assert(obj == NULL);
+}
+
+static void invalid_dict_comma(void)
+{
+    QObject *obj = qobject_from_json("{'abc':32,}");
+    g_assert(obj == NULL);
+}
+
+static void unterminated_literal(void)
+{
+    QObject *obj = qobject_from_json("nul");
+    g_assert(obj == NULL);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    g_test_add_func("/literals/string/simple", simple_string);
+    g_test_add_func("/literals/string/escaped", escaped_string);
+    g_test_add_func("/literals/string/single_quote", single_quote_string);
+    g_test_add_func("/literals/string/vararg", vararg_string);
+
+    g_test_add_func("/literals/number/simple", simple_number);
+    g_test_add_func("/literals/number/float", float_number);
+    g_test_add_func("/literals/number/vararg", vararg_number);
+
+    g_test_add_func("/literals/keyword", keyword_literal);
+
+    g_test_add_func("/dicts/simple_dict", simple_dict);
+    g_test_add_func("/lists/simple_list", simple_list);
+
+    g_test_add_func("/whitespace/simple_whitespace", simple_whitespace);
+
+    g_test_add_func("/varargs/simple_varargs", simple_varargs);
+
+    g_test_add_func("/errors/empty_input", empty_input);
+    g_test_add_func("/errors/unterminated/string", unterminated_string);
+    g_test_add_func("/errors/unterminated/escape", unterminated_escape);
+    g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string);
+    g_test_add_func("/errors/unterminated/array", unterminated_array);
+    g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma);
+    g_test_add_func("/errors/unterminated/dict", unterminated_dict);
+    g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma);
+    g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
+    g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
+    g_test_add_func("/errors/unterminated/literal", unterminated_literal);
+
+    return g_test_run();
+}
diff --git a/tests/check-qlist.c b/tests/check-qlist.c
new file mode 100644
index 0000000..501ba26
--- /dev/null
+++ b/tests/check-qlist.c
@@ -0,0 +1,127 @@
+/*
+ * QList unit-tests.
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+#include <glib.h>
+
+#include "qint.h"
+#include "qlist.h"
+
+/*
+ * Public Interface test-cases
+ *
+ * (with some violations to access 'private' data)
+ */
+
+static void qlist_new_test(void)
+{
+    QList *qlist;
+
+    qlist = qlist_new();
+    g_assert(qlist != NULL);
+    g_assert(qlist->base.refcnt == 1);
+    g_assert(qobject_type(QOBJECT(qlist)) == QTYPE_QLIST);
+
+    // destroy doesn't exist yet
+    g_free(qlist);
+}
+
+static void qlist_append_test(void)
+{
+    QInt *qi;
+    QList *qlist;
+    QListEntry *entry;
+
+    qi = qint_from_int(42);
+
+    qlist = qlist_new();
+    qlist_append(qlist, qi);
+
+    entry = QTAILQ_FIRST(&qlist->head);
+    g_assert(entry != NULL);
+    g_assert(entry->value == QOBJECT(qi));
+
+    // destroy doesn't exist yet
+    QDECREF(qi);
+    g_free(entry);
+    g_free(qlist);
+}
+
+static void qobject_to_qlist_test(void)
+{
+    QList *qlist;
+
+    qlist = qlist_new();
+
+    g_assert(qobject_to_qlist(QOBJECT(qlist)) == qlist);
+
+    // destroy doesn't exist yet
+    g_free(qlist);
+}
+
+static void qlist_destroy_test(void)
+{
+    int i;
+    QList *qlist;
+
+    qlist = qlist_new();
+
+    for (i = 0; i < 42; i++)
+        qlist_append(qlist, qint_from_int(i));
+
+    QDECREF(qlist);
+}
+
+static int iter_called;
+static const int iter_max = 42;
+
+static void iter_func(QObject *obj, void *opaque)
+{
+    QInt *qi;
+
+    g_assert(opaque == NULL);
+
+    qi = qobject_to_qint(obj);
+    g_assert(qi != NULL);
+    g_assert((qint_get_int(qi) >= 0) && (qint_get_int(qi) <= iter_max));
+
+    iter_called++;
+}
+
+static void qlist_iter_test(void)
+{
+    int i;
+    QList *qlist;
+
+    qlist = qlist_new();
+
+    for (i = 0; i < iter_max; i++)
+        qlist_append(qlist, qint_from_int(i));
+
+    iter_called = 0;
+    qlist_iter(qlist, iter_func, NULL);
+
+    g_assert(iter_called == iter_max);
+
+    QDECREF(qlist);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    g_test_add_func("/public/new", qlist_new_test);
+    g_test_add_func("/public/append", qlist_append_test);
+    g_test_add_func("/public/to_qlist", qobject_to_qlist_test);
+    g_test_add_func("/public/destroy", qlist_destroy_test);
+    g_test_add_func("/public/iter", qlist_iter_test);
+
+    return g_test_run();
+}
diff --git a/tests/check-qstring.c b/tests/check-qstring.c
new file mode 100644
index 0000000..addad6c
--- /dev/null
+++ b/tests/check-qstring.c
@@ -0,0 +1,107 @@
+/*
+ * QString unit-tests.
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+#include <glib.h>
+
+#include "qstring.h"
+#include "qemu-common.h"
+
+/*
+ * Public Interface test-cases
+ *
+ * (with some violations to access 'private' data)
+ */
+
+static void qstring_from_str_test(void)
+{
+    QString *qstring;
+    const char *str = "QEMU";
+
+    qstring = qstring_from_str(str);
+    g_assert(qstring != NULL);
+    g_assert(qstring->base.refcnt == 1);
+    g_assert(strcmp(str, qstring->string) == 0);
+    g_assert(qobject_type(QOBJECT(qstring)) == QTYPE_QSTRING);
+
+    // destroy doesn't exit yet
+    g_free(qstring->string);
+    g_free(qstring);
+}
+
+static void qstring_destroy_test(void)
+{
+    QString *qstring = qstring_from_str("destroy test");
+    QDECREF(qstring);
+}
+
+static void qstring_get_str_test(void)
+{
+    QString *qstring;
+    const char *ret_str;
+    const char *str = "QEMU/KVM";
+
+    qstring = qstring_from_str(str);
+    ret_str = qstring_get_str(qstring);
+    g_assert(strcmp(ret_str, str) == 0);
+
+    QDECREF(qstring);
+}
+
+static void qstring_append_chr_test(void)
+{
+    int i;
+    QString *qstring;
+    const char *str = "qstring append char unit-test";
+
+    qstring = qstring_new();
+
+    for (i = 0; str[i]; i++)
+        qstring_append_chr(qstring, str[i]);
+
+    g_assert(strcmp(str, qstring_get_str(qstring)) == 0);
+    QDECREF(qstring);
+}
+
+static void qstring_from_substr_test(void)
+{
+    QString *qs;
+
+    qs = qstring_from_substr("virtualization", 3, 9);
+    g_assert(qs != NULL);
+    g_assert(strcmp(qstring_get_str(qs), "tualiza") == 0);
+
+    QDECREF(qs);
+}
+
+
+static void qobject_to_qstring_test(void)
+{
+    QString *qstring;
+
+    qstring = qstring_from_str("foo");
+    g_assert(qobject_to_qstring(QOBJECT(qstring)) == qstring);
+
+    QDECREF(qstring);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    g_test_add_func("/public/from_str", qstring_from_str_test);
+    g_test_add_func("/public/destroy", qstring_destroy_test);
+    g_test_add_func("/public/get_str", qstring_get_str_test);
+    g_test_add_func("/public/append_chr", qstring_append_chr_test);
+    g_test_add_func("/public/from_substr", qstring_from_substr_test);
+    g_test_add_func("/public/to_qstring", qobject_to_qstring_test);
+
+    return g_test_run();
+}
diff --git a/tests/test-coroutine.c b/tests/test-coroutine.c
new file mode 100644
index 0000000..e5d14eb
--- /dev/null
+++ b/tests/test-coroutine.c
@@ -0,0 +1,219 @@
+/*
+ * Coroutine tests
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Stefan Hajnoczi    <stefanha at linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include <glib.h>
+#include "qemu-coroutine.h"
+
+/*
+ * Check that qemu_in_coroutine() works
+ */
+
+static void coroutine_fn verify_in_coroutine(void *opaque)
+{
+    g_assert(qemu_in_coroutine());
+}
+
+static void test_in_coroutine(void)
+{
+    Coroutine *coroutine;
+
+    g_assert(!qemu_in_coroutine());
+
+    coroutine = qemu_coroutine_create(verify_in_coroutine);
+    qemu_coroutine_enter(coroutine, NULL);
+}
+
+/*
+ * Check that qemu_coroutine_self() works
+ */
+
+static void coroutine_fn verify_self(void *opaque)
+{
+    g_assert(qemu_coroutine_self() == opaque);
+}
+
+static void test_self(void)
+{
+    Coroutine *coroutine;
+
+    coroutine = qemu_coroutine_create(verify_self);
+    qemu_coroutine_enter(coroutine, coroutine);
+}
+
+/*
+ * Check that coroutines may nest multiple levels
+ */
+
+typedef struct {
+    unsigned int n_enter;   /* num coroutines entered */
+    unsigned int n_return;  /* num coroutines returned */
+    unsigned int max;       /* maximum level of nesting */
+} NestData;
+
+static void coroutine_fn nest(void *opaque)
+{
+    NestData *nd = opaque;
+
+    nd->n_enter++;
+
+    if (nd->n_enter < nd->max) {
+        Coroutine *child;
+
+        child = qemu_coroutine_create(nest);
+        qemu_coroutine_enter(child, nd);
+    }
+
+    nd->n_return++;
+}
+
+static void test_nesting(void)
+{
+    Coroutine *root;
+    NestData nd = {
+        .n_enter  = 0,
+        .n_return = 0,
+        .max      = 128,
+    };
+
+    root = qemu_coroutine_create(nest);
+    qemu_coroutine_enter(root, &nd);
+
+    /* Must enter and return from max nesting level */
+    g_assert_cmpint(nd.n_enter, ==, nd.max);
+    g_assert_cmpint(nd.n_return, ==, nd.max);
+}
+
+/*
+ * Check that yield/enter transfer control correctly
+ */
+
+static void coroutine_fn yield_5_times(void *opaque)
+{
+    bool *done = opaque;
+    int i;
+
+    for (i = 0; i < 5; i++) {
+        qemu_coroutine_yield();
+    }
+    *done = true;
+}
+
+static void test_yield(void)
+{
+    Coroutine *coroutine;
+    bool done = false;
+    int i = -1; /* one extra time to return from coroutine */
+
+    coroutine = qemu_coroutine_create(yield_5_times);
+    while (!done) {
+        qemu_coroutine_enter(coroutine, &done);
+        i++;
+    }
+    g_assert_cmpint(i, ==, 5); /* coroutine must yield 5 times */
+}
+
+/*
+ * Check that creation, enter, and return work
+ */
+
+static void coroutine_fn set_and_exit(void *opaque)
+{
+    bool *done = opaque;
+
+    *done = true;
+}
+
+static void test_lifecycle(void)
+{
+    Coroutine *coroutine;
+    bool done = false;
+
+    /* Create, enter, and return from coroutine */
+    coroutine = qemu_coroutine_create(set_and_exit);
+    qemu_coroutine_enter(coroutine, &done);
+    g_assert(done); /* expect done to be true (first time) */
+
+    /* Repeat to check that no state affects this test */
+    done = false;
+    coroutine = qemu_coroutine_create(set_and_exit);
+    qemu_coroutine_enter(coroutine, &done);
+    g_assert(done); /* expect done to be true (second time) */
+}
+
+/*
+ * Lifecycle benchmark
+ */
+
+static void coroutine_fn empty_coroutine(void *opaque)
+{
+    /* Do nothing */
+}
+
+static void perf_lifecycle(void)
+{
+    Coroutine *coroutine;
+    unsigned int i, max;
+    double duration;
+
+    max = 1000000;
+
+    g_test_timer_start();
+    for (i = 0; i < max; i++) {
+        coroutine = qemu_coroutine_create(empty_coroutine);
+        qemu_coroutine_enter(coroutine, NULL);
+    }
+    duration = g_test_timer_elapsed();
+
+    g_test_message("Lifecycle %u iterations: %f s\n", max, duration);
+}
+
+static void perf_nesting(void)
+{
+    unsigned int i, maxcycles, maxnesting;
+    double duration;
+
+    maxcycles = 100000000;
+    maxnesting = 20000;
+    Coroutine *root;
+    NestData nd = {
+        .n_enter  = 0,
+        .n_return = 0,
+        .max      = maxnesting,
+    };
+
+    g_test_timer_start();
+    for (i = 0; i < maxcycles; i++) {
+        root = qemu_coroutine_create(nest);
+        qemu_coroutine_enter(root, &nd);
+    }
+    duration = g_test_timer_elapsed();
+
+    g_test_message("Nesting %u iterations of %u depth each: %f s\n",
+        maxcycles, maxnesting, duration);
+}
+
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+    g_test_add_func("/basic/lifecycle", test_lifecycle);
+    g_test_add_func("/basic/yield", test_yield);
+    g_test_add_func("/basic/nesting", test_nesting);
+    g_test_add_func("/basic/self", test_self);
+    g_test_add_func("/basic/in_coroutine", test_in_coroutine);
+    if (g_test_perf()) {
+        g_test_add_func("/perf/lifecycle", perf_lifecycle);
+        g_test_add_func("/perf/nesting", perf_nesting);
+    }
+    return g_test_run();
+}
diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
new file mode 100644
index 0000000..60cbf01
--- /dev/null
+++ b/tests/test-qmp-commands.c
@@ -0,0 +1,139 @@
+#include <glib.h>
+#include "qemu-objects.h"
+#include "test-qmp-commands.h"
+#include "qapi/qmp-core.h"
+#include "module.h"
+
+void qmp_user_def_cmd(Error **errp)
+{
+}
+
+void qmp_user_def_cmd1(UserDefOne * ud1, Error **errp)
+{
+}
+
+UserDefTwo * qmp_user_def_cmd2(UserDefOne * ud1a, UserDefOne * ud1b, Error **errp)
+{
+    UserDefTwo *ret;
+    UserDefOne *ud1c = g_malloc0(sizeof(UserDefOne));
+    UserDefOne *ud1d = g_malloc0(sizeof(UserDefOne));
+
+    ud1c->string = strdup(ud1a->string);
+    ud1c->integer = ud1a->integer;
+    ud1d->string = strdup(ud1b->string);
+    ud1d->integer = ud1b->integer;
+
+    ret = g_malloc0(sizeof(UserDefTwo));
+    ret->string = strdup("blah1");
+    ret->dict.string = strdup("blah2");
+    ret->dict.dict.userdef = ud1c;
+    ret->dict.dict.string = strdup("blah3");
+    ret->dict.has_dict2 = true;
+    ret->dict.dict2.userdef = ud1d;
+    ret->dict.dict2.string = strdup("blah4");
+
+    return ret;
+}
+
+/* test commands with no input and no return value */
+static void test_dispatch_cmd(void)
+{
+    QDict *req = qdict_new();
+    QObject *resp;
+
+    qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd")));
+
+    resp = qmp_dispatch(QOBJECT(req));
+    assert(resp != NULL);
+    assert(!qdict_haskey(qobject_to_qdict(resp), "error"));
+
+    qobject_decref(resp);
+    QDECREF(req);
+}
+
+/* test commands that return an error due to invalid parameters */
+static void test_dispatch_cmd_error(void)
+{
+    QDict *req = qdict_new();
+    QObject *resp;
+
+    qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd2")));
+
+    resp = qmp_dispatch(QOBJECT(req));
+    assert(resp != NULL);
+    assert(qdict_haskey(qobject_to_qdict(resp), "error"));
+
+    qobject_decref(resp);
+    QDECREF(req);
+}
+
+/* test commands that involve both input parameters and return values */
+static void test_dispatch_cmd_io(void)
+{
+    QDict *req = qdict_new();
+    QDict *args = qdict_new();
+    QDict *ud1a = qdict_new();
+    QDict *ud1b = qdict_new();
+    QObject *resp;
+
+    qdict_put_obj(ud1a, "integer", QOBJECT(qint_from_int(42)));
+    qdict_put_obj(ud1a, "string", QOBJECT(qstring_from_str("hello")));
+    qdict_put_obj(ud1b, "integer", QOBJECT(qint_from_int(422)));
+    qdict_put_obj(ud1b, "string", QOBJECT(qstring_from_str("hello2")));
+    qdict_put_obj(args, "ud1a", QOBJECT(ud1a));
+    qdict_put_obj(args, "ud1b", QOBJECT(ud1b));
+    qdict_put_obj(req, "arguments", QOBJECT(args));
+
+    qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd2")));
+
+    /* TODO: put in full payload and check for errors */
+    resp = qmp_dispatch(QOBJECT(req));
+    assert(resp != NULL);
+    assert(!qdict_haskey(qobject_to_qdict(resp), "error"));
+
+    qobject_decref(resp);
+    QDECREF(req);
+}
+
+/* test generated dealloc functions for generated types */
+static void test_dealloc_types(void)
+{
+    UserDefOne *ud1test, *ud1a, *ud1b;
+    UserDefOneList *ud1list;
+
+    ud1test = g_malloc0(sizeof(UserDefOne));
+    ud1test->integer = 42;
+    ud1test->string = g_strdup("hi there 42");
+
+    qapi_free_UserDefOne(ud1test);
+
+    ud1a = g_malloc0(sizeof(UserDefOne));
+    ud1a->integer = 43;
+    ud1a->string = g_strdup("hi there 43");
+
+    ud1b = g_malloc0(sizeof(UserDefOne));
+    ud1b->integer = 44;
+    ud1b->string = g_strdup("hi there 44");
+
+    ud1list = g_malloc0(sizeof(UserDefOneList));
+    ud1list->value = ud1a;
+    ud1list->next = g_malloc0(sizeof(UserDefOneList));
+    ud1list->next->value = ud1b;
+
+    qapi_free_UserDefOneList(ud1list);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    g_test_add_func("/0.15/dispatch_cmd", test_dispatch_cmd);
+    g_test_add_func("/0.15/dispatch_cmd_error", test_dispatch_cmd_error);
+    g_test_add_func("/0.15/dispatch_cmd_io", test_dispatch_cmd_io);
+    g_test_add_func("/0.15/dealloc_types", test_dealloc_types);
+
+    module_call_init(MODULE_INIT_QAPI);
+    g_test_run();
+
+    return 0;
+}
diff --git a/tests/test-qmp-input-strict.c b/tests/test-qmp-input-strict.c
new file mode 100644
index 0000000..f6df8cb
--- /dev/null
+++ b/tests/test-qmp-input-strict.c
@@ -0,0 +1,234 @@
+/*
+ * QMP Input Visitor unit-tests (strict mode).
+ *
+ * Copyright (C) 2011-2012 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino at redhat.com>
+ *  Paolo Bonzini <pbonzini at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <glib.h>
+#include <stdarg.h>
+
+#include "qapi/qmp-input-visitor.h"
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "qemu-objects.h"
+
+typedef struct TestInputVisitorData {
+    QObject *obj;
+    QmpInputVisitor *qiv;
+} TestInputVisitorData;
+
+static void validate_teardown(TestInputVisitorData *data,
+                               const void *unused)
+{
+    qobject_decref(data->obj);
+    data->obj = NULL;
+
+    if (data->qiv) {
+        qmp_input_visitor_cleanup(data->qiv);
+        data->qiv = NULL;
+    }
+}
+
+/* This is provided instead of a test setup function so that the JSON
+   string used by the tests are kept in the test functions (and not
+   int main()) */
+static GCC_FMT_ATTR(2, 3)
+Visitor *validate_test_init(TestInputVisitorData *data,
+                             const char *json_string, ...)
+{
+    Visitor *v;
+    va_list ap;
+
+    va_start(ap, json_string);
+    data->obj = qobject_from_jsonv(json_string, &ap);
+    va_end(ap);
+
+    g_assert(data->obj != NULL);
+
+    data->qiv = qmp_input_visitor_new_strict(data->obj);
+    g_assert(data->qiv != NULL);
+
+    v = qmp_input_get_visitor(data->qiv);
+    g_assert(v != NULL);
+
+    return v;
+}
+
+typedef struct TestStruct
+{
+    int64_t integer;
+    bool boolean;
+    char *string;
+} TestStruct;
+
+static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
+                                  const char *name, Error **errp)
+{
+    visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
+                       errp);
+
+    visit_type_int(v, &(*obj)->integer, "integer", errp);
+    visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
+    visit_type_str(v, &(*obj)->string, "string", errp);
+
+    visit_end_struct(v, errp);
+}
+
+static void test_validate_struct(TestInputVisitorData *data,
+                                  const void *unused)
+{
+    TestStruct *p = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
+
+    visit_type_TestStruct(v, &p, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_free(p->string);
+    g_free(p);
+}
+
+static void test_validate_struct_nested(TestInputVisitorData *data,
+                                         const void *unused)
+{
+    UserDefNested *udp = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string' }, 'string2': 'string2'}}}");
+
+    visit_type_UserDefNested(v, &udp, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    qapi_free_UserDefNested(udp);
+}
+
+static void test_validate_list(TestInputVisitorData *data,
+                                const void *unused)
+{
+    UserDefOneList *head = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
+
+    visit_type_UserDefOneList(v, &head, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    qapi_free_UserDefOneList(head);
+}
+
+static void test_validate_union(TestInputVisitorData *data,
+                                 const void *unused)
+{
+    UserDefUnion *tmp = NULL;
+    Visitor *v;
+    Error *errp = NULL;
+
+    v = validate_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 } }");
+
+    visit_type_UserDefUnion(v, &tmp, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    qapi_free_UserDefUnion(tmp);
+}
+
+static void test_validate_fail_struct(TestInputVisitorData *data,
+                                       const void *unused)
+{
+    TestStruct *p = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo', 'extra': 42 }");
+
+    visit_type_TestStruct(v, &p, NULL, &errp);
+    g_assert(error_is_set(&errp));
+    if (p) {
+        g_free(p->string);
+    }
+    g_free(p);
+}
+
+static void test_validate_fail_struct_nested(TestInputVisitorData *data,
+                                              const void *unused)
+{
+    UserDefNested *udp = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string', 'extra': [42, 23, {'foo':'bar'}] }, 'string2': 'string2'}}}");
+
+    visit_type_UserDefNested(v, &udp, NULL, &errp);
+    g_assert(error_is_set(&errp));
+    qapi_free_UserDefNested(udp);
+}
+
+static void test_validate_fail_list(TestInputVisitorData *data,
+                                     const void *unused)
+{
+    UserDefOneList *head = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44, 'extra': 'ggg' } ]");
+
+    visit_type_UserDefOneList(v, &head, NULL, &errp);
+    g_assert(error_is_set(&errp));
+    qapi_free_UserDefOneList(head);
+}
+
+static void test_validate_fail_union(TestInputVisitorData *data,
+                                      const void *unused)
+{
+    UserDefUnion *tmp = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 }, 'extra': 'yyy' }");
+
+    visit_type_UserDefUnion(v, &tmp, NULL, &errp);
+    g_assert(error_is_set(&errp));
+    qapi_free_UserDefUnion(tmp);
+}
+
+static void validate_test_add(const char *testpath,
+                               TestInputVisitorData *data,
+                               void (*test_func)(TestInputVisitorData *data, const void *user_data))
+{
+    g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
+               validate_teardown);
+}
+
+int main(int argc, char **argv)
+{
+    TestInputVisitorData testdata;
+
+    g_test_init(&argc, &argv, NULL);
+
+    validate_test_add("/visitor/input-strict/pass/struct",
+                       &testdata, test_validate_struct);
+    validate_test_add("/visitor/input-strict/pass/struct-nested",
+                       &testdata, test_validate_struct_nested);
+    validate_test_add("/visitor/input-strict/pass/list",
+                       &testdata, test_validate_list);
+    validate_test_add("/visitor/input-strict/pass/union",
+                       &testdata, test_validate_union);
+    validate_test_add("/visitor/input-strict/fail/struct",
+                       &testdata, test_validate_fail_struct);
+    validate_test_add("/visitor/input-strict/fail/struct-nested",
+                       &testdata, test_validate_fail_struct_nested);
+    validate_test_add("/visitor/input-strict/fail/list",
+                       &testdata, test_validate_fail_list);
+    validate_test_add("/visitor/input-strict/fail/union",
+                       &testdata, test_validate_fail_union);
+
+    g_test_run();
+
+    return 0;
+}
diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c
new file mode 100644
index 0000000..c30fdc4
--- /dev/null
+++ b/tests/test-qmp-input-visitor.c
@@ -0,0 +1,308 @@
+/*
+ * QMP Input Visitor unit-tests.
+ *
+ * Copyright (C) 2011 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <glib.h>
+#include <stdarg.h>
+
+#include "qapi/qmp-input-visitor.h"
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "qemu-objects.h"
+
+typedef struct TestInputVisitorData {
+    QObject *obj;
+    QmpInputVisitor *qiv;
+} TestInputVisitorData;
+
+static void visitor_input_teardown(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    qobject_decref(data->obj);
+    data->obj = NULL;
+
+    if (data->qiv) {
+        qmp_input_visitor_cleanup(data->qiv);
+        data->qiv = NULL;
+    }
+}
+
+/* This is provided instead of a test setup function so that the JSON
+   string used by the tests are kept in the test functions (and not
+   int main()) */
+static GCC_FMT_ATTR(2, 3)
+Visitor *visitor_input_test_init(TestInputVisitorData *data,
+                                 const char *json_string, ...)
+{
+    Visitor *v;
+    va_list ap;
+
+    va_start(ap, json_string);
+    data->obj = qobject_from_jsonv(json_string, &ap);
+    va_end(ap);
+
+    g_assert(data->obj != NULL);
+
+    data->qiv = qmp_input_visitor_new(data->obj);
+    g_assert(data->qiv != NULL);
+
+    v = qmp_input_get_visitor(data->qiv);
+    g_assert(v != NULL);
+
+    return v;
+}
+
+static void test_visitor_in_int(TestInputVisitorData *data,
+                                const void *unused)
+{
+    int64_t res = 0, value = -42;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "%" PRId64, value);
+
+    visit_type_int(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(res, ==, value);
+}
+
+static void test_visitor_in_bool(TestInputVisitorData *data,
+                                 const void *unused)
+{
+    Error *errp = NULL;
+    bool res = false;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "true");
+
+    visit_type_bool(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(res, ==, true);
+}
+
+static void test_visitor_in_number(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    double res = 0, value = 3.14;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "%f", value);
+
+    visit_type_number(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpfloat(res, ==, value);
+}
+
+static void test_visitor_in_string(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    char *res = NULL, *value = (char *) "Q E M U";
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "%s", value);
+
+    visit_type_str(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpstr(res, ==, value);
+
+    g_free(res);
+}
+
+static void test_visitor_in_enum(TestInputVisitorData *data,
+                                 const void *unused)
+{
+    Error *errp = NULL;
+    Visitor *v;
+    EnumOne i;
+
+    for (i = 0; EnumOne_lookup[i]; i++) {
+        EnumOne res = -1;
+
+        v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);
+
+        visit_type_EnumOne(v, &res, NULL, &errp);
+        g_assert(!error_is_set(&errp));
+        g_assert_cmpint(i, ==, res);
+
+        visitor_input_teardown(data, NULL);
+    }
+
+    data->obj = NULL;
+    data->qiv = NULL;
+}
+
+typedef struct TestStruct
+{
+    int64_t integer;
+    bool boolean;
+    char *string;
+} TestStruct;
+
+static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
+                                  const char *name, Error **errp)
+{
+    visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
+                       errp);
+
+    visit_type_int(v, &(*obj)->integer, "integer", errp);
+    visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
+    visit_type_str(v, &(*obj)->string, "string", errp);
+
+    visit_end_struct(v, errp);
+}
+
+static void test_visitor_in_struct(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    TestStruct *p = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
+
+    visit_type_TestStruct(v, &p, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(p->integer, ==, -42);
+    g_assert(p->boolean == true);
+    g_assert_cmpstr(p->string, ==, "foo");
+
+    g_free(p->string);
+    g_free(p);
+}
+
+static void check_and_free_str(char *str, const char *cmp)
+{
+    g_assert_cmpstr(str, ==, cmp);
+    g_free(str);
+}
+
+static void test_visitor_in_struct_nested(TestInputVisitorData *data,
+                                          const void *unused)
+{
+    UserDefNested *udp = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string' }, 'string2': 'string2'}}}");
+
+    visit_type_UserDefNested(v, &udp, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+
+    check_and_free_str(udp->string0, "string0");
+    check_and_free_str(udp->dict1.string1, "string1");
+    g_assert_cmpint(udp->dict1.dict2.userdef1->integer, ==, 42);
+    check_and_free_str(udp->dict1.dict2.userdef1->string, "string");
+    check_and_free_str(udp->dict1.dict2.string2, "string2");
+    g_assert(udp->dict1.has_dict3 == false);
+
+    g_free(udp->dict1.dict2.userdef1);
+    g_free(udp);
+}
+
+static void test_visitor_in_list(TestInputVisitorData *data,
+                                 const void *unused)
+{
+    UserDefOneList *item, *head = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+    int i;
+
+    v = visitor_input_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
+
+    visit_type_UserDefOneList(v, &head, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert(head != NULL);
+
+    for (i = 0, item = head; item; item = item->next, i++) {
+        char string[12];
+
+        snprintf(string, sizeof(string), "string%d", i);
+        g_assert_cmpstr(item->value->string, ==, string);
+        g_assert_cmpint(item->value->integer, ==, 42 + i);
+    }
+
+    qapi_free_UserDefOneList(head);
+}
+
+static void test_visitor_in_union(TestInputVisitorData *data,
+                                  const void *unused)
+{
+    Visitor *v;
+    Error *err = NULL;
+    UserDefUnion *tmp;
+
+    v = visitor_input_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 } }");
+
+    visit_type_UserDefUnion(v, &tmp, NULL, &err);
+    g_assert(err == NULL);
+    g_assert_cmpint(tmp->kind, ==, USER_DEF_UNION_KIND_B);
+    g_assert_cmpint(tmp->b->integer, ==, 42);
+    qapi_free_UserDefUnion(tmp);
+}
+
+static void input_visitor_test_add(const char *testpath,
+                                   TestInputVisitorData *data,
+                                   void (*test_func)(TestInputVisitorData *data, const void *user_data))
+{
+    g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
+               visitor_input_teardown);
+}
+
+static void test_visitor_in_errors(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    TestStruct *p = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', 'string': -42 }");
+
+    visit_type_TestStruct(v, &p, NULL, &errp);
+    g_assert(error_is_set(&errp));
+    g_assert(p->string == NULL);
+
+    g_free(p->string);
+    g_free(p);
+}
+
+int main(int argc, char **argv)
+{
+    TestInputVisitorData in_visitor_data;
+
+    g_test_init(&argc, &argv, NULL);
+
+    input_visitor_test_add("/visitor/input/int",
+                           &in_visitor_data, test_visitor_in_int);
+    input_visitor_test_add("/visitor/input/bool",
+                           &in_visitor_data, test_visitor_in_bool);
+    input_visitor_test_add("/visitor/input/number",
+                           &in_visitor_data, test_visitor_in_number);
+    input_visitor_test_add("/visitor/input/string",
+                            &in_visitor_data, test_visitor_in_string);
+    input_visitor_test_add("/visitor/input/enum",
+                            &in_visitor_data, test_visitor_in_enum);
+    input_visitor_test_add("/visitor/input/struct",
+                            &in_visitor_data, test_visitor_in_struct);
+    input_visitor_test_add("/visitor/input/struct-nested",
+                            &in_visitor_data, test_visitor_in_struct_nested);
+    input_visitor_test_add("/visitor/input/list",
+                            &in_visitor_data, test_visitor_in_list);
+    input_visitor_test_add("/visitor/input/union",
+                            &in_visitor_data, test_visitor_in_union);
+    input_visitor_test_add("/visitor/input/errors",
+                            &in_visitor_data, test_visitor_in_errors);
+
+    g_test_run();
+
+    return 0;
+}
diff --git a/tests/test-qmp-output-visitor.c b/tests/test-qmp-output-visitor.c
new file mode 100644
index 0000000..24a6359
--- /dev/null
+++ b/tests/test-qmp-output-visitor.c
@@ -0,0 +1,477 @@
+/*
+ * QMP Output Visitor unit-tests.
+ *
+ * Copyright (C) 2011 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <glib.h>
+
+#include "qapi/qmp-output-visitor.h"
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "qemu-objects.h"
+
+typedef struct TestOutputVisitorData {
+    QmpOutputVisitor *qov;
+    Visitor *ov;
+} TestOutputVisitorData;
+
+static void visitor_output_setup(TestOutputVisitorData *data,
+                                 const void *unused)
+{
+    data->qov = qmp_output_visitor_new();
+    g_assert(data->qov != NULL);
+
+    data->ov = qmp_output_get_visitor(data->qov);
+    g_assert(data->ov != NULL);
+}
+
+static void visitor_output_teardown(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    qmp_output_visitor_cleanup(data->qov);
+    data->qov = NULL;
+    data->ov = NULL;
+}
+
+static void test_visitor_out_int(TestOutputVisitorData *data,
+                                 const void *unused)
+{
+    int64_t value = -42;
+    Error *errp = NULL;
+    QObject *obj;
+
+    visit_type_int(data->ov, &value, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QINT);
+    g_assert_cmpint(qint_get_int(qobject_to_qint(obj)), ==, value);
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_bool(TestOutputVisitorData *data,
+                                  const void *unused)
+{
+    Error *errp = NULL;
+    bool value = true;
+    QObject *obj;
+
+    visit_type_bool(data->ov, &value, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QBOOL);
+    g_assert(qbool_get_int(qobject_to_qbool(obj)) == value);
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_number(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    double value = 3.14;
+    Error *errp = NULL;
+    QObject *obj;
+
+    visit_type_number(data->ov, &value, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QFLOAT);
+    g_assert(qfloat_get_double(qobject_to_qfloat(obj)) == value);
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_string(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    char *string = (char *) "Q E M U";
+    Error *errp = NULL;
+    QObject *obj;
+
+    visit_type_str(data->ov, &string, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QSTRING);
+    g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, string);
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_no_string(TestOutputVisitorData *data,
+                                       const void *unused)
+{
+    char *string = NULL;
+    Error *errp = NULL;
+    QObject *obj;
+
+    /* A null string should return "" */
+    visit_type_str(data->ov, &string, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QSTRING);
+    g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, "");
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_enum(TestOutputVisitorData *data,
+                                  const void *unused)
+{
+    Error *errp = NULL;
+    QObject *obj;
+    EnumOne i;
+
+    for (i = 0; i < ENUM_ONE_MAX; i++) {
+        visit_type_EnumOne(data->ov, &i, "unused", &errp);
+        g_assert(!error_is_set(&errp));
+
+        obj = qmp_output_get_qobject(data->qov);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QSTRING);
+        g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==,
+                        EnumOne_lookup[i]);
+        qobject_decref(obj);
+    }
+}
+
+static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
+                                         const void *unused)
+{
+    EnumOne i, bad_values[] = { ENUM_ONE_MAX, -1 };
+    Error *errp;
+
+    for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
+        errp = NULL;
+        visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp);
+        g_assert(error_is_set(&errp) == true);
+        error_free(errp);
+    }
+}
+
+typedef struct TestStruct
+{
+    int64_t integer;
+    bool boolean;
+    char *string;
+} TestStruct;
+
+static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
+                                  const char *name, Error **errp)
+{
+    visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
+                       errp);
+
+    visit_type_int(v, &(*obj)->integer, "integer", errp);
+    visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
+    visit_type_str(v, &(*obj)->string, "string", errp);
+
+    visit_end_struct(v, errp);
+}
+
+static void test_visitor_out_struct(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    TestStruct test_struct = { .integer = 42,
+                               .boolean = false,
+                               .string = (char *) "foo"};
+    TestStruct *p = &test_struct;
+    Error *errp = NULL;
+    QObject *obj;
+    QDict *qdict;
+
+    visit_type_TestStruct(data->ov, &p, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QDICT);
+
+    qdict = qobject_to_qdict(obj);
+    g_assert_cmpint(qdict_size(qdict), ==, 3);
+    g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 42);
+    g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, 0);
+    g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "foo");
+
+    QDECREF(qdict);
+}
+
+static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
+                                           const void *unused)
+{
+    int64_t value = 42;
+    Error *errp = NULL;
+    UserDefNested *ud2;
+    QObject *obj;
+    QDict *qdict, *dict1, *dict2, *dict3, *userdef;
+    const char *string = "user def string";
+    const char *strings[] = { "forty two", "forty three", "forty four",
+                              "forty five" };
+
+    ud2 = g_malloc0(sizeof(*ud2));
+    ud2->string0 = g_strdup(strings[0]);
+
+    ud2->dict1.string1 = g_strdup(strings[1]);
+    ud2->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
+    ud2->dict1.dict2.userdef1->string = g_strdup(string);
+    ud2->dict1.dict2.userdef1->integer = value;
+    ud2->dict1.dict2.string2 = g_strdup(strings[2]);
+
+    ud2->dict1.has_dict3 = true;
+    ud2->dict1.dict3.userdef2 = g_malloc0(sizeof(UserDefOne));
+    ud2->dict1.dict3.userdef2->string = g_strdup(string);
+    ud2->dict1.dict3.userdef2->integer = value;
+    ud2->dict1.dict3.string3 = g_strdup(strings[3]);
+
+    visit_type_UserDefNested(data->ov, &ud2, "unused", &errp);
+    g_assert(!error_is_set(&errp));
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QDICT);
+
+    qdict = qobject_to_qdict(obj);
+    g_assert_cmpint(qdict_size(qdict), ==, 2);
+    g_assert_cmpstr(qdict_get_str(qdict, "string0"), ==, strings[0]);
+
+    dict1 = qdict_get_qdict(qdict, "dict1");
+    g_assert_cmpint(qdict_size(dict1), ==, 3);
+    g_assert_cmpstr(qdict_get_str(dict1, "string1"), ==, strings[1]);
+
+    dict2 = qdict_get_qdict(dict1, "dict2");
+    g_assert_cmpint(qdict_size(dict2), ==, 2);
+    g_assert_cmpstr(qdict_get_str(dict2, "string2"), ==, strings[2]);
+    userdef = qdict_get_qdict(dict2, "userdef1");
+    g_assert_cmpint(qdict_size(userdef), ==, 2);
+    g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
+    g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
+
+    dict3 = qdict_get_qdict(dict1, "dict3");
+    g_assert_cmpint(qdict_size(dict3), ==, 2);
+    g_assert_cmpstr(qdict_get_str(dict3, "string3"), ==, strings[3]);
+    userdef = qdict_get_qdict(dict3, "userdef2");
+    g_assert_cmpint(qdict_size(userdef), ==, 2);
+    g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
+    g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
+
+    QDECREF(qdict);
+    qapi_free_UserDefNested(ud2);
+}
+
+static void test_visitor_out_struct_errors(TestOutputVisitorData *data,
+                                           const void *unused)
+{
+    EnumOne bad_values[] = { ENUM_ONE_MAX, -1 };
+    UserDefOne u = { 0 }, *pu = &u;
+    Error *errp;
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
+        errp = NULL;
+        u.has_enum1 = true;
+        u.enum1 = bad_values[i];
+        visit_type_UserDefOne(data->ov, &pu, "unused", &errp);
+        g_assert(error_is_set(&errp) == true);
+        error_free(errp);
+    }
+}
+
+typedef struct TestStructList
+{
+    TestStruct *value;
+    struct TestStructList *next;
+} TestStructList;
+
+static void visit_type_TestStructList(Visitor *v, TestStructList **obj,
+                                      const char *name, Error **errp)
+{
+    GenericList *i, **head = (GenericList **)obj;
+
+    visit_start_list(v, name, errp);
+
+    for (*head = i = visit_next_list(v, head, errp); i; i = visit_next_list(v, &i, errp)) {
+        TestStructList *native_i = (TestStructList *)i;
+        visit_type_TestStruct(v, &native_i->value, NULL, errp);
+    }
+
+    visit_end_list(v, errp);
+}
+
+static void test_visitor_out_list(TestOutputVisitorData *data,
+                                  const void *unused)
+{
+    char *value_str = (char *) "list value";
+    TestStructList *p, *head = NULL;
+    const int max_items = 10;
+    bool value_bool = true;
+    int value_int = 10;
+    Error *errp = NULL;
+    QListEntry *entry;
+    QObject *obj;
+    QList *qlist;
+    int i;
+
+    for (i = 0; i < max_items; i++) {
+        p = g_malloc0(sizeof(*p));
+        p->value = g_malloc0(sizeof(*p->value));
+        p->value->integer = value_int;
+        p->value->boolean = value_bool;
+        p->value->string = value_str;
+
+        p->next = head;
+        head = p;
+    }
+
+    visit_type_TestStructList(data->ov, &head, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QLIST);
+
+    qlist = qobject_to_qlist(obj);
+    g_assert(!qlist_empty(qlist));
+
+    i = 0;
+    QLIST_FOREACH_ENTRY(qlist, entry) {
+        QDict *qdict;
+
+        g_assert(qobject_type(entry->value) == QTYPE_QDICT);
+        qdict = qobject_to_qdict(entry->value);
+        g_assert_cmpint(qdict_size(qdict), ==, 3);
+        g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, value_int);
+        g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, value_bool);
+        g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, value_str);
+        i++;
+    }
+    g_assert_cmpint(i, ==, max_items);
+
+    QDECREF(qlist);
+
+    for (p = head; p;) {
+        TestStructList *tmp = p->next;
+        g_free(p->value);
+        g_free(p);
+        p = tmp;
+    }
+}
+
+static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
+                                            const void *unused)
+{
+    UserDefNestedList *p, *head = NULL;
+    const char string[] = "foo bar";
+    int i, max_count = 1024;
+
+    for (i = 0; i < max_count; i++) {
+        p = g_malloc0(sizeof(*p));
+        p->value = g_malloc0(sizeof(*p->value));
+
+        p->value->string0 = g_strdup(string);
+        p->value->dict1.string1 = g_strdup(string);
+        p->value->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
+        p->value->dict1.dict2.userdef1->string = g_strdup(string);
+        p->value->dict1.dict2.userdef1->integer = 42;
+        p->value->dict1.dict2.string2 = g_strdup(string);
+        p->value->dict1.has_dict3 = false;
+
+        p->next = head;
+        head = p;
+    }
+
+    qapi_free_UserDefNestedList(head);
+}
+
+static void test_visitor_out_union(TestOutputVisitorData *data,
+                                   const void *unused)
+{
+    QObject *arg, *qvalue;
+    QDict *qdict, *value;
+
+    Error *err = NULL;
+
+    UserDefUnion *tmp = g_malloc0(sizeof(UserDefUnion));
+    tmp->kind = USER_DEF_UNION_KIND_A;
+    tmp->a = g_malloc0(sizeof(UserDefA));
+    tmp->a->boolean = true;
+
+    visit_type_UserDefUnion(data->ov, &tmp, NULL, &err);
+    g_assert(err == NULL);
+    arg = qmp_output_get_qobject(data->qov);
+
+    g_assert(qobject_type(arg) == QTYPE_QDICT);
+    qdict = qobject_to_qdict(arg);
+
+    g_assert_cmpstr(qdict_get_str(qdict, "type"), ==, "a");
+
+    qvalue = qdict_get(qdict, "data");
+    g_assert(data != NULL);
+    g_assert(qobject_type(qvalue) == QTYPE_QDICT);
+    value = qobject_to_qdict(qvalue);
+    g_assert_cmpint(qdict_get_bool(value, "boolean"), ==, true);
+
+    qapi_free_UserDefUnion(tmp);
+    QDECREF(qdict);
+}
+
+static void output_visitor_test_add(const char *testpath,
+                                    TestOutputVisitorData *data,
+                                    void (*test_func)(TestOutputVisitorData *data, const void *user_data))
+{
+    g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup,
+               test_func, visitor_output_teardown);
+}
+
+int main(int argc, char **argv)
+{
+    TestOutputVisitorData out_visitor_data;
+
+    g_test_init(&argc, &argv, NULL);
+
+    output_visitor_test_add("/visitor/output/int",
+                            &out_visitor_data, test_visitor_out_int);
+    output_visitor_test_add("/visitor/output/bool",
+                            &out_visitor_data, test_visitor_out_bool);
+    output_visitor_test_add("/visitor/output/number",
+                            &out_visitor_data, test_visitor_out_number);
+    output_visitor_test_add("/visitor/output/string",
+                            &out_visitor_data, test_visitor_out_string);
+    output_visitor_test_add("/visitor/output/no-string",
+                            &out_visitor_data, test_visitor_out_no_string);
+    output_visitor_test_add("/visitor/output/enum",
+                            &out_visitor_data, test_visitor_out_enum);
+    output_visitor_test_add("/visitor/output/enum-errors",
+                            &out_visitor_data, test_visitor_out_enum_errors);
+    output_visitor_test_add("/visitor/output/struct",
+                            &out_visitor_data, test_visitor_out_struct);
+    output_visitor_test_add("/visitor/output/struct-nested",
+                            &out_visitor_data, test_visitor_out_struct_nested);
+    output_visitor_test_add("/visitor/output/struct-errors",
+                            &out_visitor_data, test_visitor_out_struct_errors);
+    output_visitor_test_add("/visitor/output/list",
+                            &out_visitor_data, test_visitor_out_list);
+    output_visitor_test_add("/visitor/output/list-qapi-free",
+                            &out_visitor_data, test_visitor_out_list_qapi_free);
+    output_visitor_test_add("/visitor/output/union",
+                            &out_visitor_data, test_visitor_out_union);
+
+    g_test_run();
+
+    return 0;
+}
diff --git a/tests/test-string-input-visitor.c b/tests/test-string-input-visitor.c
new file mode 100644
index 0000000..5370e32
--- /dev/null
+++ b/tests/test-string-input-visitor.c
@@ -0,0 +1,195 @@
+/*
+ * String Input Visitor unit-tests.
+ *
+ * Copyright (C) 2012 Red Hat Inc.
+ *
+ * Authors:
+ *  Paolo Bonzini <pbonzini at redhat.com> (based on test-qmp-input-visitor)
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <glib.h>
+#include <stdarg.h>
+
+#include "qapi/string-input-visitor.h"
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "qemu-objects.h"
+
+typedef struct TestInputVisitorData {
+    StringInputVisitor *siv;
+} TestInputVisitorData;
+
+static void visitor_input_teardown(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    if (data->siv) {
+        string_input_visitor_cleanup(data->siv);
+        data->siv = NULL;
+    }
+}
+
+/* This is provided instead of a test setup function so that the JSON
+   string used by the tests are kept in the test functions (and not
+   int main()) */
+static
+Visitor *visitor_input_test_init(TestInputVisitorData *data,
+                                 const char *string)
+{
+    Visitor *v;
+
+    data->siv = string_input_visitor_new(string);
+    g_assert(data->siv != NULL);
+
+    v = string_input_get_visitor(data->siv);
+    g_assert(v != NULL);
+
+    return v;
+}
+
+static void test_visitor_in_int(TestInputVisitorData *data,
+                                const void *unused)
+{
+    int64_t res = 0, value = -42;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "-42");
+
+    visit_type_int(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(res, ==, value);
+}
+
+static void test_visitor_in_bool(TestInputVisitorData *data,
+                                 const void *unused)
+{
+    Error *errp = NULL;
+    bool res = false;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "true");
+
+    visit_type_bool(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(res, ==, true);
+    visitor_input_teardown(data, unused);
+
+    v = visitor_input_test_init(data, "yes");
+
+    visit_type_bool(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(res, ==, true);
+    visitor_input_teardown(data, unused);
+
+    v = visitor_input_test_init(data, "on");
+
+    visit_type_bool(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(res, ==, true);
+    visitor_input_teardown(data, unused);
+
+    v = visitor_input_test_init(data, "false");
+
+    visit_type_bool(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(res, ==, false);
+    visitor_input_teardown(data, unused);
+
+    v = visitor_input_test_init(data, "no");
+
+    visit_type_bool(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(res, ==, false);
+    visitor_input_teardown(data, unused);
+
+    v = visitor_input_test_init(data, "off");
+
+    visit_type_bool(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(res, ==, false);
+}
+
+static void test_visitor_in_number(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    double res = 0, value = 3.14;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "3.14");
+
+    visit_type_number(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpfloat(res, ==, value);
+}
+
+static void test_visitor_in_string(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    char *res = NULL, *value = (char *) "Q E M U";
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, value);
+
+    visit_type_str(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpstr(res, ==, value);
+
+    g_free(res);
+}
+
+static void test_visitor_in_enum(TestInputVisitorData *data,
+                                 const void *unused)
+{
+    Error *errp = NULL;
+    Visitor *v;
+    EnumOne i;
+
+    for (i = 0; EnumOne_lookup[i]; i++) {
+        EnumOne res = -1;
+
+        v = visitor_input_test_init(data, EnumOne_lookup[i]);
+
+        visit_type_EnumOne(v, &res, NULL, &errp);
+        g_assert(!error_is_set(&errp));
+        g_assert_cmpint(i, ==, res);
+
+        visitor_input_teardown(data, NULL);
+    }
+
+    data->siv = NULL;
+}
+
+static void input_visitor_test_add(const char *testpath,
+                                   TestInputVisitorData *data,
+                                   void (*test_func)(TestInputVisitorData *data, const void *user_data))
+{
+    g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
+               visitor_input_teardown);
+}
+
+int main(int argc, char **argv)
+{
+    TestInputVisitorData in_visitor_data;
+
+    g_test_init(&argc, &argv, NULL);
+
+    input_visitor_test_add("/string-visitor/input/int",
+                           &in_visitor_data, test_visitor_in_int);
+    input_visitor_test_add("/string-visitor/input/bool",
+                           &in_visitor_data, test_visitor_in_bool);
+    input_visitor_test_add("/string-visitor/input/number",
+                           &in_visitor_data, test_visitor_in_number);
+    input_visitor_test_add("/string-visitor/input/string",
+                            &in_visitor_data, test_visitor_in_string);
+    input_visitor_test_add("/string-visitor/input/enum",
+                            &in_visitor_data, test_visitor_in_enum);
+
+    g_test_run();
+
+    return 0;
+}
diff --git a/tests/test-string-output-visitor.c b/tests/test-string-output-visitor.c
new file mode 100644
index 0000000..22909b8
--- /dev/null
+++ b/tests/test-string-output-visitor.c
@@ -0,0 +1,188 @@
+/*
+ * String Output Visitor unit-tests.
+ *
+ * Copyright (C) 2012 Red Hat Inc.
+ *
+ * Authors:
+ *  Paolo Bonzini <pbonzini at redhat.com> (based on test-qmp-output-visitor)
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <glib.h>
+
+#include "qapi/string-output-visitor.h"
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "qemu-objects.h"
+
+typedef struct TestOutputVisitorData {
+    StringOutputVisitor *sov;
+    Visitor *ov;
+} TestOutputVisitorData;
+
+static void visitor_output_setup(TestOutputVisitorData *data,
+                                 const void *unused)
+{
+    data->sov = string_output_visitor_new();
+    g_assert(data->sov != NULL);
+
+    data->ov = string_output_get_visitor(data->sov);
+    g_assert(data->ov != NULL);
+}
+
+static void visitor_output_teardown(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    string_output_visitor_cleanup(data->sov);
+    data->sov = NULL;
+    data->ov = NULL;
+}
+
+static void test_visitor_out_int(TestOutputVisitorData *data,
+                                 const void *unused)
+{
+    int64_t value = -42;
+    Error *errp = NULL;
+    char *str;
+
+    visit_type_int(data->ov, &value, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    str = string_output_get_string(data->sov);
+    g_assert(str != NULL);
+    g_assert_cmpstr(str, ==, "-42");
+    g_free(str);
+}
+
+static void test_visitor_out_bool(TestOutputVisitorData *data,
+                                  const void *unused)
+{
+    Error *errp = NULL;
+    bool value = true;
+    char *str;
+
+    visit_type_bool(data->ov, &value, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    str = string_output_get_string(data->sov);
+    g_assert(str != NULL);
+    g_assert_cmpstr(str, ==, "true");
+    g_free(str);
+}
+
+static void test_visitor_out_number(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    double value = 3.14;
+    Error *errp = NULL;
+    char *str;
+
+    visit_type_number(data->ov, &value, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    str = string_output_get_string(data->sov);
+    g_assert(str != NULL);
+    g_assert_cmpstr(str, ==, "3.14");
+    g_free(str);
+}
+
+static void test_visitor_out_string(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    char *string = (char *) "Q E M U";
+    Error *errp = NULL;
+    char *str;
+
+    visit_type_str(data->ov, &string, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    str = string_output_get_string(data->sov);
+    g_assert(str != NULL);
+    g_assert_cmpstr(str, ==, string);
+    g_free(str);
+}
+
+static void test_visitor_out_no_string(TestOutputVisitorData *data,
+                                       const void *unused)
+{
+    char *string = NULL;
+    Error *errp = NULL;
+    char *str;
+
+    /* A null string should return "" */
+    visit_type_str(data->ov, &string, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    str = string_output_get_string(data->sov);
+    g_assert(str != NULL);
+    g_assert_cmpstr(str, ==, "");
+    g_free(str);
+}
+
+static void test_visitor_out_enum(TestOutputVisitorData *data,
+                                  const void *unused)
+{
+    Error *errp = NULL;
+    char *str;
+    EnumOne i;
+
+    for (i = 0; i < ENUM_ONE_MAX; i++) {
+        visit_type_EnumOne(data->ov, &i, "unused", &errp);
+        g_assert(!error_is_set(&errp));
+
+        str = string_output_get_string(data->sov);
+        g_assert(str != NULL);
+        g_assert_cmpstr(str, ==, EnumOne_lookup[i]);
+	g_free(str);
+    }
+}
+
+static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
+                                         const void *unused)
+{
+    EnumOne i, bad_values[] = { ENUM_ONE_MAX, -1 };
+    Error *errp;
+
+    for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
+        errp = NULL;
+        visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp);
+        g_assert(error_is_set(&errp) == true);
+        error_free(errp);
+    }
+}
+
+static void output_visitor_test_add(const char *testpath,
+                                    TestOutputVisitorData *data,
+                                    void (*test_func)(TestOutputVisitorData *data, const void *user_data))
+{
+    g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup,
+               test_func, visitor_output_teardown);
+}
+
+int main(int argc, char **argv)
+{
+    TestOutputVisitorData out_visitor_data;
+
+    g_test_init(&argc, &argv, NULL);
+
+    output_visitor_test_add("/string-visitor/output/int",
+                            &out_visitor_data, test_visitor_out_int);
+    output_visitor_test_add("/string-visitor/output/bool",
+                            &out_visitor_data, test_visitor_out_bool);
+    output_visitor_test_add("/string-visitor/output/number",
+                            &out_visitor_data, test_visitor_out_number);
+    output_visitor_test_add("/string-visitor/output/string",
+                            &out_visitor_data, test_visitor_out_string);
+    output_visitor_test_add("/string-visitor/output/no-string",
+                            &out_visitor_data, test_visitor_out_no_string);
+    output_visitor_test_add("/string-visitor/output/enum",
+                            &out_visitor_data, test_visitor_out_enum);
+    output_visitor_test_add("/string-visitor/output/enum-errors",
+                            &out_visitor_data, test_visitor_out_enum_errors);
+
+    g_test_run();
+
+    return 0;
+}
commit 703e01e6e249e6d0a74e0cbab827b235032ec7f3
Author: Alon Levy <alevy at redhat.com>
Date:   Thu Mar 29 23:35:36 2012 +0200

    tracetool: dtrace: handle in and next reserved words
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/scripts/tracetool b/scripts/tracetool
index a279c2c..5e77aa2 100755
--- a/scripts/tracetool
+++ b/scripts/tracetool
@@ -506,10 +506,12 @@ EOF
     i=1
     for arg in $arglist
     do
-        # 'limit' is a reserved keyword
-        if [ "$arg" = "limit" ]; then
-          arg="_limit"
-        fi
+        # postfix reserved words with '_'
+        case "$arg" in
+            limit|in|next|self)
+                arg="${arg}_"
+                ;;
+        esac
         cat <<EOF
   $arg = \$arg$i;
 EOF
commit 60be795f0b9ca06030b942367a82d80f125a50f7
Author: Lee Essen <lee.essen at nowonline.co.uk>
Date:   Tue Mar 20 17:02:40 2012 +0000

    tracetool: dtrace disabled-events fix
    
    If there are "disabled" entries in the trace-events file then
    linetod_nop() is called if the backend is dtrace, it's currently
    not present. Also equivalent fix for stap.
    
    Signed-off-by: Lee Essen <lee.essen at nowonline.co.uk>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/scripts/tracetool b/scripts/tracetool
index 65bd0a1..a279c2c 100755
--- a/scripts/tracetool
+++ b/scripts/tracetool
@@ -161,6 +161,18 @@ linetoc_nop()
     return
 }
 
+linetod_nop()
+{
+    # Used when "disabled" events are processed
+    return
+}
+
+linetostap_nop()
+{
+    # Used when "disabled" events are processed
+    return
+}
+
 linetoc_end_nop()
 {
     return
commit 2174e2380fcf853977a73be935b369218671a9a6
Author: Alon Levy <alevy at redhat.com>
Date:   Sun Mar 18 08:47:15 2012 +0100

    Makefile.target: code stp dependency on trace-events
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/Makefile.target b/Makefile.target
index 44b2e83..9f3c100 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -58,7 +58,7 @@ else
 TARGET_TYPE=system
 endif
 
-$(QEMU_PROG).stp:
+$(QEMU_PROG).stp: $(SRC_PATH)/trace-events
 	$(call quiet-command,sh $(SRC_PATH)/scripts/tracetool \
 		--$(TRACE_BACKEND) \
 		--binary $(bindir)/$(QEMU_PROG) \
commit b0f26631bc51790069b0c0b3935b20f9a54e3ab3
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Mar 30 10:31:23 2012 +0000

    pl031: switch clock base to rtc_clock
    
    This lets the user specify the desired semantics.  By default, the RTC
    will follow adjustments from the host's NTP client, and will remain in
    sync when the virtual machine is stopped.  The previous behavior, which
    provides determinism with both icount and qtest, remains available with
    "-rtc clock=vm".
    
    pl031 supports migration, so we need to convert the time base from
    rtc_clock to vm_clock and back for backwards compatibility.  (The
    rtc_clock may not be synchronized on the two machines, especially with
    savevm/loadvm, so the conversion is needed anyway.  And since any time
    base will do, why not pick the one base that is backwards compatible).
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/pl031.c b/hw/pl031.c
index 713f85d..9602664 100644
--- a/hw/pl031.c
+++ b/hw/pl031.c
@@ -13,6 +13,7 @@
 
 #include "sysbus.h"
 #include "qemu-timer.h"
+#include "sysemu.h"
 
 //#define DEBUG_PL031
 
@@ -38,6 +39,11 @@ typedef struct {
     QEMUTimer *timer;
     qemu_irq irq;
 
+    /* Needed to preserve the tick_count across migration, even if the
+     * absolute value of the rtc_clock is different on the source and
+     * destination.
+     */
+    uint32_t tick_offset_vmstate;
     uint32_t tick_offset;
 
     uint32_t mr;
@@ -68,27 +74,23 @@ static void pl031_interrupt(void * opaque)
 
 static uint32_t pl031_get_count(pl031_state *s)
 {
-    /* This assumes qemu_get_clock_ns returns the time since the machine was
-       created.  */
-    return s->tick_offset + qemu_get_clock_ns(vm_clock) / get_ticks_per_sec();
+    int64_t now = qemu_get_clock_ns(rtc_clock);
+    return s->tick_offset + now / get_ticks_per_sec();
 }
 
 static void pl031_set_alarm(pl031_state *s)
 {
-    int64_t now;
     uint32_t ticks;
 
-    now = qemu_get_clock_ns(vm_clock);
-    ticks = s->tick_offset + now / get_ticks_per_sec();
-
     /* The timer wraps around.  This subtraction also wraps in the same way,
        and gives correct results when alarm < now_ticks.  */
-    ticks = s->mr - ticks;
+    ticks = s->mr - pl031_get_count(s);
     DPRINTF("Alarm set in %ud ticks\n", ticks);
     if (ticks == 0) {
         qemu_del_timer(s->timer);
         pl031_interrupt(s);
     } else {
+        int64_t now = qemu_get_clock_ns(rtc_clock);
         qemu_mod_timer(s->timer, now + (int64_t)ticks * get_ticks_per_sec());
     }
 }
@@ -190,18 +192,29 @@ static int pl031_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, &s->iomem);
 
     sysbus_init_irq(dev, &s->irq);
-    /* ??? We assume vm_clock is zero at this point.  */
     qemu_get_timedate(&tm, 0);
-    s->tick_offset = mktimegm(&tm);
+    s->tick_offset = mktimegm(&tm) - qemu_get_clock_ns(rtc_clock) / get_ticks_per_sec();
 
-    s->timer = qemu_new_timer_ns(vm_clock, pl031_interrupt, s);
+    s->timer = qemu_new_timer_ns(rtc_clock, pl031_interrupt, s);
     return 0;
 }
 
+static void pl031_pre_save(void *opaque)
+{
+    pl031_state *s = opaque;
+
+    /* tick_offset is base_time - rtc_clock base time.  Instead, we want to
+     * store the base time relative to the vm_clock for backwards-compatibility.  */
+    int64_t delta = qemu_get_clock_ns(rtc_clock) - qemu_get_clock_ns(vm_clock);
+    s->tick_offset_vmstate = s->tick_offset + delta / get_ticks_per_sec();
+}
+
 static int pl031_post_load(void *opaque, int version_id)
 {
     pl031_state *s = opaque;
 
+    int64_t delta = qemu_get_clock_ns(rtc_clock) - qemu_get_clock_ns(vm_clock);
+    s->tick_offset = s->tick_offset_vmstate - delta / get_ticks_per_sec();
     pl031_set_alarm(s);
     return 0;
 }
@@ -210,9 +223,10 @@ static const VMStateDescription vmstate_pl031 = {
     .name = "pl031",
     .version_id = 1,
     .minimum_version_id = 1,
+    .pre_save = pl031_pre_save,
     .post_load = pl031_post_load,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT32(tick_offset, pl031_state),
+        VMSTATE_UINT32(tick_offset_vmstate, pl031_state),
         VMSTATE_UINT32(mr, pl031_state),
         VMSTATE_UINT32(lr, pl031_state),
         VMSTATE_UINT32(cr, pl031_state),
commit ac204b8f67d17881bd61f2439005d02b1de3736e
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Mar 30 10:31:22 2012 +0000

    pl031: rearm alarm timer upon load
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/pl031.c b/hw/pl031.c
index 69abc4f..713f85d 100644
--- a/hw/pl031.c
+++ b/hw/pl031.c
@@ -47,21 +47,6 @@ typedef struct {
     uint32_t is;
 } pl031_state;
 
-static const VMStateDescription vmstate_pl031 = {
-    .name = "pl031",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32(tick_offset, pl031_state),
-        VMSTATE_UINT32(mr, pl031_state),
-        VMSTATE_UINT32(lr, pl031_state),
-        VMSTATE_UINT32(cr, pl031_state),
-        VMSTATE_UINT32(im, pl031_state),
-        VMSTATE_UINT32(is, pl031_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
 static const unsigned char pl031_id[] = {
     0x31, 0x10, 0x14, 0x00,         /* Device ID        */
     0x0d, 0xf0, 0x05, 0xb1          /* Cell ID      */
@@ -213,6 +198,30 @@ static int pl031_init(SysBusDevice *dev)
     return 0;
 }
 
+static int pl031_post_load(void *opaque, int version_id)
+{
+    pl031_state *s = opaque;
+
+    pl031_set_alarm(s);
+    return 0;
+}
+
+static const VMStateDescription vmstate_pl031 = {
+    .name = "pl031",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .post_load = pl031_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(tick_offset, pl031_state),
+        VMSTATE_UINT32(mr, pl031_state),
+        VMSTATE_UINT32(lr, pl031_state),
+        VMSTATE_UINT32(cr, pl031_state),
+        VMSTATE_UINT32(im, pl031_state),
+        VMSTATE_UINT32(is, pl031_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static void pl031_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
commit 348abc86c8f4b07264b0ff939394b878a3beace1
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Mar 30 10:31:22 2012 +0000

    arm: switch real-time clocks to rtc_clock
    
    This lets the user specify the desired semantics.  By default, the RTC
    will follow adjustments from the host's NTP client.  "-rtc clock=vm" will
    improve determinism with both icount and qtest.  Finally, the previous
    behavior is available with "-rtc clock=rt".
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/omap1.c b/hw/omap1.c
index 39e731a..80d47f0 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -2888,7 +2888,7 @@ static void omap_rtc_reset(struct omap_rtc_s *s)
     s->pm_am = 0;
     s->auto_comp = 0;
     s->round = 0;
-    s->tick = qemu_get_clock_ms(rt_clock);
+    s->tick = qemu_get_clock_ms(rtc_clock);
     memset(&s->alarm_tm, 0, sizeof(s->alarm_tm));
     s->alarm_tm.tm_mday = 0x01;
     s->status = 1 << 7;
@@ -2909,7 +2909,7 @@ static struct omap_rtc_s *omap_rtc_init(MemoryRegion *system_memory,
 
     s->irq = timerirq;
     s->alarm = alarmirq;
-    s->clk = qemu_new_timer_ms(rt_clock, omap_rtc_tick, s);
+    s->clk = qemu_new_timer_ms(rtc_clock, omap_rtc_tick, s);
 
     omap_rtc_reset(s);
 
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 1d5c35f..ddaa846 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -875,7 +875,7 @@ static inline void pxa2xx_rtc_int_update(PXA2xxRTCState *s)
 
 static void pxa2xx_rtc_hzupdate(PXA2xxRTCState *s)
 {
-    int64_t rt = qemu_get_clock_ms(rt_clock);
+    int64_t rt = qemu_get_clock_ms(rtc_clock);
     s->last_rcnr += ((rt - s->last_hz) << 15) /
             (1000 * ((s->rttr & 0xffff) + 1));
     s->last_rdcr += ((rt - s->last_hz) << 15) /
@@ -885,7 +885,7 @@ static void pxa2xx_rtc_hzupdate(PXA2xxRTCState *s)
 
 static void pxa2xx_rtc_swupdate(PXA2xxRTCState *s)
 {
-    int64_t rt = qemu_get_clock_ms(rt_clock);
+    int64_t rt = qemu_get_clock_ms(rtc_clock);
     if (s->rtsr & (1 << 12))
         s->last_swcr += (rt - s->last_sw) / 10;
     s->last_sw = rt;
@@ -893,7 +893,7 @@ static void pxa2xx_rtc_swupdate(PXA2xxRTCState *s)
 
 static void pxa2xx_rtc_piupdate(PXA2xxRTCState *s)
 {
-    int64_t rt = qemu_get_clock_ms(rt_clock);
+    int64_t rt = qemu_get_clock_ms(rtc_clock);
     if (s->rtsr & (1 << 15))
         s->last_swcr += rt - s->last_pi;
     s->last_pi = rt;
@@ -1019,16 +1019,16 @@ static uint64_t pxa2xx_rtc_read(void *opaque, target_phys_addr_t addr,
     case PIAR:
         return s->piar;
     case RCNR:
-        return s->last_rcnr + ((qemu_get_clock_ms(rt_clock) - s->last_hz) << 15) /
+        return s->last_rcnr + ((qemu_get_clock_ms(rtc_clock) - s->last_hz) << 15) /
                 (1000 * ((s->rttr & 0xffff) + 1));
     case RDCR:
-        return s->last_rdcr + ((qemu_get_clock_ms(rt_clock) - s->last_hz) << 15) /
+        return s->last_rdcr + ((qemu_get_clock_ms(rtc_clock) - s->last_hz) << 15) /
                 (1000 * ((s->rttr & 0xffff) + 1));
     case RYCR:
         return s->last_rycr;
     case SWCR:
         if (s->rtsr & (1 << 12))
-            return s->last_swcr + (qemu_get_clock_ms(rt_clock) - s->last_sw) / 10;
+            return s->last_swcr + (qemu_get_clock_ms(rtc_clock) - s->last_sw) / 10;
         else
             return s->last_swcr;
     default:
@@ -1168,14 +1168,14 @@ static int pxa2xx_rtc_init(SysBusDevice *dev)
     s->last_swcr = (tm.tm_hour << 19) |
             (tm.tm_min << 13) | (tm.tm_sec << 7);
     s->last_rtcpicr = 0;
-    s->last_hz = s->last_sw = s->last_pi = qemu_get_clock_ms(rt_clock);
-
-    s->rtc_hz    = qemu_new_timer_ms(rt_clock, pxa2xx_rtc_hz_tick,    s);
-    s->rtc_rdal1 = qemu_new_timer_ms(rt_clock, pxa2xx_rtc_rdal1_tick, s);
-    s->rtc_rdal2 = qemu_new_timer_ms(rt_clock, pxa2xx_rtc_rdal2_tick, s);
-    s->rtc_swal1 = qemu_new_timer_ms(rt_clock, pxa2xx_rtc_swal1_tick, s);
-    s->rtc_swal2 = qemu_new_timer_ms(rt_clock, pxa2xx_rtc_swal2_tick, s);
-    s->rtc_pi    = qemu_new_timer_ms(rt_clock, pxa2xx_rtc_pi_tick,    s);
+    s->last_hz = s->last_sw = s->last_pi = qemu_get_clock_ms(rtc_clock);
+
+    s->rtc_hz    = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_hz_tick,    s);
+    s->rtc_rdal1 = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_rdal1_tick, s);
+    s->rtc_rdal2 = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_rdal2_tick, s);
+    s->rtc_swal1 = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_swal1_tick, s);
+    s->rtc_swal2 = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_swal2_tick, s);
+    s->rtc_pi    = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_pi_tick,    s);
 
     sysbus_init_irq(dev, &s->rtc_irq);
 
diff --git a/hw/strongarm.c b/hw/strongarm.c
index 4d5b60f..1b15f39 100644
--- a/hw/strongarm.c
+++ b/hw/strongarm.c
@@ -255,7 +255,7 @@ static inline void strongarm_rtc_int_update(StrongARMRTCState *s)
 
 static void strongarm_rtc_hzupdate(StrongARMRTCState *s)
 {
-    int64_t rt = qemu_get_clock_ms(rt_clock);
+    int64_t rt = qemu_get_clock_ms(rtc_clock);
     s->last_rcnr += ((rt - s->last_hz) << 15) /
             (1000 * ((s->rttr & 0xffff) + 1));
     s->last_hz = rt;
@@ -308,7 +308,7 @@ static uint64_t strongarm_rtc_read(void *opaque, target_phys_addr_t addr,
         return s->rtar;
     case RCNR:
         return s->last_rcnr +
-                ((qemu_get_clock_ms(rt_clock) - s->last_hz) << 15) /
+                ((qemu_get_clock_ms(rtc_clock) - s->last_hz) << 15) /
                 (1000 * ((s->rttr & 0xffff) + 1));
     default:
         printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr);
@@ -374,10 +374,10 @@ static int strongarm_rtc_init(SysBusDevice *dev)
     qemu_get_timedate(&tm, 0);
 
     s->last_rcnr = (uint32_t) mktimegm(&tm);
-    s->last_hz = qemu_get_clock_ms(rt_clock);
+    s->last_hz = qemu_get_clock_ms(rtc_clock);
 
-    s->rtc_alarm = qemu_new_timer_ms(rt_clock, strongarm_rtc_alarm_tick, s);
-    s->rtc_hz = qemu_new_timer_ms(rt_clock, strongarm_rtc_hz_tick, s);
+    s->rtc_alarm = qemu_new_timer_ms(rtc_clock, strongarm_rtc_alarm_tick, s);
+    s->rtc_hz = qemu_new_timer_ms(rtc_clock, strongarm_rtc_hz_tick, s);
 
     sysbus_init_irq(dev, &s->rtc_irq);
     sysbus_init_irq(dev, &s->rtc_hz_irq);
diff --git a/hw/twl92230.c b/hw/twl92230.c
index 22da6f8..0d70d84 100644
--- a/hw/twl92230.c
+++ b/hw/twl92230.c
@@ -22,6 +22,7 @@
 #include "hw.h"
 #include "qemu-timer.h"
 #include "i2c.h"
+#include "sysemu.h"
 #include "console.h"
 
 #define VERBOSE 1
@@ -71,14 +72,14 @@ static inline void menelaus_update(MenelausState *s)
 
 static inline void menelaus_rtc_start(MenelausState *s)
 {
-    s->rtc.next += qemu_get_clock_ms(rt_clock);
+    s->rtc.next += qemu_get_clock_ms(rtc_clock);
     qemu_mod_timer(s->rtc.hz_tm, s->rtc.next);
 }
 
 static inline void menelaus_rtc_stop(MenelausState *s)
 {
     qemu_del_timer(s->rtc.hz_tm);
-    s->rtc.next -= qemu_get_clock_ms(rt_clock);
+    s->rtc.next -= qemu_get_clock_ms(rtc_clock);
     if (s->rtc.next < 1)
         s->rtc.next = 1;
 }
@@ -781,7 +782,7 @@ static void menelaus_pre_save(void *opaque)
 {
     MenelausState *s = opaque;
     /* Should be <= 1000 */
-    s->rtc_next_vmstate =  s->rtc.next - qemu_get_clock_ms(rt_clock);
+    s->rtc_next_vmstate =  s->rtc.next - qemu_get_clock_ms(rtc_clock);
 }
 
 static int menelaus_post_load(void *opaque, int version_id)
@@ -842,7 +843,7 @@ static int twl92230_init(I2CSlave *i2c)
 {
     MenelausState *s = FROM_I2C_SLAVE(MenelausState, i2c);
 
-    s->rtc.hz_tm = qemu_new_timer_ms(rt_clock, menelaus_rtc_hz, s);
+    s->rtc.hz_tm = qemu_new_timer_ms(rtc_clock, menelaus_rtc_hz, s);
     /* Three output pins plus one interrupt pin.  */
     qdev_init_gpio_out(&i2c->qdev, s->out, 4);
 
commit e230d4e8bd79a7a7b6d431d6659fa0234f95c82d
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Mar 30 10:31:22 2012 +0000

    omap: switch omap_lpg to vm_clock
    
    The output of the pulse generator needs to be deterministic when
    running in -icount mode, and to remain constant whenever the VM is
    stopped.  So the right clock to use is vm_clock.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/omap1.c b/hw/omap1.c
index 2a341bf..39e731a 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -3497,9 +3497,9 @@ static void omap_lpg_tick(void *opaque)
     struct omap_lpg_s *s = opaque;
 
     if (s->cycle)
-        qemu_mod_timer(s->tm, qemu_get_clock_ms(rt_clock) + s->period - s->on);
+        qemu_mod_timer(s->tm, qemu_get_clock_ms(vm_clock) + s->period - s->on);
     else
-        qemu_mod_timer(s->tm, qemu_get_clock_ms(rt_clock) + s->on);
+        qemu_mod_timer(s->tm, qemu_get_clock_ms(vm_clock) + s->on);
 
     s->cycle = !s->cycle;
     printf("%s: LED is %s\n", __FUNCTION__, s->cycle ? "on" : "off");
@@ -3617,7 +3617,7 @@ static struct omap_lpg_s *omap_lpg_init(MemoryRegion *system_memory,
     struct omap_lpg_s *s = (struct omap_lpg_s *)
             g_malloc0(sizeof(struct omap_lpg_s));
 
-    s->tm = qemu_new_timer_ms(rt_clock, omap_lpg_tick, s);
+    s->tm = qemu_new_timer_ms(vm_clock, omap_lpg_tick, s);
 
     omap_lpg_reset(s);
 
commit 788081417ae250e69bfa1d33d11d774bc4c03a27
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Mar 30 10:31:21 2012 +0000

    rtc: add -rtc clock=rt
    
    This will let people use backwards-compatible semantics for devices that
    will be affected by the following patches.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/qemu-options.hx b/qemu-options.hx
index 662f571..a6cd8e9 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2453,7 +2453,7 @@ DEF("localtime", 0, QEMU_OPTION_localtime, "", QEMU_ARCH_ALL)
 DEF("startdate", HAS_ARG, QEMU_OPTION_startdate, "", QEMU_ARCH_ALL)
 
 DEF("rtc", HAS_ARG, QEMU_OPTION_rtc, \
-    "-rtc [base=utc|localtime|date][,clock=host|vm][,driftfix=none|slew]\n" \
+    "-rtc [base=utc|localtime|date][,clock=host|rt|vm][,driftfix=none|slew]\n" \
     "                set the RTC base and clock, enable drift fix for clock ticks (x86 only)\n",
     QEMU_ARCH_ALL)
 
@@ -2469,8 +2469,9 @@ format @code{2006-06-17T16:01:21} or @code{2006-06-17}. The default base is UTC.
 By default the RTC is driven by the host system time. This allows to use the
 RTC as accurate reference clock inside the guest, specifically if the host
 time is smoothly following an accurate external reference clock, e.g. via NTP.
-If you want to isolate the guest time from the host, even prevent it from
-progressing during suspension, you can set @option{clock} to @code{vm} instead.
+If you want to isolate the guest time from the host, you can set @option{clock}
+to @code{rt} instead.  To even prevent it from progressing during suspension,
+you can set it to @code{vm}.
 
 Enable @option{driftfix} (i386 targets only) if you experience time drift problems,
 specifically with Windows' ACPI HAL. This option will try to figure out how
diff --git a/vl.c b/vl.c
index 0fccf50..71a4755 100644
--- a/vl.c
+++ b/vl.c
@@ -529,6 +529,8 @@ static void configure_rtc(QemuOpts *opts)
     if (value) {
         if (!strcmp(value, "host")) {
             rtc_clock = host_clock;
+        } else if (!strcmp(value, "rt")) {
+            rtc_clock = rt_clock;
         } else if (!strcmp(value, "vm")) {
             rtc_clock = vm_clock;
         } else {
commit 06ed5d66f77f2794344c7dfd3d21a07e97f0b8fa
Author: Andrew Towers <atowers at gmail.com>
Date:   Thu Mar 29 02:41:08 2012 +0000

    ARM: Permit any ARMv6K CPU to read the MVFR0 and MVFR1 VFP registers.
    
    This patch replaces the ARM_FEATURE_VFP3 test when reading MVFR registers
    with a test for a new feature flag ARM_FEATURE_MVFR, and sets this feature
    for all ARMv6K cores (ARM1156 is not a v6K core, yet supports MVFR; qemu
    does not support ARM1156 at this time.)
    
    MVFR0 and MVFR1 were introduced in ARM1136JF-S r1p0 (ARMv6K, VFPv2) and are
    present in ARM1156T2F-S (non-v6K), ARM1176JZF-S, ARM11MPCore and newer cores.
    Reference: ARM DDI 0211H, 0290G, 0301H, 0360E.
    http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0211h/Ffbefjag.html
    
    Without this change, the linux kernel will not boot with VFP support enabled
    under ARM1176 system emulation, due to the unconditional use of MVFR1 at the
    end of vfp_init() in arch/arm/vfp/vfpmodule.c:
    
      VFP support v0.3: implemetor 41 architecture 1 part 20 variant b rev 5
      Internal error: Oops - undefined instruction: 0 [#1]
    
    Signed-off-by: Andrew Towers <atowers at gmail.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index a68df61..e176c5f 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -382,6 +382,7 @@ enum arm_features {
     ARM_FEATURE_ARM_DIV, /* divide supported in ARM encoding */
     ARM_FEATURE_VFP4, /* VFPv4 (implies that NEON is v2) */
     ARM_FEATURE_GENERIC_TIMER,
+    ARM_FEATURE_MVFR, /* Media and VFP Feature Registers 0 and 1 */
 };
 
 static inline int arm_feature(CPUARMState *env, int feature)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index dd8e306..d974b57 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -254,6 +254,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     }
     if (arm_feature(env, ARM_FEATURE_V6K)) {
         set_feature(env, ARM_FEATURE_V6);
+        set_feature(env, ARM_FEATURE_MVFR);
     }
     if (arm_feature(env, ARM_FEATURE_V6)) {
         set_feature(env, ARM_FEATURE_V5);
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 81725d1..46d1d3e 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -2906,7 +2906,7 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
                         case ARM_VFP_MVFR0:
                         case ARM_VFP_MVFR1:
                             if (IS_USER(s)
-                                || !arm_feature(env, ARM_FEATURE_VFP3))
+                                || !arm_feature(env, ARM_FEATURE_MVFR))
                                 return 1;
                             tmp = load_cpu_field(vfp.xregs[rn]);
                             break;
commit 8df9082da6b7a24b299d37462bc3539c15f26135
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu Mar 29 18:03:18 2012 +0200

    target-unicore32: Move CPU-dependent init into initfn
    
    Instead of setting values in a CPUID switch, do so in initfn functions.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Guan Xuetao <gxt at mprc.pku.edu.cn>

diff --git a/target-unicore32/cpu.c b/target-unicore32/cpu.c
index 189b6f6..de63f58 100644
--- a/target-unicore32/cpu.c
+++ b/target-unicore32/cpu.c
@@ -15,6 +15,11 @@
 #include "cpu-qom.h"
 #include "qemu-common.h"
 
+static inline void set_feature(CPUUniCore32State *env, int feature)
+{
+    env->features |= feature;
+}
+
 /* CPU models */
 
 typedef struct UniCore32CPUInfo {
@@ -28,6 +33,12 @@ static void unicore_ii_cpu_initfn(Object *obj)
     CPUUniCore32State *env = &cpu->env;
 
     env->cp0.c0_cpuid = 0x40010863;
+
+    set_feature(env, UC32_HWCAP_CMOV);
+    set_feature(env, UC32_HWCAP_UCF64);
+    env->ucf64.xregs[UC32_UCF64_FPSCR] = 0;
+    env->cp0.c0_cachetype = 0x1dd20d2;
+    env->cp0.c1_sys = 0x00090078;
 }
 
 static void uc32_any_cpu_initfn(Object *obj)
@@ -36,6 +47,9 @@ static void uc32_any_cpu_initfn(Object *obj)
     CPUUniCore32State *env = &cpu->env;
 
     env->cp0.c0_cpuid = 0xffffffff;
+
+    set_feature(env, UC32_HWCAP_CMOV);
+    set_feature(env, UC32_HWCAP_UCF64);
 }
 
 static const UniCore32CPUInfo uc32_cpus[] = {
diff --git a/target-unicore32/helper.c b/target-unicore32/helper.c
index 0f23a40..9fe4a37 100644
--- a/target-unicore32/helper.c
+++ b/target-unicore32/helper.c
@@ -14,16 +14,10 @@
 #include "helper.h"
 #include "host-utils.h"
 
-static inline void set_feature(CPUUniCore32State *env, int feature)
-{
-    env->features |= feature;
-}
-
 CPUUniCore32State *uc32_cpu_init(const char *cpu_model)
 {
     UniCore32CPU *cpu;
     CPUUniCore32State *env;
-    uint32_t id;
     static int inited = 1;
 
     if (object_class_by_name(cpu_model) == NULL) {
@@ -32,23 +26,6 @@ CPUUniCore32State *uc32_cpu_init(const char *cpu_model)
     cpu = UNICORE32_CPU(object_new(cpu_model));
     env = &cpu->env;
 
-    id = env->cp0.c0_cpuid;
-    switch (id) {
-    case UC32_CPUID_UCV2:
-        set_feature(env, UC32_HWCAP_CMOV);
-        set_feature(env, UC32_HWCAP_UCF64);
-        env->ucf64.xregs[UC32_UCF64_FPSCR] = 0;
-        env->cp0.c0_cachetype = 0x1dd20d2;
-        env->cp0.c1_sys = 0x00090078;
-        break;
-    case UC32_CPUID_ANY: /* For userspace emulation.  */
-        set_feature(env, UC32_HWCAP_CMOV);
-        set_feature(env, UC32_HWCAP_UCF64);
-        break;
-    default:
-        cpu_abort(env, "Bad CPU ID: %x\n", id);
-    }
-
     if (inited) {
         inited = 0;
         uc32_translate_init();
commit ae0f5e9ea80de923ae1c11289cf6ac468f657880
Author: Andreas Färber <afaerber at suse.de>
Date:   Tue Feb 14 01:16:17 2012 +0100

    target-unicore32: QOM'ify CPU
    
    Embed CPUUniCore32State as first member of UniCore32CPU.
    
    Contributed under GPLv2+.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Guan Xuetao <gxt at mprc.pku.edu.cn>

diff --git a/Makefile.target b/Makefile.target
index 44b2e83..7cff65f 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -98,6 +98,7 @@ libobj-y += cpu_init.o
 endif
 libobj-$(TARGET_SPARC) += int32_helper.o
 libobj-$(TARGET_SPARC64) += int64_helper.o
+libobj-$(TARGET_UNICORE32) += cpu.o
 libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o sys_helper.o mem_helper.o
 
 libobj-y += disas.o
diff --git a/target-unicore32/cpu-qom.h b/target-unicore32/cpu-qom.h
new file mode 100644
index 0000000..342d85e
--- /dev/null
+++ b/target-unicore32/cpu-qom.h
@@ -0,0 +1,59 @@
+/*
+ * QEMU UniCore32 CPU
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation, or (at your option) any
+ * later version. See the COPYING file in the top-level directory.
+ */
+#ifndef QEMU_UC32_CPU_QOM_H
+#define QEMU_UC32_CPU_QOM_H
+
+#include "qemu/cpu.h"
+#include "cpu.h"
+
+#define TYPE_UNICORE32_CPU "unicore32-cpu"
+
+#define UNICORE32_CPU_CLASS(klass) \
+    OBJECT_CLASS_CHECK(UniCore32CPUClass, (klass), TYPE_UNICORE32_CPU)
+#define UNICORE32_CPU(obj) \
+    OBJECT_CHECK(UniCore32CPU, (obj), TYPE_UNICORE32_CPU)
+#define UNICORE32_CPU_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(UniCore32CPUClass, (obj), TYPE_UNICORE32_CPU)
+
+/**
+ * UniCore32CPUClass:
+ *
+ * A UniCore32 CPU model.
+ */
+typedef struct UniCore32CPUClass {
+    /*< private >*/
+    CPUClass parent_class;
+    /*< public >*/
+} UniCore32CPUClass;
+
+/**
+ * UniCore32CPU:
+ * @env: #CPUUniCore32State
+ *
+ * A UniCore32 CPU.
+ */
+typedef struct UniCore32CPU {
+    /*< private >*/
+    CPUState parent_obj;
+    /*< public >*/
+
+    CPUUniCore32State env;
+} UniCore32CPU;
+
+static inline UniCore32CPU *uc32_env_get_cpu(CPUUniCore32State *env)
+{
+    return UNICORE32_CPU(container_of(env, UniCore32CPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(uc32_env_get_cpu(e))
+
+
+#endif
diff --git a/target-unicore32/cpu.c b/target-unicore32/cpu.c
new file mode 100644
index 0000000..189b6f6
--- /dev/null
+++ b/target-unicore32/cpu.c
@@ -0,0 +1,90 @@
+/*
+ * QEMU UniCore32 CPU
+ *
+ * Copyright (c) 2010-2011 GUAN Xue-tao
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Contributions from 2012-04-01 on are considered under GPL version 2,
+ * or (at your option) any later version.
+ */
+
+#include "cpu-qom.h"
+#include "qemu-common.h"
+
+/* CPU models */
+
+typedef struct UniCore32CPUInfo {
+    const char *name;
+    void (*instance_init)(Object *obj);
+} UniCore32CPUInfo;
+
+static void unicore_ii_cpu_initfn(Object *obj)
+{
+    UniCore32CPU *cpu = UNICORE32_CPU(obj);
+    CPUUniCore32State *env = &cpu->env;
+
+    env->cp0.c0_cpuid = 0x40010863;
+}
+
+static void uc32_any_cpu_initfn(Object *obj)
+{
+    UniCore32CPU *cpu = UNICORE32_CPU(obj);
+    CPUUniCore32State *env = &cpu->env;
+
+    env->cp0.c0_cpuid = 0xffffffff;
+}
+
+static const UniCore32CPUInfo uc32_cpus[] = {
+    { .name = "UniCore-II", .instance_init = unicore_ii_cpu_initfn },
+    { .name = "any",        .instance_init = uc32_any_cpu_initfn },
+};
+
+static void uc32_cpu_initfn(Object *obj)
+{
+    UniCore32CPU *cpu = UNICORE32_CPU(obj);
+    CPUUniCore32State *env = &cpu->env;
+
+    cpu_exec_init(env);
+    env->cpu_model_str = object_get_typename(obj);
+
+    env->uncached_asr = ASR_MODE_USER;
+    env->regs[31] = 0;
+
+    tlb_flush(env, 1);
+}
+
+static void uc32_register_cpu_type(const UniCore32CPUInfo *info)
+{
+    TypeInfo type_info = {
+        .name = info->name,
+        .parent = TYPE_UNICORE32_CPU,
+        .instance_init = info->instance_init,
+    };
+
+    type_register_static(&type_info);
+}
+
+static const TypeInfo uc32_cpu_type_info = {
+    .name = TYPE_UNICORE32_CPU,
+    .parent = TYPE_CPU,
+    .instance_size = sizeof(UniCore32CPU),
+    .instance_init = uc32_cpu_initfn,
+    .abstract = true,
+    .class_size = sizeof(UniCore32CPUClass),
+};
+
+static void uc32_cpu_register_types(void)
+{
+    int i;
+
+    type_register_static(&uc32_cpu_type_info);
+    for (i = 0; i < ARRAY_SIZE(uc32_cpus); i++) {
+        uc32_register_cpu_type(&uc32_cpus[i]);
+    }
+}
+
+type_init(uc32_cpu_register_types)
diff --git a/target-unicore32/cpu.h b/target-unicore32/cpu.h
index 8ec0d2f..81c14ff 100644
--- a/target-unicore32/cpu.h
+++ b/target-unicore32/cpu.h
@@ -160,6 +160,7 @@ static inline void cpu_set_tls(CPUUniCore32State *env, target_ulong newtls)
 }
 
 #include "cpu-all.h"
+#include "cpu-qom.h"
 #include "exec-all.h"
 
 static inline void cpu_pc_from_tb(CPUUniCore32State *env, TranslationBlock *tb)
diff --git a/target-unicore32/helper.c b/target-unicore32/helper.c
index 18a9cbb..0f23a40 100644
--- a/target-unicore32/helper.c
+++ b/target-unicore32/helper.c
@@ -19,43 +19,20 @@ static inline void set_feature(CPUUniCore32State *env, int feature)
     env->features |= feature;
 }
 
-struct uc32_cpu_t {
-    uint32_t id;
-    const char *name;
-};
-
-static const struct uc32_cpu_t uc32_cpu_names[] = {
-    { UC32_CPUID_UCV2, "UniCore-II"},
-    { UC32_CPUID_ANY, "any"},
-    { 0, NULL}
-};
-
-/* return 0 if not found */
-static uint32_t uc32_cpu_find_by_name(const char *name)
-{
-    int i;
-    uint32_t id;
-
-    id = 0;
-    for (i = 0; uc32_cpu_names[i].name; i++) {
-        if (strcmp(name, uc32_cpu_names[i].name) == 0) {
-            id = uc32_cpu_names[i].id;
-            break;
-        }
-    }
-    return id;
-}
-
 CPUUniCore32State *uc32_cpu_init(const char *cpu_model)
 {
+    UniCore32CPU *cpu;
     CPUUniCore32State *env;
     uint32_t id;
     static int inited = 1;
 
-    env = g_malloc0(sizeof(CPUUniCore32State));
-    cpu_exec_init(env);
+    if (object_class_by_name(cpu_model) == NULL) {
+        return NULL;
+    }
+    cpu = UNICORE32_CPU(object_new(cpu_model));
+    env = &cpu->env;
 
-    id = uc32_cpu_find_by_name(cpu_model);
+    id = env->cp0.c0_cpuid;
     switch (id) {
     case UC32_CPUID_UCV2:
         set_feature(env, UC32_HWCAP_CMOV);
@@ -72,17 +49,11 @@ CPUUniCore32State *uc32_cpu_init(const char *cpu_model)
         cpu_abort(env, "Bad CPU ID: %x\n", id);
     }
 
-    env->cpu_model_str = cpu_model;
-    env->cp0.c0_cpuid = id;
-    env->uncached_asr = ASR_MODE_USER;
-    env->regs[31] = 0;
-
     if (inited) {
         inited = 0;
         uc32_translate_init();
     }
 
-    tlb_flush(env, 1);
     qemu_init_vcpu(env);
     return env;
 }
commit c3a8baa90d98edcf290bfda6850615368738a17c
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu Mar 15 15:02:14 2012 +0100

    target-unicore32: License future contributions under GPLv2+
    
    This is to limit relicensing obstacles to the pending IBM investigation.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Guan Xuetao <gxt at mprc.pku.edu.cn>

diff --git a/target-unicore32/helper.c b/target-unicore32/helper.c
index 6af492d..18a9cbb 100644
--- a/target-unicore32/helper.c
+++ b/target-unicore32/helper.c
@@ -4,6 +4,9 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
+ *
+ * Contributions from 2012-04-01 on are considered under GPL version 2,
+ * or (at your option) any later version.
  */
 
 #include "cpu.h"
commit 2b3bc6c0f56968631c4d92b7e06ec969ed0700bb
Author: Andreas Färber <afaerber at suse.de>
Date:   Tue Mar 13 16:48:19 2012 +0100

    target-unicore32: Relicense to GPLv2+
    
    Adopt the license text suggested by Guan Xue-tao (with a minor
    simplification) for all target-unicore/ files except helper.c.
    
    To helper.c Anthony Liguori contributed a qemu_malloc() -> g_malloc()
    conversion, still pending IBM relicensing approval, so that remains
    GPLv2 for now.
    
    By relicensing all possible parts now, we avoid having to formally
    relicense new, e.g., QOM code.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Guan Xuetao <gxt at mprc.pku.edu.cn>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Dor Laor <dlaor at redhat.com>

diff --git a/target-unicore32/cpu.h b/target-unicore32/cpu.h
index a3f8589..8ec0d2f 100644
--- a/target-unicore32/cpu.h
+++ b/target-unicore32/cpu.h
@@ -5,7 +5,8 @@
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * published by the Free Software Foundation, or (at your option) any
+ * later version. See the COPYING file in the top-level directory.
  */
 #ifndef __CPU_UC32_H__
 #define __CPU_UC32_H__
diff --git a/target-unicore32/helper.h b/target-unicore32/helper.h
index 615de2a..5a3b8a4 100644
--- a/target-unicore32/helper.h
+++ b/target-unicore32/helper.h
@@ -3,7 +3,8 @@
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * published by the Free Software Foundation, or (at your option) any
+ * later version. See the COPYING file in the top-level directory.
  */
 #include "def-helper.h"
 
diff --git a/target-unicore32/op_helper.c b/target-unicore32/op_helper.c
index 638a020..b954c30 100644
--- a/target-unicore32/op_helper.c
+++ b/target-unicore32/op_helper.c
@@ -5,7 +5,8 @@
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * published by the Free Software Foundation, or (at your option) any
+ * later version. See the COPYING file in the top-level directory.
  */
 #include "cpu.h"
 #include "dyngen-exec.h"
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index 3b3ba16..9793d14 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -5,7 +5,8 @@
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * published by the Free Software Foundation, or (at your option) any
+ * later version. See the COPYING file in the top-level directory.
  */
 #include <stdarg.h>
 #include <stdlib.h>
commit a6ea7b4c5e44ba6965accd3ada3a9c02fead042d
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 00:45:43 2012 +0100

    MAINTAINERS: Add entry for UniCore32
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Guan Xuetao <gxt at mprc.pku.edu.cn>

diff --git a/MAINTAINERS b/MAINTAINERS
index f83d07c..922945c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -112,6 +112,11 @@ M: Blue Swirl <blauwirbel at gmail.com>
 S: Maintained
 F: target-sparc/
 
+UniCore32
+M: Guan Xuetao <gxt at mprc.pku.edu.cn>
+S: Maintained
+F: target-unicore32/
+
 X86
 M: qemu-devel at nongnu.org
 S: Odd Fixes
commit 040b66f3f97ba9299c0be9da025a9197db654198
Merge: cbd5979... f638f0d...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Mar 29 13:32:41 2012 -0500

    Merge remote-tracking branch 'origin/master' into staging
    
    * origin/master:
      qemu tcg: Remove one entry of INDEX_op_ld_i64 from ppc_op_defs

commit dec9c2d4306d7b4f8ffff482ac42dc468ed2a61d
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu Mar 29 04:50:31 2012 +0000

    target-arm: Minimalistic CPU QOM'ification
    
    Introduce only one non-abstract type TYPE_ARM_CPU and do not touch
    cp15 registers to not interfere with Peter's ongoing remodelling.
    Embed CPUARMState as first (additional) field of ARMCPU.
    
    Let CPUClass::reset() call cpu_state_reset() for now.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/Makefile.target b/Makefile.target
index 44b2e83..6e8b997 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -92,6 +92,7 @@ endif
 libobj-$(TARGET_SPARC64) += vis_helper.o
 libobj-$(CONFIG_NEED_MMU) += mmu.o
 libobj-$(TARGET_ARM) += neon_helper.o iwmmxt_helper.o
+libobj-$(TARGET_ARM) += cpu.o
 ifeq ($(TARGET_BASE_ARCH), sparc)
 libobj-y += fop_helper.o cc_helper.o win_helper.o mmu_helper.o ldst_helper.o
 libobj-y += cpu_init.o
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
new file mode 100644
index 0000000..42d2a6b
--- /dev/null
+++ b/target-arm/cpu-qom.h
@@ -0,0 +1,71 @@
+/*
+ * QEMU ARM CPU
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
+ */
+#ifndef QEMU_ARM_CPU_QOM_H
+#define QEMU_ARM_CPU_QOM_H
+
+#include "qemu/cpu.h"
+#include "cpu.h"
+
+#define TYPE_ARM_CPU "arm-cpu"
+
+#define ARM_CPU_CLASS(klass) \
+    OBJECT_CLASS_CHECK(ARMCPUClass, (klass), TYPE_ARM_CPU)
+#define ARM_CPU(obj) \
+    OBJECT_CHECK(ARMCPU, (obj), TYPE_ARM_CPU)
+#define ARM_CPU_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(ARMCPUClass, (obj), TYPE_ARM_CPU)
+
+/**
+ * ARMCPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * An ARM CPU model.
+ */
+typedef struct ARMCPUClass {
+    /*< private >*/
+    CPUClass parent_class;
+    /*< public >*/
+
+    void (*parent_reset)(CPUState *cpu);
+} ARMCPUClass;
+
+/**
+ * ARMCPU:
+ * @env: #CPUARMState
+ *
+ * An ARM CPU core.
+ */
+typedef struct ARMCPU {
+    /*< private >*/
+    CPUState parent_obj;
+    /*< public >*/
+
+    CPUARMState env;
+} ARMCPU;
+
+static inline ARMCPU *arm_env_get_cpu(CPUARMState *env)
+{
+    return ARM_CPU(container_of(env, ARMCPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(arm_env_get_cpu(e))
+
+
+#endif
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
new file mode 100644
index 0000000..c3ed45b
--- /dev/null
+++ b/target-arm/cpu.c
@@ -0,0 +1,60 @@
+/*
+ * QEMU ARM CPU
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
+ */
+
+#include "cpu-qom.h"
+#include "qemu-common.h"
+
+/* CPUClass::reset() */
+static void arm_cpu_reset(CPUState *s)
+{
+    ARMCPU *cpu = ARM_CPU(s);
+    ARMCPUClass *acc = ARM_CPU_GET_CLASS(cpu);
+
+    acc->parent_reset(s);
+
+    /* TODO Inline the current contents of cpu_state_reset(),
+            once cpu_reset_model_id() is eliminated. */
+    cpu_state_reset(&cpu->env);
+}
+
+static void arm_cpu_class_init(ObjectClass *oc, void *data)
+{
+    ARMCPUClass *acc = ARM_CPU_CLASS(oc);
+    CPUClass *cc = CPU_CLASS(acc);
+
+    acc->parent_reset = cc->reset;
+    cc->reset = arm_cpu_reset;
+}
+
+static const TypeInfo arm_cpu_type_info = {
+    .name = TYPE_ARM_CPU,
+    .parent = TYPE_CPU,
+    .instance_size = sizeof(ARMCPU),
+    .abstract = false,
+    .class_size = sizeof(ARMCPUClass),
+    .class_init = arm_cpu_class_init,
+};
+
+static void arm_cpu_register_types(void)
+{
+    type_register_static(&arm_cpu_type_info);
+}
+
+type_init(arm_cpu_register_types)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 69ef142..a68df61 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -475,6 +475,7 @@ static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp)
 #endif
 
 #include "cpu-all.h"
+#include "cpu-qom.h"
 
 /* Bit usage in the TB flags field: */
 #define ARM_TBFLAG_THUMB_SHIFT      0
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 1ce8105..dd8e306 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -278,6 +278,10 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     }
 }
 
+/* TODO Move contents into arm_cpu_reset() in cpu.c,
+ *      once cpu_reset_model_id() is eliminated,
+ *      and then forward to cpu_reset() here.
+ */
 void cpu_state_reset(CPUARMState *env)
 {
     uint32_t id;
@@ -400,6 +404,7 @@ static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
 
 CPUARMState *cpu_arm_init(const char *cpu_model)
 {
+    ARMCPU *cpu;
     CPUARMState *env;
     uint32_t id;
     static int inited = 0;
@@ -407,7 +412,8 @@ CPUARMState *cpu_arm_init(const char *cpu_model)
     id = cpu_arm_find_by_name(cpu_model);
     if (id == 0)
         return NULL;
-    env = g_malloc0(sizeof(CPUARMState));
+    cpu = ARM_CPU(object_new(TYPE_ARM_CPU));
+    env = &cpu->env;
     cpu_exec_init(env);
     if (tcg_enabled() && !inited) {
         inited = 1;
commit 0bcd08b3522e4feffe3111e7c8145f62d32cc1fb
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu Mar 29 04:50:30 2012 +0000

    target-arm: Drop cpu_arm_close()
    
    It's unused, so no need to QOM'ify it later.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 26c114b..69ef142 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -238,7 +238,6 @@ typedef struct CPUARMState {
 CPUARMState *cpu_arm_init(const char *cpu_model);
 void arm_translate_init(void);
 int cpu_arm_exec(CPUARMState *s);
-void cpu_arm_close(CPUARMState *s);
 void do_interrupt(CPUARMState *);
 void switch_mode(CPUARMState *, int);
 uint32_t do_arm_semihosting(CPUARMState *env);
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 1314f23..1ce8105 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -493,11 +493,6 @@ static uint32_t cpu_arm_find_by_name(const char *name)
     return id;
 }
 
-void cpu_arm_close(CPUARMState *env)
-{
-    g_free(env);
-}
-
 static int bad_mode_switch(CPUARMState *env, int mode)
 {
     /* Return true if it is not valid for us to switch to
commit f638f0d3ae214d995cdd94578195700cda24597b
Author: Li Zhang <zhlcindy at linux.vnet.ibm.com>
Date:   Thu Mar 29 14:29:02 2012 +1100

    qemu tcg: Remove one entry of INDEX_op_ld_i64 from ppc_op_defs
    
    There two entries of INDEX_op_ld_i64 in the ppc_op_defs.  That causes an
    assertion failure in tcg_add_target_add_op_defs() when --enable-debug is
    used on a ppc64 backend (that's ppc64 host, not target).
    
    Signed-off-by: Li Zhang <zhlcindy at linux.vnet.ibm.com>
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: malc <av1474 at comtv.ru>

diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 409a1ac..f2ad9e3 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -1656,7 +1656,6 @@ static const TCGTargetOpDef ppc_op_defs[] = {
     { INDEX_op_ld16s_i64, { "r", "r" } },
     { INDEX_op_ld32u_i64, { "r", "r" } },
     { INDEX_op_ld32s_i64, { "r", "r" } },
-    { INDEX_op_ld_i64, { "r", "r" } },
 
     { INDEX_op_add_i32, { "r", "r", "ri" } },
     { INDEX_op_mul_i32, { "r", "r", "ri" } },
commit 56688961634a2d05fb5841a149bb5c1a17239e4c
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Mar 28 21:03:42 2012 +0200

    w32/slirp: Undefine error constants before their redefinition
    
    Less warnings for your console.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>

diff --git a/slirp/slirp.h b/slirp/slirp.h
index 2098b20..46bfe46 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -15,6 +15,12 @@ typedef char *caddr_t;
 # include <sys/timeb.h>
 # include <iphlpapi.h>
 
+# undef EWOULDBLOCK
+# undef EINPROGRESS
+# undef ENOTCONN
+# undef EHOSTUNREACH
+# undef ENETUNREACH
+# undef ECONNREFUSED
 # define EWOULDBLOCK WSAEWOULDBLOCK
 # define EINPROGRESS WSAEINPROGRESS
 # define ENOTCONN WSAENOTCONN
commit 1c5970a8b8ed79334e8ab303fec7287442538c3c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Mar 22 01:02:52 2012 +0100

    slirp: use socket_set_nonblock
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>

diff --git a/slirp/misc.c b/slirp/misc.c
index 0308a62..0bee864 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -215,7 +215,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
                 setsockopt(so->s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int));
                 opt = 1;
                 setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, (char *)&opt, sizeof(int));
-		fd_nonblock(so->s);
+		socket_set_nonblock(so->s);
 
 		/* Append the telnet options now */
                 if (so->so_m != NULL && do_pty == 1)  {
@@ -267,50 +267,6 @@ u_sleep(int usec)
 	select(0, &fdset, &fdset, &fdset, &t);
 }
 
-/*
- * Set fd blocking and non-blocking
- */
-
-void
-fd_nonblock(int fd)
-{
-#ifdef FIONBIO
-#ifdef _WIN32
-        unsigned long opt = 1;
-#else
-        int opt = 1;
-#endif
-
-	ioctlsocket(fd, FIONBIO, &opt);
-#else
-	int opt;
-
-	opt = fcntl(fd, F_GETFL, 0);
-	opt |= O_NONBLOCK;
-	fcntl(fd, F_SETFL, opt);
-#endif
-}
-
-void
-fd_block(int fd)
-{
-#ifdef FIONBIO
-#ifdef _WIN32
-        unsigned long opt = 0;
-#else
-	int opt = 0;
-#endif
-
-	ioctlsocket(fd, FIONBIO, &opt);
-#else
-	int opt;
-
-	opt = fcntl(fd, F_GETFL, 0);
-	opt &= ~O_NONBLOCK;
-	fcntl(fd, F_SETFL, opt);
-#endif
-}
-
 void slirp_connection_info(Slirp *slirp, Monitor *mon)
 {
     const char * const tcpstates[] = {
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index 6f6585a..0a545c4 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -336,7 +336,7 @@ int tcp_fconnect(struct socket *so)
     int opt, s=so->s;
     struct sockaddr_in addr;
 
-    fd_nonblock(s);
+    socket_set_nonblock(s);
     opt = 1;
     setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(opt ));
     opt = 1;
@@ -424,7 +424,7 @@ tcp_connect(struct socket *inso)
 		tcp_close(sototcpcb(so)); /* This will sofree() as well */
 		return;
 	}
-	fd_nonblock(s);
+	socket_set_nonblock(s);
 	opt = 1;
 	setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
 	opt = 1;
commit b72210568ef0c0fb141a01cffb71a09c4efa0364
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Mar 22 01:02:51 2012 +0100

    slirp: clean up conflicts with system headers
    
    Right now, slirp/slirp.h cannot include some system headers and,
    indirectly, qemu_socket.h.  Clean this up, and remove a duplicate
    prototype that was introduced because of that.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>

diff --git a/slirp/slirp.h b/slirp/slirp.h
index 5033ee3..2098b20 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -88,10 +88,6 @@ void *malloc(size_t arg);
 void free(void *ptr);
 #endif
 
-#ifndef HAVE_INET_ATON
-int inet_aton(const char *cp, struct in_addr *ia);
-#endif
-
 #include <fcntl.h>
 #ifndef NO_UNIX_SOCKETS
 #include <sys/un.h>
@@ -144,6 +140,7 @@ int inet_aton(const char *cp, struct in_addr *ia);
 #include "debug.h"
 
 #include "qemu-queue.h"
+#include "qemu_socket.h"
 
 #include "libslirp.h"
 #include "ip.h"
@@ -167,9 +164,6 @@ int inet_aton(const char *cp, struct in_addr *ia);
 #include "bootp.h"
 #include "tftp.h"
 
-/* osdep.c */
-int qemu_socket(int domain, int type, int protocol);
-
 #define ETH_ALEN 6
 #define ETH_HLEN 14
 
diff --git a/slirp/tcp.h b/slirp/tcp.h
index b3817cb..8299603 100644
--- a/slirp/tcp.h
+++ b/slirp/tcp.h
@@ -45,6 +45,7 @@ typedef	uint32_t tcp_seq;
  * TCP header.
  * Per RFC 793, September, 1981.
  */
+#define tcphdr slirp_tcphdr
 struct tcphdr {
 	uint16_t th_sport;              /* source port */
 	uint16_t th_dport;              /* destination port */
@@ -58,12 +59,6 @@ struct tcphdr {
 		th_off:4;		/* data offset */
 #endif
 	uint8_t th_flags;
-#define	TH_FIN	0x01
-#define	TH_SYN	0x02
-#define	TH_RST	0x04
-#define	TH_PUSH	0x08
-#define	TH_ACK	0x10
-#define	TH_URG	0x20
 	uint16_t th_win;                /* window */
 	uint16_t th_sum;                /* checksum */
 	uint16_t th_urp;                /* urgent pointer */
@@ -71,6 +66,16 @@ struct tcphdr {
 
 #include "tcp_var.h"
 
+#ifndef TH_FIN
+#define	TH_FIN	0x01
+#define	TH_SYN	0x02
+#define	TH_RST	0x04
+#define	TH_PUSH	0x08
+#define	TH_ACK	0x10
+#define	TH_URG	0x20
+#endif
+
+#ifndef TCPOPT_EOL
 #define	TCPOPT_EOL		0
 #define	TCPOPT_NOP		1
 #define	TCPOPT_MAXSEG		2
@@ -86,6 +91,7 @@ struct tcphdr {
 
 #define TCPOPT_TSTAMP_HDR	\
     (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP)
+#endif
 
 /*
  * Default maximum segment size for TCP.
@@ -95,10 +101,13 @@ struct tcphdr {
  *
  * We make this 1460 because we only care about Ethernet in the qemu context.
  */
+#undef TCP_MSS
 #define	TCP_MSS	1460
 
+#undef TCP_MAXWIN
 #define	TCP_MAXWIN	65535	/* largest value for (unscaled) window */
 
+#undef TCP_MAX_WINSHIFT
 #define TCP_MAX_WINSHIFT	14	/* maximum window shift */
 
 /*
commit cbd5979bb2ca8609ef19ebdfdc46043c46f0b42e
Merge: 49e00ba... d56de07...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Mar 28 12:46:39 2012 -0500

    Merge remote-tracking branch 'sstabellini/disk_io' into staging
    
    * sstabellini/disk_io:
      xen_disk: when using AIO flush after the operation is completed
      xen_disk: open disk with BDRV_O_NOCACHE | BDRV_O_CACHE_WB | BDRV_O_NATIVE_AIO

commit 49e00ba9698469b5eccec947050216192d9a9e34
Merge: c76d1a9... 7429f2e...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Mar 28 12:46:11 2012 -0500

    Merge remote-tracking branch 'sstabellini/xen-fixes' into staging
    
    * sstabellini/xen-fixes:
      xen_disk: detach the blkdev before bdrv_delete
      xen_console: ignore console disconnect events from console/0

commit c76d1a9b3f367754966c326d81ff8566798b473a
Merge: 0a5a4e0... 1829851...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Mar 28 12:45:22 2012 -0500

    Merge remote-tracking branch 'qmp/queue/qmp' into staging
    
    * qmp/queue/qmp:
      qmp: document strict parsing
      qmp: parse commands in strict mode
      qmp: add and use q type specifier
      qapi: add strict mode to input visitor
      qapi: place outermost object on qiv stack
      qapi: untangle next_list
      qapi: allow freeing partially-allocated objects
      qapi: shortcut visits on errors
      qapi: fix memory leak on error
      qapi: fail hard on stack imbalance
      qapi: add a test case for type errors
      qapi: add struct-errors test case to test-qmp-output-visitor
      qapi: fix double free in qmp_output_visitor_cleanup()

commit 0a5a4e0568d4cc981457a2d1e7f86923eeff94ed
Merge: 1658dd3... 6f06f17...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Mar 28 12:44:04 2012 -0500

    Merge remote-tracking branch 'alon/libcacard' into staging
    
    * alon/libcacard:
      libcacard/vcard_emul_nss: add warning for old coolkey
      libcacard/vcard_emul_nss: handle no readers at startup
      libcacard/vcard_emul_nss: don't stop thread when there are no slots

commit 1658dd32408c75e850b55ab0ff70d5cc402674d5
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Mar 18 11:31:23 2012 +0000

    sparc: pass page aligned addresses to tlb_set_page
    
    Mask incoming page address early so that resolved addresses
    are page aligned. Remove further address masking.
    
    Tested-by: Artyom Tarasenko <atar4qemu at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/mmu_helper.c b/target-sparc/mmu_helper.c
index 11fb9f5..cb73c44 100644
--- a/target-sparc/mmu_helper.c
+++ b/target-sparc/mmu_helper.c
@@ -150,18 +150,17 @@ static int get_physical_address(CPUSPARCState *env, target_phys_addr_t *physical
                 case 3: /* Reserved */
                     return (3 << 8) | (4 << 2);
                 case 2: /* L3 PTE */
-                    page_offset = (address & TARGET_PAGE_MASK) &
-                        (TARGET_PAGE_SIZE - 1);
+                    page_offset = 0;
                 }
                 *page_size = TARGET_PAGE_SIZE;
                 break;
             case 2: /* L2 PTE */
-                page_offset = address & 0x3ffff;
+                page_offset = address & 0x3f000;
                 *page_size = 0x40000;
             }
             break;
         case 2: /* L1 PTE */
-            page_offset = address & 0xffffff;
+            page_offset = address & 0xfff000;
             *page_size = 0x1000000;
         }
     }
@@ -206,11 +205,11 @@ int cpu_sparc_handle_mmu_fault(CPUSPARCState *env, target_ulong address, int rw,
     target_ulong page_size;
     int error_code = 0, prot, access_index;
 
+    address &= TARGET_PAGE_MASK;
     error_code = get_physical_address(env, &paddr, &prot, &access_index,
                                       address, rw, mmu_idx, &page_size);
+    vaddr = address;
     if (error_code == 0) {
-        vaddr = address & TARGET_PAGE_MASK;
-        paddr &= TARGET_PAGE_MASK;
 #ifdef DEBUG_MMU
         printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
                TARGET_FMT_lx "\n", address, paddr, vaddr);
@@ -230,7 +229,6 @@ int cpu_sparc_handle_mmu_fault(CPUSPARCState *env, target_ulong address, int rw,
            permissions. If no mapping is available, redirect accesses to
            neverland. Fake/overridden mappings will be flushed when
            switching to normal mode. */
-        vaddr = address & TARGET_PAGE_MASK;
         prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
         tlb_set_page(env, vaddr, paddr, prot, mmu_idx, TARGET_PAGE_SIZE);
         return 0;
@@ -704,17 +702,16 @@ static int get_physical_address(CPUSPARCState *env, target_phys_addr_t *physical
 int cpu_sparc_handle_mmu_fault(CPUSPARCState *env, target_ulong address, int rw,
                                int mmu_idx)
 {
-    target_ulong virt_addr, vaddr;
+    target_ulong vaddr;
     target_phys_addr_t paddr;
     target_ulong page_size;
     int error_code = 0, prot, access_index;
 
+    address &= TARGET_PAGE_MASK;
     error_code = get_physical_address(env, &paddr, &prot, &access_index,
                                       address, rw, mmu_idx, &page_size);
     if (error_code == 0) {
-        virt_addr = address & TARGET_PAGE_MASK;
-        vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
-                             (TARGET_PAGE_SIZE - 1));
+        vaddr = address;
 
         trace_mmu_helper_mmu_fault(address, paddr, mmu_idx, env->tl,
                                    env->dmmu.mmu_primary_context,
commit 7429f2e1981c6cc77a853e2e88654001bdddd461
Author: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Date:   Tue Mar 27 16:03:07 2012 +0000

    xen_disk: detach the blkdev before bdrv_delete
    
    We need to detach the blkdev from the BlockDriverState before calling
    bdrv_delete.
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 68fa36a..bf06fc1 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -726,6 +726,7 @@ static void blk_disconnect(struct XenDevice *xendev)
         if (!blkdev->dinfo) {
             /* close/delete only if we created it ourself */
             bdrv_close(blkdev->bs);
+            bdrv_detach_dev(blkdev->bs, blkdev);
             bdrv_delete(blkdev->bs);
         }
         blkdev->bs = NULL;
commit 028c85f0fffe5d4fdd435e06af4188397acf1cb6
Author: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Date:   Tue Mar 27 16:02:21 2012 +0000

    xen_console: ignore console disconnect events from console/0
    
    The first console has a different location compared to other PV devices
    (console, rather than device/console/0) and doesn't obey the xenstore
    state protocol. We already special case the first console in con_init
    and con_initialise, we should also do it in con_disconnect.
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/hw/xen_console.c b/hw/xen_console.c
index edcb31c..3794b19 100644
--- a/hw/xen_console.c
+++ b/hw/xen_console.c
@@ -248,6 +248,9 @@ static void con_disconnect(struct XenDevice *xendev)
 {
     struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
 
+    if (!xendev->dev) {
+        return;
+    }
     if (con->chr)
         qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL);
     xen_be_unbind_evtchn(&con->xendev);
commit 1829851cfee10e196abec50325d828de182fd356
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Mar 22 22:39:39 2012 +0100

    qmp: document strict parsing
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/QMP/qmp-spec.txt b/QMP/qmp-spec.txt
index 9d30a8c..1ba916c 100644
--- a/QMP/qmp-spec.txt
+++ b/QMP/qmp-spec.txt
@@ -209,13 +209,27 @@ incompatible way are disabled by default and will be advertised by the
 capabilities array (section '2.2 Server Greeting'). Thus, Clients can check
 that array and enable the capabilities they support.
 
-Additionally, Clients must not assume any particular:
-
-- Size of json-objects or length of json-arrays
+The QMP Server performs a type check on the arguments to a command.  It
+generates an error if a value does not have the expected type for its
+key, or if it does not understand a key that the Client included.  The
+strictness of the Server catches wrong assumptions of Clients about
+the Server's schema.  Clients can assume that, when such validation
+errors occur, they will be reported before the command generated any
+side effect.
+
+However, Clients must not assume any particular:
+
+- Length of json-arrays
+- Size of json-objects; in particular, future versions of QEMU may add
+  new keys and Clients should be able to ignore them.
 - Order of json-object members or json-array elements
 - Amount of errors generated by a command, that is, new errors can be added
   to any existing command in newer versions of the Server
 
+Of course, the Server does guarantee to send valid JSON.  But apart from
+this, a Client should be "conservative in what they send, and liberal in
+what they accept".
+
 6. Downstream extension of QMP
 ------------------------------
 
commit 6d36d7dc2b1eeded7627745989fa6e20cb39eefd
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Mar 22 12:51:12 2012 +0100

    qmp: parse commands in strict mode
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Reviewed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index 30a24d2..0b4f0a0 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -140,7 +140,7 @@ v = qapi_dealloc_get_visitor(md);
 ''')
     else:
         ret += mcgen('''
-mi = qmp_input_visitor_new(%(obj)s);
+mi = qmp_input_visitor_new_strict(%(obj)s);
 v = qmp_input_get_visitor(mi);
 ''',
                      obj=obj)
commit b9f8978cc428559c684df88ed69b709e33ba17dc
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Mar 22 12:51:11 2012 +0100

    qmp: add and use q type specifier
    
    "O" is being used by the transaction and qom-set commands to mean "any
    QObject", but it really means "do not validate the argument list".
    Add a new specifier with the correct meaning.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/monitor.c b/monitor.c
index 2ff1e0b..8946a10 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4157,6 +4157,9 @@ static int check_client_args_type(const QDict *client_args,
         case 'O':
             assert(flags & QMP_ACCEPT_UNKNOWNS);
             break;
+        case 'q':
+            /* Any QObject can be passed.  */
+            break;
         case '/':
         case '.':
             /*
diff --git a/qmp-commands.hx b/qmp-commands.hx
index c626ba8..9447871 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -708,7 +708,7 @@ EQMP
     },
     {
         .name       = "transaction",
-        .args_type  = "actions:O",
+        .args_type  = "actions:q",
         .mhandler.cmd_new = qmp_marshal_input_transaction,
     },
 
@@ -2125,7 +2125,7 @@ EQMP
 
     {
         .name       = "qom-set",
-	.args_type  = "path:s,property:s,opts:O",
+	.args_type  = "path:s,property:s,value:q",
 	.mhandler.cmd_new = qmp_qom_set,
     },
 
commit e38ac9621c8ab51880b9e6e833a125342d6b46b2
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Mar 22 12:51:10 2012 +0100

    qapi: add strict mode to input visitor
    
    While QMP in general is designed so that it is possible to ignore
    unknown arguments, in the case of the QMP server it is better to
    reject them to detect bad clients.  In fact, we're already doing
    this at the top level in the argument checker.  To extend this to
    complex structures, add a mode to the input visitor where it checks
    for unvisited keys and raises an error if it finds one.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
index 5765e76..74386b9 100644
--- a/qapi/qmp-input-visitor.c
+++ b/qapi/qmp-input-visitor.c
@@ -24,6 +24,7 @@ typedef struct StackObject
 {
     QObject *obj;
     const QListEntry *entry;
+    GHashTable *h;
 } StackObject;
 
 struct QmpInputVisitor
@@ -31,6 +32,7 @@ struct QmpInputVisitor
     Visitor visitor;
     StackObject stack[QIV_STACK_SIZE];
     int nb_stack;
+    bool strict;
 };
 
 static QmpInputVisitor *to_qiv(Visitor *v)
@@ -45,6 +47,9 @@ static QObject *qmp_input_get_object(QmpInputVisitor *qiv,
 
     if (qobj) {
         if (name && qobject_type(qobj) == QTYPE_QDICT) {
+            if (qiv->stack[qiv->nb_stack - 1].h) {
+                g_hash_table_remove(qiv->stack[qiv->nb_stack - 1].h, name);
+            }
             return qdict_get(qobject_to_qdict(qobj), name);
         } else if (qiv->stack[qiv->nb_stack - 1].entry) {
             return qlist_entry_obj(qiv->stack[qiv->nb_stack - 1].entry);
@@ -54,20 +59,47 @@ static QObject *qmp_input_get_object(QmpInputVisitor *qiv,
     return qobj;
 }
 
+static void qdict_add_key(const char *key, QObject *obj, void *opaque)
+{
+    GHashTable *h = opaque;
+    g_hash_table_insert(h, (gpointer) key, NULL);
+}
+
 static void qmp_input_push(QmpInputVisitor *qiv, QObject *obj, Error **errp)
 {
-    qiv->stack[qiv->nb_stack].obj = obj;
-    qiv->stack[qiv->nb_stack].entry = NULL;
-    qiv->nb_stack++;
+    GHashTable *h;
 
     if (qiv->nb_stack >= QIV_STACK_SIZE) {
         error_set(errp, QERR_BUFFER_OVERRUN);
         return;
     }
+
+    qiv->stack[qiv->nb_stack].obj = obj;
+    qiv->stack[qiv->nb_stack].entry = NULL;
+    qiv->stack[qiv->nb_stack].h = NULL;
+
+    if (qiv->strict && qobject_type(obj) == QTYPE_QDICT) {
+        h = g_hash_table_new(g_str_hash, g_str_equal);
+        qdict_iter(qobject_to_qdict(obj), qdict_add_key, h);
+        qiv->stack[qiv->nb_stack].h = h;
+    }
+
+    qiv->nb_stack++;
 }
 
 static void qmp_input_pop(QmpInputVisitor *qiv, Error **errp)
 {
+    GHashTableIter iter;
+    gpointer key;
+
+    if (qiv->strict && qiv->stack[qiv->nb_stack - 1].h) {
+        g_hash_table_iter_init(&iter, qiv->stack[qiv->nb_stack - 1].h);
+        if (g_hash_table_iter_next(&iter, &key, NULL)) {
+            error_set(errp, QERR_QMP_EXTRA_MEMBER, (char *) key);
+        }
+        g_hash_table_unref(qiv->stack[qiv->nb_stack - 1].h);
+    }
+
     assert(qiv->nb_stack > 0);
     qiv->nb_stack--;
 }
@@ -262,3 +294,13 @@ QmpInputVisitor *qmp_input_visitor_new(QObject *obj)
 
     return v;
 }
+
+QmpInputVisitor *qmp_input_visitor_new_strict(QObject *obj)
+{
+    QmpInputVisitor *v;
+
+    v = qmp_input_visitor_new(obj);
+    v->strict = true;
+
+    return v;
+}
diff --git a/qapi/qmp-input-visitor.h b/qapi/qmp-input-visitor.h
index 3f798f0..e0a48a5 100644
--- a/qapi/qmp-input-visitor.h
+++ b/qapi/qmp-input-visitor.h
@@ -20,6 +20,8 @@
 typedef struct QmpInputVisitor QmpInputVisitor;
 
 QmpInputVisitor *qmp_input_visitor_new(QObject *obj);
+QmpInputVisitor *qmp_input_visitor_new_strict(QObject *obj);
+
 void qmp_input_visitor_cleanup(QmpInputVisitor *v);
 
 Visitor *qmp_input_get_visitor(QmpInputVisitor *v);
diff --git a/test-qmp-input-strict.c b/test-qmp-input-strict.c
new file mode 100644
index 0000000..f6df8cb
--- /dev/null
+++ b/test-qmp-input-strict.c
@@ -0,0 +1,234 @@
+/*
+ * QMP Input Visitor unit-tests (strict mode).
+ *
+ * Copyright (C) 2011-2012 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino at redhat.com>
+ *  Paolo Bonzini <pbonzini at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <glib.h>
+#include <stdarg.h>
+
+#include "qapi/qmp-input-visitor.h"
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "qemu-objects.h"
+
+typedef struct TestInputVisitorData {
+    QObject *obj;
+    QmpInputVisitor *qiv;
+} TestInputVisitorData;
+
+static void validate_teardown(TestInputVisitorData *data,
+                               const void *unused)
+{
+    qobject_decref(data->obj);
+    data->obj = NULL;
+
+    if (data->qiv) {
+        qmp_input_visitor_cleanup(data->qiv);
+        data->qiv = NULL;
+    }
+}
+
+/* This is provided instead of a test setup function so that the JSON
+   string used by the tests are kept in the test functions (and not
+   int main()) */
+static GCC_FMT_ATTR(2, 3)
+Visitor *validate_test_init(TestInputVisitorData *data,
+                             const char *json_string, ...)
+{
+    Visitor *v;
+    va_list ap;
+
+    va_start(ap, json_string);
+    data->obj = qobject_from_jsonv(json_string, &ap);
+    va_end(ap);
+
+    g_assert(data->obj != NULL);
+
+    data->qiv = qmp_input_visitor_new_strict(data->obj);
+    g_assert(data->qiv != NULL);
+
+    v = qmp_input_get_visitor(data->qiv);
+    g_assert(v != NULL);
+
+    return v;
+}
+
+typedef struct TestStruct
+{
+    int64_t integer;
+    bool boolean;
+    char *string;
+} TestStruct;
+
+static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
+                                  const char *name, Error **errp)
+{
+    visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
+                       errp);
+
+    visit_type_int(v, &(*obj)->integer, "integer", errp);
+    visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
+    visit_type_str(v, &(*obj)->string, "string", errp);
+
+    visit_end_struct(v, errp);
+}
+
+static void test_validate_struct(TestInputVisitorData *data,
+                                  const void *unused)
+{
+    TestStruct *p = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
+
+    visit_type_TestStruct(v, &p, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_free(p->string);
+    g_free(p);
+}
+
+static void test_validate_struct_nested(TestInputVisitorData *data,
+                                         const void *unused)
+{
+    UserDefNested *udp = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string' }, 'string2': 'string2'}}}");
+
+    visit_type_UserDefNested(v, &udp, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    qapi_free_UserDefNested(udp);
+}
+
+static void test_validate_list(TestInputVisitorData *data,
+                                const void *unused)
+{
+    UserDefOneList *head = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
+
+    visit_type_UserDefOneList(v, &head, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    qapi_free_UserDefOneList(head);
+}
+
+static void test_validate_union(TestInputVisitorData *data,
+                                 const void *unused)
+{
+    UserDefUnion *tmp = NULL;
+    Visitor *v;
+    Error *errp = NULL;
+
+    v = validate_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 } }");
+
+    visit_type_UserDefUnion(v, &tmp, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    qapi_free_UserDefUnion(tmp);
+}
+
+static void test_validate_fail_struct(TestInputVisitorData *data,
+                                       const void *unused)
+{
+    TestStruct *p = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo', 'extra': 42 }");
+
+    visit_type_TestStruct(v, &p, NULL, &errp);
+    g_assert(error_is_set(&errp));
+    if (p) {
+        g_free(p->string);
+    }
+    g_free(p);
+}
+
+static void test_validate_fail_struct_nested(TestInputVisitorData *data,
+                                              const void *unused)
+{
+    UserDefNested *udp = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string', 'extra': [42, 23, {'foo':'bar'}] }, 'string2': 'string2'}}}");
+
+    visit_type_UserDefNested(v, &udp, NULL, &errp);
+    g_assert(error_is_set(&errp));
+    qapi_free_UserDefNested(udp);
+}
+
+static void test_validate_fail_list(TestInputVisitorData *data,
+                                     const void *unused)
+{
+    UserDefOneList *head = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44, 'extra': 'ggg' } ]");
+
+    visit_type_UserDefOneList(v, &head, NULL, &errp);
+    g_assert(error_is_set(&errp));
+    qapi_free_UserDefOneList(head);
+}
+
+static void test_validate_fail_union(TestInputVisitorData *data,
+                                      const void *unused)
+{
+    UserDefUnion *tmp = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 }, 'extra': 'yyy' }");
+
+    visit_type_UserDefUnion(v, &tmp, NULL, &errp);
+    g_assert(error_is_set(&errp));
+    qapi_free_UserDefUnion(tmp);
+}
+
+static void validate_test_add(const char *testpath,
+                               TestInputVisitorData *data,
+                               void (*test_func)(TestInputVisitorData *data, const void *user_data))
+{
+    g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
+               validate_teardown);
+}
+
+int main(int argc, char **argv)
+{
+    TestInputVisitorData testdata;
+
+    g_test_init(&argc, &argv, NULL);
+
+    validate_test_add("/visitor/input-strict/pass/struct",
+                       &testdata, test_validate_struct);
+    validate_test_add("/visitor/input-strict/pass/struct-nested",
+                       &testdata, test_validate_struct_nested);
+    validate_test_add("/visitor/input-strict/pass/list",
+                       &testdata, test_validate_list);
+    validate_test_add("/visitor/input-strict/pass/union",
+                       &testdata, test_validate_union);
+    validate_test_add("/visitor/input-strict/fail/struct",
+                       &testdata, test_validate_fail_struct);
+    validate_test_add("/visitor/input-strict/fail/struct-nested",
+                       &testdata, test_validate_fail_struct_nested);
+    validate_test_add("/visitor/input-strict/fail/list",
+                       &testdata, test_validate_fail_list);
+    validate_test_add("/visitor/input-strict/fail/union",
+                       &testdata, test_validate_fail_union);
+
+    g_test_run();
+
+    return 0;
+}
diff --git a/tests/Makefile b/tests/Makefile
index 94ea342..2a2fff7 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -16,7 +16,7 @@ check-qfloat: check-qfloat.o qfloat.o $(tools-obj-y)
 check-qjson: check-qjson.o $(qobject-obj-y) $(tools-obj-y)
 test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y) $(tools-obj-y)
 
-test-qmp-input-visitor.o test-qmp-output-visitor.o \
+test-qmp-input-visitor.o test-qmp-output-visitor.o test-qmp-input-strict.o \
 test-string-input-visitor.o test-string-output-visitor.o \
 	test-qmp-commands.o: QEMU_CFLAGS += -I $(qapi-dir)
 
@@ -37,6 +37,9 @@ test-string-output-visitor: test-string-output-visitor.o $(qobject-obj-y) $(qapi
 test-string-input-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
 test-string-input-visitor: test-string-input-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
 
+test-qmp-input-strict.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
+test-qmp-input-strict: test-qmp-input-strict.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
+
 test-qmp-output-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
 test-qmp-output-visitor: test-qmp-output-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
 
commit 4faaec6acf7f18b39c362edb9f6aa5658aab8b85
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Mar 22 12:51:09 2012 +0100

    qapi: place outermost object on qiv stack
    
    This is a slight change in the implementation of QMPInputVisitor
    that helps when adding strict mode.
    
    Const QObjects cannot be inc/decref-ed, and that's why QMPInputVisitor
    relies heavily on weak references to inner objects.  I'm not removing
    the weak references now, but since refcount+const is a lost battle in C
    (C++ has "mutable") I think removing const is fine in this case.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
index 413e333..5765e76 100644
--- a/qapi/qmp-input-visitor.c
+++ b/qapi/qmp-input-visitor.c
@@ -22,14 +22,13 @@
 
 typedef struct StackObject
 {
-    const QObject *obj;
-    const  QListEntry *entry;
+    QObject *obj;
+    const QListEntry *entry;
 } StackObject;
 
 struct QmpInputVisitor
 {
     Visitor visitor;
-    QObject *obj;
     StackObject stack[QIV_STACK_SIZE];
     int nb_stack;
 };
@@ -39,21 +38,15 @@ static QmpInputVisitor *to_qiv(Visitor *v)
     return container_of(v, QmpInputVisitor, visitor);
 }
 
-static const QObject *qmp_input_get_object(QmpInputVisitor *qiv,
-                                           const char *name)
+static QObject *qmp_input_get_object(QmpInputVisitor *qiv,
+                                     const char *name)
 {
-    const QObject *qobj;
-
-    if (qiv->nb_stack == 0) {
-        qobj = qiv->obj;
-    } else {
-        qobj = qiv->stack[qiv->nb_stack - 1].obj;
-    }
+    QObject *qobj = qiv->stack[qiv->nb_stack - 1].obj;
 
     if (qobj) {
         if (name && qobject_type(qobj) == QTYPE_QDICT) {
             return qdict_get(qobject_to_qdict(qobj), name);
-        } else if (qiv->nb_stack > 0 && qobject_type(qobj) == QTYPE_QLIST) {
+        } else if (qiv->stack[qiv->nb_stack - 1].entry) {
             return qlist_entry_obj(qiv->stack[qiv->nb_stack - 1].entry);
         }
     }
@@ -61,7 +54,7 @@ static const QObject *qmp_input_get_object(QmpInputVisitor *qiv,
     return qobj;
 }
 
-static void qmp_input_push(QmpInputVisitor *qiv, const QObject *obj, Error **errp)
+static void qmp_input_push(QmpInputVisitor *qiv, QObject *obj, Error **errp)
 {
     qiv->stack[qiv->nb_stack].obj = obj;
     qiv->stack[qiv->nb_stack].entry = NULL;
@@ -83,7 +76,7 @@ static void qmp_input_start_struct(Visitor *v, void **obj, const char *kind,
                                    const char *name, size_t size, Error **errp)
 {
     QmpInputVisitor *qiv = to_qiv(v);
-    const QObject *qobj = qmp_input_get_object(qiv, name);
+    QObject *qobj = qmp_input_get_object(qiv, name);
     Error *err = NULL;
 
     if (!qobj || qobject_type(qobj) != QTYPE_QDICT) {
@@ -113,7 +106,7 @@ static void qmp_input_end_struct(Visitor *v, Error **errp)
 static void qmp_input_start_list(Visitor *v, const char *name, Error **errp)
 {
     QmpInputVisitor *qiv = to_qiv(v);
-    const QObject *qobj = qmp_input_get_object(qiv, name);
+    QObject *qobj = qmp_input_get_object(qiv, name);
 
     if (!qobj || qobject_type(qobj) != QTYPE_QLIST) {
         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
@@ -165,7 +158,7 @@ static void qmp_input_type_int(Visitor *v, int64_t *obj, const char *name,
                                Error **errp)
 {
     QmpInputVisitor *qiv = to_qiv(v);
-    const QObject *qobj = qmp_input_get_object(qiv, name);
+    QObject *qobj = qmp_input_get_object(qiv, name);
 
     if (!qobj || qobject_type(qobj) != QTYPE_QINT) {
         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
@@ -180,7 +173,7 @@ static void qmp_input_type_bool(Visitor *v, bool *obj, const char *name,
                                 Error **errp)
 {
     QmpInputVisitor *qiv = to_qiv(v);
-    const QObject *qobj = qmp_input_get_object(qiv, name);
+    QObject *qobj = qmp_input_get_object(qiv, name);
 
     if (!qobj || qobject_type(qobj) != QTYPE_QBOOL) {
         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
@@ -195,7 +188,7 @@ static void qmp_input_type_str(Visitor *v, char **obj, const char *name,
                                Error **errp)
 {
     QmpInputVisitor *qiv = to_qiv(v);
-    const QObject *qobj = qmp_input_get_object(qiv, name);
+    QObject *qobj = qmp_input_get_object(qiv, name);
 
     if (!qobj || qobject_type(qobj) != QTYPE_QSTRING) {
         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
@@ -210,7 +203,7 @@ static void qmp_input_type_number(Visitor *v, double *obj, const char *name,
                                   Error **errp)
 {
     QmpInputVisitor *qiv = to_qiv(v);
-    const QObject *qobj = qmp_input_get_object(qiv, name);
+    QObject *qobj = qmp_input_get_object(qiv, name);
 
     if (!qobj || qobject_type(qobj) != QTYPE_QFLOAT) {
         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
@@ -225,7 +218,7 @@ static void qmp_input_start_optional(Visitor *v, bool *present,
                                      const char *name, Error **errp)
 {
     QmpInputVisitor *qiv = to_qiv(v);
-    const QObject *qobj = qmp_input_get_object(qiv, name);
+    QObject *qobj = qmp_input_get_object(qiv, name);
 
     if (!qobj) {
         *present = false;
@@ -242,7 +235,7 @@ Visitor *qmp_input_get_visitor(QmpInputVisitor *v)
 
 void qmp_input_visitor_cleanup(QmpInputVisitor *v)
 {
-    qobject_decref(v->obj);
+    qobject_decref(v->stack[0].obj);
     g_free(v);
 }
 
@@ -264,8 +257,8 @@ QmpInputVisitor *qmp_input_visitor_new(QObject *obj)
     v->visitor.type_number = qmp_input_type_number;
     v->visitor.start_optional = qmp_input_start_optional;
 
-    v->obj = obj;
-    qobject_incref(v->obj);
+    qmp_input_push(v, obj, NULL);
+    qobject_incref(obj);
 
     return v;
 }
commit 3a86a0fa76b5103a122b6e817b3827b2837f4956
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Mar 22 22:38:40 2012 +0100

    qapi: untangle next_list
    
    Right now, the semantics of next_list are complicated.  The caller must:
    
    * call start_list
    
    * call next_list for each element *including the first*
    
    * on the first call to next_list, the second argument should point to
    NULL and the result is the head of the list.  On subsequent calls,
    the second argument should point to the last node (last result of
    next_list) and next_list itself tacks the element at the tail of the
    list.
    
    This works for both input and output visitor, but having the visitor
    write memory when it is only reading the list is ugly.  Plus, relying
    on *list to detect the first call is tricky and undocumented.
    
    We can initialize so->entry in next_list instead of start_list, leaving
    it NULL in start_list.  This way next_list sees clearly whether it is
    on the first call---as a bonus, it discriminates the cases based on
    internal state of the visitor rather than external state.  We can
    also pull the assignment of the list head from generated code up to
    next_list.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Reviewed-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
index 5831e37..ad11767 100644
--- a/docs/qapi-code-gen.txt
+++ b/docs/qapi-code-gen.txt
@@ -194,11 +194,11 @@ Example:
 
     void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp)
     {
-        GenericList *i;
+        GenericList *i, **prev = (GenericList **)obj;
 
         visit_start_list(m, name, errp);
 
-        for (i = visit_next_list(m, (GenericList **)obj, errp); i; i = visit_next_list(m, &i, errp)) {
+        for (; (i = visit_next_list(m, prev, errp)) != NULL; prev = &i) {
             UserDefOneList *native_i = (UserDefOneList *)i;
             visit_type_UserDefOne(m, &native_i->value, NULL, errp);
         }
diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
index ef9288f..413e333 100644
--- a/qapi/qmp-input-visitor.c
+++ b/qapi/qmp-input-visitor.c
@@ -64,9 +64,7 @@ static const QObject *qmp_input_get_object(QmpInputVisitor *qiv,
 static void qmp_input_push(QmpInputVisitor *qiv, const QObject *obj, Error **errp)
 {
     qiv->stack[qiv->nb_stack].obj = obj;
-    if (qobject_type(obj) == QTYPE_QLIST) {
-        qiv->stack[qiv->nb_stack].entry = qlist_first(qobject_to_qlist(obj));
-    }
+    qiv->stack[qiv->nb_stack].entry = NULL;
     qiv->nb_stack++;
 
     if (qiv->nb_stack >= QIV_STACK_SIZE) {
@@ -132,18 +130,24 @@ static GenericList *qmp_input_next_list(Visitor *v, GenericList **list,
     QmpInputVisitor *qiv = to_qiv(v);
     GenericList *entry;
     StackObject *so = &qiv->stack[qiv->nb_stack - 1];
+    bool first;
+
+    if (so->entry == NULL) {
+        so->entry = qlist_first(qobject_to_qlist(so->obj));
+        first = true;
+    } else {
+        so->entry = qlist_next(so->entry);
+        first = false;
+    }
 
     if (so->entry == NULL) {
         return NULL;
     }
 
     entry = g_malloc0(sizeof(*entry));
-    if (*list) {
-        so->entry = qlist_next(so->entry);
-        if (so->entry == NULL) {
-            g_free(entry);
-            return NULL;
-        }
+    if (first) {
+        *list = entry;
+    } else {
         (*list)->next = entry;
     }
 
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 31d50a6..8d4e94a 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -86,14 +86,14 @@ def generate_visit_list(name, members):
 
 void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, Error **errp)
 {
-    GenericList *i, **head = (GenericList **)obj;
+    GenericList *i, **prev = (GenericList **)obj;
 
     if (error_is_set(errp)) {
         return;
     }
     visit_start_list(m, name, errp);
 
-    for (*head = i = visit_next_list(m, head, errp); i; i = visit_next_list(m, &i, errp)) {
+    for (; (i = visit_next_list(m, prev, errp)) != NULL; prev = &i) {
         %(name)sList *native_i = (%(name)sList *)i;
         visit_type_%(name)s(m, &native_i->value, NULL, errp);
     }
commit 69b50071d8dc1b4e06724bb73cda8e2f10fe30c7
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Mar 22 12:51:07 2012 +0100

    qapi: allow freeing partially-allocated objects
    
    Objects going through the dealloc visitor can be only partially allocated.
    Detect the situation and avoid a segfault.  This also helps with the
    input visitor, when there are errors.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 4297621..31d50a6 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -65,6 +65,9 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
         return;
     }
     visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), errp);
+    if (obj && !*obj) {
+        goto end;
+    }
 ''',
                 name=name)
     push_indent()
@@ -72,6 +75,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
     pop_indent()
 
     ret += mcgen('''
+end:
     visit_end_struct(m, errp);
 }
 ''')
@@ -122,6 +126,9 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
         return;
     }
     visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err);
+    if (obj && !*obj) {
+        goto end;
+    }
     visit_type_%(name)sKind(m, &(*obj)->kind, "type", &err);
     if (err) {
         error_propagate(errp, err);
commit b6f0474fc0fe6f81d93d620a5d24bc30b22d561b
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Mar 22 12:51:06 2012 +0100

    qapi: shortcut visits on errors
    
    We can exit very soon if we enter a visitor with a preexisting error.
    This simplifies some cases because we will not have to deal with
    obj being non-NULL while *obj is NULL.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 78c947c..4297621 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -61,6 +61,9 @@ def generate_visit_struct(name, members):
 
 void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp)
 {
+    if (error_is_set(errp)) {
+        return;
+    }
     visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), errp);
 ''',
                 name=name)
@@ -81,6 +84,9 @@ void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name,
 {
     GenericList *i, **head = (GenericList **)obj;
 
+    if (error_is_set(errp)) {
+        return;
+    }
     visit_start_list(m, name, errp);
 
     for (*head = i = visit_next_list(m, head, errp); i; i = visit_next_list(m, &i, errp)) {
@@ -112,6 +118,9 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
 {
     Error *err = NULL;
 
+    if (error_is_set(errp)) {
+        return;
+    }
     visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err);
     visit_type_%(name)sKind(m, &(*obj)->kind, "type", &err);
     if (err) {
commit 8b714d3747e6870db85dd9382adb8ee371633092
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Mar 22 12:51:05 2012 +0100

    qapi: fix memory leak on error
    
    QmpInputVisitor would leak the malloced struct if the stack was
    overflowed.  This can be easily fixed using error_propagate.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
index b4013cc..ef9288f 100644
--- a/qapi/qmp-input-visitor.c
+++ b/qapi/qmp-input-visitor.c
@@ -86,6 +86,7 @@ static void qmp_input_start_struct(Visitor *v, void **obj, const char *kind,
 {
     QmpInputVisitor *qiv = to_qiv(v);
     const QObject *qobj = qmp_input_get_object(qiv, name);
+    Error *err = NULL;
 
     if (!qobj || qobject_type(qobj) != QTYPE_QDICT) {
         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
@@ -93,8 +94,9 @@ static void qmp_input_start_struct(Visitor *v, void **obj, const char *kind,
         return;
     }
 
-    qmp_input_push(qiv, qobj, errp);
-    if (error_is_set(errp)) {
+    qmp_input_push(qiv, qobj, &err);
+    if (err) {
+        error_propagate(errp, err);
         return;
     }
 
commit 2c7ff93359e820f90bfb4ac9efd6ec35949e5630
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Mar 22 12:51:04 2012 +0100

    qapi: fail hard on stack imbalance
    
    QmpOutputVisitor will segfault if an imbalanced end function is
    called.  So we can abort in QmpInputVisitor too.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
index e6b6152..b4013cc 100644
--- a/qapi/qmp-input-visitor.c
+++ b/qapi/qmp-input-visitor.c
@@ -77,11 +77,8 @@ static void qmp_input_push(QmpInputVisitor *qiv, const QObject *obj, Error **err
 
 static void qmp_input_pop(QmpInputVisitor *qiv, Error **errp)
 {
+    assert(qiv->nb_stack > 0);
     qiv->nb_stack--;
-    if (qiv->nb_stack < 0) {
-        error_set(errp, QERR_BUFFER_OVERRUN);
-        return;
-    }
 }
 
 static void qmp_input_start_struct(Visitor *v, void **obj, const char *kind,
commit 3dcf71f632a0a41ff8c9a27f7cf967c647806c07
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Mar 22 12:51:03 2012 +0100

    qapi: add a test case for type errors
    
    There is no test case for parse errors, add one.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/test-qmp-input-visitor.c b/test-qmp-input-visitor.c
index 1996e49..c30fdc4 100644
--- a/test-qmp-input-visitor.c
+++ b/test-qmp-input-visitor.c
@@ -258,6 +258,23 @@ static void input_visitor_test_add(const char *testpath,
                visitor_input_teardown);
 }
 
+static void test_visitor_in_errors(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    TestStruct *p = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', 'string': -42 }");
+
+    visit_type_TestStruct(v, &p, NULL, &errp);
+    g_assert(error_is_set(&errp));
+    g_assert(p->string == NULL);
+
+    g_free(p->string);
+    g_free(p);
+}
+
 int main(int argc, char **argv)
 {
     TestInputVisitorData in_visitor_data;
@@ -282,6 +299,8 @@ int main(int argc, char **argv)
                             &in_visitor_data, test_visitor_in_list);
     input_visitor_test_add("/visitor/input/union",
                             &in_visitor_data, test_visitor_in_union);
+    input_visitor_test_add("/visitor/input/errors",
+                            &in_visitor_data, test_visitor_in_errors);
 
     g_test_run();
 
commit 9e9eace89e2a8180f0a5fd312bb87e53e6f2004b
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Mar 20 11:22:49 2012 +0100

    qapi: add struct-errors test case to test-qmp-output-visitor
    
    This test case verifies that invalid native enums are caught, and causes
    qapi to tear down the QObject tree under construction, exercising the
    previous patch.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qapi-schema-test.json b/qapi-schema-test.json
index 8c7f9f7..9eae350 100644
--- a/qapi-schema-test.json
+++ b/qapi-schema-test.json
@@ -8,7 +8,7 @@
 
 # for testing nested structs
 { 'type': 'UserDefOne',
-  'data': { 'integer': 'int', 'string': 'str' } }
+  'data': { 'integer': 'int', 'string': 'str', '*enum1': 'EnumOne' } }
 
 { 'type': 'UserDefTwo',
   'data': { 'string': 'str',
diff --git a/test-qmp-output-visitor.c b/test-qmp-output-visitor.c
index 4d6c4d4..24a6359 100644
--- a/test-qmp-output-visitor.c
+++ b/test-qmp-output-visitor.c
@@ -274,6 +274,24 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
     qapi_free_UserDefNested(ud2);
 }
 
+static void test_visitor_out_struct_errors(TestOutputVisitorData *data,
+                                           const void *unused)
+{
+    EnumOne bad_values[] = { ENUM_ONE_MAX, -1 };
+    UserDefOne u = { 0 }, *pu = &u;
+    Error *errp;
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
+        errp = NULL;
+        u.has_enum1 = true;
+        u.enum1 = bad_values[i];
+        visit_type_UserDefOne(data->ov, &pu, "unused", &errp);
+        g_assert(error_is_set(&errp) == true);
+        error_free(errp);
+    }
+}
+
 typedef struct TestStructList
 {
     TestStruct *value;
@@ -444,6 +462,8 @@ int main(int argc, char **argv)
                             &out_visitor_data, test_visitor_out_struct);
     output_visitor_test_add("/visitor/output/struct-nested",
                             &out_visitor_data, test_visitor_out_struct_nested);
+    output_visitor_test_add("/visitor/output/struct-errors",
+                            &out_visitor_data, test_visitor_out_struct_errors);
     output_visitor_test_add("/visitor/output/list",
                             &out_visitor_data, test_visitor_out_list);
     output_visitor_test_add("/visitor/output/list-qapi-free",
commit f24582d6ad8a080e008974c000bf0ae635d036ac
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Tue Mar 20 11:22:48 2012 +0100

    qapi: fix double free in qmp_output_visitor_cleanup()
    
    Stack entries in QmpOutputVisitor are navigation links (weak references),
    except the bottom (ie. least recently added) entry, which owns the root
    QObject [1]. Make qmp_output_visitor_cleanup() drop the stack entries,
    then release the QObject tree by the root.
    
    Attempting to serialize an invalid enum inside a dictionary is an example
    for triggering the double free.
    
    [1] http://lists.nongnu.org/archive/html/qemu-devel/2012-03/msg03276.html
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qapi/qmp-output-visitor.c b/qapi/qmp-output-visitor.c
index e0697b0..2bce9d5 100644
--- a/qapi/qmp-output-visitor.c
+++ b/qapi/qmp-output-visitor.c
@@ -199,14 +199,16 @@ void qmp_output_visitor_cleanup(QmpOutputVisitor *v)
 {
     QStackEntry *e, *tmp;
 
+    /* The bottom QStackEntry, if any, owns the root QObject. See the
+     * qmp_output_push_obj() invocations in qmp_output_add_obj(). */
+    QObject *root = QTAILQ_EMPTY(&v->stack) ? NULL : qmp_output_first(v);
+
     QTAILQ_FOREACH_SAFE(e, &v->stack, node, tmp) {
         QTAILQ_REMOVE(&v->stack, e, node);
-        if (e->value) {
-            qobject_decref(e->value);
-        }
         g_free(e);
     }
 
+    qobject_decref(root);
     g_free(v);
 }
 
commit 8a22565b7c2d1920b02b94e7a8021c65895a3a22
Merge: 29b18b7... e72c3f2...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 26 15:17:51 2012 -0500

    Merge remote-tracking branch 'mdroth/qga-pull-3-26-12' into staging
    
    * mdroth/qga-pull-3-26-12:
      qemu-ga: fix bsd build, and re-org linux-specific implementations

commit 29b18b7a53c0b5053e895947b0b9008120632f9b
Merge: 3d032f0... 95b752b...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 26 15:08:26 2012 -0500

    Merge remote-tracking branch 'stefanha/trivial-patches' into staging
    
    * stefanha/trivial-patches:
      trace-events: Fix broken build caused by wrong format specifier
      test: add test-qmp-commands to make check
      qapi: remove print statements from test-qmp-commands
      test: remove qemu-ga reference
      vl.c: fix '-cpu ?' segfault

commit 3d032f0f5a7968e1721dd6eca00b61ee84510411
Merge: 81fe74d... a13ccc9...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 26 15:08:15 2012 -0500

    Merge remote-tracking branch 'spice/spice.v51' into staging
    
    * spice/spice.v51:
      ui/spice-display: use uintptr_t when casting qxl physical addresses
      ui/spice-display.c: Fix compilation warnings on 32 bit hosts

commit 81fe74dc1cffc9451bf836e732e526b3ce3e085b
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Wed Mar 21 10:10:46 2012 -0500

    test: remove qemu-ga reference
    
    This was added by mistake a while back.
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile b/Makefile
index 8d6b558..d8e1f36 100644
--- a/Makefile
+++ b/Makefile
@@ -173,6 +173,7 @@ qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
 $(qapi-obj-y): $(GENERATED_HEADERS)
 qapi-dir := $(BUILD_DIR)/qapi-generated
 qemu-ga$(EXESUF): LIBS = $(LIBS_QGA)
+qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
 
 gen-out-type = $(subst .,-,$(suffix $@))
 
diff --git a/tests/Makefile b/tests/Makefile
index c78ade1..354fdbb 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -17,7 +17,7 @@ test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y)
 
 test-qmp-input-visitor.o test-qmp-output-visitor.o \
 test-string-input-visitor.o test-string-output-visitor.o \
-	test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
+	test-qmp-commands.o: QEMU_CFLAGS += -I $(qapi-dir)
 
 $(qapi-dir)/test-qapi-types.c $(qapi-dir)/test-qapi-types.h :\
 $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
commit 3017b72cd0f4c7f7df9e93d3f7a4f600669187f7
Author: Miroslav Rezanina <mrezanin at redhat.com>
Date:   Wed Mar 21 13:46:54 2012 +0100

    Man page: Add -global description
    
    There's only TODO information in qemu man page for -global option. This is a basic description of this option with simple example.
    
    Signed-off-by: Miroslav Rezanina <mrezanin at redhat.com>
    
    v4:
     - break long line
    
    v3:
     - add use case description
     - use prop instead of property
    
    v2:
     - Use better value in example
    Patch:
    --
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-options.hx b/qemu-options.hx
index daefce3..662f571 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -288,13 +288,21 @@ TODO
 ETEXI
 
 DEF("global", HAS_ARG, QEMU_OPTION_global,
-    "-global driver.property=value\n"
+    "-global driver.prop=value\n"
     "                set a global default for a driver property\n",
     QEMU_ARCH_ALL)
 STEXI
- at item -global
+ at item -global @var{driver}. at var{prop}=@var{value}
 @findex -global
-TODO
+Set default value of @var{driver}'s property @var{prop} to @var{value}, e.g.:
+
+ at example
+qemu -global ide-drive.physical_block_size=4096 -drive file=file,if=ide,index=0,media=disk
+ at end example
+
+In particular, you can use this to set driver properties for devices which are 
+created automatically by the machine model. To create a device which is not 
+created automatically and set properties on it, use - at option{device}.
 ETEXI
 
 DEF("mtdblock", HAS_ARG, QEMU_OPTION_mtdblock,
commit c9da228b49792354af6bb6735bc48bc1c156bc0d
Author: Federico Simoncelli <fsimonce at redhat.com>
Date:   Tue Mar 20 13:54:35 2012 +0000

    qapi: add c_fun to escape function names
    
    Signed-off-by: Federico Simoncelli <fsimonce at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index 3aabf61..30a24d2 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -42,7 +42,7 @@ def generate_command_decl(name, args, ret_type):
     return mcgen('''
 %(ret_type)s qmp_%(name)s(%(args)sError **errp);
 ''',
-                 ret_type=c_type(ret_type), name=c_var(name), args=arglist).strip()
+                 ret_type=c_type(ret_type), name=c_fun(name), args=arglist).strip()
 
 def gen_sync_call(name, args, ret_type, indent=0):
     ret = ""
@@ -59,7 +59,7 @@ def gen_sync_call(name, args, ret_type, indent=0):
 %(retval)sqmp_%(name)s(%(args)serrp);
 
 ''',
-                name=c_var(name), args=arglist, retval=retval).rstrip()
+                name=c_fun(name), args=arglist, retval=retval).rstrip()
     if ret_type:
         ret += "\n" + mcgen(''''
 if (!error_is_set(errp)) {
@@ -74,7 +74,7 @@ if (!error_is_set(errp)) {
 def gen_marshal_output_call(name, ret_type):
     if not ret_type:
         return ""
-    return "qmp_marshal_output_%s(retval, ret, errp);" % c_var(name)
+    return "qmp_marshal_output_%s(retval, ret, errp);" % c_fun(name)
 
 def gen_visitor_output_containers_decl(ret_type):
     ret = ""
@@ -198,16 +198,16 @@ static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_o
     qapi_dealloc_visitor_cleanup(md);
 }
 ''',
-                c_ret_type=c_type(ret_type), c_name=c_var(name),
+                c_ret_type=c_type(ret_type), c_name=c_fun(name),
                 visitor=type_visitor(ret_type))
 
     return ret
 
 def gen_marshal_input_decl(name, args, ret_type, middle_mode):
     if middle_mode:
-        return 'int qmp_marshal_input_%s(Monitor *mon, const QDict *qdict, QObject **ret)' % c_var(name)
+        return 'int qmp_marshal_input_%s(Monitor *mon, const QDict *qdict, QObject **ret)' % c_fun(name)
     else:
-        return 'static void qmp_marshal_input_%s(QDict *args, QObject **ret, Error **errp)' % c_var(name)
+        return 'static void qmp_marshal_input_%s(QDict *args, QObject **ret, Error **errp)' % c_fun(name)
 
 
 
@@ -298,7 +298,7 @@ def gen_registry(commands):
         registry += mcgen('''
 qmp_register_command("%(name)s", qmp_marshal_input_%(c_name)s);
 ''',
-                     name=cmd['command'], c_name=c_var(cmd['command']))
+                     name=cmd['command'], c_name=c_fun(cmd['command']))
     pop_indent()
     ret = mcgen('''
 static void qmp_init_marshal(void)
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 727fb77..4a734f5 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -100,7 +100,7 @@ typedef enum %(name)s
     %(abbrev)s_%(value)s = %(i)d,
 ''',
                      abbrev=de_camel_case(name).upper(),
-                     value=c_var(value).upper(),
+                     value=c_fun(value).upper(),
                      i=i)
         i += 1
 
@@ -126,7 +126,7 @@ struct %(name)s
         %(c_type)s %(c_name)s;
 ''',
                      c_type=c_type(typeinfo[key]),
-                     c_name=c_var(key))
+                     c_name=c_fun(key))
 
     ret += mcgen('''
     };
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 54117d4..78c947c 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -129,9 +129,9 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
         break;
 ''',
                 abbrev = de_camel_case(name).upper(),
-                enum = de_camel_case(key).upper(),
+                enum = c_fun(de_camel_case(key)).upper(),
                 c_type=members[key],
-                c_name=c_var(key))
+                c_name=c_fun(key))
 
     ret += mcgen('''
     default:
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 6e05469..e062336 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -131,7 +131,10 @@ def camel_case(name):
     return new_name
 
 def c_var(name):
-    return '_'.join(name.split('-')).lstrip("*")
+    return name.replace('-', '_').lstrip("*")
+
+def c_fun(name):
+    return c_var(name).replace('.', '_')
 
 def c_list_type(name):
     return '%sList' % name
commit 6f06f178f96de3597e1098258ab5d11733ae8602
Author: Alon Levy <alevy at redhat.com>
Date:   Thu Mar 22 20:00:36 2012 +0200

    libcacard/vcard_emul_nss: add warning for old coolkey
    
    Older coolkey versions (before the future fix of RHBZ 802435) have
    a fake card reader created if no reader is detected during module
    initialization. Warn libcacard users if the faulty coolkey is detected
    by checking for the fake reader name "E-Gate 0 0".
    
    Signed-off-by: Alon Levy <alevy at redhat.com>

diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index 3703fdc..802cae3 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -1018,6 +1018,16 @@ vcard_emul_init(const VCardEmulOptions *options)
             if (slot == NULL || !PK11_IsRemovable(slot) || !PK11_IsHW(slot)) {
                 continue;
             }
+            if (strcmp("E-Gate 0 0", PK11_GetSlotName(slot)) == 0) {
+                /*
+                 * coolkey <= 1.1.0-20 emulates this reader if it can't find
+                 * any hardware readers. This causes problems, warn user of
+                 * problems.
+                 */
+                fprintf(stderr, "known bad coolkey version - see "
+                        "https://bugzilla.redhat.com/show_bug.cgi?id=802435\n");
+                continue;
+            }
             vreader_emul = vreader_emul_new(slot, options->hw_card_type,
                                             options->hw_type_params);
             vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul,
commit 4e339882362102da63ab060f952d249a99ab6752
Author: Alon Levy <alevy at redhat.com>
Date:   Thu Mar 22 19:58:58 2012 +0200

    libcacard/vcard_emul_nss: handle no readers at startup
    
    When starting with no readers, coolkey should show no slots (with
    RHBZ 806038 fixed). Fix initialization to launch the event handling
    thread for each module that isn't the internal module regardless of the
    number of slots detected for it at initialization time, since slot
    number may start as 0 and is dynamic.
    
    RHBZ: 802435
    Signed-off-by: Alon Levy <alevy at redhat.com>

diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index 7de5d5b..3703fdc 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -1005,10 +1005,10 @@ vcard_emul_init(const VCardEmulOptions *options)
     SECMOD_GetReadLock(module_lock);
     for (mlp = module_list; mlp; mlp = mlp->next) {
         SECMODModule *module = mlp->module;
-        PRBool has_emul_slots = PR_FALSE;
 
-        if (module == NULL) {
-                continue;
+        /* Ignore the internal module */
+        if (module == NULL || module == SECMOD_GetInternalModule()) {
+            continue;
         }
 
         for (i = 0; i < module->slotCount; i++) {
@@ -1024,9 +1024,6 @@ vcard_emul_init(const VCardEmulOptions *options)
                                   vreader_emul_delete);
             vreader_add_reader(vreader);
 
-            has_readers = PR_TRUE;
-            has_emul_slots = PR_TRUE;
-
             if (PK11_IsPresent(slot)) {
                 VCard *vcard;
                 vcard = vcard_emul_mirror_card(vreader);
@@ -1035,12 +1032,10 @@ vcard_emul_init(const VCardEmulOptions *options)
                 vcard_free(vcard);
             }
         }
-        if (has_emul_slots) {
-            vcard_emul_new_event_thread(module);
-        }
+        vcard_emul_new_event_thread(module);
     }
     SECMOD_ReleaseReadLock(module_lock);
-    nss_emul_init = has_readers;
+    nss_emul_init = PR_TRUE;
 
     return VCARD_EMUL_OK;
 }
commit 1b902f7defa9f5229f92dfb32406c5b30c8045ab
Author: Alon Levy <alevy at redhat.com>
Date:   Thu Mar 22 19:44:49 2012 +0200

    libcacard/vcard_emul_nss: don't stop thread when there are no slots
    
    Signed-off-by: Alon Levy <alevy at redhat.com>

diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index bdc3c79..7de5d5b 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -682,8 +682,19 @@ vcard_emul_event_thread(void *arg)
     SECMODModule *module = (SECMODModule *)arg;
 
     do {
+        /*
+         * XXX - the latency value doesn't matter one bit. you only get no
+         * blocking (flags |= CKF_DONT_BLOCK) or PKCS11_WAIT_LATENCY (==500),
+         * hard coded in coolkey.  And it isn't coolkey's fault - the timeout
+         * value we pass get's dropped on the floor before C_WaitForSlotEvent
+         * is called.
+         */
         slot = SECMOD_WaitForAnyTokenEvent(module, 0, 500);
         if (slot == NULL) {
+            /* this could be just a no event indication */
+            if (PORT_GetError() == SEC_ERROR_NO_EVENT) {
+                continue;
+            }
             break;
         }
         vreader = vcard_emul_find_vreader_from_slot(slot);
commit 95b752bc32ccabe48430c0d0062b7c6947d864d0
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Mar 24 08:13:34 2012 +0100

    trace-events: Fix broken build caused by wrong format specifier
    
    mem is an uint64_t value, so %lx was wrong.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/trace-events b/trace-events
index 70f059d..db2cd39 100644
--- a/trace-events
+++ b/trace-events
@@ -726,7 +726,7 @@ ppm_save(const char *filename, void *display_surface) "%s surface=%p"
 # hw/qxl.c
 disable qxl_interface_set_mm_time(int qid, uint32_t mm_time) "%d %d"
 disable qxl_io_write_vga(int qid, const char *mode, uint32_t addr, uint32_t val) "%d %s addr=%u val=%u"
-qxl_create_guest_primary(int qid, uint32_t width, uint32_t height, uint64_t mem, uint32_t format, uint32_t position) "%d %dx%d mem=%lx %d,%d"
+qxl_create_guest_primary(int qid, uint32_t width, uint32_t height, uint64_t mem, uint32_t format, uint32_t position) "%d %ux%u mem=%" PRIx64 " %u,%u"
 qxl_create_guest_primary_rest(int qid, int32_t stride, uint32_t type, uint32_t flags) "%d %d,%d,%d"
 qxl_destroy_primary(int qid) "%d"
 qxl_enter_vga_mode(int qid) "%d"
commit 2db5b068ac16dc1d5403503d829ed9b046aca20c
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Mon Mar 19 19:18:26 2012 -0500

    test: add test-qmp-commands to make check
    
    All the deps are here but the test was never added to the list of tests
    for make check
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/tests/Makefile b/tests/Makefile
index 354fdbb..94ea342 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -3,6 +3,7 @@ export SRC_PATH
 CHECKS = check-qdict check-qfloat check-qint check-qstring check-qlist
 CHECKS += check-qjson test-qmp-output-visitor test-qmp-input-visitor
 CHECKS += test-string-input-visitor test-string-output-visitor test-coroutine
+CHECKS += test-qmp-commands
 CHECKS += $(SRC_PATH)/tests/qemu-iotests-quick.sh
 
 check-qint.o check-qstring.o check-qdict.o check-qlist.o check-qfloat.o check-qjson.o test-coroutine.o: $(GENERATED_HEADERS)
commit 151c5693258f594541fa9ea585547a0a8dd68abc
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Mon Mar 19 19:18:25 2012 -0500

    qapi: remove print statements from test-qmp-commands
    
    This is necessary for nicer make check integration.
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/test-qmp-commands.c b/test-qmp-commands.c
index fa5a7bd..60cbf01 100644
--- a/test-qmp-commands.c
+++ b/test-qmp-commands.c
@@ -46,7 +46,6 @@ static void test_dispatch_cmd(void)
     resp = qmp_dispatch(QOBJECT(req));
     assert(resp != NULL);
     assert(!qdict_haskey(qobject_to_qdict(resp), "error"));
-    g_print("\nresp: %s\n", qstring_get_str(qobject_to_json(resp)));
 
     qobject_decref(resp);
     QDECREF(req);
@@ -63,7 +62,6 @@ static void test_dispatch_cmd_error(void)
     resp = qmp_dispatch(QOBJECT(req));
     assert(resp != NULL);
     assert(qdict_haskey(qobject_to_qdict(resp), "error"));
-    g_print("\nresp: %s\n", qstring_get_str(qobject_to_json_pretty(resp)));
 
     qobject_decref(resp);
     QDECREF(req);
@@ -92,7 +90,6 @@ static void test_dispatch_cmd_io(void)
     resp = qmp_dispatch(QOBJECT(req));
     assert(resp != NULL);
     assert(!qdict_haskey(qobject_to_qdict(resp), "error"));
-    g_print("\nresp: %s\n", qstring_get_str(qobject_to_json_pretty(resp)));
 
     qobject_decref(resp);
     QDECREF(req);
commit 3ac805d9223ba9b9e38570ed5883c410746a34da
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Wed Mar 21 10:10:46 2012 -0500

    test: remove qemu-ga reference
    
    This was added by mistake a while back.
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/Makefile b/Makefile
index 8d6b558..d8e1f36 100644
--- a/Makefile
+++ b/Makefile
@@ -173,6 +173,7 @@ qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
 $(qapi-obj-y): $(GENERATED_HEADERS)
 qapi-dir := $(BUILD_DIR)/qapi-generated
 qemu-ga$(EXESUF): LIBS = $(LIBS_QGA)
+qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
 
 gen-out-type = $(subst .,-,$(suffix $@))
 
diff --git a/tests/Makefile b/tests/Makefile
index c78ade1..354fdbb 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -17,7 +17,7 @@ test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y)
 
 test-qmp-input-visitor.o test-qmp-output-visitor.o \
 test-string-input-visitor.o test-string-output-visitor.o \
-	test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
+	test-qmp-commands.o: QEMU_CFLAGS += -I $(qapi-dir)
 
 $(qapi-dir)/test-qapi-types.c $(qapi-dir)/test-qapi-types.h :\
 $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
commit 1d6528af68ca4afa3177d18542155976df505872
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Wed Mar 21 09:33:40 2012 -0300

    vl.c: fix '-cpu ?' segfault
    
    Fix stupid copy&paste mistake at commit
    ecf40beae7dcbb057d4f115207f9d8276832a774: I moved code around but kept
    "optarg" on the cpu_list() call.
    
    Reported-by: Jiri Denemark <jdenemar at redhat.com>
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/vl.c b/vl.c
index 112b0e0..0fccf50 100644
--- a/vl.c
+++ b/vl.c
@@ -3196,7 +3196,7 @@ int main(int argc, char **argv, char **envp)
     cpudef_init();
 
     if (cpu_model && *cpu_model == '?') {
-        list_cpus(stdout, &fprintf, optarg);
+        list_cpus(stdout, &fprintf, cpu_model);
         exit(0);
     }
 
commit e72c3f2ed9c4fe482ebe34d1079a9ebb8baca552
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Sun Mar 25 13:59:41 2012 -0500

    qemu-ga: fix bsd build, and re-org linux-specific implementations

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 7b2be2f..faf970d 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -12,29 +12,30 @@
  */
 
 #include <glib.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include "qga/guest-agent-core.h"
+#include "qga-qmp-commands.h"
+#include "qerror.h"
+#include "qemu-queue.h"
+#include "host-utils.h"
 
 #if defined(__linux__)
 #include <mntent.h>
 #include <linux/fs.h>
-
-#if defined(__linux__) && defined(FIFREEZE)
-#define CONFIG_FSFREEZE
-#endif
-#endif
-
-#include <sys/types.h>
-#include <sys/ioctl.h>
 #include <ifaddrs.h>
 #include <arpa/inet.h>
 #include <sys/socket.h>
 #include <net/if.h>
 #include <sys/wait.h>
-#include "qga/guest-agent-core.h"
-#include "qga-qmp-commands.h"
-#include "qerror.h"
-#include "qemu-queue.h"
-#include "host-utils.h"
 
+#if defined(__linux__) && defined(FIFREEZE)
+#define CONFIG_FSFREEZE
+#endif
+#endif
+
+#if defined(__linux__)
+/* TODO: use this in place of all post-fork() fclose(std*) callers */
 static void reopen_fd_to_null(int fd)
 {
     int nullfd;
@@ -50,6 +51,7 @@ static void reopen_fd_to_null(int fd)
         close(nullfd);
     }
 }
+#endif /* defined(__linux__) */
 
 void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
 {
@@ -309,7 +311,11 @@ static void guest_file_init(void)
     QTAILQ_INIT(&guest_file_state.filehandles);
 }
 
+/* linux-specific implementations. avoid this if at all possible. */
+#if defined(__linux__)
+
 #if defined(CONFIG_FSFREEZE)
+
 static void disable_logging(void)
 {
     ga_disable_logging(ga_state);
@@ -505,38 +511,7 @@ static void guest_fsfreeze_cleanup(void)
         }
     }
 }
-#else
-/*
- * Return status of freeze/thaw
- */
-GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
-{
-    error_set(err, QERR_UNSUPPORTED);
-
-    return 0;
-}
-
-/*
- * Walk list of mounted file systems in the guest, and freeze the ones which
- * are real local file systems.
- */
-int64_t qmp_guest_fsfreeze_freeze(Error **err)
-{
-    error_set(err, QERR_UNSUPPORTED);
-
-    return 0;
-}
-
-/*
- * Walk list of frozen file systems in the guest, and thaw them.
- */
-int64_t qmp_guest_fsfreeze_thaw(Error **err)
-{
-    error_set(err, QERR_UNSUPPORTED);
-
-    return 0;
-}
-#endif
+#endif /* CONFIG_FSFREEZE */
 
 #define LINUX_SYS_STATE_FILE "/sys/power/state"
 #define SUSPEND_SUPPORTED 0
@@ -904,6 +879,52 @@ error:
     return NULL;
 }
 
+#else /* defined(__linux__) */
+
+GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
+{
+    error_set(err, QERR_UNSUPPORTED);
+
+    return 0;
+}
+
+int64_t qmp_guest_fsfreeze_freeze(Error **err)
+{
+    error_set(err, QERR_UNSUPPORTED);
+
+    return 0;
+}
+
+int64_t qmp_guest_fsfreeze_thaw(Error **err)
+{
+    error_set(err, QERR_UNSUPPORTED);
+
+    return 0;
+}
+
+void qmp_guest_suspend_disk(Error **err)
+{
+    error_set(err, QERR_UNSUPPORTED);
+}
+
+void qmp_guest_suspend_ram(Error **err)
+{
+    error_set(err, QERR_UNSUPPORTED);
+}
+
+void qmp_guest_suspend_hybrid(Error **err)
+{
+    error_set(err, QERR_UNSUPPORTED);
+}
+
+GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
+{
+    error_set(errp, QERR_UNSUPPORTED);
+    return NULL;
+}
+
+#endif
+
 /* register init/cleanup routines for stateful command groups */
 void ga_command_state_init(GAState *s, GACommandState *cs)
 {
commit cb1977d308f6e1d6bf398d42e6148187b82456c1
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Mar 24 10:47:39 2012 -0700

    tcg-sparc: Add debug_frame support.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/elf.h b/elf.h
index 310e05a..36bcac4 100644
--- a/elf.h
+++ b/elf.h
@@ -346,6 +346,21 @@ typedef struct {
 #define R_MIPS_HIVENDOR		127
 
 
+/* SUN SPARC specific definitions.  */
+
+/* Values for Elf64_Ehdr.e_flags.  */
+
+#define EF_SPARCV9_MM           3
+#define EF_SPARCV9_TSO          0
+#define EF_SPARCV9_PSO          1
+#define EF_SPARCV9_RMO          2
+#define EF_SPARC_LEDATA         0x800000 /* little endian data */
+#define EF_SPARC_EXT_MASK       0xFFFF00
+#define EF_SPARC_32PLUS         0x000100 /* generic V8+ features */
+#define EF_SPARC_SUN_US1        0x000200 /* Sun UltraSPARC1 extensions */
+#define EF_SPARC_HAL_R1         0x000400 /* HAL R1 extensions */
+#define EF_SPARC_SUN_US3        0x000800 /* Sun UltraSPARCIII extensions */
+
 /*
  * Sparc ELF relocation types
  */
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 491c979..247a278 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -1624,3 +1624,66 @@ static void tcg_target_init(TCGContext *s)
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_O7);
     tcg_add_target_add_op_defs(sparc_op_defs);
 }
+
+#if TCG_TARGET_REG_BITS == 64
+# define ELF_HOST_MACHINE  EM_SPARCV9
+#elif defined(__sparc_v8plus__)
+# define ELF_HOST_MACHINE  EM_SPARC32PLUS
+# define ELF_HOST_FLAGS    EF_SPARC_32PLUS
+#else
+# define ELF_HOST_MACHINE  EM_SPARC
+#endif
+
+typedef struct {
+    uint32_t len __attribute__((aligned((sizeof(void *)))));
+    uint32_t id;
+    uint8_t version;
+    char augmentation[1];
+    uint8_t code_align;
+    uint8_t data_align;
+    uint8_t return_column;
+} DebugFrameCIE;
+
+typedef struct {
+    uint32_t len __attribute__((aligned((sizeof(void *)))));
+    uint32_t cie_offset;
+    tcg_target_long func_start __attribute__((packed));
+    tcg_target_long func_len __attribute__((packed));
+    uint8_t def_cfa[TCG_TARGET_REG_BITS == 64 ? 4 : 2];
+    uint8_t win_save;
+    uint8_t ret_save[3];
+} DebugFrameFDE;
+
+typedef struct {
+    DebugFrameCIE cie;
+    DebugFrameFDE fde;
+} DebugFrame;
+
+static DebugFrame debug_frame = {
+    .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
+    .cie.id = -1,
+    .cie.version = 1,
+    .cie.code_align = 1,
+    .cie.data_align = -sizeof(void *) & 0x7f,
+    .cie.return_column = 15,            /* o7 */
+
+    .fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */
+    .fde.def_cfa = {
+#if TCG_TARGET_REG_BITS == 64
+        12, 30,                         /* DW_CFA_def_cfa i6, 2047 */
+        (2047 & 0x7f) | 0x80, (2047 >> 7)
+#else
+        13, 30                          /* DW_CFA_def_cfa_register i6 */
+#endif
+    },
+    .fde.win_save = 0x2d,               /* DW_CFA_GNU_window_save */
+    .fde.ret_save = { 9, 15, 31 },      /* DW_CFA_register o7, i7 */
+};
+
+void tcg_register_jit(void *buf, size_t buf_size)
+{
+    debug_frame.fde.func_start = (tcg_target_long) buf;
+    debug_frame.fde.func_len = buf_size;
+
+    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
+}
commit e7bd63006412cb21bf2616f464955cf875a0f627
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Mar 24 10:47:38 2012 -0700

    tcg-hppa: Add debug_frame support.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index e579ef0..2885212 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -336,7 +336,7 @@ static int tcg_target_const_match(tcg_target_long val,
 #define INSN_COMIBF     (INSN_OP(0x23))
 
 /* supplied by libgcc */
-extern void *__canonicalize_funcptr_for_compare(void *);
+extern void *__canonicalize_funcptr_for_compare(const void *);
 
 static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
 {
@@ -628,7 +628,7 @@ static void tcg_out_bswap32(TCGContext *s, int ret, int arg, int temp)
     tcg_out_shd(s, ret, arg, temp, 8);    /* ret =  DCBA */
 }
 
-static void tcg_out_call(TCGContext *s, void *func)
+static void tcg_out_call(TCGContext *s, const void *func)
 {
     tcg_target_long val, hi, lo, disp;
 
@@ -1661,23 +1661,18 @@ static int tcg_target_callee_save_regs[] = {
     TCG_REG_R18
 };
 
+#define FRAME_SIZE ((-TCG_TARGET_CALL_STACK_OFFSET \
+                     + TCG_TARGET_STATIC_CALL_ARGS_SIZE \
+                     + ARRAY_SIZE(tcg_target_callee_save_regs) * 4 \
+                     + CPU_TEMP_BUF_NLONGS * sizeof(long) \
+                     + TCG_TARGET_STACK_ALIGN - 1) \
+                    & -TCG_TARGET_STACK_ALIGN)
+
 static void tcg_target_qemu_prologue(TCGContext *s)
 {
     int frame_size, i;
 
-    /* Allocate space for the fixed frame marker.  */
-    frame_size = -TCG_TARGET_CALL_STACK_OFFSET;
-    frame_size += TCG_TARGET_STATIC_CALL_ARGS_SIZE;
-
-    /* Allocate space for the saved registers.  */
-    frame_size += ARRAY_SIZE(tcg_target_callee_save_regs) * 4;
-
-    /* Allocate space for the TCG temps. */
-    frame_size += CPU_TEMP_BUF_NLONGS * sizeof(long);
-
-    /* Align the allocated space.  */
-    frame_size = ((frame_size + TCG_TARGET_STACK_ALIGN - 1)
-                  & -TCG_TARGET_STACK_ALIGN);
+    frame_size = FRAME_SIZE;
 
     /* The return address is stored in the caller's frame.  */
     tcg_out_st(s, TCG_TYPE_PTR, TCG_REG_RP, TCG_REG_CALL_STACK, -20);
@@ -1752,3 +1747,81 @@ static void tcg_target_init(TCGContext *s)
 
     tcg_add_target_add_op_defs(hppa_op_defs);
 }
+
+typedef struct {
+    uint32_t len __attribute__((aligned((sizeof(void *)))));
+    uint32_t id;
+    uint8_t version;
+    char augmentation[1];
+    uint8_t code_align;
+    uint8_t data_align;
+    uint8_t return_column;
+} DebugFrameCIE;
+
+typedef struct {
+    uint32_t len __attribute__((aligned((sizeof(void *)))));
+    uint32_t cie_offset;
+    tcg_target_long func_start __attribute__((packed));
+    tcg_target_long func_len __attribute__((packed));
+    uint8_t def_cfa[4];
+    uint8_t ret_ofs[3];
+    uint8_t reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
+} DebugFrameFDE;
+
+typedef struct {
+    DebugFrameCIE cie;
+    DebugFrameFDE fde;
+} DebugFrame;
+
+#define ELF_HOST_MACHINE  EM_PARISC
+#define ELF_HOST_FLAGS    EFA_PARISC_1_1
+
+/* ??? BFD (and thus GDB) wants very much to distinguish between HPUX
+   and other extensions.  We don't really care, but if we don't set this
+   to *something* then the object file won't be properly matched.  */
+#define ELF_OSABI         ELFOSABI_LINUX
+
+static DebugFrame debug_frame = {
+    .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
+    .cie.id = -1,
+    .cie.version = 1,
+    .cie.code_align = 1,
+    .cie.data_align = 1,
+    .cie.return_column = 2,
+
+    .fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */
+    .fde.def_cfa = {
+        0x12, 30,                       /* DW_CFA_def_cfa_sf sp, ... */
+        (-FRAME_SIZE & 0x7f) | 0x80,     /* ... sleb128 -FRAME_SIZE */
+        (-FRAME_SIZE >> 7) & 0x7f
+    },
+    .fde.ret_ofs = {
+        0x11, 2, (-20 / 4) & 0x7f       /* DW_CFA_offset_extended_sf r2, 20 */
+    },
+    .fde.reg_ofs = {
+        /* This must match the ordering in tcg_target_callee_save_regs.  */
+        0x80 + 4, 0,                    /* DW_CFA_offset r4, 0 */
+        0x80 + 5, 4,                    /* DW_CFA_offset r5, 4 */
+        0x80 + 6, 8,                    /* DW_CFA_offset r6, 8 */
+        0x80 + 7, 12,                    /* ... */
+        0x80 + 8, 16,
+        0x80 + 9, 20,
+        0x80 + 10, 24,
+        0x80 + 11, 28,
+        0x80 + 12, 32,
+        0x80 + 13, 36,
+        0x80 + 14, 40,
+        0x80 + 15, 44,
+        0x80 + 16, 48,
+        0x80 + 17, 52,
+        0x80 + 18, 56,
+    }
+};
+
+void tcg_register_jit(void *buf, size_t buf_size)
+{
+    debug_frame.fde.func_start = (tcg_target_long) buf;
+    debug_frame.fde.func_len = buf_size;
+
+    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
+}
commit abbb3eae1033a5ba6058457336cce9370146d425
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Mar 24 10:47:37 2012 -0700

    tcg: Allow ELF_HOST_FLAGS and ELF_OSABI overrides in gdb-jit.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/tcg.c b/tcg/tcg.c
index df4edc0..ab589c7 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -2360,6 +2360,12 @@ static void tcg_register_jit_int(void *buf_ptr, size_t buf_size,
             .e_shentsize = sizeof(ElfW(Shdr)),
             .e_shnum = ARRAY_SIZE(img->shdr),
             .e_shstrndx = ARRAY_SIZE(img->shdr) - 1,
+#ifdef ELF_HOST_FLAGS
+            .e_flags = ELF_HOST_FLAGS,
+#endif
+#ifdef ELF_OSABI
+            .e_ident[EI_OSABI] = ELF_OSABI,
+#endif
         },
         .phdr = {
             .p_type = PT_LOAD,
commit 5872bbf24e524899d002dc4fc9a8544b8334137a
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Mar 24 10:47:36 2012 -0700

    tcg: Add debug_info to JIT ELF image.
    
    This allows us to actually supply a function name in softmmu builds;
    gdb doesn't pick up the minimal symbol table otherwise.  Also add a
    bit of documentation and statically generate more of the ELF image.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/tcg.c b/tcg/tcg.c
index eb595ce..df4edc0 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -2252,8 +2252,17 @@ void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
 #endif
 
 #ifdef ELF_HOST_MACHINE
-/* The backend should define ELF_HOST_MACHINE to indicate both what value to
-   put into the ELF image and to indicate support for the feature.  */
+/* In order to use this feature, the backend needs to do three things:
+
+   (1) Define ELF_HOST_MACHINE to indicate both what value to
+       put into the ELF image and to indicate support for the feature.
+
+   (2) Define tcg_register_jit.  This should create a buffer containing
+       the contents of a .debug_frame section that describes the post-
+       prologue unwind info for the tcg machine.
+
+   (3) Call tcg_register_jit_int, with the constructed .debug_frame.
+*/
 
 /* Begin GDB interface.  THE FOLLOWING MUST MATCH GDB DOCS.  */
 typedef enum {
@@ -2300,96 +2309,169 @@ static int find_string(const char *strtab, const char *str)
     }
 }
 
-static void tcg_register_jit_int(void *buf, size_t buf_size,
+static void tcg_register_jit_int(void *buf_ptr, size_t buf_size,
                                  void *debug_frame, size_t debug_frame_size)
 {
-    static const char strings[64] =
-        "\0"
-        ".text\0"
-        ".debug_frame\0"
-        ".symtab\0"
-        ".strtab\0"
-        "code_gen_buffer";
+    struct __attribute__((packed)) DebugInfo {
+        uint32_t  len;
+        uint16_t  version;
+        uint32_t  abbrev;
+        uint8_t   ptr_size;
+        uint8_t   cu_die;
+        uint16_t  cu_lang;
+        uintptr_t cu_low_pc;
+        uintptr_t cu_high_pc;
+        uint8_t   fn_die;
+        char      fn_name[16];
+        uintptr_t fn_low_pc;
+        uintptr_t fn_high_pc;
+        uint8_t   cu_eoc;
+    };
 
     struct ElfImage {
         ElfW(Ehdr) ehdr;
         ElfW(Phdr) phdr;
-        ElfW(Shdr) shdr[5];
-        ElfW(Sym)  sym[1];
-        char       str[64];
+        ElfW(Shdr) shdr[7];
+        ElfW(Sym)  sym[2];
+        struct DebugInfo di;
+        uint8_t    da[24];
+        char       str[80];
+    };
+
+    struct ElfImage *img;
+
+    static const struct ElfImage img_template = {
+        .ehdr = {
+            .e_ident[EI_MAG0] = ELFMAG0,
+            .e_ident[EI_MAG1] = ELFMAG1,
+            .e_ident[EI_MAG2] = ELFMAG2,
+            .e_ident[EI_MAG3] = ELFMAG3,
+            .e_ident[EI_CLASS] = ELF_CLASS,
+            .e_ident[EI_DATA] = ELF_DATA,
+            .e_ident[EI_VERSION] = EV_CURRENT,
+            .e_type = ET_EXEC,
+            .e_machine = ELF_HOST_MACHINE,
+            .e_version = EV_CURRENT,
+            .e_phoff = offsetof(struct ElfImage, phdr),
+            .e_shoff = offsetof(struct ElfImage, shdr),
+            .e_ehsize = sizeof(ElfW(Shdr)),
+            .e_phentsize = sizeof(ElfW(Phdr)),
+            .e_phnum = 1,
+            .e_shentsize = sizeof(ElfW(Shdr)),
+            .e_shnum = ARRAY_SIZE(img->shdr),
+            .e_shstrndx = ARRAY_SIZE(img->shdr) - 1,
+        },
+        .phdr = {
+            .p_type = PT_LOAD,
+            .p_flags = PF_X,
+        },
+        .shdr = {
+            [0] = { .sh_type = SHT_NULL },
+            /* Trick: The contents of code_gen_buffer are not present in
+               this fake ELF file; that got allocated elsewhere.  Therefore
+               we mark .text as SHT_NOBITS (similar to .bss) so that readers
+               will not look for contents.  We can record any address.  */
+            [1] = { /* .text */
+                .sh_type = SHT_NOBITS,
+                .sh_flags = SHF_EXECINSTR | SHF_ALLOC,
+            },
+            [2] = { /* .debug_info */
+                .sh_type = SHT_PROGBITS,
+                .sh_offset = offsetof(struct ElfImage, di),
+                .sh_size = sizeof(struct DebugInfo),
+            },
+            [3] = { /* .debug_abbrev */
+                .sh_type = SHT_PROGBITS,
+                .sh_offset = offsetof(struct ElfImage, da),
+                .sh_size = sizeof(img->da),
+            },
+            [4] = { /* .debug_frame */
+                .sh_type = SHT_PROGBITS,
+                .sh_offset = sizeof(struct ElfImage),
+            },
+            [5] = { /* .symtab */
+                .sh_type = SHT_SYMTAB,
+                .sh_offset = offsetof(struct ElfImage, sym),
+                .sh_size = sizeof(img->sym),
+                .sh_info = 1,
+                .sh_link = ARRAY_SIZE(img->shdr) - 1,
+                .sh_entsize = sizeof(ElfW(Sym)),
+            },
+            [6] = { /* .strtab */
+                .sh_type = SHT_STRTAB,
+                .sh_offset = offsetof(struct ElfImage, str),
+                .sh_size = sizeof(img->str),
+            }
+        },
+        .sym = {
+            [1] = { /* code_gen_buffer */
+                .st_info = ELF_ST_INFO(STB_GLOBAL, STT_FUNC),
+                .st_shndx = 1,
+            }
+        },
+        .di = {
+            .len = sizeof(struct DebugInfo) - 4,
+            .version = 2,
+            .ptr_size = sizeof(void *),
+            .cu_die = 1,
+            .cu_lang = 0x8001,  /* DW_LANG_Mips_Assembler */
+            .fn_die = 2,
+            .fn_name = "code_gen_buffer"
+        },
+        .da = {
+            1,          /* abbrev number (the cu) */
+            0x11, 1,    /* DW_TAG_compile_unit, has children */
+            0x13, 0x5,  /* DW_AT_language, DW_FORM_data2 */
+            0x11, 0x1,  /* DW_AT_low_pc, DW_FORM_addr */
+            0x12, 0x1,  /* DW_AT_high_pc, DW_FORM_addr */
+            0, 0,       /* end of abbrev */
+            2,          /* abbrev number (the fn) */
+            0x2e, 0,    /* DW_TAG_subprogram, no children */
+            0x3, 0x8,   /* DW_AT_name, DW_FORM_string */
+            0x11, 0x1,  /* DW_AT_low_pc, DW_FORM_addr */
+            0x12, 0x1,  /* DW_AT_high_pc, DW_FORM_addr */
+            0, 0,       /* end of abbrev */
+            0           /* no more abbrev */
+        },
+        .str = "\0" ".text\0" ".debug_info\0" ".debug_abbrev\0"
+               ".debug_frame\0" ".symtab\0" ".strtab\0" "code_gen_buffer",
     };
 
     /* We only need a single jit entry; statically allocate it.  */
     static struct jit_code_entry one_entry;
 
+    uintptr_t buf = (uintptr_t)buf_ptr;
     size_t img_size = sizeof(struct ElfImage) + debug_frame_size;
-    struct ElfImage *img = g_malloc0(img_size);
-
-    img->ehdr.e_ident[EI_MAG0] = ELFMAG0;
-    img->ehdr.e_ident[EI_MAG1] = ELFMAG1;
-    img->ehdr.e_ident[EI_MAG2] = ELFMAG2;
-    img->ehdr.e_ident[EI_MAG3] = ELFMAG3;
-    img->ehdr.e_ident[EI_CLASS] = ELF_CLASS;
-    img->ehdr.e_ident[EI_DATA] = ELF_DATA;
-    img->ehdr.e_ident[EI_VERSION] = EV_CURRENT;
-    img->ehdr.e_type = ET_EXEC;
-    img->ehdr.e_machine = ELF_HOST_MACHINE;
-    img->ehdr.e_version = EV_CURRENT;
-    img->ehdr.e_phoff = offsetof(struct ElfImage, phdr);
-    img->ehdr.e_shoff = offsetof(struct ElfImage, shdr);
-    img->ehdr.e_ehsize = sizeof(ElfW(Shdr));
-    img->ehdr.e_phentsize = sizeof(ElfW(Phdr));
-    img->ehdr.e_phnum = 1;
-    img->ehdr.e_shentsize = sizeof(img->shdr[0]);
-    img->ehdr.e_shnum = ARRAY_SIZE(img->shdr);
-    img->ehdr.e_shstrndx = ARRAY_SIZE(img->shdr) - 1;
-
-    img->phdr.p_type = PT_LOAD;
-    img->phdr.p_offset = (char *)buf - (char *)img;
-    img->phdr.p_vaddr = (ElfW(Addr))buf;
-    img->phdr.p_paddr = img->phdr.p_vaddr;
-    img->phdr.p_filesz = 0;
-    img->phdr.p_memsz = buf_size;
-    img->phdr.p_flags = PF_X;
 
-    memcpy(img->str, strings, sizeof(img->str));
+    img = g_malloc(img_size);
+    *img = img_template;
+    memcpy(img + 1, debug_frame, debug_frame_size);
 
-    img->shdr[0].sh_type = SHT_NULL;
+    img->phdr.p_vaddr = buf;
+    img->phdr.p_paddr = buf;
+    img->phdr.p_memsz = buf_size;
 
-    /* Trick: The contents of code_gen_buffer are not present in this fake
-       ELF file; that got allocated elsewhere, discontiguously.  Therefore
-       we mark .text as SHT_NOBITS (similar to .bss) so that readers will
-       not look for contents.  We can record any address at will.  */
     img->shdr[1].sh_name = find_string(img->str, ".text");
-    img->shdr[1].sh_type = SHT_NOBITS;
-    img->shdr[1].sh_flags = SHF_EXECINSTR | SHF_ALLOC;
-    img->shdr[1].sh_addr = (ElfW(Addr))buf;
+    img->shdr[1].sh_addr = buf;
     img->shdr[1].sh_size = buf_size;
 
-    img->shdr[2].sh_name = find_string(img->str, ".debug_frame");
-    img->shdr[2].sh_type = SHT_PROGBITS;
-    img->shdr[2].sh_offset = sizeof(*img);
-    img->shdr[2].sh_size = debug_frame_size;
-    memcpy(img + 1, debug_frame, debug_frame_size);
+    img->shdr[2].sh_name = find_string(img->str, ".debug_info");
+    img->shdr[3].sh_name = find_string(img->str, ".debug_abbrev");
+
+    img->shdr[4].sh_name = find_string(img->str, ".debug_frame");
+    img->shdr[4].sh_size = debug_frame_size;
+
+    img->shdr[5].sh_name = find_string(img->str, ".symtab");
+    img->shdr[6].sh_name = find_string(img->str, ".strtab");
+
+    img->sym[1].st_name = find_string(img->str, "code_gen_buffer");
+    img->sym[1].st_value = buf;
+    img->sym[1].st_size = buf_size;
 
-    img->shdr[3].sh_name = find_string(img->str, ".symtab");
-    img->shdr[3].sh_type = SHT_SYMTAB;
-    img->shdr[3].sh_offset = offsetof(struct ElfImage, sym);
-    img->shdr[3].sh_size = sizeof(img->sym);
-    img->shdr[3].sh_info = ARRAY_SIZE(img->sym);
-    img->shdr[3].sh_link = img->ehdr.e_shstrndx;
-    img->shdr[3].sh_entsize = sizeof(ElfW(Sym));
-
-    img->shdr[4].sh_name = find_string(img->str, ".strtab");
-    img->shdr[4].sh_type = SHT_STRTAB;
-    img->shdr[4].sh_offset = offsetof(struct ElfImage, str);
-    img->shdr[4].sh_size = sizeof(img->str);
-
-    img->sym[0].st_name = find_string(img->str, "code_gen_buffer");
-    img->sym[0].st_info = ELF_ST_INFO(STB_GLOBAL, STT_FUNC);
-    img->sym[0].st_shndx = 1;
-    img->sym[0].st_value = (ElfW(Addr))buf;
-    img->sym[0].st_size = buf_size;
+    img->di.cu_low_pc = buf;
+    img->di.cu_high_pc = buf_size;
+    img->di.fn_low_pc = buf;
+    img->di.fn_high_pc = buf_size;
 
 #ifdef DEBUG_JIT
     /* Enable this block to be able to debug the ELF image file creation.
@@ -2397,7 +2479,7 @@ static void tcg_register_jit_int(void *buf, size_t buf_size,
     {
         FILE *f = fopen("/tmp/qemu.jit", "w+b");
         if (f) {
-            if (fwrite(img, img_size, 1, f) != buf_size) {
+            if (fwrite(img, img_size, 1, f) != img_size) {
                 /* Avoid stupid unused return value warning for fwrite.  */
             }
             fclose(f);
@@ -2414,7 +2496,8 @@ static void tcg_register_jit_int(void *buf, size_t buf_size,
     __jit_debug_register_code();
 }
 #else
-/* No support for the feature.  Provide the entry point expected by exec.c.  */
+/* No support for the feature.  Provide the entry point expected by exec.c,
+   and implement the internal function we declared earlier.  */
 
 static void tcg_register_jit_int(void *buf, size_t size,
                                  void *debug_frame, size_t debug_frame_size)
commit 55fddd661187bd321343776e2d460cc4e67d225b
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Mar 24 09:51:15 2012 -0700

    target-alpha: Use noreturn marker in helper.h.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 9f97c5d..a184def 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -1,6 +1,6 @@
 #include "def-helper.h"
 
-DEF_HELPER_3(excp, void, env, int, int)
+DEF_HELPER_3(excp, noreturn, env, int, int)
 DEF_HELPER_FLAGS_1(load_pcc, TCG_CALL_CONST | TCG_CALL_PURE, i64, env)
 
 DEF_HELPER_3(addqv, i64, env, i64, i64)
commit 743434099d427c17f6c8f36de81a83f83ec13fb2
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Mar 24 09:51:14 2012 -0700

    target-alpha: Make use of fp_status.flush_inputs_to_zero.
    
    This softfp feature post-dates the last major update to the Alpha
    fpu translation.  We can make use of this to eliminate at least
    one helper function that was performing this operation by hand.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index c7787f6..6c5d28b 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -234,7 +234,6 @@ struct CPUAlphaState {
     uint8_t fpcr_exc_mask;
     uint8_t fpcr_dyn_round;
     uint8_t fpcr_flush_to_zero;
-    uint8_t fpcr_dnz;
     uint8_t fpcr_dnod;
     uint8_t fpcr_undz;
 
diff --git a/target-alpha/fpu_helper.c b/target-alpha/fpu_helper.c
index d38521b..dda1103 100644
--- a/target-alpha/fpu_helper.c
+++ b/target-alpha/fpu_helper.c
@@ -88,21 +88,17 @@ void helper_fp_exc_raise_s(CPUAlphaState *env, uint32_t exc, uint32_t regno)
     }
 }
 
-/* Input remapping without software completion.  Handle denormal-map-to-zero
-   and trap for all other non-finite numbers.  */
-uint64_t helper_ieee_input(CPUAlphaState *env, uint64_t val)
+/* Input handing without software completion.  Trap for all
+   non-finite numbers.  */
+void helper_ieee_input(CPUAlphaState *env, uint64_t val)
 {
     uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
     uint64_t frac = val & 0xfffffffffffffull;
 
     if (exp == 0) {
-        if (frac != 0) {
-            /* If DNZ is set flush denormals to zero on input.  */
-            if (env->fpcr_dnz) {
-                val &= 1ull << 63;
-            } else {
-                arith_excp(env, GETPC(), EXC_M_UNF, 0);
-            }
+        /* Denormals without DNZ set raise an exception.  */
+        if (frac != 0 && !env->fp_status.flush_inputs_to_zero) {
+            arith_excp(env, GETPC(), EXC_M_UNF, 0);
         }
     } else if (exp == 0x7ff) {
         /* Infinity or NaN.  */
@@ -111,43 +107,23 @@ uint64_t helper_ieee_input(CPUAlphaState *env, uint64_t val)
            just emulates the insn to figure out what exception to use.  */
         arith_excp(env, GETPC(), frac ? EXC_M_INV : EXC_M_FOV, 0);
     }
-    return val;
 }
 
 /* Similar, but does not trap for infinities.  Used for comparisons.  */
-uint64_t helper_ieee_input_cmp(CPUAlphaState *env, uint64_t val)
+void helper_ieee_input_cmp(CPUAlphaState *env, uint64_t val)
 {
     uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
     uint64_t frac = val & 0xfffffffffffffull;
 
     if (exp == 0) {
-        if (frac != 0) {
-            /* If DNZ is set flush denormals to zero on input.  */
-            if (env->fpcr_dnz) {
-                val &= 1ull << 63;
-            } else {
-                arith_excp(env, GETPC(), EXC_M_UNF, 0);
-            }
+        /* Denormals without DNZ set raise an exception.  */
+        if (frac != 0 && !env->fp_status.flush_inputs_to_zero) {
+            arith_excp(env, GETPC(), EXC_M_UNF, 0);
         }
     } else if (exp == 0x7ff && frac) {
         /* NaN.  */
         arith_excp(env, GETPC(), EXC_M_INV, 0);
     }
-    return val;
-}
-
-/* Input remapping with software completion enabled.  All we have to do
-   is handle denormal-map-to-zero; all other inputs get exceptions as
-   needed from the actual operation.  */
-uint64_t helper_ieee_input_s(CPUAlphaState *env, uint64_t val)
-{
-    if (env->fpcr_dnz) {
-        uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
-        if (exp == 0) {
-            val &= 1ull << 63;
-        }
-    }
-    return val;
 }
 
 /* F floating (VAX) */
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 3333bfa..765e650 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -82,7 +82,7 @@ uint64_t cpu_alpha_load_fpcr (CPUAlphaState *env)
         break;
     }
 
-    if (env->fpcr_dnz) {
+    if (env->fp_status.flush_inputs_to_zero) {
         r |= FPCR_DNZ;
     }
     if (env->fpcr_dnod) {
@@ -151,12 +151,10 @@ void cpu_alpha_store_fpcr (CPUAlphaState *env, uint64_t val)
     }
     env->fpcr_dyn_round = t;
 
-    env->fpcr_flush_to_zero
-      = (val & (FPCR_UNDZ|FPCR_UNFD)) == (FPCR_UNDZ|FPCR_UNFD);
-
-    env->fpcr_dnz = (val & FPCR_DNZ) != 0;
     env->fpcr_dnod = (val & FPCR_DNOD) != 0;
     env->fpcr_undz = (val & FPCR_UNDZ) != 0;
+    env->fpcr_flush_to_zero = env->fpcr_dnod & env->fpcr_undz;
+    env->fp_status.flush_inputs_to_zero = (val & FPCR_DNZ) != 0;
 }
 
 uint64_t helper_load_fpcr(CPUAlphaState *env)
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 03cc185..9f97c5d 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -95,9 +95,8 @@ DEF_HELPER_FLAGS_1(fp_exc_get, TCG_CALL_CONST | TCG_CALL_PURE, i32, env)
 DEF_HELPER_3(fp_exc_raise, void, env, i32, i32)
 DEF_HELPER_3(fp_exc_raise_s, void, env, i32, i32)
 
-DEF_HELPER_2(ieee_input, i64, env, i64)
-DEF_HELPER_2(ieee_input_cmp, i64, env, i64)
-DEF_HELPER_2(ieee_input_s, i64, env, i64)
+DEF_HELPER_2(ieee_input, void, env, i64)
+DEF_HELPER_2(ieee_input_cmp, void, env, i64)
 
 #if !defined (CONFIG_USER_ONLY)
 DEF_HELPER_2(hw_ret, void, env, i64)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index dd09ad8..1f4565d 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -661,15 +661,19 @@ static void gen_qual_flushzero(DisasContext *ctx, int fn11)
 
 static TCGv gen_ieee_input(int reg, int fn11, int is_cmp)
 {
-    TCGv val = tcg_temp_new();
+    TCGv val;
     if (reg == 31) {
-        tcg_gen_movi_i64(val, 0);
-    } else if (fn11 & QUAL_S) {
-        gen_helper_ieee_input_s(val, cpu_env, cpu_fir[reg]);
-    } else if (is_cmp) {
-        gen_helper_ieee_input_cmp(val, cpu_env, cpu_fir[reg]);
+        val = tcg_const_i64(0);
     } else {
-        gen_helper_ieee_input(val, cpu_env, cpu_fir[reg]);
+        if ((fn11 & QUAL_S) == 0) {
+            if (is_cmp) {
+                gen_helper_ieee_input_cmp(cpu_env, cpu_fir[reg]);
+            } else {
+                gen_helper_ieee_input(cpu_env, cpu_fir[reg]);
+            }
+        }
+        val = tcg_temp_new();
+        tcg_gen_mov_i64(val, cpu_fir[reg]);
     }
     return val;
 }
commit c30827555d5305d42f7b164dc69a381c4882e77a
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Mar 24 09:51:13 2012 -0700

    target-alpha: Move memory helpers to mem_helper.c.
    
    This completes the transition away from AREG0.  This patch must
    be last because it requires CONFIG_TCG_PASS_AREG0 set too.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 254a9fa..44b2e83 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -81,8 +81,10 @@ libobj-y += tcg/tcg.o tcg/optimize.o
 libobj-$(CONFIG_TCG_INTERPRETER) += tci.o
 libobj-y += fpu/softfloat.o
 ifneq ($(TARGET_BASE_ARCH), sparc)
+ifneq ($(TARGET_BASE_ARCH), alpha)
 libobj-y += op_helper.o
 endif
+endif
 libobj-y += helper.o
 ifeq ($(TARGET_BASE_ARCH), i386)
 libobj-y += cpuid.o
@@ -96,7 +98,7 @@ libobj-y += cpu_init.o
 endif
 libobj-$(TARGET_SPARC) += int32_helper.o
 libobj-$(TARGET_SPARC64) += int64_helper.o
-libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o sys_helper.o
+libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o sys_helper.o mem_helper.o
 
 libobj-y += disas.o
 libobj-$(CONFIG_TCI_DIS) += tci-dis.o
diff --git a/configure b/configure
index 8b4e3c1..14ef738 100755
--- a/configure
+++ b/configure
@@ -3608,7 +3608,7 @@ case "$target_arch2" in
 esac
 
 case "$target_arch2" in
-  sparc*)
+  alpha | sparc*)
     echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak
   ;;
 esac
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index f057ecf..03cc185 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -104,12 +104,12 @@ DEF_HELPER_2(hw_ret, void, env, i64)
 
 DEF_HELPER_1(ldl_phys, i64, i64)
 DEF_HELPER_1(ldq_phys, i64, i64)
-DEF_HELPER_1(ldl_l_phys, i64, i64)
-DEF_HELPER_1(ldq_l_phys, i64, i64)
+DEF_HELPER_2(ldl_l_phys, i64, env, i64)
+DEF_HELPER_2(ldq_l_phys, i64, env, i64)
 DEF_HELPER_2(stl_phys, void, i64, i64)
 DEF_HELPER_2(stq_phys, void, i64, i64)
-DEF_HELPER_2(stl_c_phys, i64, i64, i64)
-DEF_HELPER_2(stq_c_phys, i64, i64, i64)
+DEF_HELPER_3(stl_c_phys, i64, env, i64, i64)
+DEF_HELPER_3(stq_c_phys, i64, env, i64, i64)
 
 DEF_HELPER_FLAGS_1(tbia, TCG_CALL_CONST, void, env)
 DEF_HELPER_FLAGS_2(tbis, TCG_CALL_CONST, void, env, i64)
diff --git a/target-alpha/mem_helper.c b/target-alpha/mem_helper.c
new file mode 100644
index 0000000..dd5ca49
--- /dev/null
+++ b/target-alpha/mem_helper.c
@@ -0,0 +1,151 @@
+/*
+ *  Helpers for loads and stores
+ *
+ *  Copyright (c) 2007 Jocelyn Mayer
+ *
+ * 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/>.
+ */
+
+#include "cpu.h"
+#include "helper.h"
+
+
+/* Softmmu support */
+#ifndef CONFIG_USER_ONLY
+
+uint64_t helper_ldl_phys(uint64_t p)
+{
+    return (int32_t)ldl_phys(p);
+}
+
+uint64_t helper_ldq_phys(uint64_t p)
+{
+    return ldq_phys(p);
+}
+
+uint64_t helper_ldl_l_phys(CPUAlphaState *env, uint64_t p)
+{
+    env->lock_addr = p;
+    return env->lock_value = (int32_t)ldl_phys(p);
+}
+
+uint64_t helper_ldq_l_phys(CPUAlphaState *env, uint64_t p)
+{
+    env->lock_addr = p;
+    return env->lock_value = ldq_phys(p);
+}
+
+void helper_stl_phys(uint64_t p, uint64_t v)
+{
+    stl_phys(p, v);
+}
+
+void helper_stq_phys(uint64_t p, uint64_t v)
+{
+    stq_phys(p, v);
+}
+
+uint64_t helper_stl_c_phys(CPUAlphaState *env, uint64_t p, uint64_t v)
+{
+    uint64_t ret = 0;
+
+    if (p == env->lock_addr) {
+        int32_t old = ldl_phys(p);
+        if (old == (int32_t)env->lock_value) {
+            stl_phys(p, v);
+            ret = 1;
+        }
+    }
+    env->lock_addr = -1;
+
+    return ret;
+}
+
+uint64_t helper_stq_c_phys(CPUAlphaState *env, uint64_t p, uint64_t v)
+{
+    uint64_t ret = 0;
+
+    if (p == env->lock_addr) {
+        uint64_t old = ldq_phys(p);
+        if (old == env->lock_value) {
+            stq_phys(p, v);
+            ret = 1;
+        }
+    }
+    env->lock_addr = -1;
+
+    return ret;
+}
+
+static void do_unaligned_access(CPUAlphaState *env, target_ulong addr,
+                                int is_write, int is_user, void *retaddr)
+{
+    uint64_t pc;
+    uint32_t insn;
+
+    do_restore_state(env, retaddr);
+
+    pc = env->pc;
+    insn = cpu_ldl_code(env, pc);
+
+    env->trap_arg0 = addr;
+    env->trap_arg1 = insn >> 26;                /* opcode */
+    env->trap_arg2 = (insn >> 21) & 31;         /* dest regno */
+    env->exception_index = EXCP_UNALIGN;
+    env->error_code = 0;
+    cpu_loop_exit(env);
+}
+
+void cpu_unassigned_access(CPUAlphaState *env, target_phys_addr_t addr,
+                           int is_write, int is_exec, int unused, int size)
+{
+    env->trap_arg0 = addr;
+    env->trap_arg1 = is_write;
+    dynamic_excp(env, NULL, EXCP_MCHK, 0);
+}
+
+#include "softmmu_exec.h"
+
+#define MMUSUFFIX _mmu
+#define ALIGNED_ONLY
+
+#define SHIFT 0
+#include "softmmu_template.h"
+
+#define SHIFT 1
+#include "softmmu_template.h"
+
+#define SHIFT 2
+#include "softmmu_template.h"
+
+#define SHIFT 3
+#include "softmmu_template.h"
+
+/* try to fill the TLB and return an exception if error. If retaddr is
+   NULL, it means that the function was called in C code (i.e. not
+   from generated code or from helper.c) */
+/* XXX: fix it to restore all registers */
+void tlb_fill(CPUAlphaState *env, target_ulong addr, int is_write,
+              int mmu_idx, void *retaddr)
+{
+    int ret;
+
+    ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx);
+    if (unlikely(ret != 0)) {
+        do_restore_state(env, retaddr);
+        /* Exception index and error code are already set */
+        cpu_loop_exit(env);
+    }
+}
+#endif /* CONFIG_USER_ONLY */
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
deleted file mode 100644
index df1f01c..0000000
--- a/target-alpha/op_helper.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- *  Alpha emulation cpu micro-operations helpers for qemu.
- *
- *  Copyright (c) 2007 Jocelyn Mayer
- *
- * 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/>.
- */
-
-#include "cpu.h"
-#include "dyngen-exec.h"
-#include "host-utils.h"
-#include "softfloat.h"
-#include "helper.h"
-#include "sysemu.h"
-#include "qemu-timer.h"
-
-
-/*****************************************************************************/
-/* Softmmu support */
-#if !defined (CONFIG_USER_ONLY)
-uint64_t helper_ldl_phys(uint64_t p)
-{
-    return (int32_t)ldl_phys(p);
-}
-
-uint64_t helper_ldq_phys(uint64_t p)
-{
-    return ldq_phys(p);
-}
-
-uint64_t helper_ldl_l_phys(uint64_t p)
-{
-    env->lock_addr = p;
-    return env->lock_value = (int32_t)ldl_phys(p);
-}
-
-uint64_t helper_ldq_l_phys(uint64_t p)
-{
-    env->lock_addr = p;
-    return env->lock_value = ldl_phys(p);
-}
-
-void helper_stl_phys(uint64_t p, uint64_t v)
-{
-    stl_phys(p, v);
-}
-
-void helper_stq_phys(uint64_t p, uint64_t v)
-{
-    stq_phys(p, v);
-}
-
-uint64_t helper_stl_c_phys(uint64_t p, uint64_t v)
-{
-    uint64_t ret = 0;
-
-    if (p == env->lock_addr) {
-        int32_t old = ldl_phys(p);
-        if (old == (int32_t)env->lock_value) {
-            stl_phys(p, v);
-            ret = 1;
-        }
-    }
-    env->lock_addr = -1;
-
-    return ret;
-}
-
-uint64_t helper_stq_c_phys(uint64_t p, uint64_t v)
-{
-    uint64_t ret = 0;
-
-    if (p == env->lock_addr) {
-        uint64_t old = ldq_phys(p);
-        if (old == env->lock_value) {
-            stq_phys(p, v);
-            ret = 1;
-        }
-    }
-    env->lock_addr = -1;
-
-    return ret;
-}
-
-static void QEMU_NORETURN do_unaligned_access(target_ulong addr, int is_write,
-                                              int is_user, void *retaddr)
-{
-    uint64_t pc;
-    uint32_t insn;
-
-    do_restore_state(env, retaddr);
-
-    pc = env->pc;
-    insn = ldl_code(pc);
-
-    env->trap_arg0 = addr;
-    env->trap_arg1 = insn >> 26;                /* opcode */
-    env->trap_arg2 = (insn >> 21) & 31;         /* dest regno */
-    env->exception_index = EXCP_UNALIGN;
-    env->error_code = 0;
-    cpu_loop_exit(env);
-}
-
-void QEMU_NORETURN cpu_unassigned_access(CPUAlphaState *env1,
-                                         target_phys_addr_t addr, int is_write,
-                                         int is_exec, int unused, int size)
-{
-    env = env1;
-    env->trap_arg0 = addr;
-    env->trap_arg1 = is_write;
-    dynamic_excp(env1, GETPC(), EXCP_MCHK, 0);
-}
-
-#include "softmmu_exec.h"
-
-#define MMUSUFFIX _mmu
-#define ALIGNED_ONLY
-
-#define SHIFT 0
-#include "softmmu_template.h"
-
-#define SHIFT 1
-#include "softmmu_template.h"
-
-#define SHIFT 2
-#include "softmmu_template.h"
-
-#define SHIFT 3
-#include "softmmu_template.h"
-
-/* try to fill the TLB and return an exception if error. If retaddr is
-   NULL, it means that the function was called in C code (i.e. not
-   from generated code or from helper.c) */
-/* XXX: fix it to restore all registers */
-void tlb_fill(CPUAlphaState *env1, target_ulong addr, int is_write, int mmu_idx,
-              void *retaddr)
-{
-    CPUAlphaState *saved_env;
-    int ret;
-
-    saved_env = env;
-    env = env1;
-    ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx);
-    if (unlikely(ret != 0)) {
-        do_restore_state(env, retaddr);
-        /* Exception index and error code are already set */
-        cpu_loop_exit(env);
-    }
-    env = saved_env;
-}
-#endif
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index cc87320..dd09ad8 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -2867,11 +2867,11 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
                 break;
             case 0x2:
                 /* Longword physical access with lock (hw_ldl_l/p) */
-                gen_helper_ldl_l_phys(cpu_ir[ra], addr);
+                gen_helper_ldl_l_phys(cpu_ir[ra], cpu_env, addr);
                 break;
             case 0x3:
                 /* Quadword physical access with lock (hw_ldq_l/p) */
-                gen_helper_ldq_l_phys(cpu_ir[ra], addr);
+                gen_helper_ldq_l_phys(cpu_ir[ra], cpu_env, addr);
                 break;
             case 0x4:
                 /* Longword virtual PTE fetch (hw_ldl/v) */
@@ -3180,11 +3180,11 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
                 break;
             case 0x2:
                 /* Longword physical access with lock */
-                gen_helper_stl_c_phys(val, addr, val);
+                gen_helper_stl_c_phys(val, cpu_env, addr, val);
                 break;
             case 0x3:
                 /* Quadword physical access with lock */
-                gen_helper_stq_c_phys(val, addr, val);
+                gen_helper_stq_c_phys(val, cpu_env, addr, val);
                 break;
             case 0x4:
                 /* Longword virtual access */
@@ -3420,7 +3420,7 @@ static inline void gen_intermediate_code_internal(CPUAlphaState *env,
         }
         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
             gen_io_start();
-        insn = ldl_code(ctx.pc);
+        insn = cpu_ldl_code(env, ctx.pc);
         num_insns++;
 
 	if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
commit 69163fbb0c4d7d3c270bd79d14d6ac076143975e
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Mar 24 09:51:12 2012 -0700

    target-alpha: Move palcode support helpers to sys_helper.c.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 256e7b5..254a9fa 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -96,7 +96,7 @@ libobj-y += cpu_init.o
 endif
 libobj-$(TARGET_SPARC) += int32_helper.o
 libobj-$(TARGET_SPARC64) += int64_helper.o
-libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o
+libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o sys_helper.o
 
 libobj-y += disas.o
 libobj-$(CONFIG_TCI_DIS) += tci-dis.o
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 45e187d..f057ecf 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -1,7 +1,7 @@
 #include "def-helper.h"
 
 DEF_HELPER_3(excp, void, env, int, int)
-DEF_HELPER_FLAGS_0(load_pcc, TCG_CALL_CONST | TCG_CALL_PURE, i64)
+DEF_HELPER_FLAGS_1(load_pcc, TCG_CALL_CONST | TCG_CALL_PURE, i64, env)
 
 DEF_HELPER_3(addqv, i64, env, i64, i64)
 DEF_HELPER_3(addlv, i64, env, i64, i64)
@@ -100,7 +100,7 @@ DEF_HELPER_2(ieee_input_cmp, i64, env, i64)
 DEF_HELPER_2(ieee_input_s, i64, env, i64)
 
 #if !defined (CONFIG_USER_ONLY)
-DEF_HELPER_1(hw_ret, void, i64)
+DEF_HELPER_2(hw_ret, void, env, i64)
 
 DEF_HELPER_1(ldl_phys, i64, i64)
 DEF_HELPER_1(ldq_phys, i64, i64)
@@ -111,13 +111,13 @@ DEF_HELPER_2(stq_phys, void, i64, i64)
 DEF_HELPER_2(stl_c_phys, i64, i64, i64)
 DEF_HELPER_2(stq_c_phys, i64, i64, i64)
 
-DEF_HELPER_FLAGS_0(tbia, TCG_CALL_CONST, void)
-DEF_HELPER_FLAGS_1(tbis, TCG_CALL_CONST, void, i64)
+DEF_HELPER_FLAGS_1(tbia, TCG_CALL_CONST, void, env)
+DEF_HELPER_FLAGS_2(tbis, TCG_CALL_CONST, void, env, i64)
 
 DEF_HELPER_1(halt, void, i64);
 
 DEF_HELPER_FLAGS_0(get_time, TCG_CALL_CONST, i64)
-DEF_HELPER_FLAGS_1(set_alarm, TCG_CALL_CONST, void, i64)
+DEF_HELPER_FLAGS_2(set_alarm, TCG_CALL_CONST, void, env, i64)
 #endif
 
 #include "def-helper.h"
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index c51b535..df1f01c 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -25,71 +25,6 @@
 #include "sysemu.h"
 #include "qemu-timer.h"
 
-/*****************************************************************************/
-/* Exceptions processing helpers */
-
-uint64_t helper_load_pcc (void)
-{
-#ifndef CONFIG_USER_ONLY
-    /* In system mode we have access to a decent high-resolution clock.
-       In order to make OS-level time accounting work with the RPCC,
-       present it with a well-timed clock fixed at 250MHz.  */
-    return (((uint64_t)env->pcc_ofs << 32)
-            | (uint32_t)(qemu_get_clock_ns(vm_clock) >> 2));
-#else
-    /* In user-mode, vm_clock doesn't exist.  Just pass through the host cpu
-       clock ticks.  Also, don't bother taking PCC_OFS into account.  */
-    return (uint32_t)cpu_get_real_ticks();
-#endif
-}
-
-/* PALcode support special instructions */
-#if !defined (CONFIG_USER_ONLY)
-void helper_hw_ret (uint64_t a)
-{
-    env->pc = a & ~3;
-    env->intr_flag = 0;
-    env->lock_addr = -1;
-    if ((a & 1) == 0) {
-        env->pal_mode = 0;
-        swap_shadow_regs(env);
-    }
-}
-
-void helper_tbia(void)
-{
-    tlb_flush(env, 1);
-}
-
-void helper_tbis(uint64_t p)
-{
-    tlb_flush_page(env, p);
-}
-
-void helper_halt(uint64_t restart)
-{
-    if (restart) {
-        qemu_system_reset_request();
-    } else {
-        qemu_system_shutdown_request();
-    }
-}
-
-uint64_t helper_get_time(void)
-{
-    return qemu_get_clock_ns(rtc_clock);
-}
-
-void helper_set_alarm(uint64_t expire)
-{
-    if (expire) {
-        env->alarm_expire = expire;
-        qemu_mod_timer(env->alarm_timer, expire);
-    } else {
-        qemu_del_timer(env->alarm_timer);
-    }
-}
-#endif
 
 /*****************************************************************************/
 /* Softmmu support */
diff --git a/target-alpha/sys_helper.c b/target-alpha/sys_helper.c
new file mode 100644
index 0000000..40ca49c
--- /dev/null
+++ b/target-alpha/sys_helper.c
@@ -0,0 +1,87 @@
+/*
+ *  Helpers for system instructions.
+ *
+ *  Copyright (c) 2007 Jocelyn Mayer
+ *
+ * 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/>.
+ */
+
+#include "cpu.h"
+#include "helper.h"
+#include "sysemu.h"
+#include "qemu-timer.h"
+
+
+uint64_t helper_load_pcc(CPUAlphaState *env)
+{
+#ifndef CONFIG_USER_ONLY
+    /* In system mode we have access to a decent high-resolution clock.
+       In order to make OS-level time accounting work with the RPCC,
+       present it with a well-timed clock fixed at 250MHz.  */
+    return (((uint64_t)env->pcc_ofs << 32)
+            | (uint32_t)(qemu_get_clock_ns(vm_clock) >> 2));
+#else
+    /* In user-mode, vm_clock doesn't exist.  Just pass through the host cpu
+       clock ticks.  Also, don't bother taking PCC_OFS into account.  */
+    return (uint32_t)cpu_get_real_ticks();
+#endif
+}
+
+/* PALcode support special instructions */
+#ifndef CONFIG_USER_ONLY
+void helper_hw_ret(CPUAlphaState *env, uint64_t a)
+{
+    env->pc = a & ~3;
+    env->intr_flag = 0;
+    env->lock_addr = -1;
+    if ((a & 1) == 0) {
+        env->pal_mode = 0;
+        swap_shadow_regs(env);
+    }
+}
+
+void helper_tbia(CPUAlphaState *env)
+{
+    tlb_flush(env, 1);
+}
+
+void helper_tbis(CPUAlphaState *env, uint64_t p)
+{
+    tlb_flush_page(env, p);
+}
+
+void helper_halt(uint64_t restart)
+{
+    if (restart) {
+        qemu_system_reset_request();
+    } else {
+        qemu_system_shutdown_request();
+    }
+}
+
+uint64_t helper_get_time(void)
+{
+    return qemu_get_clock_ns(rtc_clock);
+}
+
+void helper_set_alarm(CPUAlphaState *env, uint64_t expire)
+{
+    if (expire) {
+        env->alarm_expire = expire;
+        qemu_mod_timer(env->alarm_timer, expire);
+    } else {
+        qemu_del_timer(env->alarm_timer);
+    }
+}
+#endif /* CONFIG_USER_ONLY */
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 551237c..cc87320 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1678,12 +1678,12 @@ static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno)
     switch (regno) {
     case 255:
         /* TBIA */
-        gen_helper_tbia();
+        gen_helper_tbia(cpu_env);
         break;
 
     case 254:
         /* TBIS */
-        gen_helper_tbis(tmp);
+        gen_helper_tbis(cpu_env, tmp);
         break;
 
     case 253:
@@ -1699,7 +1699,7 @@ static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno)
 
     case 251:
         /* ALARM */
-        gen_helper_set_alarm(tmp);
+        gen_helper_set_alarm(cpu_env, tmp);
         break;
 
     default:
@@ -2793,11 +2793,11 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
             if (ra != 31) {
                 if (use_icount) {
                     gen_io_start();
-                    gen_helper_load_pcc(cpu_ir[ra]);
+                    gen_helper_load_pcc(cpu_ir[ra], cpu_env);
                     gen_io_end();
                     ret = EXIT_PC_STALE;
                 } else {
-                    gen_helper_load_pcc(cpu_ir[ra]);
+                    gen_helper_load_pcc(cpu_ir[ra], cpu_env);
                 }
             }
             break;
@@ -3143,10 +3143,10 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
                    emulation PALcode, so continue to accept it.  */
                 TCGv tmp = tcg_temp_new();
                 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUAlphaState, exc_addr));
-                gen_helper_hw_ret(tmp);
+                gen_helper_hw_ret(cpu_env, tmp);
                 tcg_temp_free(tmp);
             } else {
-                gen_helper_hw_ret(cpu_ir[rb]);
+                gen_helper_hw_ret(cpu_env, cpu_ir[rb]);
             }
             ret = EXIT_PC_UPDATED;
             break;
commit 2958620f67dcfd11476e62b4ca704dae0b978ea3
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Mar 24 09:51:11 2012 -0700

    target-alpha: Move integer overflow helpers to int_helper.c.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index e193c26..45e187d 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -3,12 +3,12 @@
 DEF_HELPER_3(excp, void, env, int, int)
 DEF_HELPER_FLAGS_0(load_pcc, TCG_CALL_CONST | TCG_CALL_PURE, i64)
 
-DEF_HELPER_2(addqv, i64, i64, i64)
-DEF_HELPER_2(addlv, i64, i64, i64)
-DEF_HELPER_2(subqv, i64, i64, i64)
-DEF_HELPER_2(sublv, i64, i64, i64)
-DEF_HELPER_2(mullv, i64, i64, i64)
-DEF_HELPER_2(mulqv, i64, i64, i64)
+DEF_HELPER_3(addqv, i64, env, i64, i64)
+DEF_HELPER_3(addlv, i64, env, i64, i64)
+DEF_HELPER_3(subqv, i64, env, i64, i64)
+DEF_HELPER_3(sublv, i64, env, i64, i64)
+DEF_HELPER_3(mullv, i64, env, i64, i64)
+DEF_HELPER_3(mulqv, i64, env, i64, i64)
 DEF_HELPER_FLAGS_2(umulh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
 
 DEF_HELPER_FLAGS_1(ctpop, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
diff --git a/target-alpha/int_helper.c b/target-alpha/int_helper.c
index 79c0cfe..1d832f0 100644
--- a/target-alpha/int_helper.c
+++ b/target-alpha/int_helper.c
@@ -255,3 +255,65 @@ uint64_t helper_unpkbw(uint64_t op1)
             | ((op1 & 0xff0000) << 16)
             | ((op1 & 0xff000000) << 24));
 }
+
+uint64_t helper_addqv(CPUAlphaState *env, uint64_t op1, uint64_t op2)
+{
+    uint64_t tmp = op1;
+    op1 += op2;
+    if (unlikely((tmp ^ op2 ^ (-1ULL)) & (tmp ^ op1) & (1ULL << 63))) {
+        arith_excp(env, GETPC(), EXC_M_IOV, 0);
+    }
+    return op1;
+}
+
+uint64_t helper_addlv(CPUAlphaState *env, uint64_t op1, uint64_t op2)
+{
+    uint64_t tmp = op1;
+    op1 = (uint32_t)(op1 + op2);
+    if (unlikely((tmp ^ op2 ^ (-1UL)) & (tmp ^ op1) & (1UL << 31))) {
+        arith_excp(env, GETPC(), EXC_M_IOV, 0);
+    }
+    return op1;
+}
+
+uint64_t helper_subqv(CPUAlphaState *env, uint64_t op1, uint64_t op2)
+{
+    uint64_t res;
+    res = op1 - op2;
+    if (unlikely((op1 ^ op2) & (res ^ op1) & (1ULL << 63))) {
+        arith_excp(env, GETPC(), EXC_M_IOV, 0);
+    }
+    return res;
+}
+
+uint64_t helper_sublv(CPUAlphaState *env, uint64_t op1, uint64_t op2)
+{
+    uint32_t res;
+    res = op1 - op2;
+    if (unlikely((op1 ^ op2) & (res ^ op1) & (1UL << 31))) {
+        arith_excp(env, GETPC(), EXC_M_IOV, 0);
+    }
+    return res;
+}
+
+uint64_t helper_mullv(CPUAlphaState *env, uint64_t op1, uint64_t op2)
+{
+    int64_t res = (int64_t)op1 * (int64_t)op2;
+
+    if (unlikely((int32_t)res != res)) {
+        arith_excp(env, GETPC(), EXC_M_IOV, 0);
+    }
+    return (int64_t)((int32_t)res);
+}
+
+uint64_t helper_mulqv(CPUAlphaState *env, uint64_t op1, uint64_t op2)
+{
+    uint64_t tl, th;
+
+    muls64(&tl, &th, op1, op2);
+    /* If th != 0 && th != -1, then we had an overflow */
+    if (unlikely((th + 1) > 1)) {
+        arith_excp(env, GETPC(), EXC_M_IOV, 0);
+    }
+    return tl;
+}
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 59ee31e..c51b535 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -43,68 +43,6 @@ uint64_t helper_load_pcc (void)
 #endif
 }
 
-uint64_t helper_addqv (uint64_t op1, uint64_t op2)
-{
-    uint64_t tmp = op1;
-    op1 += op2;
-    if (unlikely((tmp ^ op2 ^ (-1ULL)) & (tmp ^ op1) & (1ULL << 63))) {
-        arith_excp(env, GETPC(), EXC_M_IOV, 0);
-    }
-    return op1;
-}
-
-uint64_t helper_addlv (uint64_t op1, uint64_t op2)
-{
-    uint64_t tmp = op1;
-    op1 = (uint32_t)(op1 + op2);
-    if (unlikely((tmp ^ op2 ^ (-1UL)) & (tmp ^ op1) & (1UL << 31))) {
-        arith_excp(env, GETPC(), EXC_M_IOV, 0);
-    }
-    return op1;
-}
-
-uint64_t helper_subqv (uint64_t op1, uint64_t op2)
-{
-    uint64_t res;
-    res = op1 - op2;
-    if (unlikely((op1 ^ op2) & (res ^ op1) & (1ULL << 63))) {
-        arith_excp(env, GETPC(), EXC_M_IOV, 0);
-    }
-    return res;
-}
-
-uint64_t helper_sublv (uint64_t op1, uint64_t op2)
-{
-    uint32_t res;
-    res = op1 - op2;
-    if (unlikely((op1 ^ op2) & (res ^ op1) & (1UL << 31))) {
-        arith_excp(env, GETPC(), EXC_M_IOV, 0);
-    }
-    return res;
-}
-
-uint64_t helper_mullv (uint64_t op1, uint64_t op2)
-{
-    int64_t res = (int64_t)op1 * (int64_t)op2;
-
-    if (unlikely((int32_t)res != res)) {
-        arith_excp(env, GETPC(), EXC_M_IOV, 0);
-    }
-    return (int64_t)((int32_t)res);
-}
-
-uint64_t helper_mulqv (uint64_t op1, uint64_t op2)
-{
-    uint64_t tl, th;
-
-    muls64(&tl, &th, op1, op2);
-    /* If th != 0 && th != -1, then we had an overflow */
-    if (unlikely((th + 1) > 1)) {
-        arith_excp(env, GETPC(), EXC_M_IOV, 0);
-    }
-    return tl;
-}
-
 /* PALcode support special instructions */
 #if !defined (CONFIG_USER_ONLY)
 void helper_hw_ret (uint64_t a)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 6f31b6d..551237c 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1392,14 +1392,8 @@ static inline void glue(gen_, name)(int ra, int rb, int rc, int islit,\
         tcg_temp_free(tmp1);                                          \
     }                                                                 \
 }
-ARITH3(cmpbge)
-ARITH3(addlv)
-ARITH3(sublv)
-ARITH3(addqv)
-ARITH3(subqv)
 ARITH3(umulh)
-ARITH3(mullv)
-ARITH3(mulqv)
+ARITH3(cmpbge)
 ARITH3(minub8)
 ARITH3(minsb8)
 ARITH3(minuw4)
@@ -1410,6 +1404,43 @@ ARITH3(maxuw4)
 ARITH3(maxsw4)
 ARITH3(perr)
 
+/* Code to call arith3 helpers */
+#define ARITH3_EX(name)                                                 \
+    static inline void glue(gen_, name)(int ra, int rb, int rc,         \
+                                        int islit, uint8_t lit)         \
+    {                                                                   \
+        if (unlikely(rc == 31)) {                                       \
+            return;                                                     \
+        }                                                               \
+        if (ra != 31) {                                                 \
+            if (islit) {                                                \
+                TCGv tmp = tcg_const_i64(lit);                          \
+                gen_helper_ ## name(cpu_ir[rc], cpu_env,                \
+                                    cpu_ir[ra], tmp);                   \
+                tcg_temp_free(tmp);                                     \
+            } else {                                                    \
+                gen_helper_ ## name(cpu_ir[rc], cpu_env,                \
+                                    cpu_ir[ra], cpu_ir[rb]);            \
+            }                                                           \
+        } else {                                                        \
+            TCGv tmp1 = tcg_const_i64(0);                               \
+            if (islit) {                                                \
+                TCGv tmp2 = tcg_const_i64(lit);                         \
+                gen_helper_ ## name(cpu_ir[rc], cpu_env, tmp1, tmp2);   \
+                tcg_temp_free(tmp2);                                    \
+            } else {                                                    \
+                gen_helper_ ## name(cpu_ir[rc], cpu_env, tmp1, cpu_ir[rb]); \
+            }                                                           \
+            tcg_temp_free(tmp1);                                        \
+        }                                                               \
+    }
+ARITH3_EX(addlv)
+ARITH3_EX(sublv)
+ARITH3_EX(addqv)
+ARITH3_EX(subqv)
+ARITH3_EX(mullv)
+ARITH3_EX(mulqv)
+
 #define MVIOP2(name)                                    \
 static inline void glue(gen_, name)(int rb, int rc)     \
 {                                                       \
commit a44a27775af6e745be50b23ae0f0aeb6f8462c80
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Mar 24 09:51:10 2012 -0700

    target-alpha: Move fpcr helpers from op_helper.c to helper.c.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 584457f..3333bfa 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -159,9 +159,19 @@ void cpu_alpha_store_fpcr (CPUAlphaState *env, uint64_t val)
     env->fpcr_undz = (val & FPCR_UNDZ) != 0;
 }
 
+uint64_t helper_load_fpcr(CPUAlphaState *env)
+{
+    return cpu_alpha_load_fpcr(env);
+}
+
+void helper_store_fpcr(CPUAlphaState *env, uint64_t val)
+{
+    cpu_alpha_store_fpcr(env, val);
+}
+
 #if defined(CONFIG_USER_ONLY)
-int cpu_alpha_handle_mmu_fault (CPUAlphaState *env, target_ulong address, int rw,
-                                int mmu_idx)
+int cpu_alpha_handle_mmu_fault(CPUAlphaState *env, target_ulong address,
+                               int rw, int mmu_idx)
 {
     env->exception_index = EXCP_MMFAULT;
     env->trap_arg0 = address;
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index d36df5f..e193c26 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -34,8 +34,8 @@ DEF_HELPER_FLAGS_1(pkwb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
 DEF_HELPER_FLAGS_1(unpkbl, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
 DEF_HELPER_FLAGS_1(unpkbw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
 
-DEF_HELPER_FLAGS_0(load_fpcr, TCG_CALL_CONST | TCG_CALL_PURE, i64)
-DEF_HELPER_FLAGS_1(store_fpcr, TCG_CALL_CONST, void, i64)
+DEF_HELPER_FLAGS_1(load_fpcr, TCG_CALL_CONST | TCG_CALL_PURE, i64, env)
+DEF_HELPER_FLAGS_2(store_fpcr, TCG_CALL_CONST, void, env, i64)
 
 DEF_HELPER_FLAGS_1(f_to_memory, TCG_CALL_CONST | TCG_CALL_PURE, i32, i64)
 DEF_HELPER_FLAGS_1(memory_to_f, TCG_CALL_CONST | TCG_CALL_PURE, i64, i32)
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 6711d99..59ee31e 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -43,16 +43,6 @@ uint64_t helper_load_pcc (void)
 #endif
 }
 
-uint64_t helper_load_fpcr (void)
-{
-    return cpu_alpha_load_fpcr (env);
-}
-
-void helper_store_fpcr (uint64_t val)
-{
-    cpu_alpha_store_fpcr (env, val);
-}
-
 uint64_t helper_addqv (uint64_t op1, uint64_t op2)
 {
     uint64_t tmp = op1;
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index a9b97a3..6f31b6d 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -2678,17 +2678,17 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
         case 0x024:
             /* MT_FPCR */
             if (likely(ra != 31))
-                gen_helper_store_fpcr(cpu_fir[ra]);
+                gen_helper_store_fpcr(cpu_env, cpu_fir[ra]);
             else {
                 TCGv tmp = tcg_const_i64(0);
-                gen_helper_store_fpcr(tmp);
+                gen_helper_store_fpcr(cpu_env, tmp);
                 tcg_temp_free(tmp);
             }
             break;
         case 0x025:
             /* MF_FPCR */
             if (likely(ra != 31))
-                gen_helper_load_fpcr(cpu_fir[ra]);
+                gen_helper_load_fpcr(cpu_fir[ra], cpu_env);
             break;
         case 0x02A:
             /* FCMOVEQ */
commit 4a58aedff479e02c33ba74d752f34944751ba28b
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Mar 24 09:51:09 2012 -0700

    target-alpha: Move floating-point helpers to fpu_helper.c.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index ddeb7e0..256e7b5 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -96,7 +96,7 @@ libobj-y += cpu_init.o
 endif
 libobj-$(TARGET_SPARC) += int32_helper.o
 libobj-$(TARGET_SPARC64) += int64_helper.o
-libobj-$(TARGET_ALPHA) += int_helper.o
+libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o
 
 libobj-y += disas.o
 libobj-$(CONFIG_TCI_DIS) += tci-dis.o
diff --git a/target-alpha/fpu_helper.c b/target-alpha/fpu_helper.c
new file mode 100644
index 0000000..d38521b
--- /dev/null
+++ b/target-alpha/fpu_helper.c
@@ -0,0 +1,846 @@
+/*
+ *  Helpers for floating point instructions.
+ *
+ *  Copyright (c) 2007 Jocelyn Mayer
+ *
+ * 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/>.
+ */
+
+#include "cpu.h"
+#include "helper.h"
+#include "softfloat.h"
+
+#define FP_STATUS (env->fp_status)
+
+
+void helper_setroundmode(CPUAlphaState *env, uint32_t val)
+{
+    set_float_rounding_mode(val, &FP_STATUS);
+}
+
+void helper_setflushzero(CPUAlphaState *env, uint32_t val)
+{
+    set_flush_to_zero(val, &FP_STATUS);
+}
+
+void helper_fp_exc_clear(CPUAlphaState *env)
+{
+    set_float_exception_flags(0, &FP_STATUS);
+}
+
+uint32_t helper_fp_exc_get(CPUAlphaState *env)
+{
+    return get_float_exception_flags(&FP_STATUS);
+}
+
+static inline void inline_fp_exc_raise(CPUAlphaState *env, void *retaddr,
+                                       uint32_t exc, uint32_t regno)
+{
+    if (exc) {
+        uint32_t hw_exc = 0;
+
+        if (exc & float_flag_invalid) {
+            hw_exc |= EXC_M_INV;
+        }
+        if (exc & float_flag_divbyzero) {
+            hw_exc |= EXC_M_DZE;
+        }
+        if (exc & float_flag_overflow) {
+            hw_exc |= EXC_M_FOV;
+        }
+        if (exc & float_flag_underflow) {
+            hw_exc |= EXC_M_UNF;
+        }
+        if (exc & float_flag_inexact) {
+            hw_exc |= EXC_M_INE;
+        }
+
+        arith_excp(env, retaddr, hw_exc, 1ull << regno);
+    }
+}
+
+/* Raise exceptions for ieee fp insns without software completion.
+   In that case there are no exceptions that don't trap; the mask
+   doesn't apply.  */
+void helper_fp_exc_raise(CPUAlphaState *env, uint32_t exc, uint32_t regno)
+{
+    inline_fp_exc_raise(env, GETPC(), exc, regno);
+}
+
+/* Raise exceptions for ieee fp insns with software completion.  */
+void helper_fp_exc_raise_s(CPUAlphaState *env, uint32_t exc, uint32_t regno)
+{
+    if (exc) {
+        env->fpcr_exc_status |= exc;
+        exc &= ~env->fpcr_exc_mask;
+        inline_fp_exc_raise(env, GETPC(), exc, regno);
+    }
+}
+
+/* Input remapping without software completion.  Handle denormal-map-to-zero
+   and trap for all other non-finite numbers.  */
+uint64_t helper_ieee_input(CPUAlphaState *env, uint64_t val)
+{
+    uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
+    uint64_t frac = val & 0xfffffffffffffull;
+
+    if (exp == 0) {
+        if (frac != 0) {
+            /* If DNZ is set flush denormals to zero on input.  */
+            if (env->fpcr_dnz) {
+                val &= 1ull << 63;
+            } else {
+                arith_excp(env, GETPC(), EXC_M_UNF, 0);
+            }
+        }
+    } else if (exp == 0x7ff) {
+        /* Infinity or NaN.  */
+        /* ??? I'm not sure these exception bit flags are correct.  I do
+           know that the Linux kernel, at least, doesn't rely on them and
+           just emulates the insn to figure out what exception to use.  */
+        arith_excp(env, GETPC(), frac ? EXC_M_INV : EXC_M_FOV, 0);
+    }
+    return val;
+}
+
+/* Similar, but does not trap for infinities.  Used for comparisons.  */
+uint64_t helper_ieee_input_cmp(CPUAlphaState *env, uint64_t val)
+{
+    uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
+    uint64_t frac = val & 0xfffffffffffffull;
+
+    if (exp == 0) {
+        if (frac != 0) {
+            /* If DNZ is set flush denormals to zero on input.  */
+            if (env->fpcr_dnz) {
+                val &= 1ull << 63;
+            } else {
+                arith_excp(env, GETPC(), EXC_M_UNF, 0);
+            }
+        }
+    } else if (exp == 0x7ff && frac) {
+        /* NaN.  */
+        arith_excp(env, GETPC(), EXC_M_INV, 0);
+    }
+    return val;
+}
+
+/* Input remapping with software completion enabled.  All we have to do
+   is handle denormal-map-to-zero; all other inputs get exceptions as
+   needed from the actual operation.  */
+uint64_t helper_ieee_input_s(CPUAlphaState *env, uint64_t val)
+{
+    if (env->fpcr_dnz) {
+        uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
+        if (exp == 0) {
+            val &= 1ull << 63;
+        }
+    }
+    return val;
+}
+
+/* F floating (VAX) */
+static uint64_t float32_to_f(float32 fa)
+{
+    uint64_t r, exp, mant, sig;
+    CPU_FloatU a;
+
+    a.f = fa;
+    sig = ((uint64_t)a.l & 0x80000000) << 32;
+    exp = (a.l >> 23) & 0xff;
+    mant = ((uint64_t)a.l & 0x007fffff) << 29;
+
+    if (exp == 255) {
+        /* NaN or infinity */
+        r = 1; /* VAX dirty zero */
+    } else if (exp == 0) {
+        if (mant == 0) {
+            /* Zero */
+            r = 0;
+        } else {
+            /* Denormalized */
+            r = sig | ((exp + 1) << 52) | mant;
+        }
+    } else {
+        if (exp >= 253) {
+            /* Overflow */
+            r = 1; /* VAX dirty zero */
+        } else {
+            r = sig | ((exp + 2) << 52);
+        }
+    }
+
+    return r;
+}
+
+static float32 f_to_float32(CPUAlphaState *env, void *retaddr, uint64_t a)
+{
+    uint32_t exp, mant_sig;
+    CPU_FloatU r;
+
+    exp = ((a >> 55) & 0x80) | ((a >> 52) & 0x7f);
+    mant_sig = ((a >> 32) & 0x80000000) | ((a >> 29) & 0x007fffff);
+
+    if (unlikely(!exp && mant_sig)) {
+        /* Reserved operands / Dirty zero */
+        dynamic_excp(env, retaddr, EXCP_OPCDEC, 0);
+    }
+
+    if (exp < 3) {
+        /* Underflow */
+        r.l = 0;
+    } else {
+        r.l = ((exp - 2) << 23) | mant_sig;
+    }
+
+    return r.f;
+}
+
+uint32_t helper_f_to_memory(uint64_t a)
+{
+    uint32_t r;
+    r =  (a & 0x00001fffe0000000ull) >> 13;
+    r |= (a & 0x07ffe00000000000ull) >> 45;
+    r |= (a & 0xc000000000000000ull) >> 48;
+    return r;
+}
+
+uint64_t helper_memory_to_f(uint32_t a)
+{
+    uint64_t r;
+    r =  ((uint64_t)(a & 0x0000c000)) << 48;
+    r |= ((uint64_t)(a & 0x003fffff)) << 45;
+    r |= ((uint64_t)(a & 0xffff0000)) << 13;
+    if (!(a & 0x00004000)) {
+        r |= 0x7ll << 59;
+    }
+    return r;
+}
+
+/* ??? Emulating VAX arithmetic with IEEE arithmetic is wrong.  We should
+   either implement VAX arithmetic properly or just signal invalid opcode.  */
+
+uint64_t helper_addf(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float32 fa, fb, fr;
+
+    fa = f_to_float32(env, GETPC(), a);
+    fb = f_to_float32(env, GETPC(), b);
+    fr = float32_add(fa, fb, &FP_STATUS);
+    return float32_to_f(fr);
+}
+
+uint64_t helper_subf(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float32 fa, fb, fr;
+
+    fa = f_to_float32(env, GETPC(), a);
+    fb = f_to_float32(env, GETPC(), b);
+    fr = float32_sub(fa, fb, &FP_STATUS);
+    return float32_to_f(fr);
+}
+
+uint64_t helper_mulf(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float32 fa, fb, fr;
+
+    fa = f_to_float32(env, GETPC(), a);
+    fb = f_to_float32(env, GETPC(), b);
+    fr = float32_mul(fa, fb, &FP_STATUS);
+    return float32_to_f(fr);
+}
+
+uint64_t helper_divf(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float32 fa, fb, fr;
+
+    fa = f_to_float32(env, GETPC(), a);
+    fb = f_to_float32(env, GETPC(), b);
+    fr = float32_div(fa, fb, &FP_STATUS);
+    return float32_to_f(fr);
+}
+
+uint64_t helper_sqrtf(CPUAlphaState *env, uint64_t t)
+{
+    float32 ft, fr;
+
+    ft = f_to_float32(env, GETPC(), t);
+    fr = float32_sqrt(ft, &FP_STATUS);
+    return float32_to_f(fr);
+}
+
+
+/* G floating (VAX) */
+static uint64_t float64_to_g(float64 fa)
+{
+    uint64_t r, exp, mant, sig;
+    CPU_DoubleU a;
+
+    a.d = fa;
+    sig = a.ll & 0x8000000000000000ull;
+    exp = (a.ll >> 52) & 0x7ff;
+    mant = a.ll & 0x000fffffffffffffull;
+
+    if (exp == 2047) {
+        /* NaN or infinity */
+        r = 1; /* VAX dirty zero */
+    } else if (exp == 0) {
+        if (mant == 0) {
+            /* Zero */
+            r = 0;
+        } else {
+            /* Denormalized */
+            r = sig | ((exp + 1) << 52) | mant;
+        }
+    } else {
+        if (exp >= 2045) {
+            /* Overflow */
+            r = 1; /* VAX dirty zero */
+        } else {
+            r = sig | ((exp + 2) << 52);
+        }
+    }
+
+    return r;
+}
+
+static float64 g_to_float64(CPUAlphaState *env, void *retaddr, uint64_t a)
+{
+    uint64_t exp, mant_sig;
+    CPU_DoubleU r;
+
+    exp = (a >> 52) & 0x7ff;
+    mant_sig = a & 0x800fffffffffffffull;
+
+    if (!exp && mant_sig) {
+        /* Reserved operands / Dirty zero */
+        dynamic_excp(env, retaddr, EXCP_OPCDEC, 0);
+    }
+
+    if (exp < 3) {
+        /* Underflow */
+        r.ll = 0;
+    } else {
+        r.ll = ((exp - 2) << 52) | mant_sig;
+    }
+
+    return r.d;
+}
+
+uint64_t helper_g_to_memory(uint64_t a)
+{
+    uint64_t r;
+    r =  (a & 0x000000000000ffffull) << 48;
+    r |= (a & 0x00000000ffff0000ull) << 16;
+    r |= (a & 0x0000ffff00000000ull) >> 16;
+    r |= (a & 0xffff000000000000ull) >> 48;
+    return r;
+}
+
+uint64_t helper_memory_to_g(uint64_t a)
+{
+    uint64_t r;
+    r =  (a & 0x000000000000ffffull) << 48;
+    r |= (a & 0x00000000ffff0000ull) << 16;
+    r |= (a & 0x0000ffff00000000ull) >> 16;
+    r |= (a & 0xffff000000000000ull) >> 48;
+    return r;
+}
+
+uint64_t helper_addg(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb, fr;
+
+    fa = g_to_float64(env, GETPC(), a);
+    fb = g_to_float64(env, GETPC(), b);
+    fr = float64_add(fa, fb, &FP_STATUS);
+    return float64_to_g(fr);
+}
+
+uint64_t helper_subg(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb, fr;
+
+    fa = g_to_float64(env, GETPC(), a);
+    fb = g_to_float64(env, GETPC(), b);
+    fr = float64_sub(fa, fb, &FP_STATUS);
+    return float64_to_g(fr);
+}
+
+uint64_t helper_mulg(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb, fr;
+
+    fa = g_to_float64(env, GETPC(), a);
+    fb = g_to_float64(env, GETPC(), b);
+    fr = float64_mul(fa, fb, &FP_STATUS);
+    return float64_to_g(fr);
+}
+
+uint64_t helper_divg(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb, fr;
+
+    fa = g_to_float64(env, GETPC(), a);
+    fb = g_to_float64(env, GETPC(), b);
+    fr = float64_div(fa, fb, &FP_STATUS);
+    return float64_to_g(fr);
+}
+
+uint64_t helper_sqrtg(CPUAlphaState *env, uint64_t a)
+{
+    float64 fa, fr;
+
+    fa = g_to_float64(env, GETPC(), a);
+    fr = float64_sqrt(fa, &FP_STATUS);
+    return float64_to_g(fr);
+}
+
+
+/* S floating (single) */
+
+/* Taken from linux/arch/alpha/kernel/traps.c, s_mem_to_reg.  */
+static inline uint64_t float32_to_s_int(uint32_t fi)
+{
+    uint32_t frac = fi & 0x7fffff;
+    uint32_t sign = fi >> 31;
+    uint32_t exp_msb = (fi >> 30) & 1;
+    uint32_t exp_low = (fi >> 23) & 0x7f;
+    uint32_t exp;
+
+    exp = (exp_msb << 10) | exp_low;
+    if (exp_msb) {
+        if (exp_low == 0x7f) {
+            exp = 0x7ff;
+        }
+    } else {
+        if (exp_low != 0x00) {
+            exp |= 0x380;
+        }
+    }
+
+    return (((uint64_t)sign << 63)
+            | ((uint64_t)exp << 52)
+            | ((uint64_t)frac << 29));
+}
+
+static inline uint64_t float32_to_s(float32 fa)
+{
+    CPU_FloatU a;
+    a.f = fa;
+    return float32_to_s_int(a.l);
+}
+
+static inline uint32_t s_to_float32_int(uint64_t a)
+{
+    return ((a >> 32) & 0xc0000000) | ((a >> 29) & 0x3fffffff);
+}
+
+static inline float32 s_to_float32(uint64_t a)
+{
+    CPU_FloatU r;
+    r.l = s_to_float32_int(a);
+    return r.f;
+}
+
+uint32_t helper_s_to_memory(uint64_t a)
+{
+    return s_to_float32_int(a);
+}
+
+uint64_t helper_memory_to_s(uint32_t a)
+{
+    return float32_to_s_int(a);
+}
+
+uint64_t helper_adds(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float32 fa, fb, fr;
+
+    fa = s_to_float32(a);
+    fb = s_to_float32(b);
+    fr = float32_add(fa, fb, &FP_STATUS);
+    return float32_to_s(fr);
+}
+
+uint64_t helper_subs(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float32 fa, fb, fr;
+
+    fa = s_to_float32(a);
+    fb = s_to_float32(b);
+    fr = float32_sub(fa, fb, &FP_STATUS);
+    return float32_to_s(fr);
+}
+
+uint64_t helper_muls(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float32 fa, fb, fr;
+
+    fa = s_to_float32(a);
+    fb = s_to_float32(b);
+    fr = float32_mul(fa, fb, &FP_STATUS);
+    return float32_to_s(fr);
+}
+
+uint64_t helper_divs(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float32 fa, fb, fr;
+
+    fa = s_to_float32(a);
+    fb = s_to_float32(b);
+    fr = float32_div(fa, fb, &FP_STATUS);
+    return float32_to_s(fr);
+}
+
+uint64_t helper_sqrts(CPUAlphaState *env, uint64_t a)
+{
+    float32 fa, fr;
+
+    fa = s_to_float32(a);
+    fr = float32_sqrt(fa, &FP_STATUS);
+    return float32_to_s(fr);
+}
+
+
+/* T floating (double) */
+static inline float64 t_to_float64(uint64_t a)
+{
+    /* Memory format is the same as float64 */
+    CPU_DoubleU r;
+    r.ll = a;
+    return r.d;
+}
+
+static inline uint64_t float64_to_t(float64 fa)
+{
+    /* Memory format is the same as float64 */
+    CPU_DoubleU r;
+    r.d = fa;
+    return r.ll;
+}
+
+uint64_t helper_addt(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb, fr;
+
+    fa = t_to_float64(a);
+    fb = t_to_float64(b);
+    fr = float64_add(fa, fb, &FP_STATUS);
+    return float64_to_t(fr);
+}
+
+uint64_t helper_subt(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb, fr;
+
+    fa = t_to_float64(a);
+    fb = t_to_float64(b);
+    fr = float64_sub(fa, fb, &FP_STATUS);
+    return float64_to_t(fr);
+}
+
+uint64_t helper_mult(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb, fr;
+
+    fa = t_to_float64(a);
+    fb = t_to_float64(b);
+    fr = float64_mul(fa, fb, &FP_STATUS);
+    return float64_to_t(fr);
+}
+
+uint64_t helper_divt(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb, fr;
+
+    fa = t_to_float64(a);
+    fb = t_to_float64(b);
+    fr = float64_div(fa, fb, &FP_STATUS);
+    return float64_to_t(fr);
+}
+
+uint64_t helper_sqrtt(CPUAlphaState *env, uint64_t a)
+{
+    float64 fa, fr;
+
+    fa = t_to_float64(a);
+    fr = float64_sqrt(fa, &FP_STATUS);
+    return float64_to_t(fr);
+}
+
+/* Comparisons */
+uint64_t helper_cmptun(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb;
+
+    fa = t_to_float64(a);
+    fb = t_to_float64(b);
+
+    if (float64_unordered_quiet(fa, fb, &FP_STATUS)) {
+        return 0x4000000000000000ULL;
+    } else {
+        return 0;
+    }
+}
+
+uint64_t helper_cmpteq(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb;
+
+    fa = t_to_float64(a);
+    fb = t_to_float64(b);
+
+    if (float64_eq_quiet(fa, fb, &FP_STATUS)) {
+        return 0x4000000000000000ULL;
+    } else {
+        return 0;
+    }
+}
+
+uint64_t helper_cmptle(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb;
+
+    fa = t_to_float64(a);
+    fb = t_to_float64(b);
+
+    if (float64_le(fa, fb, &FP_STATUS)) {
+        return 0x4000000000000000ULL;
+    } else {
+        return 0;
+    }
+}
+
+uint64_t helper_cmptlt(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb;
+
+    fa = t_to_float64(a);
+    fb = t_to_float64(b);
+
+    if (float64_lt(fa, fb, &FP_STATUS)) {
+        return 0x4000000000000000ULL;
+    } else {
+        return 0;
+    }
+}
+
+uint64_t helper_cmpgeq(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb;
+
+    fa = g_to_float64(env, GETPC(), a);
+    fb = g_to_float64(env, GETPC(), b);
+
+    if (float64_eq_quiet(fa, fb, &FP_STATUS)) {
+        return 0x4000000000000000ULL;
+    } else {
+        return 0;
+    }
+}
+
+uint64_t helper_cmpgle(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb;
+
+    fa = g_to_float64(env, GETPC(), a);
+    fb = g_to_float64(env, GETPC(), b);
+
+    if (float64_le(fa, fb, &FP_STATUS)) {
+        return 0x4000000000000000ULL;
+    } else {
+        return 0;
+    }
+}
+
+uint64_t helper_cmpglt(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb;
+
+    fa = g_to_float64(env, GETPC(), a);
+    fb = g_to_float64(env, GETPC(), b);
+
+    if (float64_lt(fa, fb, &FP_STATUS)) {
+        return 0x4000000000000000ULL;
+    } else {
+        return 0;
+    }
+}
+
+/* Floating point format conversion */
+uint64_t helper_cvtts(CPUAlphaState *env, uint64_t a)
+{
+    float64 fa;
+    float32 fr;
+
+    fa = t_to_float64(a);
+    fr = float64_to_float32(fa, &FP_STATUS);
+    return float32_to_s(fr);
+}
+
+uint64_t helper_cvtst(CPUAlphaState *env, uint64_t a)
+{
+    float32 fa;
+    float64 fr;
+
+    fa = s_to_float32(a);
+    fr = float32_to_float64(fa, &FP_STATUS);
+    return float64_to_t(fr);
+}
+
+uint64_t helper_cvtqs(CPUAlphaState *env, uint64_t a)
+{
+    float32 fr = int64_to_float32(a, &FP_STATUS);
+    return float32_to_s(fr);
+}
+
+/* Implement float64 to uint64 conversion without saturation -- we must
+   supply the truncated result.  This behaviour is used by the compiler
+   to get unsigned conversion for free with the same instruction.
+
+   The VI flag is set when overflow or inexact exceptions should be raised.  */
+
+static inline uint64_t inline_cvttq(CPUAlphaState *env, uint64_t a,
+                                    int roundmode, int VI)
+{
+    uint64_t frac, ret = 0;
+    uint32_t exp, sign, exc = 0;
+    int shift;
+
+    sign = (a >> 63);
+    exp = (uint32_t)(a >> 52) & 0x7ff;
+    frac = a & 0xfffffffffffffull;
+
+    if (exp == 0) {
+        if (unlikely(frac != 0)) {
+            goto do_underflow;
+        }
+    } else if (exp == 0x7ff) {
+        exc = (frac ? float_flag_invalid : VI ? float_flag_overflow : 0);
+    } else {
+        /* Restore implicit bit.  */
+        frac |= 0x10000000000000ull;
+
+        shift = exp - 1023 - 52;
+        if (shift >= 0) {
+            /* In this case the number is so large that we must shift
+               the fraction left.  There is no rounding to do.  */
+            if (shift < 63) {
+                ret = frac << shift;
+                if (VI && (ret >> shift) != frac) {
+                    exc = float_flag_overflow;
+                }
+            }
+        } else {
+            uint64_t round;
+
+            /* In this case the number is smaller than the fraction as
+               represented by the 52 bit number.  Here we must think
+               about rounding the result.  Handle this by shifting the
+               fractional part of the number into the high bits of ROUND.
+               This will let us efficiently handle round-to-nearest.  */
+            shift = -shift;
+            if (shift < 63) {
+                ret = frac >> shift;
+                round = frac << (64 - shift);
+            } else {
+                /* The exponent is so small we shift out everything.
+                   Leave a sticky bit for proper rounding below.  */
+            do_underflow:
+                round = 1;
+            }
+
+            if (round) {
+                exc = (VI ? float_flag_inexact : 0);
+                switch (roundmode) {
+                case float_round_nearest_even:
+                    if (round == (1ull << 63)) {
+                        /* Fraction is exactly 0.5; round to even.  */
+                        ret += (ret & 1);
+                    } else if (round > (1ull << 63)) {
+                        ret += 1;
+                    }
+                    break;
+                case float_round_to_zero:
+                    break;
+                case float_round_up:
+                    ret += 1 - sign;
+                    break;
+                case float_round_down:
+                    ret += sign;
+                    break;
+                }
+            }
+        }
+        if (sign) {
+            ret = -ret;
+        }
+    }
+    if (unlikely(exc)) {
+        float_raise(exc, &FP_STATUS);
+    }
+
+    return ret;
+}
+
+uint64_t helper_cvttq(CPUAlphaState *env, uint64_t a)
+{
+    return inline_cvttq(env, a, FP_STATUS.float_rounding_mode, 1);
+}
+
+uint64_t helper_cvttq_c(CPUAlphaState *env, uint64_t a)
+{
+    return inline_cvttq(env, a, float_round_to_zero, 0);
+}
+
+uint64_t helper_cvttq_svic(CPUAlphaState *env, uint64_t a)
+{
+    return inline_cvttq(env, a, float_round_to_zero, 1);
+}
+
+uint64_t helper_cvtqt(CPUAlphaState *env, uint64_t a)
+{
+    float64 fr = int64_to_float64(a, &FP_STATUS);
+    return float64_to_t(fr);
+}
+
+uint64_t helper_cvtqf(CPUAlphaState *env, uint64_t a)
+{
+    float32 fr = int64_to_float32(a, &FP_STATUS);
+    return float32_to_f(fr);
+}
+
+uint64_t helper_cvtgf(CPUAlphaState *env, uint64_t a)
+{
+    float64 fa;
+    float32 fr;
+
+    fa = g_to_float64(env, GETPC(), a);
+    fr = float64_to_float32(fa, &FP_STATUS);
+    return float32_to_f(fr);
+}
+
+uint64_t helper_cvtgq(CPUAlphaState *env, uint64_t a)
+{
+    float64 fa = g_to_float64(env, GETPC(), a);
+    return float64_to_int64_round_to_zero(fa, &FP_STATUS);
+}
+
+uint64_t helper_cvtqg(CPUAlphaState *env, uint64_t a)
+{
+    float64 fr;
+    fr = int64_to_float64(a, &FP_STATUS);
+    return float64_to_g(fr);
+}
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 91a9e39..d36df5f 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -39,65 +39,65 @@ DEF_HELPER_FLAGS_1(store_fpcr, TCG_CALL_CONST, void, i64)
 
 DEF_HELPER_FLAGS_1(f_to_memory, TCG_CALL_CONST | TCG_CALL_PURE, i32, i64)
 DEF_HELPER_FLAGS_1(memory_to_f, TCG_CALL_CONST | TCG_CALL_PURE, i64, i32)
-DEF_HELPER_FLAGS_2(addf, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(subf, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(mulf, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(divf, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_1(sqrtf, TCG_CALL_CONST, i64, i64)
+DEF_HELPER_FLAGS_3(addf, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(subf, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(mulf, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(divf, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_2(sqrtf, TCG_CALL_CONST, i64, env, i64)
 
 DEF_HELPER_FLAGS_1(g_to_memory, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
 DEF_HELPER_FLAGS_1(memory_to_g, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
-DEF_HELPER_FLAGS_2(addg, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(subg, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(mulg, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(divg, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_1(sqrtg, TCG_CALL_CONST, i64, i64)
+DEF_HELPER_FLAGS_3(addg, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(subg, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(mulg, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(divg, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_2(sqrtg, TCG_CALL_CONST, i64, env, i64)
 
 DEF_HELPER_FLAGS_1(s_to_memory, TCG_CALL_CONST | TCG_CALL_PURE, i32, i64)
 DEF_HELPER_FLAGS_1(memory_to_s, TCG_CALL_CONST | TCG_CALL_PURE, i64, i32)
-DEF_HELPER_FLAGS_2(adds, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(subs, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(muls, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(divs, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_1(sqrts, TCG_CALL_CONST, i64, i64)
-
-DEF_HELPER_FLAGS_2(addt, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(subt, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(mult, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(divt, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_1(sqrtt, TCG_CALL_CONST, i64, i64)
-
-DEF_HELPER_FLAGS_2(cmptun, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cmpteq, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cmptle, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cmptlt, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cmpgeq, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cmpgle, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cmpglt, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-
-DEF_HELPER_FLAGS_1(cvtts, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtst, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtqs, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtqt, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtqf, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtgf, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtgq, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtqg, TCG_CALL_CONST, i64, i64)
-
-DEF_HELPER_FLAGS_1(cvttq, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvttq_c, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvttq_svic, TCG_CALL_CONST, i64, i64)
-
-DEF_HELPER_FLAGS_1(setroundmode, TCG_CALL_CONST, void, i32)
-DEF_HELPER_FLAGS_1(setflushzero, TCG_CALL_CONST, void, i32)
-DEF_HELPER_FLAGS_0(fp_exc_clear, TCG_CALL_CONST, void)
-DEF_HELPER_FLAGS_0(fp_exc_get, TCG_CALL_CONST | TCG_CALL_PURE, i32)
-DEF_HELPER_2(fp_exc_raise, void, i32, i32)
-DEF_HELPER_2(fp_exc_raise_s, void, i32, i32)
-
-DEF_HELPER_1(ieee_input, i64, i64)
-DEF_HELPER_1(ieee_input_cmp, i64, i64)
-DEF_HELPER_1(ieee_input_s, i64, i64)
+DEF_HELPER_FLAGS_3(adds, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(subs, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(muls, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(divs, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_2(sqrts, TCG_CALL_CONST, i64, env, i64)
+
+DEF_HELPER_FLAGS_3(addt, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(subt, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(mult, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(divt, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_2(sqrtt, TCG_CALL_CONST, i64, env, i64)
+
+DEF_HELPER_FLAGS_3(cmptun, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(cmpteq, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(cmptle, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(cmptlt, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(cmpgeq, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(cmpgle, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(cmpglt, TCG_CALL_CONST, i64, env, i64, i64)
+
+DEF_HELPER_FLAGS_2(cvtts, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvtst, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvtqs, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvtqt, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvtqf, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvtgf, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvtgq, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvtqg, TCG_CALL_CONST, i64, env, i64)
+
+DEF_HELPER_FLAGS_2(cvttq, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvttq_c, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvttq_svic, TCG_CALL_CONST, i64, env, i64)
+
+DEF_HELPER_FLAGS_2(setroundmode, TCG_CALL_CONST, void, env, i32)
+DEF_HELPER_FLAGS_2(setflushzero, TCG_CALL_CONST, void, env, i32)
+DEF_HELPER_FLAGS_1(fp_exc_clear, TCG_CALL_CONST, void, env)
+DEF_HELPER_FLAGS_1(fp_exc_get, TCG_CALL_CONST | TCG_CALL_PURE, i32, env)
+DEF_HELPER_3(fp_exc_raise, void, env, i32, i32)
+DEF_HELPER_3(fp_exc_raise_s, void, env, i32, i32)
+
+DEF_HELPER_2(ieee_input, i64, env, i64)
+DEF_HELPER_2(ieee_input_cmp, i64, env, i64)
+DEF_HELPER_2(ieee_input_s, i64, env, i64)
 
 #if !defined (CONFIG_USER_ONLY)
 DEF_HELPER_1(hw_ret, void, i64)
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index af5fa82..6711d99 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -25,8 +25,6 @@
 #include "sysemu.h"
 #include "qemu-timer.h"
 
-#define FP_STATUS (env->fp_status)
-
 /*****************************************************************************/
 /* Exceptions processing helpers */
 
@@ -117,816 +115,6 @@ uint64_t helper_mulqv (uint64_t op1, uint64_t op2)
     return tl;
 }
 
-/* Floating point helpers */
-
-void helper_setroundmode (uint32_t val)
-{
-    set_float_rounding_mode(val, &FP_STATUS);
-}
-
-void helper_setflushzero (uint32_t val)
-{
-    set_flush_to_zero(val, &FP_STATUS);
-}
-
-void helper_fp_exc_clear (void)
-{
-    set_float_exception_flags(0, &FP_STATUS);
-}
-
-uint32_t helper_fp_exc_get (void)
-{
-    return get_float_exception_flags(&FP_STATUS);
-}
-
-/* Raise exceptions for ieee fp insns without software completion.
-   In that case there are no exceptions that don't trap; the mask
-   doesn't apply.  */
-void helper_fp_exc_raise(uint32_t exc, uint32_t regno)
-{
-    if (exc) {
-        uint32_t hw_exc = 0;
-
-        if (exc & float_flag_invalid) {
-            hw_exc |= EXC_M_INV;
-        }
-        if (exc & float_flag_divbyzero) {
-            hw_exc |= EXC_M_DZE;
-        }
-        if (exc & float_flag_overflow) {
-            hw_exc |= EXC_M_FOV;
-        }
-        if (exc & float_flag_underflow) {
-            hw_exc |= EXC_M_UNF;
-        }
-        if (exc & float_flag_inexact) {
-            hw_exc |= EXC_M_INE;
-        }
-
-        arith_excp(env, GETPC(), hw_exc, 1ull << regno);
-    }
-}
-
-/* Raise exceptions for ieee fp insns with software completion.  */
-void helper_fp_exc_raise_s(uint32_t exc, uint32_t regno)
-{
-    if (exc) {
-        env->fpcr_exc_status |= exc;
-
-        exc &= ~env->fpcr_exc_mask;
-        if (exc) {
-            helper_fp_exc_raise(exc, regno);
-        }
-    }
-}
-
-/* Input remapping without software completion.  Handle denormal-map-to-zero
-   and trap for all other non-finite numbers.  */
-uint64_t helper_ieee_input(uint64_t val)
-{
-    uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
-    uint64_t frac = val & 0xfffffffffffffull;
-
-    if (exp == 0) {
-        if (frac != 0) {
-            /* If DNZ is set flush denormals to zero on input.  */
-            if (env->fpcr_dnz) {
-                val &= 1ull << 63;
-            } else {
-                arith_excp(env, GETPC(), EXC_M_UNF, 0);
-            }
-        }
-    } else if (exp == 0x7ff) {
-        /* Infinity or NaN.  */
-        /* ??? I'm not sure these exception bit flags are correct.  I do
-           know that the Linux kernel, at least, doesn't rely on them and
-           just emulates the insn to figure out what exception to use.  */
-        arith_excp(env, GETPC(), frac ? EXC_M_INV : EXC_M_FOV, 0);
-    }
-    return val;
-}
-
-/* Similar, but does not trap for infinities.  Used for comparisons.  */
-uint64_t helper_ieee_input_cmp(uint64_t val)
-{
-    uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
-    uint64_t frac = val & 0xfffffffffffffull;
-
-    if (exp == 0) {
-        if (frac != 0) {
-            /* If DNZ is set flush denormals to zero on input.  */
-            if (env->fpcr_dnz) {
-                val &= 1ull << 63;
-            } else {
-                arith_excp(env, GETPC(), EXC_M_UNF, 0);
-            }
-        }
-    } else if (exp == 0x7ff && frac) {
-        /* NaN.  */
-        arith_excp(env, GETPC(), EXC_M_INV, 0);
-    }
-    return val;
-}
-
-/* Input remapping with software completion enabled.  All we have to do
-   is handle denormal-map-to-zero; all other inputs get exceptions as
-   needed from the actual operation.  */
-uint64_t helper_ieee_input_s(uint64_t val)
-{
-    if (env->fpcr_dnz) {
-        uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
-        if (exp == 0) {
-            val &= 1ull << 63;
-        }
-    }
-    return val;
-}
-
-/* F floating (VAX) */
-static inline uint64_t float32_to_f(float32 fa)
-{
-    uint64_t r, exp, mant, sig;
-    CPU_FloatU a;
-
-    a.f = fa;
-    sig = ((uint64_t)a.l & 0x80000000) << 32;
-    exp = (a.l >> 23) & 0xff;
-    mant = ((uint64_t)a.l & 0x007fffff) << 29;
-
-    if (exp == 255) {
-        /* NaN or infinity */
-        r = 1; /* VAX dirty zero */
-    } else if (exp == 0) {
-        if (mant == 0) {
-            /* Zero */
-            r = 0;
-        } else {
-            /* Denormalized */
-            r = sig | ((exp + 1) << 52) | mant;
-        }
-    } else {
-        if (exp >= 253) {
-            /* Overflow */
-            r = 1; /* VAX dirty zero */
-        } else {
-            r = sig | ((exp + 2) << 52);
-        }
-    }
-
-    return r;
-}
-
-static inline float32 f_to_float32(uint64_t a)
-{
-    uint32_t exp, mant_sig;
-    CPU_FloatU r;
-
-    exp = ((a >> 55) & 0x80) | ((a >> 52) & 0x7f);
-    mant_sig = ((a >> 32) & 0x80000000) | ((a >> 29) & 0x007fffff);
-
-    if (unlikely(!exp && mant_sig)) {
-        /* Reserved operands / Dirty zero */
-        dynamic_excp(env, GETPC(), EXCP_OPCDEC, 0);
-    }
-
-    if (exp < 3) {
-        /* Underflow */
-        r.l = 0;
-    } else {
-        r.l = ((exp - 2) << 23) | mant_sig;
-    }
-
-    return r.f;
-}
-
-uint32_t helper_f_to_memory (uint64_t a)
-{
-    uint32_t r;
-    r =  (a & 0x00001fffe0000000ull) >> 13;
-    r |= (a & 0x07ffe00000000000ull) >> 45;
-    r |= (a & 0xc000000000000000ull) >> 48;
-    return r;
-}
-
-uint64_t helper_memory_to_f (uint32_t a)
-{
-    uint64_t r;
-    r =  ((uint64_t)(a & 0x0000c000)) << 48;
-    r |= ((uint64_t)(a & 0x003fffff)) << 45;
-    r |= ((uint64_t)(a & 0xffff0000)) << 13;
-    if (!(a & 0x00004000))
-        r |= 0x7ll << 59;
-    return r;
-}
-
-/* ??? Emulating VAX arithmetic with IEEE arithmetic is wrong.  We should
-   either implement VAX arithmetic properly or just signal invalid opcode.  */
-
-uint64_t helper_addf (uint64_t a, uint64_t b)
-{
-    float32 fa, fb, fr;
-
-    fa = f_to_float32(a);
-    fb = f_to_float32(b);
-    fr = float32_add(fa, fb, &FP_STATUS);
-    return float32_to_f(fr);
-}
-
-uint64_t helper_subf (uint64_t a, uint64_t b)
-{
-    float32 fa, fb, fr;
-
-    fa = f_to_float32(a);
-    fb = f_to_float32(b);
-    fr = float32_sub(fa, fb, &FP_STATUS);
-    return float32_to_f(fr);
-}
-
-uint64_t helper_mulf (uint64_t a, uint64_t b)
-{
-    float32 fa, fb, fr;
-
-    fa = f_to_float32(a);
-    fb = f_to_float32(b);
-    fr = float32_mul(fa, fb, &FP_STATUS);
-    return float32_to_f(fr);
-}
-
-uint64_t helper_divf (uint64_t a, uint64_t b)
-{
-    float32 fa, fb, fr;
-
-    fa = f_to_float32(a);
-    fb = f_to_float32(b);
-    fr = float32_div(fa, fb, &FP_STATUS);
-    return float32_to_f(fr);
-}
-
-uint64_t helper_sqrtf (uint64_t t)
-{
-    float32 ft, fr;
-
-    ft = f_to_float32(t);
-    fr = float32_sqrt(ft, &FP_STATUS);
-    return float32_to_f(fr);
-}
-
-
-/* G floating (VAX) */
-static inline uint64_t float64_to_g(float64 fa)
-{
-    uint64_t r, exp, mant, sig;
-    CPU_DoubleU a;
-
-    a.d = fa;
-    sig = a.ll & 0x8000000000000000ull;
-    exp = (a.ll >> 52) & 0x7ff;
-    mant = a.ll & 0x000fffffffffffffull;
-
-    if (exp == 2047) {
-        /* NaN or infinity */
-        r = 1; /* VAX dirty zero */
-    } else if (exp == 0) {
-        if (mant == 0) {
-            /* Zero */
-            r = 0;
-        } else {
-            /* Denormalized */
-            r = sig | ((exp + 1) << 52) | mant;
-        }
-    } else {
-        if (exp >= 2045) {
-            /* Overflow */
-            r = 1; /* VAX dirty zero */
-        } else {
-            r = sig | ((exp + 2) << 52);
-        }
-    }
-
-    return r;
-}
-
-static inline float64 g_to_float64(uint64_t a)
-{
-    uint64_t exp, mant_sig;
-    CPU_DoubleU r;
-
-    exp = (a >> 52) & 0x7ff;
-    mant_sig = a & 0x800fffffffffffffull;
-
-    if (!exp && mant_sig) {
-        /* Reserved operands / Dirty zero */
-        dynamic_excp(env, GETPC(), EXCP_OPCDEC, 0);
-    }
-
-    if (exp < 3) {
-        /* Underflow */
-        r.ll = 0;
-    } else {
-        r.ll = ((exp - 2) << 52) | mant_sig;
-    }
-
-    return r.d;
-}
-
-uint64_t helper_g_to_memory (uint64_t a)
-{
-    uint64_t r;
-    r =  (a & 0x000000000000ffffull) << 48;
-    r |= (a & 0x00000000ffff0000ull) << 16;
-    r |= (a & 0x0000ffff00000000ull) >> 16;
-    r |= (a & 0xffff000000000000ull) >> 48;
-    return r;
-}
-
-uint64_t helper_memory_to_g (uint64_t a)
-{
-    uint64_t r;
-    r =  (a & 0x000000000000ffffull) << 48;
-    r |= (a & 0x00000000ffff0000ull) << 16;
-    r |= (a & 0x0000ffff00000000ull) >> 16;
-    r |= (a & 0xffff000000000000ull) >> 48;
-    return r;
-}
-
-uint64_t helper_addg (uint64_t a, uint64_t b)
-{
-    float64 fa, fb, fr;
-
-    fa = g_to_float64(a);
-    fb = g_to_float64(b);
-    fr = float64_add(fa, fb, &FP_STATUS);
-    return float64_to_g(fr);
-}
-
-uint64_t helper_subg (uint64_t a, uint64_t b)
-{
-    float64 fa, fb, fr;
-
-    fa = g_to_float64(a);
-    fb = g_to_float64(b);
-    fr = float64_sub(fa, fb, &FP_STATUS);
-    return float64_to_g(fr);
-}
-
-uint64_t helper_mulg (uint64_t a, uint64_t b)
-{
-    float64 fa, fb, fr;
-
-    fa = g_to_float64(a);
-    fb = g_to_float64(b);
-    fr = float64_mul(fa, fb, &FP_STATUS);
-    return float64_to_g(fr);
-}
-
-uint64_t helper_divg (uint64_t a, uint64_t b)
-{
-    float64 fa, fb, fr;
-
-    fa = g_to_float64(a);
-    fb = g_to_float64(b);
-    fr = float64_div(fa, fb, &FP_STATUS);
-    return float64_to_g(fr);
-}
-
-uint64_t helper_sqrtg (uint64_t a)
-{
-    float64 fa, fr;
-
-    fa = g_to_float64(a);
-    fr = float64_sqrt(fa, &FP_STATUS);
-    return float64_to_g(fr);
-}
-
-
-/* S floating (single) */
-
-/* Taken from linux/arch/alpha/kernel/traps.c, s_mem_to_reg.  */
-static inline uint64_t float32_to_s_int(uint32_t fi)
-{
-    uint32_t frac = fi & 0x7fffff;
-    uint32_t sign = fi >> 31;
-    uint32_t exp_msb = (fi >> 30) & 1;
-    uint32_t exp_low = (fi >> 23) & 0x7f;
-    uint32_t exp;
-
-    exp = (exp_msb << 10) | exp_low;
-    if (exp_msb) {
-        if (exp_low == 0x7f)
-            exp = 0x7ff;
-    } else {
-        if (exp_low != 0x00)
-            exp |= 0x380;
-    }
-
-    return (((uint64_t)sign << 63)
-            | ((uint64_t)exp << 52)
-            | ((uint64_t)frac << 29));
-}
-
-static inline uint64_t float32_to_s(float32 fa)
-{
-    CPU_FloatU a;
-    a.f = fa;
-    return float32_to_s_int(a.l);
-}
-
-static inline uint32_t s_to_float32_int(uint64_t a)
-{
-    return ((a >> 32) & 0xc0000000) | ((a >> 29) & 0x3fffffff);
-}
-
-static inline float32 s_to_float32(uint64_t a)
-{
-    CPU_FloatU r;
-    r.l = s_to_float32_int(a);
-    return r.f;
-}
-
-uint32_t helper_s_to_memory (uint64_t a)
-{
-    return s_to_float32_int(a);
-}
-
-uint64_t helper_memory_to_s (uint32_t a)
-{
-    return float32_to_s_int(a);
-}
-
-uint64_t helper_adds (uint64_t a, uint64_t b)
-{
-    float32 fa, fb, fr;
-
-    fa = s_to_float32(a);
-    fb = s_to_float32(b);
-    fr = float32_add(fa, fb, &FP_STATUS);
-    return float32_to_s(fr);
-}
-
-uint64_t helper_subs (uint64_t a, uint64_t b)
-{
-    float32 fa, fb, fr;
-
-    fa = s_to_float32(a);
-    fb = s_to_float32(b);
-    fr = float32_sub(fa, fb, &FP_STATUS);
-    return float32_to_s(fr);
-}
-
-uint64_t helper_muls (uint64_t a, uint64_t b)
-{
-    float32 fa, fb, fr;
-
-    fa = s_to_float32(a);
-    fb = s_to_float32(b);
-    fr = float32_mul(fa, fb, &FP_STATUS);
-    return float32_to_s(fr);
-}
-
-uint64_t helper_divs (uint64_t a, uint64_t b)
-{
-    float32 fa, fb, fr;
-
-    fa = s_to_float32(a);
-    fb = s_to_float32(b);
-    fr = float32_div(fa, fb, &FP_STATUS);
-    return float32_to_s(fr);
-}
-
-uint64_t helper_sqrts (uint64_t a)
-{
-    float32 fa, fr;
-
-    fa = s_to_float32(a);
-    fr = float32_sqrt(fa, &FP_STATUS);
-    return float32_to_s(fr);
-}
-
-
-/* T floating (double) */
-static inline float64 t_to_float64(uint64_t a)
-{
-    /* Memory format is the same as float64 */
-    CPU_DoubleU r;
-    r.ll = a;
-    return r.d;
-}
-
-static inline uint64_t float64_to_t(float64 fa)
-{
-    /* Memory format is the same as float64 */
-    CPU_DoubleU r;
-    r.d = fa;
-    return r.ll;
-}
-
-uint64_t helper_addt (uint64_t a, uint64_t b)
-{
-    float64 fa, fb, fr;
-
-    fa = t_to_float64(a);
-    fb = t_to_float64(b);
-    fr = float64_add(fa, fb, &FP_STATUS);
-    return float64_to_t(fr);
-}
-
-uint64_t helper_subt (uint64_t a, uint64_t b)
-{
-    float64 fa, fb, fr;
-
-    fa = t_to_float64(a);
-    fb = t_to_float64(b);
-    fr = float64_sub(fa, fb, &FP_STATUS);
-    return float64_to_t(fr);
-}
-
-uint64_t helper_mult (uint64_t a, uint64_t b)
-{
-    float64 fa, fb, fr;
-
-    fa = t_to_float64(a);
-    fb = t_to_float64(b);
-    fr = float64_mul(fa, fb, &FP_STATUS);
-    return float64_to_t(fr);
-}
-
-uint64_t helper_divt (uint64_t a, uint64_t b)
-{
-    float64 fa, fb, fr;
-
-    fa = t_to_float64(a);
-    fb = t_to_float64(b);
-    fr = float64_div(fa, fb, &FP_STATUS);
-    return float64_to_t(fr);
-}
-
-uint64_t helper_sqrtt (uint64_t a)
-{
-    float64 fa, fr;
-
-    fa = t_to_float64(a);
-    fr = float64_sqrt(fa, &FP_STATUS);
-    return float64_to_t(fr);
-}
-
-/* Comparisons */
-uint64_t helper_cmptun (uint64_t a, uint64_t b)
-{
-    float64 fa, fb;
-
-    fa = t_to_float64(a);
-    fb = t_to_float64(b);
-
-    if (float64_unordered_quiet(fa, fb, &FP_STATUS)) {
-        return 0x4000000000000000ULL;
-    } else {
-        return 0;
-    }
-}
-
-uint64_t helper_cmpteq(uint64_t a, uint64_t b)
-{
-    float64 fa, fb;
-
-    fa = t_to_float64(a);
-    fb = t_to_float64(b);
-
-    if (float64_eq_quiet(fa, fb, &FP_STATUS))
-        return 0x4000000000000000ULL;
-    else
-        return 0;
-}
-
-uint64_t helper_cmptle(uint64_t a, uint64_t b)
-{
-    float64 fa, fb;
-
-    fa = t_to_float64(a);
-    fb = t_to_float64(b);
-
-    if (float64_le(fa, fb, &FP_STATUS))
-        return 0x4000000000000000ULL;
-    else
-        return 0;
-}
-
-uint64_t helper_cmptlt(uint64_t a, uint64_t b)
-{
-    float64 fa, fb;
-
-    fa = t_to_float64(a);
-    fb = t_to_float64(b);
-
-    if (float64_lt(fa, fb, &FP_STATUS))
-        return 0x4000000000000000ULL;
-    else
-        return 0;
-}
-
-uint64_t helper_cmpgeq(uint64_t a, uint64_t b)
-{
-    float64 fa, fb;
-
-    fa = g_to_float64(a);
-    fb = g_to_float64(b);
-
-    if (float64_eq_quiet(fa, fb, &FP_STATUS))
-        return 0x4000000000000000ULL;
-    else
-        return 0;
-}
-
-uint64_t helper_cmpgle(uint64_t a, uint64_t b)
-{
-    float64 fa, fb;
-
-    fa = g_to_float64(a);
-    fb = g_to_float64(b);
-
-    if (float64_le(fa, fb, &FP_STATUS))
-        return 0x4000000000000000ULL;
-    else
-        return 0;
-}
-
-uint64_t helper_cmpglt(uint64_t a, uint64_t b)
-{
-    float64 fa, fb;
-
-    fa = g_to_float64(a);
-    fb = g_to_float64(b);
-
-    if (float64_lt(fa, fb, &FP_STATUS))
-        return 0x4000000000000000ULL;
-    else
-        return 0;
-}
-
-/* Floating point format conversion */
-uint64_t helper_cvtts (uint64_t a)
-{
-    float64 fa;
-    float32 fr;
-
-    fa = t_to_float64(a);
-    fr = float64_to_float32(fa, &FP_STATUS);
-    return float32_to_s(fr);
-}
-
-uint64_t helper_cvtst (uint64_t a)
-{
-    float32 fa;
-    float64 fr;
-
-    fa = s_to_float32(a);
-    fr = float32_to_float64(fa, &FP_STATUS);
-    return float64_to_t(fr);
-}
-
-uint64_t helper_cvtqs (uint64_t a)
-{
-    float32 fr = int64_to_float32(a, &FP_STATUS);
-    return float32_to_s(fr);
-}
-
-/* Implement float64 to uint64 conversion without saturation -- we must
-   supply the truncated result.  This behaviour is used by the compiler
-   to get unsigned conversion for free with the same instruction.
-
-   The VI flag is set when overflow or inexact exceptions should be raised.  */
-
-static inline uint64_t helper_cvttq_internal(uint64_t a, int roundmode, int VI)
-{
-    uint64_t frac, ret = 0;
-    uint32_t exp, sign, exc = 0;
-    int shift;
-
-    sign = (a >> 63);
-    exp = (uint32_t)(a >> 52) & 0x7ff;
-    frac = a & 0xfffffffffffffull;
-
-    if (exp == 0) {
-        if (unlikely(frac != 0)) {
-            goto do_underflow;
-        }
-    } else if (exp == 0x7ff) {
-        exc = (frac ? float_flag_invalid : VI ? float_flag_overflow : 0);
-    } else {
-        /* Restore implicit bit.  */
-        frac |= 0x10000000000000ull;
-
-        shift = exp - 1023 - 52;
-        if (shift >= 0) {
-            /* In this case the number is so large that we must shift
-               the fraction left.  There is no rounding to do.  */
-            if (shift < 63) {
-                ret = frac << shift;
-                if (VI && (ret >> shift) != frac) {
-                    exc = float_flag_overflow;
-                }
-            }
-        } else {
-            uint64_t round;
-
-            /* In this case the number is smaller than the fraction as
-               represented by the 52 bit number.  Here we must think
-               about rounding the result.  Handle this by shifting the
-               fractional part of the number into the high bits of ROUND.
-               This will let us efficiently handle round-to-nearest.  */
-            shift = -shift;
-            if (shift < 63) {
-                ret = frac >> shift;
-                round = frac << (64 - shift);
-            } else {
-                /* The exponent is so small we shift out everything.
-                   Leave a sticky bit for proper rounding below.  */
-            do_underflow:
-                round = 1;
-            }
-
-            if (round) {
-                exc = (VI ? float_flag_inexact : 0);
-                switch (roundmode) {
-                case float_round_nearest_even:
-                    if (round == (1ull << 63)) {
-                        /* Fraction is exactly 0.5; round to even.  */
-                        ret += (ret & 1);
-                    } else if (round > (1ull << 63)) {
-                        ret += 1;
-                    }
-                    break;
-                case float_round_to_zero:
-                    break;
-                case float_round_up:
-                    ret += 1 - sign;
-                    break;
-                case float_round_down:
-                    ret += sign;
-                    break;
-                }
-            }
-        }
-        if (sign) {
-            ret = -ret;
-        }
-    }
-    if (unlikely(exc)) {
-        float_raise(exc, &FP_STATUS);
-    }
-
-    return ret;
-}
-
-uint64_t helper_cvttq(uint64_t a)
-{
-    return helper_cvttq_internal(a, FP_STATUS.float_rounding_mode, 1);
-}
-
-uint64_t helper_cvttq_c(uint64_t a)
-{
-    return helper_cvttq_internal(a, float_round_to_zero, 0);
-}
-
-uint64_t helper_cvttq_svic(uint64_t a)
-{
-    return helper_cvttq_internal(a, float_round_to_zero, 1);
-}
-
-uint64_t helper_cvtqt (uint64_t a)
-{
-    float64 fr = int64_to_float64(a, &FP_STATUS);
-    return float64_to_t(fr);
-}
-
-uint64_t helper_cvtqf (uint64_t a)
-{
-    float32 fr = int64_to_float32(a, &FP_STATUS);
-    return float32_to_f(fr);
-}
-
-uint64_t helper_cvtgf (uint64_t a)
-{
-    float64 fa;
-    float32 fr;
-
-    fa = g_to_float64(a);
-    fr = float64_to_float32(fa, &FP_STATUS);
-    return float32_to_f(fr);
-}
-
-uint64_t helper_cvtgq (uint64_t a)
-{
-    float64 fa = g_to_float64(a);
-    return float64_to_int64_round_to_zero(fa, &FP_STATUS);
-}
-
-uint64_t helper_cvtqg (uint64_t a)
-{
-    float64 fr;
-    fr = int64_to_float64(a, &FP_STATUS);
-    return float64_to_g(fr);
-}
-
 /* PALcode support special instructions */
 #if !defined (CONFIG_USER_ONLY)
 void helper_hw_ret (uint64_t a)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 0c06b55..a9b97a3 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -611,7 +611,8 @@ static void gen_qual_roundmode(DisasContext *ctx, int fn11)
         tcg_gen_movi_i32(tmp, float_round_down);
         break;
     case QUAL_RM_D:
-        tcg_gen_ld8u_i32(tmp, cpu_env, offsetof(CPUAlphaState, fpcr_dyn_round));
+        tcg_gen_ld8u_i32(tmp, cpu_env,
+                         offsetof(CPUAlphaState, fpcr_dyn_round));
         break;
     }
 
@@ -641,7 +642,8 @@ static void gen_qual_flushzero(DisasContext *ctx, int fn11)
     tmp = tcg_temp_new_i32();
     if (fn11) {
         /* Underflow is enabled, use the FPCR setting.  */
-        tcg_gen_ld8u_i32(tmp, cpu_env, offsetof(CPUAlphaState, fpcr_flush_to_zero));
+        tcg_gen_ld8u_i32(tmp, cpu_env,
+                         offsetof(CPUAlphaState, fpcr_flush_to_zero));
     } else {
         /* Underflow is disabled, force flush-to-zero.  */
         tcg_gen_movi_i32(tmp, 1);
@@ -663,11 +665,11 @@ static TCGv gen_ieee_input(int reg, int fn11, int is_cmp)
     if (reg == 31) {
         tcg_gen_movi_i64(val, 0);
     } else if (fn11 & QUAL_S) {
-        gen_helper_ieee_input_s(val, cpu_fir[reg]);
+        gen_helper_ieee_input_s(val, cpu_env, cpu_fir[reg]);
     } else if (is_cmp) {
-        gen_helper_ieee_input_cmp(val, cpu_fir[reg]);
+        gen_helper_ieee_input_cmp(val, cpu_env, cpu_fir[reg]);
     } else {
-        gen_helper_ieee_input(val, cpu_fir[reg]);
+        gen_helper_ieee_input(val, cpu_env, cpu_fir[reg]);
     }
     return val;
 }
@@ -680,7 +682,7 @@ static void gen_fp_exc_clear(void)
                     offsetof(CPUAlphaState, fp_status.float_exception_flags));
     tcg_temp_free_i32(zero);
 #else
-    gen_helper_fp_exc_clear();
+    gen_helper_fp_exc_clear(cpu_env);
 #endif
 }
 
@@ -698,7 +700,7 @@ static void gen_fp_exc_raise_ignore(int rc, int fn11, int ignore)
     tcg_gen_ld8u_i32(exc, cpu_env,
                      offsetof(CPUAlphaState, fp_status.float_exception_flags));
 #else
-    gen_helper_fp_exc_get(exc);
+    gen_helper_fp_exc_get(exc, cpu_env);
 #endif
 
     if (ignore) {
@@ -713,9 +715,9 @@ static void gen_fp_exc_raise_ignore(int rc, int fn11, int ignore)
     reg = tcg_const_i32(rc + 32);
 
     if (fn11 & QUAL_S) {
-        gen_helper_fp_exc_raise_s(exc, reg);
+        gen_helper_fp_exc_raise_s(cpu_env, exc, reg);
     } else {
-        gen_helper_fp_exc_raise(exc, reg);
+        gen_helper_fp_exc_raise(cpu_env, exc, reg);
     }
 
     tcg_temp_free_i32(reg);
@@ -784,20 +786,20 @@ static void gen_fcvtql_v(DisasContext *ctx, int rb, int rc)
     gen_fcvtql(rb, rc);
 }
 
-#define FARITH2(name)                                   \
-static inline void glue(gen_f, name)(int rb, int rc)    \
-{                                                       \
-    if (unlikely(rc == 31)) {                           \
-        return;                                         \
-    }                                                   \
-    if (rb != 31) {                                     \
-        gen_helper_ ## name (cpu_fir[rc], cpu_fir[rb]); \
-    } else {						\
-        TCGv tmp = tcg_const_i64(0);                    \
-        gen_helper_ ## name (cpu_fir[rc], tmp);         \
-        tcg_temp_free(tmp);                             \
-    }                                                   \
-}
+#define FARITH2(name)                                                   \
+    static inline void glue(gen_f, name)(int rb, int rc)                \
+    {                                                                   \
+        if (unlikely(rc == 31)) {                                       \
+            return;                                                     \
+        }                                                               \
+        if (rb != 31) {                                                 \
+            gen_helper_ ## name(cpu_fir[rc], cpu_env, cpu_fir[rb]);     \
+        } else {                                                        \
+            TCGv tmp = tcg_const_i64(0);                                \
+            gen_helper_ ## name(cpu_fir[rc], cpu_env, tmp);             \
+            tcg_temp_free(tmp);                                         \
+        }                                                               \
+    }
 
 /* ??? VAX instruction qualifiers ignored.  */
 FARITH2(sqrtf)
@@ -807,7 +809,8 @@ FARITH2(cvtgq)
 FARITH2(cvtqf)
 FARITH2(cvtqg)
 
-static void gen_ieee_arith2(DisasContext *ctx, void (*helper)(TCGv, TCGv),
+static void gen_ieee_arith2(DisasContext *ctx,
+                            void (*helper)(TCGv, TCGv_ptr, TCGv),
                             int rb, int rc, int fn11)
 {
     TCGv vb;
@@ -823,7 +826,7 @@ static void gen_ieee_arith2(DisasContext *ctx, void (*helper)(TCGv, TCGv),
     gen_fp_exc_clear();
 
     vb = gen_ieee_input(rb, fn11, 0);
-    helper(cpu_fir[rc], vb);
+    helper(cpu_fir[rc], cpu_env, vb);
     tcg_temp_free(vb);
 
     gen_fp_exc_raise(rc, fn11);
@@ -859,18 +862,18 @@ static void gen_fcvttq(DisasContext *ctx, int rb, int rc, int fn11)
        also do not have integer overflow enabled.  Special case that.  */
     switch (fn11) {
     case QUAL_RM_C:
-        gen_helper_cvttq_c(cpu_fir[rc], vb);
+        gen_helper_cvttq_c(cpu_fir[rc], cpu_env, vb);
         break;
     case QUAL_V | QUAL_RM_C:
     case QUAL_S | QUAL_V | QUAL_RM_C:
         ignore = float_flag_inexact;
         /* FALLTHRU */
     case QUAL_S | QUAL_V | QUAL_I | QUAL_RM_C:
-        gen_helper_cvttq_svic(cpu_fir[rc], vb);
+        gen_helper_cvttq_svic(cpu_fir[rc], cpu_env, vb);
         break;
     default:
         gen_qual_roundmode(ctx, fn11);
-        gen_helper_cvttq(cpu_fir[rc], vb);
+        gen_helper_cvttq(cpu_fir[rc], cpu_env, vb);
         ignore |= (fn11 & QUAL_V ? 0 : float_flag_overflow);
         ignore |= (fn11 & QUAL_I ? 0 : float_flag_inexact);
         break;
@@ -880,7 +883,8 @@ static void gen_fcvttq(DisasContext *ctx, int rb, int rc, int fn11)
     gen_fp_exc_raise_ignore(rc, fn11, ignore);
 }
 
-static void gen_ieee_intcvt(DisasContext *ctx, void (*helper)(TCGv, TCGv),
+static void gen_ieee_intcvt(DisasContext *ctx,
+                            void (*helper)(TCGv, TCGv_ptr, TCGv),
 			    int rb, int rc, int fn11)
 {
     TCGv vb;
@@ -904,10 +908,10 @@ static void gen_ieee_intcvt(DisasContext *ctx, void (*helper)(TCGv, TCGv),
        inexact handling is requested.  */
     if (fn11 & QUAL_I) {
         gen_fp_exc_clear();
-        helper(cpu_fir[rc], vb);
+        helper(cpu_fir[rc], cpu_env, vb);
         gen_fp_exc_raise(rc, fn11);
     } else {
-        helper(cpu_fir[rc], vb);
+        helper(cpu_fir[rc], cpu_env, vb);
     }
 
     if (rb == 31) {
@@ -999,34 +1003,34 @@ static inline void gen_fcpyse(int ra, int rb, int rc)
     gen_cpys_internal(ra, rb, rc, 0, 0xFFF0000000000000ULL);
 }
 
-#define FARITH3(name)                                           \
-static inline void glue(gen_f, name)(int ra, int rb, int rc)    \
-{                                                               \
-    TCGv va, vb;                                                \
-                                                                \
-    if (unlikely(rc == 31)) {                                   \
-        return;                                                 \
-    }                                                           \
-    if (ra == 31) {                                             \
-        va = tcg_const_i64(0);                                  \
-    } else {                                                    \
-        va = cpu_fir[ra];                                       \
-    }                                                           \
-    if (rb == 31) {                                             \
-        vb = tcg_const_i64(0);                                  \
-    } else {                                                    \
-        vb = cpu_fir[rb];                                       \
-    }                                                           \
-                                                                \
-    gen_helper_ ## name (cpu_fir[rc], va, vb);                  \
-                                                                \
-    if (ra == 31) {                                             \
-        tcg_temp_free(va);                                      \
-    }                                                           \
-    if (rb == 31) {                                             \
-        tcg_temp_free(vb);                                      \
-    }                                                           \
-}
+#define FARITH3(name)                                                   \
+    static inline void glue(gen_f, name)(int ra, int rb, int rc)        \
+    {                                                                   \
+        TCGv va, vb;                                                    \
+                                                                        \
+        if (unlikely(rc == 31)) {                                       \
+            return;                                                     \
+        }                                                               \
+        if (ra == 31) {                                                 \
+            va = tcg_const_i64(0);                                      \
+        } else {                                                        \
+            va = cpu_fir[ra];                                           \
+        }                                                               \
+        if (rb == 31) {                                                 \
+            vb = tcg_const_i64(0);                                      \
+        } else {                                                        \
+            vb = cpu_fir[rb];                                           \
+        }                                                               \
+                                                                        \
+        gen_helper_ ## name(cpu_fir[rc], cpu_env, va, vb);              \
+                                                                        \
+        if (ra == 31) {                                                 \
+            tcg_temp_free(va);                                          \
+        }                                                               \
+        if (rb == 31) {                                                 \
+            tcg_temp_free(vb);                                          \
+        }                                                               \
+    }
 
 /* ??? VAX instruction qualifiers ignored.  */
 FARITH3(addf)
@@ -1042,7 +1046,7 @@ FARITH3(cmpglt)
 FARITH3(cmpgle)
 
 static void gen_ieee_arith3(DisasContext *ctx,
-                            void (*helper)(TCGv, TCGv, TCGv),
+                            void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
                             int ra, int rb, int rc, int fn11)
 {
     TCGv va, vb;
@@ -1059,7 +1063,7 @@ static void gen_ieee_arith3(DisasContext *ctx,
 
     va = gen_ieee_input(ra, fn11, 0);
     vb = gen_ieee_input(rb, fn11, 0);
-    helper(cpu_fir[rc], va, vb);
+    helper(cpu_fir[rc], cpu_env, va, vb);
     tcg_temp_free(va);
     tcg_temp_free(vb);
 
@@ -1082,7 +1086,7 @@ IEEE_ARITH3(mult)
 IEEE_ARITH3(divt)
 
 static void gen_ieee_compare(DisasContext *ctx,
-                             void (*helper)(TCGv, TCGv, TCGv),
+                             void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
                              int ra, int rb, int rc, int fn11)
 {
     TCGv va, vb;
@@ -1097,7 +1101,7 @@ static void gen_ieee_compare(DisasContext *ctx,
 
     va = gen_ieee_input(ra, fn11, 1);
     vb = gen_ieee_input(rb, fn11, 1);
-    helper(cpu_fir[rc], va, vb);
+    helper(cpu_fir[rc], cpu_env, va, vb);
     tcg_temp_free(va);
     tcg_temp_free(vb);
 
commit b9f0923eb782b92a85657092b625d96b0af26e2e
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Mar 24 09:51:08 2012 -0700

    target-alpha: Move exception helpers to helper.c.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 48c0fdc..c7787f6 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -434,6 +434,9 @@ int cpu_alpha_handle_mmu_fault (CPUAlphaState *env, uint64_t address, int rw,
                                 int mmu_idx);
 #define cpu_handle_mmu_fault cpu_alpha_handle_mmu_fault
 void do_interrupt (CPUAlphaState *env);
+void do_restore_state(CPUAlphaState *, void *retaddr);
+void QEMU_NORETURN dynamic_excp(CPUAlphaState *, void *, int, int);
+void QEMU_NORETURN arith_excp(CPUAlphaState *, void *, int, uint64_t);
 
 uint64_t cpu_alpha_load_fpcr (CPUAlphaState *env);
 void cpu_alpha_store_fpcr (CPUAlphaState *env, uint64_t val);
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 3f2e7c3..584457f 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -23,6 +23,7 @@
 
 #include "cpu.h"
 #include "softfloat.h"
+#include "helper.h"
 
 uint64_t cpu_alpha_load_fpcr (CPUAlphaState *env)
 {
@@ -484,3 +485,41 @@ void cpu_dump_state (CPUAlphaState *env, FILE *f, fprintf_function cpu_fprintf,
     }
     cpu_fprintf(f, "\n");
 }
+
+void do_restore_state(CPUAlphaState *env, void *retaddr)
+{
+    uintptr_t pc = (uintptr_t)retaddr;
+    if (pc) {
+        TranslationBlock *tb = tb_find_pc(pc);
+        if (tb) {
+            cpu_restore_state(tb, env, pc);
+        }
+    }
+}
+
+/* This should only be called from translate, via gen_excp.
+   We expect that ENV->PC has already been updated.  */
+void QEMU_NORETURN helper_excp(CPUAlphaState *env, int excp, int error)
+{
+    env->exception_index = excp;
+    env->error_code = error;
+    cpu_loop_exit(env);
+}
+
+/* This may be called from any of the helpers to set up EXCEPTION_INDEX.  */
+void QEMU_NORETURN dynamic_excp(CPUAlphaState *env, void *retaddr,
+                                int excp, int error)
+{
+    env->exception_index = excp;
+    env->error_code = error;
+    do_restore_state(env, retaddr);
+    cpu_loop_exit(env);
+}
+
+void QEMU_NORETURN arith_excp(CPUAlphaState *env, void *retaddr,
+                              int exc, uint64_t mask)
+{
+    env->trap_arg0 = exc;
+    env->trap_arg1 = mask;
+    dynamic_excp(env, retaddr, EXCP_ARITH, 0);
+}
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index b693cee..91a9e39 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -1,6 +1,6 @@
 #include "def-helper.h"
 
-DEF_HELPER_2(excp, void, int, int)
+DEF_HELPER_3(excp, void, env, int, int)
 DEF_HELPER_FLAGS_0(load_pcc, TCG_CALL_CONST | TCG_CALL_PURE, i64)
 
 DEF_HELPER_2(addqv, i64, i64, i64)
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index eab7a82..af5fa82 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -30,43 +30,6 @@
 /*****************************************************************************/
 /* Exceptions processing helpers */
 
-/* This should only be called from translate, via gen_excp.
-   We expect that ENV->PC has already been updated.  */
-void QEMU_NORETURN helper_excp(int excp, int error)
-{
-    env->exception_index = excp;
-    env->error_code = error;
-    cpu_loop_exit(env);
-}
-
-static void do_restore_state(void *retaddr)
-{
-    unsigned long pc = (unsigned long)retaddr;
-
-    if (pc) {
-        TranslationBlock *tb = tb_find_pc(pc);
-        if (tb) {
-            cpu_restore_state(tb, env, pc);
-        }
-    }
-}
-
-/* This may be called from any of the helpers to set up EXCEPTION_INDEX.  */
-static void QEMU_NORETURN dynamic_excp(int excp, int error)
-{
-    env->exception_index = excp;
-    env->error_code = error;
-    do_restore_state(GETPC());
-    cpu_loop_exit(env);
-}
-
-static void QEMU_NORETURN arith_excp(int exc, uint64_t mask)
-{
-    env->trap_arg0 = exc;
-    env->trap_arg1 = mask;
-    dynamic_excp(EXCP_ARITH, 0);
-}
-
 uint64_t helper_load_pcc (void)
 {
 #ifndef CONFIG_USER_ONLY
@@ -97,7 +60,7 @@ uint64_t helper_addqv (uint64_t op1, uint64_t op2)
     uint64_t tmp = op1;
     op1 += op2;
     if (unlikely((tmp ^ op2 ^ (-1ULL)) & (tmp ^ op1) & (1ULL << 63))) {
-        arith_excp(EXC_M_IOV, 0);
+        arith_excp(env, GETPC(), EXC_M_IOV, 0);
     }
     return op1;
 }
@@ -107,7 +70,7 @@ uint64_t helper_addlv (uint64_t op1, uint64_t op2)
     uint64_t tmp = op1;
     op1 = (uint32_t)(op1 + op2);
     if (unlikely((tmp ^ op2 ^ (-1UL)) & (tmp ^ op1) & (1UL << 31))) {
-        arith_excp(EXC_M_IOV, 0);
+        arith_excp(env, GETPC(), EXC_M_IOV, 0);
     }
     return op1;
 }
@@ -117,7 +80,7 @@ uint64_t helper_subqv (uint64_t op1, uint64_t op2)
     uint64_t res;
     res = op1 - op2;
     if (unlikely((op1 ^ op2) & (res ^ op1) & (1ULL << 63))) {
-        arith_excp(EXC_M_IOV, 0);
+        arith_excp(env, GETPC(), EXC_M_IOV, 0);
     }
     return res;
 }
@@ -127,7 +90,7 @@ uint64_t helper_sublv (uint64_t op1, uint64_t op2)
     uint32_t res;
     res = op1 - op2;
     if (unlikely((op1 ^ op2) & (res ^ op1) & (1UL << 31))) {
-        arith_excp(EXC_M_IOV, 0);
+        arith_excp(env, GETPC(), EXC_M_IOV, 0);
     }
     return res;
 }
@@ -137,7 +100,7 @@ uint64_t helper_mullv (uint64_t op1, uint64_t op2)
     int64_t res = (int64_t)op1 * (int64_t)op2;
 
     if (unlikely((int32_t)res != res)) {
-        arith_excp(EXC_M_IOV, 0);
+        arith_excp(env, GETPC(), EXC_M_IOV, 0);
     }
     return (int64_t)((int32_t)res);
 }
@@ -149,7 +112,7 @@ uint64_t helper_mulqv (uint64_t op1, uint64_t op2)
     muls64(&tl, &th, op1, op2);
     /* If th != 0 && th != -1, then we had an overflow */
     if (unlikely((th + 1) > 1)) {
-        arith_excp(EXC_M_IOV, 0);
+        arith_excp(env, GETPC(), EXC_M_IOV, 0);
     }
     return tl;
 }
@@ -200,7 +163,7 @@ void helper_fp_exc_raise(uint32_t exc, uint32_t regno)
             hw_exc |= EXC_M_INE;
         }
 
-        arith_excp(hw_exc, 1ull << regno);
+        arith_excp(env, GETPC(), hw_exc, 1ull << regno);
     }
 }
 
@@ -230,7 +193,7 @@ uint64_t helper_ieee_input(uint64_t val)
             if (env->fpcr_dnz) {
                 val &= 1ull << 63;
             } else {
-                arith_excp(EXC_M_UNF, 0);
+                arith_excp(env, GETPC(), EXC_M_UNF, 0);
             }
         }
     } else if (exp == 0x7ff) {
@@ -238,7 +201,7 @@ uint64_t helper_ieee_input(uint64_t val)
         /* ??? I'm not sure these exception bit flags are correct.  I do
            know that the Linux kernel, at least, doesn't rely on them and
            just emulates the insn to figure out what exception to use.  */
-        arith_excp(frac ? EXC_M_INV : EXC_M_FOV, 0);
+        arith_excp(env, GETPC(), frac ? EXC_M_INV : EXC_M_FOV, 0);
     }
     return val;
 }
@@ -255,12 +218,12 @@ uint64_t helper_ieee_input_cmp(uint64_t val)
             if (env->fpcr_dnz) {
                 val &= 1ull << 63;
             } else {
-                arith_excp(EXC_M_UNF, 0);
+                arith_excp(env, GETPC(), EXC_M_UNF, 0);
             }
         }
     } else if (exp == 0x7ff && frac) {
         /* NaN.  */
-        arith_excp(EXC_M_INV, 0);
+        arith_excp(env, GETPC(), EXC_M_INV, 0);
     }
     return val;
 }
@@ -323,7 +286,7 @@ static inline float32 f_to_float32(uint64_t a)
 
     if (unlikely(!exp && mant_sig)) {
         /* Reserved operands / Dirty zero */
-        dynamic_excp(EXCP_OPCDEC, 0);
+        dynamic_excp(env, GETPC(), EXCP_OPCDEC, 0);
     }
 
     if (exp < 3) {
@@ -453,7 +416,7 @@ static inline float64 g_to_float64(uint64_t a)
 
     if (!exp && mant_sig) {
         /* Reserved operands / Dirty zero */
-        dynamic_excp(EXCP_OPCDEC, 0);
+        dynamic_excp(env, GETPC(), EXCP_OPCDEC, 0);
     }
 
     if (exp < 3) {
@@ -1085,7 +1048,7 @@ static void QEMU_NORETURN do_unaligned_access(target_ulong addr, int is_write,
     uint64_t pc;
     uint32_t insn;
 
-    do_restore_state(retaddr);
+    do_restore_state(env, retaddr);
 
     pc = env->pc;
     insn = ldl_code(pc);
@@ -1093,7 +1056,9 @@ static void QEMU_NORETURN do_unaligned_access(target_ulong addr, int is_write,
     env->trap_arg0 = addr;
     env->trap_arg1 = insn >> 26;                /* opcode */
     env->trap_arg2 = (insn >> 21) & 31;         /* dest regno */
-    helper_excp(EXCP_UNALIGN, 0);
+    env->exception_index = EXCP_UNALIGN;
+    env->error_code = 0;
+    cpu_loop_exit(env);
 }
 
 void QEMU_NORETURN cpu_unassigned_access(CPUAlphaState *env1,
@@ -1103,7 +1068,7 @@ void QEMU_NORETURN cpu_unassigned_access(CPUAlphaState *env1,
     env = env1;
     env->trap_arg0 = addr;
     env->trap_arg1 = is_write;
-    dynamic_excp(EXCP_MCHK, 0);
+    dynamic_excp(env1, GETPC(), EXCP_MCHK, 0);
 }
 
 #include "softmmu_exec.h"
@@ -1137,7 +1102,7 @@ void tlb_fill(CPUAlphaState *env1, target_ulong addr, int is_write, int mmu_idx,
     env = env1;
     ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx);
     if (unlikely(ret != 0)) {
-        do_restore_state(retaddr);
+        do_restore_state(env, retaddr);
         /* Exception index and error code are already set */
         cpu_loop_exit(env);
     }
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 2c24619..0c06b55 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -149,7 +149,7 @@ static void gen_excp_1(int exception, int error_code)
 
     tmp1 = tcg_const_i32(exception);
     tmp2 = tcg_const_i32(error_code);
-    gen_helper_excp(tmp1, tmp2);
+    gen_helper_excp(cpu_env, tmp1, tmp2);
     tcg_temp_free_i32(tmp2);
     tcg_temp_free_i32(tmp1);
 }
commit 0be034bc2cc0e06584ee368759c47e5efa1439e7
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Mar 24 09:51:07 2012 -0700

    target-alpha: Move integer helpers to int_helper.c.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 63cf769..ddeb7e0 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -96,6 +96,7 @@ libobj-y += cpu_init.o
 endif
 libobj-$(TARGET_SPARC) += int32_helper.o
 libobj-$(TARGET_SPARC64) += int64_helper.o
+libobj-$(TARGET_ALPHA) += int_helper.o
 
 libobj-y += disas.o
 libobj-$(CONFIG_TCI_DIS) += tci-dis.o
diff --git a/target-alpha/int_helper.c b/target-alpha/int_helper.c
new file mode 100644
index 0000000..79c0cfe
--- /dev/null
+++ b/target-alpha/int_helper.c
@@ -0,0 +1,257 @@
+/*
+ *  Helpers for integer and multimedia instructions.
+ *
+ *  Copyright (c) 2007 Jocelyn Mayer
+ *
+ * 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/>.
+ */
+
+#include "cpu.h"
+#include "helper.h"
+#include "host-utils.h"
+
+
+uint64_t helper_umulh(uint64_t op1, uint64_t op2)
+{
+    uint64_t tl, th;
+    mulu64(&tl, &th, op1, op2);
+    return th;
+}
+
+uint64_t helper_ctpop(uint64_t arg)
+{
+    return ctpop64(arg);
+}
+
+uint64_t helper_ctlz(uint64_t arg)
+{
+    return clz64(arg);
+}
+
+uint64_t helper_cttz(uint64_t arg)
+{
+    return ctz64(arg);
+}
+
+static inline uint64_t byte_zap(uint64_t op, uint8_t mskb)
+{
+    uint64_t mask;
+
+    mask = 0;
+    mask |= ((mskb >> 0) & 1) * 0x00000000000000FFULL;
+    mask |= ((mskb >> 1) & 1) * 0x000000000000FF00ULL;
+    mask |= ((mskb >> 2) & 1) * 0x0000000000FF0000ULL;
+    mask |= ((mskb >> 3) & 1) * 0x00000000FF000000ULL;
+    mask |= ((mskb >> 4) & 1) * 0x000000FF00000000ULL;
+    mask |= ((mskb >> 5) & 1) * 0x0000FF0000000000ULL;
+    mask |= ((mskb >> 6) & 1) * 0x00FF000000000000ULL;
+    mask |= ((mskb >> 7) & 1) * 0xFF00000000000000ULL;
+
+    return op & ~mask;
+}
+
+uint64_t helper_zap(uint64_t val, uint64_t mask)
+{
+    return byte_zap(val, mask);
+}
+
+uint64_t helper_zapnot(uint64_t val, uint64_t mask)
+{
+    return byte_zap(val, ~mask);
+}
+
+uint64_t helper_cmpbge(uint64_t op1, uint64_t op2)
+{
+    uint8_t opa, opb, res;
+    int i;
+
+    res = 0;
+    for (i = 0; i < 8; i++) {
+        opa = op1 >> (i * 8);
+        opb = op2 >> (i * 8);
+        if (opa >= opb) {
+            res |= 1 << i;
+        }
+    }
+    return res;
+}
+
+uint64_t helper_minub8(uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    uint8_t opa, opb, opr;
+    int i;
+
+    for (i = 0; i < 8; ++i) {
+        opa = op1 >> (i * 8);
+        opb = op2 >> (i * 8);
+        opr = opa < opb ? opa : opb;
+        res |= (uint64_t)opr << (i * 8);
+    }
+    return res;
+}
+
+uint64_t helper_minsb8(uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    int8_t opa, opb;
+    uint8_t opr;
+    int i;
+
+    for (i = 0; i < 8; ++i) {
+        opa = op1 >> (i * 8);
+        opb = op2 >> (i * 8);
+        opr = opa < opb ? opa : opb;
+        res |= (uint64_t)opr << (i * 8);
+    }
+    return res;
+}
+
+uint64_t helper_minuw4(uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    uint16_t opa, opb, opr;
+    int i;
+
+    for (i = 0; i < 4; ++i) {
+        opa = op1 >> (i * 16);
+        opb = op2 >> (i * 16);
+        opr = opa < opb ? opa : opb;
+        res |= (uint64_t)opr << (i * 16);
+    }
+    return res;
+}
+
+uint64_t helper_minsw4(uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    int16_t opa, opb;
+    uint16_t opr;
+    int i;
+
+    for (i = 0; i < 4; ++i) {
+        opa = op1 >> (i * 16);
+        opb = op2 >> (i * 16);
+        opr = opa < opb ? opa : opb;
+        res |= (uint64_t)opr << (i * 16);
+    }
+    return res;
+}
+
+uint64_t helper_maxub8(uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    uint8_t opa, opb, opr;
+    int i;
+
+    for (i = 0; i < 8; ++i) {
+        opa = op1 >> (i * 8);
+        opb = op2 >> (i * 8);
+        opr = opa > opb ? opa : opb;
+        res |= (uint64_t)opr << (i * 8);
+    }
+    return res;
+}
+
+uint64_t helper_maxsb8(uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    int8_t opa, opb;
+    uint8_t opr;
+    int i;
+
+    for (i = 0; i < 8; ++i) {
+        opa = op1 >> (i * 8);
+        opb = op2 >> (i * 8);
+        opr = opa > opb ? opa : opb;
+        res |= (uint64_t)opr << (i * 8);
+    }
+    return res;
+}
+
+uint64_t helper_maxuw4(uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    uint16_t opa, opb, opr;
+    int i;
+
+    for (i = 0; i < 4; ++i) {
+        opa = op1 >> (i * 16);
+        opb = op2 >> (i * 16);
+        opr = opa > opb ? opa : opb;
+        res |= (uint64_t)opr << (i * 16);
+    }
+    return res;
+}
+
+uint64_t helper_maxsw4(uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    int16_t opa, opb;
+    uint16_t opr;
+    int i;
+
+    for (i = 0; i < 4; ++i) {
+        opa = op1 >> (i * 16);
+        opb = op2 >> (i * 16);
+        opr = opa > opb ? opa : opb;
+        res |= (uint64_t)opr << (i * 16);
+    }
+    return res;
+}
+
+uint64_t helper_perr(uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    uint8_t opa, opb, opr;
+    int i;
+
+    for (i = 0; i < 8; ++i) {
+        opa = op1 >> (i * 8);
+        opb = op2 >> (i * 8);
+        if (opa >= opb) {
+            opr = opa - opb;
+        } else {
+            opr = opb - opa;
+        }
+        res += opr;
+    }
+    return res;
+}
+
+uint64_t helper_pklb(uint64_t op1)
+{
+    return (op1 & 0xff) | ((op1 >> 24) & 0xff00);
+}
+
+uint64_t helper_pkwb(uint64_t op1)
+{
+    return ((op1 & 0xff)
+            | ((op1 >> 8) & 0xff00)
+            | ((op1 >> 16) & 0xff0000)
+            | ((op1 >> 24) & 0xff000000));
+}
+
+uint64_t helper_unpkbl(uint64_t op1)
+{
+    return (op1 & 0xff) | ((op1 & 0xff00) << 24);
+}
+
+uint64_t helper_unpkbw(uint64_t op1)
+{
+    return ((op1 & 0xff)
+            | ((op1 & 0xff00) << 8)
+            | ((op1 & 0xff0000) << 16)
+            | ((op1 & 0xff000000) << 24));
+}
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index c77f009..eab7a82 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -154,239 +154,6 @@ uint64_t helper_mulqv (uint64_t op1, uint64_t op2)
     return tl;
 }
 
-uint64_t helper_umulh (uint64_t op1, uint64_t op2)
-{
-    uint64_t tl, th;
-
-    mulu64(&tl, &th, op1, op2);
-    return th;
-}
-
-uint64_t helper_ctpop (uint64_t arg)
-{
-    return ctpop64(arg);
-}
-
-uint64_t helper_ctlz (uint64_t arg)
-{
-    return clz64(arg);
-}
-
-uint64_t helper_cttz (uint64_t arg)
-{
-    return ctz64(arg);
-}
-
-static inline uint64_t byte_zap(uint64_t op, uint8_t mskb)
-{
-    uint64_t mask;
-
-    mask = 0;
-    mask |= ((mskb >> 0) & 1) * 0x00000000000000FFULL;
-    mask |= ((mskb >> 1) & 1) * 0x000000000000FF00ULL;
-    mask |= ((mskb >> 2) & 1) * 0x0000000000FF0000ULL;
-    mask |= ((mskb >> 3) & 1) * 0x00000000FF000000ULL;
-    mask |= ((mskb >> 4) & 1) * 0x000000FF00000000ULL;
-    mask |= ((mskb >> 5) & 1) * 0x0000FF0000000000ULL;
-    mask |= ((mskb >> 6) & 1) * 0x00FF000000000000ULL;
-    mask |= ((mskb >> 7) & 1) * 0xFF00000000000000ULL;
-
-    return op & ~mask;
-}
-
-uint64_t helper_zap(uint64_t val, uint64_t mask)
-{
-    return byte_zap(val, mask);
-}
-
-uint64_t helper_zapnot(uint64_t val, uint64_t mask)
-{
-    return byte_zap(val, ~mask);
-}
-
-uint64_t helper_cmpbge (uint64_t op1, uint64_t op2)
-{
-    uint8_t opa, opb, res;
-    int i;
-
-    res = 0;
-    for (i = 0; i < 8; i++) {
-        opa = op1 >> (i * 8);
-        opb = op2 >> (i * 8);
-        if (opa >= opb)
-            res |= 1 << i;
-    }
-    return res;
-}
-
-uint64_t helper_minub8 (uint64_t op1, uint64_t op2)
-{
-    uint64_t res = 0;
-    uint8_t opa, opb, opr;
-    int i;
-
-    for (i = 0; i < 8; ++i) {
-        opa = op1 >> (i * 8);
-        opb = op2 >> (i * 8);
-        opr = opa < opb ? opa : opb;
-        res |= (uint64_t)opr << (i * 8);
-    }
-    return res;
-}
-
-uint64_t helper_minsb8 (uint64_t op1, uint64_t op2)
-{
-    uint64_t res = 0;
-    int8_t opa, opb;
-    uint8_t opr;
-    int i;
-
-    for (i = 0; i < 8; ++i) {
-        opa = op1 >> (i * 8);
-        opb = op2 >> (i * 8);
-        opr = opa < opb ? opa : opb;
-        res |= (uint64_t)opr << (i * 8);
-    }
-    return res;
-}
-
-uint64_t helper_minuw4 (uint64_t op1, uint64_t op2)
-{
-    uint64_t res = 0;
-    uint16_t opa, opb, opr;
-    int i;
-
-    for (i = 0; i < 4; ++i) {
-        opa = op1 >> (i * 16);
-        opb = op2 >> (i * 16);
-        opr = opa < opb ? opa : opb;
-        res |= (uint64_t)opr << (i * 16);
-    }
-    return res;
-}
-
-uint64_t helper_minsw4 (uint64_t op1, uint64_t op2)
-{
-    uint64_t res = 0;
-    int16_t opa, opb;
-    uint16_t opr;
-    int i;
-
-    for (i = 0; i < 4; ++i) {
-        opa = op1 >> (i * 16);
-        opb = op2 >> (i * 16);
-        opr = opa < opb ? opa : opb;
-        res |= (uint64_t)opr << (i * 16);
-    }
-    return res;
-}
-
-uint64_t helper_maxub8 (uint64_t op1, uint64_t op2)
-{
-    uint64_t res = 0;
-    uint8_t opa, opb, opr;
-    int i;
-
-    for (i = 0; i < 8; ++i) {
-        opa = op1 >> (i * 8);
-        opb = op2 >> (i * 8);
-        opr = opa > opb ? opa : opb;
-        res |= (uint64_t)opr << (i * 8);
-    }
-    return res;
-}
-
-uint64_t helper_maxsb8 (uint64_t op1, uint64_t op2)
-{
-    uint64_t res = 0;
-    int8_t opa, opb;
-    uint8_t opr;
-    int i;
-
-    for (i = 0; i < 8; ++i) {
-        opa = op1 >> (i * 8);
-        opb = op2 >> (i * 8);
-        opr = opa > opb ? opa : opb;
-        res |= (uint64_t)opr << (i * 8);
-    }
-    return res;
-}
-
-uint64_t helper_maxuw4 (uint64_t op1, uint64_t op2)
-{
-    uint64_t res = 0;
-    uint16_t opa, opb, opr;
-    int i;
-
-    for (i = 0; i < 4; ++i) {
-        opa = op1 >> (i * 16);
-        opb = op2 >> (i * 16);
-        opr = opa > opb ? opa : opb;
-        res |= (uint64_t)opr << (i * 16);
-    }
-    return res;
-}
-
-uint64_t helper_maxsw4 (uint64_t op1, uint64_t op2)
-{
-    uint64_t res = 0;
-    int16_t opa, opb;
-    uint16_t opr;
-    int i;
-
-    for (i = 0; i < 4; ++i) {
-        opa = op1 >> (i * 16);
-        opb = op2 >> (i * 16);
-        opr = opa > opb ? opa : opb;
-        res |= (uint64_t)opr << (i * 16);
-    }
-    return res;
-}
-
-uint64_t helper_perr (uint64_t op1, uint64_t op2)
-{
-    uint64_t res = 0;
-    uint8_t opa, opb, opr;
-    int i;
-
-    for (i = 0; i < 8; ++i) {
-        opa = op1 >> (i * 8);
-        opb = op2 >> (i * 8);
-        if (opa >= opb)
-            opr = opa - opb;
-        else
-            opr = opb - opa;
-        res += opr;
-    }
-    return res;
-}
-
-uint64_t helper_pklb (uint64_t op1)
-{
-    return (op1 & 0xff) | ((op1 >> 24) & 0xff00);
-}
-
-uint64_t helper_pkwb (uint64_t op1)
-{
-    return ((op1 & 0xff)
-            | ((op1 >> 8) & 0xff00)
-            | ((op1 >> 16) & 0xff0000)
-            | ((op1 >> 24) & 0xff000000));
-}
-
-uint64_t helper_unpkbl (uint64_t op1)
-{
-    return (op1 & 0xff) | ((op1 & 0xff00) << 24);
-}
-
-uint64_t helper_unpkbw (uint64_t op1)
-{
-    return ((op1 & 0xff)
-            | ((op1 & 0xff00) << 8)
-            | ((op1 & 0xff0000) << 16)
-            | ((op1 & 0xff000000) << 24));
-}
-
 /* Floating point helpers */
 
 void helper_setroundmode (uint32_t val)
commit 7b74505331fdd701557b01dd09ae9a62f31ea994
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Mar 24 09:51:06 2012 -0700

    alpha-linux-user: Initialize fpu to round-to-normal.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index b51fe5c..2c24619 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3513,7 +3513,8 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
 #if defined (CONFIG_USER_ONLY)
     env->ps = PS_USER_MODE;
     cpu_alpha_store_fpcr(env, (FPCR_INVD | FPCR_DZED | FPCR_OVFD
-                               | FPCR_UNFD | FPCR_INED | FPCR_DNOD));
+                               | FPCR_UNFD | FPCR_INED | FPCR_DNOD
+                               | FPCR_DYN_NORMAL));
 #endif
     env->lock_addr = -1;
     env->fen = 1;
commit cdb432b2020d3a5b22a7c06278088ccc7d1b2843
Author: Meador Inge <meadori at codesourcery.com>
Date:   Thu Mar 15 17:49:45 2012 +0000

    gdbserver: Don't send a GDB syscall until the system CPU is stopped
    
    Fix an issue where the GDB server implementation was sending GDB syscall
    requests while the system CPU was still running.  Syscall requests must
    be sent while the CPU is stopped otherwise replies from the GDB client
    might get dropped and the GDB server might be incorrectly transitioned
    into a 'RUN_STATE_PAUSED' state.
    
    Signed-off-by: Meador Inge <meadori at codesourcery.com>
    [PMM: trivial rebase, reinstated comma after last item in RSState enum]
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/gdbstub.c b/gdbstub.c
index f4e97f7..6a7e2c4 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -284,7 +284,6 @@ enum RSState {
     RS_GETLINE,
     RS_CHKSUM1,
     RS_CHKSUM2,
-    RS_SYSCALL,
 };
 typedef struct GDBState {
     CPUArchState *c_cpu; /* current CPU for step/continue ops */
@@ -304,6 +303,8 @@ typedef struct GDBState {
     CharDriverState *chr;
     CharDriverState *mon_chr;
 #endif
+    char syscall_buf[256];
+    gdb_syscall_complete_cb current_syscall_cb;
 } GDBState;
 
 /* By default use no IRQs and no timers while single stepping so as to
@@ -346,8 +347,6 @@ static int get_char(GDBState *s)
 }
 #endif
 
-static gdb_syscall_complete_cb gdb_current_syscall_cb;
-
 static enum {
     GDB_SYS_UNKNOWN,
     GDB_SYS_ENABLED,
@@ -2097,8 +2096,10 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
             if (*p == ',')
                 p++;
             type = *p;
-            if (gdb_current_syscall_cb)
-                gdb_current_syscall_cb(s->c_cpu, ret, err);
+            if (s->current_syscall_cb) {
+                s->current_syscall_cb(s->c_cpu, ret, err);
+                s->current_syscall_cb = NULL;
+            }
             if (type == 'C') {
                 put_packet(s, "T02");
             } else {
@@ -2398,7 +2399,12 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
     const char *type;
     int ret;
 
-    if (running || s->state == RS_INACTIVE || s->state == RS_SYSCALL) {
+    if (running || s->state == RS_INACTIVE) {
+        return;
+    }
+    /* Is there a GDB syscall waiting to be sent?  */
+    if (s->current_syscall_cb) {
+        put_packet(s, s->syscall_buf);
         return;
     }
     switch (state) {
@@ -2468,8 +2474,8 @@ send_packet:
 void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
 {
     va_list va;
-    char buf[256];
     char *p;
+    char *p_end;
     target_ulong addr;
     uint64_t i64;
     GDBState *s;
@@ -2477,14 +2483,13 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
     s = gdbserver_state;
     if (!s)
         return;
-    gdb_current_syscall_cb = cb;
-    s->state = RS_SYSCALL;
+    s->current_syscall_cb = cb;
 #ifndef CONFIG_USER_ONLY
     vm_stop(RUN_STATE_DEBUG);
 #endif
-    s->state = RS_IDLE;
     va_start(va, fmt);
-    p = buf;
+    p = s->syscall_buf;
+    p_end = &s->syscall_buf[sizeof(s->syscall_buf)];
     *(p++) = 'F';
     while (*fmt) {
         if (*fmt == '%') {
@@ -2492,17 +2497,17 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
             switch (*fmt++) {
             case 'x':
                 addr = va_arg(va, target_ulong);
-                p += snprintf(p, &buf[sizeof(buf)] - p, TARGET_FMT_lx, addr);
+                p += snprintf(p, p_end - p, TARGET_FMT_lx, addr);
                 break;
             case 'l':
                 if (*(fmt++) != 'x')
                     goto bad_format;
                 i64 = va_arg(va, uint64_t);
-                p += snprintf(p, &buf[sizeof(buf)] - p, "%" PRIx64, i64);
+                p += snprintf(p, p_end - p, "%" PRIx64, i64);
                 break;
             case 's':
                 addr = va_arg(va, target_ulong);
-                p += snprintf(p, &buf[sizeof(buf)] - p, TARGET_FMT_lx "/%x",
+                p += snprintf(p, p_end - p, TARGET_FMT_lx "/%x",
                               addr, va_arg(va, int));
                 break;
             default:
@@ -2517,10 +2522,16 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
     }
     *p = 0;
     va_end(va);
-    put_packet(s, buf);
 #ifdef CONFIG_USER_ONLY
+    put_packet(s, s->syscall_buf);
     gdb_handlesig(s->c_cpu, 0);
 #else
+    /* In this case wait to send the syscall packet until notification that
+       the CPU has stopped.  This must be done because if the packet is sent
+       now the reply from the syscall request could be received while the CPU
+       is still in the running state, which can cause packets to be dropped
+       and state transition 'T' packets to be sent while the syscall is still
+       being processed.  */
     cpu_exit(s->c_cpu);
 #endif
 }
@@ -2919,6 +2930,7 @@ int gdbserver_start(const char *device)
     s->chr = chr;
     s->state = chr ? RS_IDLE : RS_INACTIVE;
     s->mon_chr = mon_chr;
+    s->current_syscall_cb = NULL;
 
     return 0;
 }
commit 3179d694a8dcaa091131e3db644d445c0130713e
Author: Michael Tokarev <mjt at tls.msk.ru>
Date:   Tue Mar 20 02:25:57 2012 +0400

    Support utf8 chars in pod docs
    
    We've at least one UTF8 char in the qemu texi doc:
    
     $ grep Tibor qemu-doc.texi
     by Tibor "TS" Schütz.
     $ man ./qemu.1 | grep Tibor
            by Tibor "TS" SchA~Xtz.
    
    This patch allows utf8 in man/pod docs.
    
    Initially it was split into two parts and sent on 2012-02-02.
    Resending it again (3rd time) now in merged form.  If any
    other generalizations of $(POD2MAN) are needed it can be done
    in a separate patch.  Current form of $(POD2MAN) is choosen
    to be able to easily change it if some implementation does
    not support utf8 or resulting output has issues with local
    man(1) program/macros.
    
    First, add @documentencoding in scripts/texi2pod.pl:
    
    Currently our texi2pod ignores @documentencoding even if it is set
    properly in *.texi files.  This results in a mojibake in documents
    generated from qemu.pod (which is generated from qemu-doc.texi by
    texi2pod), because the rest of the tools assumes ASCII encoding.
    
    This patch recognizes first @documentencoding in input and places
    it at the beginning of output as =encoding directive.
    
    Second, run pod2man with --utf8 option to enable utf8 in manpages:
    
    This option makes no difference for manpages which contains only
    ascii chars.  But for manpages with actual UTF8 characters (qemu
    docs contains these), this change allows to see real characters
    instead of mojibakes or substitutes.
    
    Signed-off-By: Michael Tokarev <mjt at tls.msk.ru>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile b/Makefile
index 1bc3cb0..8d6b558 100644
--- a/Makefile
+++ b/Makefile
@@ -347,28 +347,29 @@ QMP/qmp-commands.txt: $(SRC_PATH)/qmp-commands.hx
 qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx
 	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"  GEN   $@")
 
+POD2MAN = pod2man --utf8
 qemu.1: qemu-doc.texi qemu-options.texi qemu-monitor.texi
 	$(call quiet-command, \
 	  perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< qemu.pod && \
-	  pod2man --section=1 --center=" " --release=" " qemu.pod > $@, \
+	  $(POD2MAN) --section=1 --center=" " --release=" " qemu.pod > $@, \
 	  "  GEN   $@")
 
 qemu-img.1: qemu-img.texi qemu-img-cmds.texi
 	$(call quiet-command, \
 	  perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< qemu-img.pod && \
-	  pod2man --section=1 --center=" " --release=" " qemu-img.pod > $@, \
+	  $(POD2MAN) --section=1 --center=" " --release=" " qemu-img.pod > $@, \
 	  "  GEN   $@")
 
 fsdev/virtfs-proxy-helper.1: fsdev/virtfs-proxy-helper.texi
 	$(call quiet-command, \
 	  perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< fsdev/virtfs-proxy-helper.pod && \
-	  pod2man --section=1 --center=" " --release=" " fsdev/virtfs-proxy-helper.pod > $@, \
+	  $(POD2MAN) --section=1 --center=" " --release=" " fsdev/virtfs-proxy-helper.pod > $@, \
 	  "  GEN   $@")
 
 qemu-nbd.8: qemu-nbd.texi
 	$(call quiet-command, \
 	  perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< qemu-nbd.pod && \
-	  pod2man --section=8 --center=" " --release=" " qemu-nbd.pod > $@, \
+	  $(POD2MAN) --section=8 --center=" " --release=" " qemu-nbd.pod > $@, \
 	  "  GEN   $@")
 
 dvi: qemu-doc.dvi qemu-tech.dvi
diff --git a/scripts/texi2pod.pl b/scripts/texi2pod.pl
index 9ed056a..94097fb 100755
--- a/scripts/texi2pod.pl
+++ b/scripts/texi2pod.pl
@@ -36,6 +36,7 @@ $fnno = 1;
 $inf = "";
 $ibase = "";
 @ipath = ();
+$encoding = undef;
 
 while ($_ = shift) {
     if (/^-D(.*)$/) {
@@ -97,6 +98,12 @@ while(<$inf>) {
     /^\@setfilename\s+([^.]+)/ and $fn = $1, next;
     /^\@settitle\s+([^.]+)/ and $tl = postprocess($1), next;
 
+    # Look for document encoding
+    /^\@documentencoding\s+([^.]+)/ and do {
+        $encoding = $1 unless defined $encoding;
+        next;
+    };
+
     # Identify a man title but keep only the one we are interested in.
     /^\@c\s+man\s+title\s+([A-Za-z0-9-]+)\s+(.+)/ and do {
 	if (exists $defs{$1}) {
@@ -336,6 +343,8 @@ $inf = pop @instack;
 
 die "No filename or title\n" unless defined $fn && defined $tl;
 
+print "=encoding $encoding\n\n" if defined $encoding;
+
 $sects{NAME} = "$fn \- $tl\n";
 $sects{FOOTNOTES} .= "=back\n" if exists $sects{FOOTNOTES};
 
commit 813da6277cf6325ee97e7b7724e1672053356f4c
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Mar 19 12:25:11 2012 -0700

    tcg: Use the GDB JIT debugging interface.
    
    This allows us to generate unwind info for the dynamicly generated
    code in the code_gen_buffer.  Only i386 is converted at this point.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/elf.h b/elf.h
index 2e05d34..310e05a 100644
--- a/elf.h
+++ b/elf.h
@@ -216,6 +216,7 @@ typedef int64_t  Elf64_Sxword;
 
 #define ELF_ST_BIND(x)		((x) >> 4)
 #define ELF_ST_TYPE(x)		(((unsigned int) x) & 0xf)
+#define ELF_ST_INFO(bind, type) (((bind) << 4) | ((type) & 0xf))
 #define ELF32_ST_BIND(x)	ELF_ST_BIND(x)
 #define ELF32_ST_TYPE(x)	ELF_ST_TYPE(x)
 #define ELF64_ST_BIND(x)	ELF_ST_BIND(x)
diff --git a/exec.c b/exec.c
index 265e895..6731ab8 100644
--- a/exec.c
+++ b/exec.c
@@ -636,6 +636,7 @@ void tcg_exec_init(unsigned long tb_size)
     cpu_gen_init();
     code_gen_alloc(tb_size);
     code_gen_ptr = code_gen_buffer;
+    tcg_register_jit(code_gen_buffer, code_gen_buffer_size);
     page_init();
 #if !defined(CONFIG_USER_ONLY) || !defined(CONFIG_USE_GUEST_BASE)
     /* There's no guest base to take into account, so go ahead and
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 43a51a1..871a7e7 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -1989,22 +1989,29 @@ static int tcg_target_callee_save_regs[] = {
 #endif
 };
 
+/* Compute frame size via macros, to share between tcg_target_qemu_prologue
+   and tcg_register_jit.  */
+
+#define PUSH_SIZE \
+    ((1 + ARRAY_SIZE(tcg_target_callee_save_regs)) \
+     * (TCG_TARGET_REG_BITS / 8))
+
+#define FRAME_SIZE \
+    ((PUSH_SIZE \
+      + TCG_STATIC_CALL_ARGS_SIZE \
+      + CPU_TEMP_BUF_NLONGS * sizeof(long) \
+      + TCG_TARGET_STACK_ALIGN - 1) \
+     & ~(TCG_TARGET_STACK_ALIGN - 1))
+
 /* Generate global QEMU prologue and epilogue code */
 static void tcg_target_qemu_prologue(TCGContext *s)
 {
-    int i, frame_size, push_size, stack_addend;
+    int i, stack_addend;
 
     /* TB prologue */
 
     /* Reserve some stack space, also for TCG temps.  */
-    push_size = 1 + ARRAY_SIZE(tcg_target_callee_save_regs);
-    push_size *= TCG_TARGET_REG_BITS / 8;
-
-    frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE +
-        CPU_TEMP_BUF_NLONGS * sizeof(long);
-    frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
-        ~(TCG_TARGET_STACK_ALIGN - 1);
-    stack_addend = frame_size - push_size;
+    stack_addend = FRAME_SIZE - PUSH_SIZE;
     tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_SIZE,
                   CPU_TEMP_BUF_NLONGS * sizeof(long));
 
@@ -2070,3 +2077,92 @@ static void tcg_target_init(TCGContext *s)
 
     tcg_add_target_add_op_defs(x86_op_defs);
 }
+
+typedef struct {
+    uint32_t len __attribute__((aligned((sizeof(void *)))));
+    uint32_t id;
+    uint8_t version;
+    char augmentation[1];
+    uint8_t code_align;
+    uint8_t data_align;
+    uint8_t return_column;
+} DebugFrameCIE;
+
+typedef struct {
+    uint32_t len __attribute__((aligned((sizeof(void *)))));
+    uint32_t cie_offset;
+    tcg_target_long func_start __attribute__((packed));
+    tcg_target_long func_len __attribute__((packed));
+    uint8_t def_cfa[4];
+    uint8_t reg_ofs[14];
+} DebugFrameFDE;
+
+typedef struct {
+    DebugFrameCIE cie;
+    DebugFrameFDE fde;
+} DebugFrame;
+
+#if TCG_TARGET_REG_BITS == 64
+#define ELF_HOST_MACHINE EM_X86_64
+static DebugFrame debug_frame = {
+    .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
+    .cie.id = -1,
+    .cie.version = 1,
+    .cie.code_align = 1,
+    .cie.data_align = 0x78,             /* sleb128 -8 */
+    .cie.return_column = 16,
+
+    .fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */
+    .fde.def_cfa = {
+        12, 7,                          /* DW_CFA_def_cfa %rsp, ... */
+        (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
+        (FRAME_SIZE >> 7)
+    },
+    .fde.reg_ofs = {
+        0x90, 1,                        /* DW_CFA_offset, %rip, -8 */
+        /* The following ordering must match tcg_target_callee_save_regs.  */
+        0x86, 2,                        /* DW_CFA_offset, %rbp, -16 */
+        0x83, 3,                        /* DW_CFA_offset, %rbx, -24 */
+        0x8c, 4,                        /* DW_CFA_offset, %r12, -32 */
+        0x8d, 5,                        /* DW_CFA_offset, %r13, -40 */
+        0x8e, 6,                        /* DW_CFA_offset, %r14, -48 */
+        0x8f, 7,                        /* DW_CFA_offset, %r15, -56 */
+    }
+};
+#else
+#define ELF_HOST_MACHINE EM_386
+static DebugFrame debug_frame = {
+    .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
+    .cie.id = -1,
+    .cie.version = 1,
+    .cie.code_align = 1,
+    .cie.data_align = 0x7c,             /* sleb128 -4 */
+    .cie.return_column = 8,
+
+    .fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */
+    .fde.def_cfa = {
+        12, 4,                          /* DW_CFA_def_cfa %esp, ... */
+        (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
+        (FRAME_SIZE >> 7)
+    },
+    .fde.reg_ofs = {
+        0x88, 1,                        /* DW_CFA_offset, %eip, -4 */
+        /* The following ordering must match tcg_target_callee_save_regs.  */
+        0x85, 2,                        /* DW_CFA_offset, %ebp, -8 */
+        0x83, 3,                        /* DW_CFA_offset, %ebx, -12 */
+        0x86, 4,                        /* DW_CFA_offset, %esi, -16 */
+        0x87, 5,                        /* DW_CFA_offset, %edi, -20 */
+    }
+};
+#endif
+
+void tcg_register_jit(void *buf, size_t buf_size)
+{
+    /* We're expecting a 2 byte uleb128 encoded value.  */
+    assert(FRAME_SIZE >> 14 == 0);
+
+    debug_frame.fde.func_start = (tcg_target_long) buf;
+    debug_frame.fde.func_len = buf_size;
+
+    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
+}
diff --git a/tcg/tcg.c b/tcg/tcg.c
index ccfcd1a..eb595ce 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -28,6 +28,9 @@
 
 #include "config.h"
 
+/* Define to jump the ELF file used to communicate with GDB.  */
+#undef DEBUG_JIT
+
 #if !defined(CONFIG_DEBUG_TCG) && !defined(NDEBUG)
 /* define it to suppress various consistency checks (faster) */
 #define NDEBUG
@@ -45,6 +48,18 @@
 #include "cpu.h"
 
 #include "tcg-op.h"
+
+#if TCG_TARGET_REG_BITS == 64
+# define ELF_CLASS  ELFCLASS64
+#else
+# define ELF_CLASS  ELFCLASS32
+#endif
+#ifdef HOST_WORDS_BIGENDIAN
+# define ELF_DATA   ELFDATA2MSB
+#else
+# define ELF_DATA   ELFDATA2LSB
+#endif
+
 #include "elf.h"
 
 #if defined(CONFIG_USE_GUEST_BASE) && !defined(TCG_TARGET_HAS_GUEST_BASE)
@@ -57,6 +72,10 @@ static void tcg_target_qemu_prologue(TCGContext *s);
 static void patch_reloc(uint8_t *code_ptr, int type, 
                         tcg_target_long value, tcg_target_long addend);
 
+static void tcg_register_jit_int(void *buf, size_t size,
+                                 void *debug_frame, size_t debug_frame_size)
+    __attribute__((unused));
+
 /* Forward declarations for functions declared and used in tcg-target.c. */
 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str);
 static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
@@ -2231,3 +2250,178 @@ void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
     cpu_fprintf(f, "[TCG profiler not compiled]\n");
 }
 #endif
+
+#ifdef ELF_HOST_MACHINE
+/* The backend should define ELF_HOST_MACHINE to indicate both what value to
+   put into the ELF image and to indicate support for the feature.  */
+
+/* Begin GDB interface.  THE FOLLOWING MUST MATCH GDB DOCS.  */
+typedef enum {
+    JIT_NOACTION = 0,
+    JIT_REGISTER_FN,
+    JIT_UNREGISTER_FN
+} jit_actions_t;
+
+struct jit_code_entry {
+    struct jit_code_entry *next_entry;
+    struct jit_code_entry *prev_entry;
+    const void *symfile_addr;
+    uint64_t symfile_size;
+};
+
+struct jit_descriptor {
+    uint32_t version;
+    uint32_t action_flag;
+    struct jit_code_entry *relevant_entry;
+    struct jit_code_entry *first_entry;
+};
+
+void __jit_debug_register_code(void) __attribute__((noinline));
+void __jit_debug_register_code(void)
+{
+    asm("");
+}
+
+/* Must statically initialize the version, because GDB may check
+   the version before we can set it.  */
+struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
+
+/* End GDB interface.  */
+
+static int find_string(const char *strtab, const char *str)
+{
+    const char *p = strtab + 1;
+
+    while (1) {
+        if (strcmp(p, str) == 0) {
+            return p - strtab;
+        }
+        p += strlen(p) + 1;
+    }
+}
+
+static void tcg_register_jit_int(void *buf, size_t buf_size,
+                                 void *debug_frame, size_t debug_frame_size)
+{
+    static const char strings[64] =
+        "\0"
+        ".text\0"
+        ".debug_frame\0"
+        ".symtab\0"
+        ".strtab\0"
+        "code_gen_buffer";
+
+    struct ElfImage {
+        ElfW(Ehdr) ehdr;
+        ElfW(Phdr) phdr;
+        ElfW(Shdr) shdr[5];
+        ElfW(Sym)  sym[1];
+        char       str[64];
+    };
+
+    /* We only need a single jit entry; statically allocate it.  */
+    static struct jit_code_entry one_entry;
+
+    size_t img_size = sizeof(struct ElfImage) + debug_frame_size;
+    struct ElfImage *img = g_malloc0(img_size);
+
+    img->ehdr.e_ident[EI_MAG0] = ELFMAG0;
+    img->ehdr.e_ident[EI_MAG1] = ELFMAG1;
+    img->ehdr.e_ident[EI_MAG2] = ELFMAG2;
+    img->ehdr.e_ident[EI_MAG3] = ELFMAG3;
+    img->ehdr.e_ident[EI_CLASS] = ELF_CLASS;
+    img->ehdr.e_ident[EI_DATA] = ELF_DATA;
+    img->ehdr.e_ident[EI_VERSION] = EV_CURRENT;
+    img->ehdr.e_type = ET_EXEC;
+    img->ehdr.e_machine = ELF_HOST_MACHINE;
+    img->ehdr.e_version = EV_CURRENT;
+    img->ehdr.e_phoff = offsetof(struct ElfImage, phdr);
+    img->ehdr.e_shoff = offsetof(struct ElfImage, shdr);
+    img->ehdr.e_ehsize = sizeof(ElfW(Shdr));
+    img->ehdr.e_phentsize = sizeof(ElfW(Phdr));
+    img->ehdr.e_phnum = 1;
+    img->ehdr.e_shentsize = sizeof(img->shdr[0]);
+    img->ehdr.e_shnum = ARRAY_SIZE(img->shdr);
+    img->ehdr.e_shstrndx = ARRAY_SIZE(img->shdr) - 1;
+
+    img->phdr.p_type = PT_LOAD;
+    img->phdr.p_offset = (char *)buf - (char *)img;
+    img->phdr.p_vaddr = (ElfW(Addr))buf;
+    img->phdr.p_paddr = img->phdr.p_vaddr;
+    img->phdr.p_filesz = 0;
+    img->phdr.p_memsz = buf_size;
+    img->phdr.p_flags = PF_X;
+
+    memcpy(img->str, strings, sizeof(img->str));
+
+    img->shdr[0].sh_type = SHT_NULL;
+
+    /* Trick: The contents of code_gen_buffer are not present in this fake
+       ELF file; that got allocated elsewhere, discontiguously.  Therefore
+       we mark .text as SHT_NOBITS (similar to .bss) so that readers will
+       not look for contents.  We can record any address at will.  */
+    img->shdr[1].sh_name = find_string(img->str, ".text");
+    img->shdr[1].sh_type = SHT_NOBITS;
+    img->shdr[1].sh_flags = SHF_EXECINSTR | SHF_ALLOC;
+    img->shdr[1].sh_addr = (ElfW(Addr))buf;
+    img->shdr[1].sh_size = buf_size;
+
+    img->shdr[2].sh_name = find_string(img->str, ".debug_frame");
+    img->shdr[2].sh_type = SHT_PROGBITS;
+    img->shdr[2].sh_offset = sizeof(*img);
+    img->shdr[2].sh_size = debug_frame_size;
+    memcpy(img + 1, debug_frame, debug_frame_size);
+
+    img->shdr[3].sh_name = find_string(img->str, ".symtab");
+    img->shdr[3].sh_type = SHT_SYMTAB;
+    img->shdr[3].sh_offset = offsetof(struct ElfImage, sym);
+    img->shdr[3].sh_size = sizeof(img->sym);
+    img->shdr[3].sh_info = ARRAY_SIZE(img->sym);
+    img->shdr[3].sh_link = img->ehdr.e_shstrndx;
+    img->shdr[3].sh_entsize = sizeof(ElfW(Sym));
+
+    img->shdr[4].sh_name = find_string(img->str, ".strtab");
+    img->shdr[4].sh_type = SHT_STRTAB;
+    img->shdr[4].sh_offset = offsetof(struct ElfImage, str);
+    img->shdr[4].sh_size = sizeof(img->str);
+
+    img->sym[0].st_name = find_string(img->str, "code_gen_buffer");
+    img->sym[0].st_info = ELF_ST_INFO(STB_GLOBAL, STT_FUNC);
+    img->sym[0].st_shndx = 1;
+    img->sym[0].st_value = (ElfW(Addr))buf;
+    img->sym[0].st_size = buf_size;
+
+#ifdef DEBUG_JIT
+    /* Enable this block to be able to debug the ELF image file creation.
+       One can use readelf, objdump, or other inspection utilities.  */
+    {
+        FILE *f = fopen("/tmp/qemu.jit", "w+b");
+        if (f) {
+            if (fwrite(img, img_size, 1, f) != buf_size) {
+                /* Avoid stupid unused return value warning for fwrite.  */
+            }
+            fclose(f);
+        }
+    }
+#endif
+
+    one_entry.symfile_addr = img;
+    one_entry.symfile_size = img_size;
+
+    __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
+    __jit_debug_descriptor.relevant_entry = &one_entry;
+    __jit_debug_descriptor.first_entry = &one_entry;
+    __jit_debug_register_code();
+}
+#else
+/* No support for the feature.  Provide the entry point expected by exec.c.  */
+
+static void tcg_register_jit_int(void *buf, size_t size,
+                                 void *debug_frame, size_t debug_frame_size)
+{
+}
+
+void tcg_register_jit(void *buf, size_t buf_size)
+{
+}
+#endif /* ELF_HOST_MACHINE */
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 5f6c647..a83bddd 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -586,3 +586,5 @@ extern uint8_t code_gen_prologue[];
 # define tcg_qemu_tb_exec(env, tb_ptr) \
     ((tcg_target_ulong (*)(void *, void *))code_gen_prologue)(env, tb_ptr)
 #endif
+
+void tcg_register_jit(void *buf, size_t buf_size);
commit 08c4ea294f38fa90c7e91d7402091ff8332bc65e
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Mar 1 08:34:40 2012 +0100

    fix screendump
    
    Commit 45efb16124efef51de5157afc31984b5a47700f9 optimized a bit too
    much.  We can skip the vga_invalidate_display() in case no console
    switch happened because we don't need a full redraw then.  We can *not*
    skip vga_hw_update() though, because the screen content will be stale
    then in case nobody else calls vga_hw_update().
    
    Trigger: vga textmode with vnc display and no client connected.
    
    Reported-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Reviewed-by: Alon Levy <alevy at redhat.com>
    Tested-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/blizzard.c b/hw/blizzard.c
index c7d844d..29074c4 100644
--- a/hw/blizzard.c
+++ b/hw/blizzard.c
@@ -937,9 +937,7 @@ static void blizzard_screen_dump(void *opaque, const char *filename,
 {
     BlizzardState *s = (BlizzardState *) opaque;
 
-    if (cswitch) {
-        blizzard_update_display(opaque);
-    }
+    blizzard_update_display(opaque);
     if (s && ds_get_data(s->state))
         ppm_save(filename, s->state->surface);
 }
diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c
index f172093..4a08e9d 100644
--- a/hw/omap_lcdc.c
+++ b/hw/omap_lcdc.c
@@ -267,9 +267,8 @@ static int ppm_save(const char *filename, uint8_t *data,
 static void omap_screen_dump(void *opaque, const char *filename, bool cswitch)
 {
     struct omap_lcd_panel_s *omap_lcd = opaque;
-    if (cswitch) {
-        omap_update_display(opaque);
-    }
+
+    omap_update_display(opaque);
     if (omap_lcd && ds_get_data(omap_lcd->state))
         ppm_save(filename, ds_get_data(omap_lcd->state),
                 omap_lcd->width, omap_lcd->height,
diff --git a/hw/vga.c b/hw/vga.c
index 6dc98f6..f80860c 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -2415,7 +2415,7 @@ static void vga_screen_dump(void *opaque, const char *filename, bool cswitch)
 
     if (cswitch) {
         vga_invalidate_display(s);
-        vga_hw_update();
     }
+    vga_hw_update();
     ppm_save(filename, s->ds->surface);
 }
commit bc09845431888a0a6a680c0feeca7c6a18f8ec43
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sun Mar 18 23:16:04 2012 +0100

    target-sparc: Add compiler attribute to some functions which don't return
    
    helper_raise_exception does not return, nor does do_unaligned_access.
    
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 1025752..885ad45 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -699,8 +699,9 @@ uint64_t cpu_tick_get_count(CPUTimer *timer);
 void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit);
 trap_state* cpu_tsptr(CPUSPARCState* env);
 #endif
-void do_unaligned_access(CPUSPARCState *env, target_ulong addr, int is_write,
-                         int is_user, void *retaddr);
+void QEMU_NORETURN do_unaligned_access(CPUSPARCState *env, target_ulong addr,
+                                       int is_write, int is_user,
+                                       void *retaddr);
 
 #define TB_FLAG_FPU_ENABLED (1 << 4)
 #define TB_FLAG_AM_ENABLED (1 << 5)
diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index c4d6225..e3c7fdd 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -78,7 +78,7 @@ DEF_HELPER_1(fcmpeq_fcc1, void, env)
 DEF_HELPER_1(fcmpeq_fcc2, void, env)
 DEF_HELPER_1(fcmpeq_fcc3, void, env)
 #endif
-DEF_HELPER_2(raise_exception, void, env, int)
+DEF_HELPER_2(raise_exception, noreturn, env, int)
 #define F_HELPER_0_1(name) DEF_HELPER_1(f ## name, void, env)
 
 DEF_HELPER_3(faddd, f64, env, f64, f64)
commit 59821ae8025dbf61323343fc074513d30013c9c0
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sun Mar 18 23:16:03 2012 +0100

    target-mips: Add compiler attribute to some functions which don't return
    
    helper_raise_exception_err does not return, nor do helper_raise_exception
    and do_unaligned_access.
    
    Cc: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-mips/helper.h b/target-mips/helper.h
index 442f684..76fb451 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -1,7 +1,7 @@
 #include "def-helper.h"
 
-DEF_HELPER_2(raise_exception_err, void, i32, int)
-DEF_HELPER_1(raise_exception, void, i32)
+DEF_HELPER_2(raise_exception_err, noreturn, i32, int)
+DEF_HELPER_1(raise_exception, noreturn, i32)
 
 #ifdef TARGET_MIPS64
 DEF_HELPER_3(ldl, tl, tl, tl, int)
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 3a20731..ce01225 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -2292,7 +2292,8 @@ void helper_wait (void)
 
 #if !defined(CONFIG_USER_ONLY)
 
-static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr);
+static void QEMU_NORETURN do_unaligned_access(target_ulong addr, int is_write,
+                                              int is_user, void *retaddr);
 
 #define MMUSUFFIX _mmu
 #define ALIGNED_ONLY
commit 1367ff497aa5200970e555bf4cce07467c3e3652
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sun Mar 18 23:16:02 2012 +0100

    Add support for target helper functions which don't return
    
    Most functions which handle exceptions don't return.
    
    With a compiler attribute (added by QEMU_NORETURN),
    gcc can optimize the code.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/def-helper.h b/def-helper.h
index 0e70c31..b98ff69 100644
--- a/def-helper.h
+++ b/def-helper.h
@@ -39,6 +39,7 @@
 #endif
 #define dh_alias_ptr ptr
 #define dh_alias_void void
+#define dh_alias_noreturn noreturn
 #define dh_alias_env ptr
 #define dh_alias(t) glue(dh_alias_, t)
 
@@ -52,36 +53,42 @@
 #define dh_ctype_tl target_ulong
 #define dh_ctype_ptr void *
 #define dh_ctype_void void
+#define dh_ctype_noreturn void QEMU_NORETURN
 #define dh_ctype_env CPUArchState *
 #define dh_ctype(t) dh_ctype_##t
 
 /* We can't use glue() here because it falls foul of C preprocessor
    recursive expansion rules.  */
 #define dh_retvar_decl0_void void
+#define dh_retvar_decl0_noreturn void
 #define dh_retvar_decl0_i32 TCGv_i32 retval
 #define dh_retvar_decl0_i64 TCGv_i64 retval
 #define dh_retvar_decl0_ptr TCGv_ptr retval
 #define dh_retvar_decl0(t) glue(dh_retvar_decl0_, dh_alias(t))
 
 #define dh_retvar_decl_void
+#define dh_retvar_decl_noreturn
 #define dh_retvar_decl_i32 TCGv_i32 retval,
 #define dh_retvar_decl_i64 TCGv_i64 retval,
 #define dh_retvar_decl_ptr TCGv_ptr retval,
 #define dh_retvar_decl(t) glue(dh_retvar_decl_, dh_alias(t))
 
 #define dh_retvar_void TCG_CALL_DUMMY_ARG
+#define dh_retvar_noreturn TCG_CALL_DUMMY_ARG
 #define dh_retvar_i32 GET_TCGV_i32(retval)
 #define dh_retvar_i64 GET_TCGV_i64(retval)
 #define dh_retvar_ptr GET_TCGV_ptr(retval)
 #define dh_retvar(t) glue(dh_retvar_, dh_alias(t))
 
 #define dh_is_64bit_void 0
+#define dh_is_64bit_noreturn 0
 #define dh_is_64bit_i32 0
 #define dh_is_64bit_i64 1
 #define dh_is_64bit_ptr (TCG_TARGET_REG_BITS == 64)
 #define dh_is_64bit(t) glue(dh_is_64bit_, dh_alias(t))
 
 #define dh_is_signed_void 0
+#define dh_is_signed_noreturn 0
 #define dh_is_signed_i32 0
 #define dh_is_signed_s32 1
 #define dh_is_signed_i64 0
commit 4daa187d49a9d242d0bda1f35e190486112915f6
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Mar 18 16:48:44 2012 +0200

    scripts: add gdb support script
    
    Add a script that enhances gdb to be aware of QEMU data structures.
    
    This patch adds a single gdb command, 'qemu mtree'.  The command is
    similar to the monitor's 'info mtree', except that it prints MemoryRegion
    addresses, and except for working from a core dump as well as a live instance.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/scripts/qemu-gdb.py b/scripts/qemu-gdb.py
new file mode 100644
index 0000000..8a0f305
--- /dev/null
+++ b/scripts/qemu-gdb.py
@@ -0,0 +1,89 @@
+#!/usr/bin/python
+
+# GDB debugging support
+#
+# Copyright 2012 Red Hat, Inc. and/or its affiliates
+#
+# Authors:
+#  Avi Kivity <avi at redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2.  See
+# the COPYING file in the top-level directory.
+#
+# Contributions after 2012-01-13 are licensed under the terms of the
+# GNU GPL, version 2 or (at your option) any later version.
+
+
+import gdb
+
+def isnull(ptr):
+    return ptr == gdb.Value(0).cast(ptr.type)
+
+def int128(p):
+    return long(p['lo']) + (long(p['hi']) << 64)
+
+class QemuCommand(gdb.Command):
+    '''Prefix for QEMU debug support commands'''
+    def __init__(self):
+        gdb.Command.__init__(self, 'qemu', gdb.COMMAND_DATA,
+                             gdb.COMPLETE_NONE, True)
+
+class MtreeCommand(gdb.Command):
+    '''Display the memory tree hierarchy'''
+    def __init__(self):
+        gdb.Command.__init__(self, 'qemu mtree', gdb.COMMAND_DATA,
+                             gdb.COMPLETE_NONE)
+        self.queue = []
+    def invoke(self, arg, from_tty):
+        self.seen = set()
+        self.queue_root('address_space_memory')
+        self.queue_root('address_space_io')
+        self.process_queue()
+    def queue_root(self, varname):
+        ptr = gdb.parse_and_eval(varname)['root']
+        self.queue.append(ptr)
+    def process_queue(self):
+        while self.queue:
+            ptr = self.queue.pop(0)
+            if long(ptr) in self.seen:
+                continue
+            self.print_item(ptr)
+    def print_item(self, ptr, offset = gdb.Value(0), level = 0):
+        self.seen.add(long(ptr))
+        addr = ptr['addr']
+        addr += offset
+        size = int128(ptr['size'])
+        alias = ptr['alias']
+        klass = ''
+        if not isnull(alias):
+            klass = ' (alias)'
+        elif not isnull(ptr['ops']):
+            klass = ' (I/O)'
+        elif bool(ptr['ram']):
+            klass = ' (RAM)'
+        gdb.write('%s%016x-%016x %s%s (@ %s)\n'
+                  % ('  ' * level,
+                     long(addr),
+                     long(addr + (size - 1)),
+                     ptr['name'].string(),
+                     klass,
+                     ptr,
+                     ),
+                  gdb.STDOUT)
+        if not isnull(alias):
+            gdb.write('%s    alias: %s@%016x (@ %s)\n' %
+                      ('  ' * level,
+                       alias['name'].string(),
+                       ptr['alias_offset'],
+                       alias,
+                       ),
+                      gdb.STDOUT)
+            self.queue.append(alias)
+        subregion = ptr['subregions']['tqh_first']
+        level += 1
+        while not isnull(subregion):
+            self.print_item(subregion, addr, level)
+            subregion = subregion['subregions_link']['tqe_next']
+
+QemuCommand()
+MtreeCommand()
commit d56de074698662b102a1901e3bae425f8e4945bf
Author: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Date:   Fri Mar 23 11:37:25 2012 +0000

    xen_disk: when using AIO flush after the operation is completed
    
    If ioreq->postsync call bdrv_flush when the AIO operation is actually
    completed.
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 0f265a4..9cb0253 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -330,6 +330,9 @@ static void qemu_aio_complete(void *opaque, int ret)
     if (ioreq->aio_inflight > 0) {
         return;
     }
+    if (ioreq->postsync) {
+        bdrv_flush(ioreq->blkdev->bs);
+    }
 
     ioreq->status = ioreq->aio_errors ? BLKIF_RSP_ERROR : BLKIF_RSP_OKAY;
     ioreq_unmap(ioreq);
@@ -376,9 +379,6 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
         goto err;
     }
 
-    if (ioreq->postsync) {
-        bdrv_flush(blkdev->bs); /* FIXME: aio_flush() ??? */
-    }
     qemu_aio_complete(ioreq, 0);
 
     return 0;
commit 820914103ca55c0eb7ecf6f458f18cb7989f439e
Author: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Date:   Fri Mar 23 11:39:51 2012 +0000

    xen_disk: open disk with BDRV_O_NOCACHE | BDRV_O_CACHE_WB | BDRV_O_NATIVE_AIO
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 68fa36a..0f265a4 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -584,10 +584,10 @@ static int blk_init(struct XenDevice *xendev)
     }
 
     /* read-only ? */
+    qflags = BDRV_O_NOCACHE | BDRV_O_CACHE_WB | BDRV_O_NATIVE_AIO;
     if (strcmp(blkdev->mode, "w") == 0) {
-        qflags = BDRV_O_RDWR;
+        qflags |= BDRV_O_RDWR;
     } else {
-        qflags = 0;
         info  |= VDISK_READONLY;
     }
 
commit a13ccc991a852cf12f2c05f537c40ce239ae464f
Author: Alon Levy <alevy at redhat.com>
Date:   Wed Mar 21 18:17:18 2012 +0200

    ui/spice-display: use uintptr_t when casting qxl physical addresses
    
    The current intptr_t casts are a problem when the address's highest
    bit is 1, and it is cast to a intptr_t and then to uint64_t, such
    as at:
         surface.mem        = (intptr_t)ssd->buf;
    
    This causes the sign bit to be extended which causes a wrong address to
    be passed on to spice, which then complains when it gets the wrong
    slot_id number, since the slot_id is taken from the higher bits.
    
    The assertion happens early - during the first primary surface creation.
    
    This fixes running "-vga qxl -spice" with 32 bit compiled
    qemu-system-i386.
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/spice-display.c b/ui/spice-display.c
index 6d7563f..cb8a7ad 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -168,7 +168,7 @@ static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
     drawable->bbox            = ssd->dirty;
     drawable->clip.type       = SPICE_CLIP_TYPE_NONE;
     drawable->effect          = QXL_EFFECT_OPAQUE;
-    drawable->release_info.id = (intptr_t)update;
+    drawable->release_info.id = (uintptr_t)update;
     drawable->type            = QXL_DRAW_COPY;
     drawable->surfaces_dest[0] = -1;
     drawable->surfaces_dest[1] = -1;
@@ -179,7 +179,7 @@ static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
                       + time_space.tv_nsec / 1000 / 1000;
 
     drawable->u.copy.rop_descriptor  = SPICE_ROPD_OP_PUT;
-    drawable->u.copy.src_bitmap      = (intptr_t)image;
+    drawable->u.copy.src_bitmap      = (uintptr_t)image;
     drawable->u.copy.src_area.right  = bw;
     drawable->u.copy.src_area.bottom = bh;
 
@@ -189,7 +189,7 @@ static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
     image->bitmap.stride     = bw * 4;
     image->descriptor.width  = image->bitmap.x = bw;
     image->descriptor.height = image->bitmap.y = bh;
-    image->bitmap.data = (intptr_t)(update->bitmap);
+    image->bitmap.data = (uintptr_t)(update->bitmap);
     image->bitmap.palette = 0;
     image->bitmap.format = SPICE_BITMAP_FMT_32BIT;
 
@@ -210,7 +210,7 @@ static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
     }
 
     cmd->type = QXL_CMD_DRAW;
-    cmd->data = (intptr_t)drawable;
+    cmd->data = (uintptr_t)drawable;
 
     memset(&ssd->dirty, 0, sizeof(ssd->dirty));
     return update;
@@ -254,7 +254,7 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
     surface.mouse_mode = true;
     surface.flags      = 0;
     surface.type       = 0;
-    surface.mem        = (intptr_t)ssd->buf;
+    surface.mem        = (uintptr_t)ssd->buf;
     surface.group_id   = MEMSLOT_GROUP_HOST;
 
     qemu_spice_create_primary_surface(ssd, 0, &surface, QXL_SYNC);
commit 34d14c6d8c7af0d2457cf5730fe5a65a878c509d
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Mar 7 13:36:48 2012 +0000

    ui/spice-display.c: Fix compilation warnings on 32 bit hosts
    
    Fix compilation failures ("cast from pointer to integer of
    different size [-Werror=pointer-to-int-cast]") by using
    uintptr_t instead.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/spice-display.c b/ui/spice-display.c
index 28d6d4a..6d7563f 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -80,8 +80,8 @@ void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot,
 
     if (async != QXL_SYNC) {
         spice_qxl_add_memslot_async(&ssd->qxl, memslot,
-                (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
-                                         QXL_IO_MEMSLOT_ADD_ASYNC));
+                (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+                                          QXL_IO_MEMSLOT_ADD_ASYNC));
     } else {
         ssd->worker->add_memslot(ssd->worker, memslot);
     }
@@ -100,8 +100,8 @@ void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id,
     trace_qemu_spice_create_primary_surface(ssd->qxl.id, id, surface, async);
     if (async != QXL_SYNC) {
         spice_qxl_create_primary_surface_async(&ssd->qxl, id, surface,
-                (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
-                                         QXL_IO_CREATE_PRIMARY_ASYNC));
+                (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+                                          QXL_IO_CREATE_PRIMARY_ASYNC));
     } else {
         ssd->worker->create_primary_surface(ssd->worker, id, surface);
     }
@@ -113,8 +113,8 @@ void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd,
     trace_qemu_spice_destroy_primary_surface(ssd->qxl.id, id, async);
     if (async != QXL_SYNC) {
         spice_qxl_destroy_primary_surface_async(&ssd->qxl, id,
-                (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
-                                         QXL_IO_DESTROY_PRIMARY_ASYNC));
+                (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+                                          QXL_IO_DESTROY_PRIMARY_ASYNC));
     } else {
         ssd->worker->destroy_primary_surface(ssd->worker, id);
     }
commit b9f9be88385e9ab51d4163bfd66f015f14f56286
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Mar 10 16:58:35 2012 +0000

    memory: print aliased IO ranges in info mtree
    
    Print also I/O ports behind bridges and other aliases.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/memory.c b/memory.c
index 22b0352..a3f5b59 100644
--- a/memory.c
+++ b/memory.c
@@ -1621,6 +1621,13 @@ void mtree_info(fprintf_function mon_printf, void *f)
     mon_printf(f, "memory\n");
     mtree_print_mr(mon_printf, f, address_space_memory.root, 0, 0, &ml_head);
 
+    if (address_space_io.root &&
+        !QTAILQ_EMPTY(&address_space_io.root->subregions)) {
+        mon_printf(f, "I/O\n");
+        mtree_print_mr(mon_printf, f, address_space_io.root, 0, 0, &ml_head);
+    }
+
+    mon_printf(f, "aliases\n");
     /* print aliased regions */
     QTAILQ_FOREACH(ml, &ml_head, queue) {
         if (!ml->printed) {
@@ -1632,11 +1639,4 @@ void mtree_info(fprintf_function mon_printf, void *f)
     QTAILQ_FOREACH_SAFE(ml, &ml_head, queue, ml2) {
         g_free(ml);
     }
-
-    if (address_space_io.root &&
-        !QTAILQ_EMPTY(&address_space_io.root->subregions)) {
-        QTAILQ_INIT(&ml_head);
-        mon_printf(f, "I/O\n");
-        mtree_print_mr(mon_printf, f, address_space_io.root, 0, 0, &ml_head);
-    }
 }
commit 4200872b37ee59b5432d010becaabf84709798c5
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Mar 10 16:57:10 2012 +0000

    ioport: use INT64_MAX for IO ranges
    
    Expression UINT64_MAX + 1 will make the range bigger than
    what can be represented with a 64 bit type. This would
    trigger an assert in int128_get64() after the next patch.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/ioport.c b/ioport.c
index 78a3b89..6e4ca0d 100644
--- a/ioport.c
+++ b/ioport.c
@@ -385,7 +385,7 @@ static void portio_list_add_1(PortioList *piolist,
      * rather than an offset relative to to start + off_low.
      */
     memory_region_init_io(region, ops, piolist->opaque, piolist->name,
-                          UINT64_MAX);
+                          INT64_MAX);
     memory_region_init_alias(alias, piolist->name,
                              region, start + off_low, off_high - off_low);
     memory_region_add_subregion(piolist->address_space,
commit ff71f2e8cacefae99179993204172bc65e4303df
Author: Jason Wang <jasowang at redhat.com>
Date:   Mon Mar 5 11:09:08 2012 +0800

    rtl8139: do the network/host communication only in normal operating mode
    
    According the spec, the card works in network/host communication mode only when
    both EEM1 and EEM0 are unset in 93C46 Command Register (normal op
    mode). So this patch check these bits before trying to receive packets.
    
    As some guest driver (such as linux, see cp_init_hw() in 8139cp.c)
    allocate rx ring after the recevier were enabled, this would cause our
    emulation codes tries to dma into guest memory when the rx descriptor
    is not properly configured. This patch fixes this.
    
    Signed-off-by: Jason Wang <jasowang at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index f3322ea..4d553a8 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -791,6 +791,9 @@ static int rtl8139_can_receive(VLANClientState *nc)
       return 1;
     if (!rtl8139_receiver_enabled(s))
       return 1;
+    /* network/host communication happens only in normal mode */
+    if ((s->Cfg9346 & Chip9346_op_mask) != Cfg9346_Normal)
+	return 0;
 
     if (rtl8139_cp_receiver_enabled(s)) {
         /* ??? Flow control not implemented in c+ mode.
@@ -833,6 +836,12 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
         return -1;
     }
 
+    /* check whether we are in normal mode */
+    if ((s->Cfg9346 & Chip9346_op_mask) != Cfg9346_Normal) {
+        DPRINTF("not in normal op mode\n");
+        return -1;
+    }
+
     /* XXX: check this */
     if (s->RxConfig & AcceptAllPhys) {
         /* promiscuous: receive all */
commit eb46c5eda7d8b38c1407dd55f67cf4a6aa3b7b23
Author: Jason Wang <jasowang at redhat.com>
Date:   Mon Mar 5 11:08:59 2012 +0800

    rtl8139: correctly check the opmode
    
    According to the spec, only when opmode is "Config. Register Write
    Enable" could driver write to CONFIG0,1,3,4 and bits 13,12,8 of BMCR.
    
    Currently, we allow modifying to those registers also when 8139 is in
    "Auto-load" mode and "93C46 (93C56) Programming" mode. This patch
    fixes this.
    
    Signed-off-by: Jason Wang <jasowang at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 5b608f5..f3322ea 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -332,8 +332,10 @@ enum CSCRBits {
 };
 
 enum Cfg9346Bits {
-    Cfg9346_Lock = 0x00,
-    Cfg9346_Unlock = 0xC0,
+    Cfg9346_Normal = 0x00,
+    Cfg9346_Autoload = 0x40,
+    Cfg9346_Programming = 0x80,
+    Cfg9346_ConfigWrite = 0xC0,
 };
 
 typedef enum {
@@ -1451,7 +1453,7 @@ static uint32_t rtl8139_IntrMitigate_read(RTL8139State *s)
 
 static int rtl8139_config_writable(RTL8139State *s)
 {
-    if (s->Cfg9346 & Cfg9346_Unlock)
+    if ((s->Cfg9346 & Chip9346_op_mask) == Cfg9346_ConfigWrite)
     {
         return 1;
     }
commit 7fc8d918b9674c3e9233d6d25da2457345d414a0
Author: Jason Wang <jasowang at redhat.com>
Date:   Mon Mar 5 11:08:50 2012 +0800

    net: move compute_mcast_idx() to net.h
    
    Reduce duplicated codes.
    
    Signed-off-by: Jason Wang <jasowang at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/eepro100.c b/hw/eepro100.c
index e3ba719..02e6f7e 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -322,33 +322,8 @@ static const uint16_t eepro100_mdi_mask[] = {
     0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
 };
 
-#define POLYNOMIAL 0x04c11db6
-
 static E100PCIDeviceInfo *eepro100_get_class(EEPRO100State *s);
 
-/* From FreeBSD */
-/* XXX: optimize */
-static unsigned compute_mcast_idx(const uint8_t * ep)
-{
-    uint32_t crc;
-    int carry, i, j;
-    uint8_t b;
-
-    crc = 0xffffffff;
-    for (i = 0; i < 6; i++) {
-        b = *ep++;
-        for (j = 0; j < 8; j++) {
-            carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
-            crc <<= 1;
-            b >>= 1;
-            if (carry) {
-                crc = ((crc ^ POLYNOMIAL) | carry);
-            }
-        }
-    }
-    return (crc & BITS(7, 2)) >> 2;
-}
-
 /* Read a 16 bit control/status (CSR) register. */
 static uint16_t e100_read_reg2(EEPRO100State *s, E100RegisterOffset addr)
 {
diff --git a/hw/ne2000.c b/hw/ne2000.c
index 71452e1..d02e60c 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -150,30 +150,6 @@ static void ne2000_update_irq(NE2000State *s)
     qemu_set_irq(s->irq, (isr != 0));
 }
 
-#define POLYNOMIAL 0x04c11db6
-
-/* From FreeBSD */
-/* XXX: optimize */
-static int compute_mcast_idx(const uint8_t *ep)
-{
-    uint32_t crc;
-    int carry, i, j;
-    uint8_t b;
-
-    crc = 0xffffffff;
-    for (i = 0; i < 6; i++) {
-        b = *ep++;
-        for (j = 0; j < 8; j++) {
-            carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
-            crc <<= 1;
-            b >>= 1;
-            if (carry)
-                crc = ((crc ^ POLYNOMIAL) | carry);
-        }
-    }
-    return (crc >> 26);
-}
-
 static int ne2000_buffer_full(NE2000State *s)
 {
     int avail, index, boundary;
diff --git a/hw/opencores_eth.c b/hw/opencores_eth.c
index 4c76969..350f731 100644
--- a/hw/opencores_eth.c
+++ b/hw/opencores_eth.c
@@ -351,31 +351,6 @@ static int open_eth_can_receive(VLANClientState *nc)
         (rx_desc(s)->len_flags & RXD_E);
 }
 
-#define POLYNOMIAL 0x04c11db6
-
-/* From FreeBSD */
-/* XXX: optimize */
-static unsigned compute_mcast_idx(const uint8_t *ep)
-{
-    uint32_t crc;
-    int carry, i, j;
-    uint8_t b;
-
-    crc = 0xffffffff;
-    for (i = 0; i < 6; i++) {
-        b = *ep++;
-        for (j = 0; j < 8; j++) {
-            carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
-            crc <<= 1;
-            b >>= 1;
-            if (carry) {
-                crc = ((crc ^ POLYNOMIAL) | carry);
-            }
-        }
-    }
-    return crc >> 26;
-}
-
 static ssize_t open_eth_receive(VLANClientState *nc,
         const uint8_t *buf, size_t size)
 {
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 1d5f78b..5b608f5 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -708,30 +708,6 @@ static void rtl8139_update_irq(RTL8139State *s)
     qemu_set_irq(s->dev.irq[0], (isr != 0));
 }
 
-#define POLYNOMIAL 0x04c11db6
-
-/* From FreeBSD */
-/* XXX: optimize */
-static int compute_mcast_idx(const uint8_t *ep)
-{
-    uint32_t crc;
-    int carry, i, j;
-    uint8_t b;
-
-    crc = 0xffffffff;
-    for (i = 0; i < 6; i++) {
-        b = *ep++;
-        for (j = 0; j < 8; j++) {
-            carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
-            crc <<= 1;
-            b >>= 1;
-            if (carry)
-                crc = ((crc ^ POLYNOMIAL) | carry);
-        }
-    }
-    return (crc >> 26);
-}
-
 static int rtl8139_RxWrap(RTL8139State *s)
 {
     /* wrapping enabled; assume 1.5k more buffer space if size < 65536 */
diff --git a/net.c b/net.c
index c34474f..1922d8a 100644
--- a/net.c
+++ b/net.c
@@ -1475,3 +1475,26 @@ int net_client_parse(QemuOptsList *opts_list, const char *optarg)
     default_net = 0;
     return 0;
 }
+
+/* From FreeBSD */
+/* XXX: optimize */
+unsigned compute_mcast_idx(const uint8_t *ep)
+{
+    uint32_t crc;
+    int carry, i, j;
+    uint8_t b;
+
+    crc = 0xffffffff;
+    for (i = 0; i < 6; i++) {
+        b = *ep++;
+        for (j = 0; j < 8; j++) {
+            carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
+            crc <<= 1;
+            b >>= 1;
+            if (carry) {
+                crc = ((crc ^ POLYNOMIAL) | carry);
+            }
+        }
+    }
+    return crc >> 26;
+}
diff --git a/net.h b/net.h
index 75a8c15..64993b4 100644
--- a/net.h
+++ b/net.h
@@ -182,6 +182,9 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd);
 
 int net_handle_fd_param(Monitor *mon, const char *param);
 
+#define POLYNOMIAL 0x04c11db6
+unsigned compute_mcast_idx(const uint8_t *ep);
+
 #define vmstate_offset_macaddr(_state, _field)                       \
     vmstate_offset_array(_state, _field.a, uint8_t,                \
                          sizeof(typeof_field(_state, _field)))
commit afe0a595356192d5f79703cf6462fcc112df007c
Author: Jason Wang <jasowang at redhat.com>
Date:   Mon Mar 5 11:08:42 2012 +0800

    rtl8139: support byte read to TxStatus registers
    
    Some drivers (such as win7) use byte read for TxStatus registers, so we need to
    support this to let guest driver behave correctly.
    
    For writing, only double-word access is allowed by spec.
    
    Signed-off-by: Jason Wang <jasowang at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index ccbde27..1d5f78b 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -2495,11 +2495,30 @@ static void rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32
     rtl8139_transmit(s);
 }
 
-static uint32_t rtl8139_TxStatus_read(RTL8139State *s, uint32_t txRegOffset)
+static uint32_t rtl8139_TxStatus_read(RTL8139State *s, uint8_t addr, int size)
 {
-    uint32_t ret = s->TxStatus[txRegOffset/4];
+    uint32_t reg = (addr - TxStatus0) / 4;
+    uint32_t offset = addr & 0x3;
+    uint32_t ret = 0;
+
+    if (addr & (size - 1)) {
+        DPRINTF("not implemented read for TxStatus addr=0x%x size=0x%x\n", addr,
+                size);
+        return ret;
+    }
 
-    DPRINTF("TxStatus read offset=0x%x val=0x%08x\n", txRegOffset, ret);
+    switch (size) {
+    case 1: /* fall through */
+    case 2: /* fall through */
+    case 4:
+        ret = (s->TxStatus[reg] >> offset * 8) & ((1 << (size * 8)) - 1);
+        DPRINTF("TxStatus[%d] read addr=0x%x size=0x%x val=0x%08x\n", reg, addr,
+                size, ret);
+        break;
+    default:
+        DPRINTF("unsupported size 0x%x of TxStatus reading\n", size);
+        break;
+    }
 
     return ret;
 }
@@ -2970,6 +2989,9 @@ static uint32_t rtl8139_io_readb(void *opaque, uint8_t addr)
         case MAR0 ... MAR0+7:
             ret = s->mult[addr - MAR0];
             break;
+        case TxStatus0 ... TxStatus0+4*4-1:
+            ret = rtl8139_TxStatus_read(s, addr, 1);
+            break;
         case ChipCmd:
             ret = rtl8139_ChipCmd_read(s);
             break;
@@ -3033,6 +3055,9 @@ static uint32_t rtl8139_io_readw(void *opaque, uint8_t addr)
 
     switch (addr)
     {
+        case TxAddr0 ... TxAddr0+4*4-1:
+            ret = rtl8139_TxStatus_read(s, addr, 2);
+            break;
         case IntrMask:
             ret = rtl8139_IntrMask_read(s);
             break;
@@ -3123,7 +3148,7 @@ static uint32_t rtl8139_io_readl(void *opaque, uint8_t addr)
             break;
 
         case TxStatus0 ... TxStatus0+4*4-1:
-            ret = rtl8139_TxStatus_read(s, addr-TxStatus0);
+            ret = rtl8139_TxStatus_read(s, addr, 4);
             break;
 
         case TxAddr0 ... TxAddr0+4*4-1:
commit b44ce451df7840a0c5dea784673529994bbe1b32
Author: Jason Wang <jasowang at redhat.com>
Date:   Mon Mar 5 11:08:33 2012 +0800

    rtl8139: remove unused marco
    
    Signed-off-by: Jason Wang <jasowang at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index be4bc6a..ccbde27 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -65,9 +65,6 @@
 
 #define PCI_FREQUENCY 33000000L
 
-/* debug RTL8139 card C+ mode only */
-//#define DEBUG_RTL8139CP 1
-
 #define SET_MASKED(input, mask, curr) \
     ( ( (input) & ~(mask) ) | ( (curr) & (mask) ) )
 
commit cde31a0e3dc0e4ac83e454d6096350cec584adf1
Author: Jason Wang <jasowang at redhat.com>
Date:   Wed Mar 7 11:17:48 2012 +0800

    rtl8139: limit transmission buffer size in c+ mode
    
    The tx buffer would be re-allocated for tx descriptor with big size
    and without LS bit set, this would make guest driver could easily let
    qemu to allocate unlimited.
    
    In linux host, a glib failure were easy to be triggered:
    
    GLib-ERROR **: gmem.c:176: failed to allocate 18446744071562067968 bytes
    
    This patch fix this by adding a limit. As the spec didn't tell the maximum size
    of buffer allowed, stick it to current CP_TX_BUFFER_SIZE (65536).
    
    Changes from V1:
    
    Drop the while statement and s->cplus_txbuffer check.
    
    Signed-off-by: Jason Wang <jasowang at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 05b8e1e..be4bc6a 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -2061,13 +2061,12 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
             s->cplus_txbuffer_len);
     }
 
-    while (s->cplus_txbuffer && s->cplus_txbuffer_offset + txsize >= s->cplus_txbuffer_len)
+    if (s->cplus_txbuffer_offset + txsize >= s->cplus_txbuffer_len)
     {
-        s->cplus_txbuffer_len += CP_TX_BUFFER_SIZE;
-        s->cplus_txbuffer = g_realloc(s->cplus_txbuffer, s->cplus_txbuffer_len);
-
-        DPRINTF("+++ C+ mode transmission buffer space changed to %d\n",
-            s->cplus_txbuffer_len);
+        /* The spec didn't tell the maximum size, stick to CP_TX_BUFFER_SIZE */
+        txsize = s->cplus_txbuffer_len - s->cplus_txbuffer_offset;
+        DPRINTF("+++ C+ mode transmission buffer overrun, truncated descriptor"
+                "length to %d\n", txsize);
     }
 
     if (!s->cplus_txbuffer)
commit 453058d3e7111632b795c85f7d3bb36df25d5beb
Author: Anthony PERARD <anthony.perard at citrix.com>
Date:   Fri Feb 17 17:08:37 2012 +0000

    pci_regs: Add PCI_EXP_TYPE_PCIE_BRIDGE
    
    Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci_regs.h b/hw/pci_regs.h
index 6b42515..56a404b 100644
--- a/hw/pci_regs.h
+++ b/hw/pci_regs.h
@@ -392,6 +392,7 @@
 #define  PCI_EXP_TYPE_UPSTREAM	0x5	/* Upstream Port */
 #define  PCI_EXP_TYPE_DOWNSTREAM 0x6	/* Downstream Port */
 #define  PCI_EXP_TYPE_PCI_BRIDGE 0x7	/* PCI/PCI-X Bridge */
+#define  PCI_EXP_TYPE_PCIE_BRIDGE 0x8   /* PCI/PCI-X to PCIE Bridge */
 #define  PCI_EXP_TYPE_RC_END	0x9	/* Root Complex Integrated Endpoint */
 #define  PCI_EXP_TYPE_RC_EC     0xa     /* Root Complex Event Collector */
 #define PCI_EXP_FLAGS_SLOT	0x0100	/* Slot implemented */
commit ca384784af5f472f0b94c9205f8c500c1b5a43b6
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Fri Mar 16 00:43:25 2012 +0200

    virtio-net: add DATA_VALID flag
    
    Add DATA_VALID flag from the Linux header, to
    keep us in sync with that.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/virtio-net.h b/hw/virtio-net.h
index 4468741..36aa463 100644
--- a/hw/virtio-net.h
+++ b/hw/virtio-net.h
@@ -79,6 +79,7 @@ struct virtio_net_config
 struct virtio_net_hdr
 {
 #define VIRTIO_NET_HDR_F_NEEDS_CSUM     1       // Use csum_start, csum_offset
+#define VIRTIO_NET_HDR_F_DATA_VALID	2	// Csum is valid
     uint8_t flags;
 #define VIRTIO_NET_HDR_GSO_NONE         0       // Not a GSO frame
 #define VIRTIO_NET_HDR_GSO_TCPV4        1       // GSO frame, IPv4 TCP (TSO)
commit cd7898f714773f7a317b122eaa45e701fd4f9849
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Sun Mar 4 15:35:29 2012 +0200

    pci_bridge: upper 32 bit are long registers
    
    Use pci_set_long for accesses.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci_bridge.c b/hw/pci_bridge.c
index eeee8a6..866f0b6 100644
--- a/hw/pci_bridge.c
+++ b/hw/pci_bridge.c
@@ -249,8 +249,8 @@ void pci_bridge_disable_base_limit(PCIDevice *dev)
                                PCI_PREF_RANGE_MASK & 0xffff);
     pci_word_test_and_clear_mask(conf + PCI_PREF_MEMORY_LIMIT,
                                  PCI_PREF_RANGE_MASK & 0xffff);
-    pci_set_word(conf + PCI_PREF_BASE_UPPER32, 0);
-    pci_set_word(conf + PCI_PREF_LIMIT_UPPER32, 0);
+    pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0);
+    pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0);
 }
 
 /* reset bridge specific configuration registers */
@@ -285,8 +285,8 @@ void pci_bridge_reset_reg(PCIDevice *dev)
                                  PCI_PREF_RANGE_MASK & 0xffff);
     pci_word_test_and_clear_mask(conf + PCI_PREF_MEMORY_LIMIT,
                                  PCI_PREF_RANGE_MASK & 0xffff);
-    pci_set_word(conf + PCI_PREF_BASE_UPPER32, 0);
-    pci_set_word(conf + PCI_PREF_LIMIT_UPPER32, 0);
+    pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0);
+    pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0);
 
     pci_set_word(conf + PCI_BRIDGE_CONTROL, 0);
 }
commit 68917102740d9aa96c8f3ed4b95eab9917e8c61b
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Sun Mar 4 11:36:35 2012 +0200

    pci: fix bridge IO/BASE
    
    commit 5caef97a16010f818ea8b950e2ee24ba876643ad introduced
    a regression: we do not make IO base/limit upper 16
    bit registers writeable, so we should report a 16 bit
    IO range type, not a 32 bit one.
    Note that PCI_PREF_RANGE_TYPE_32 is 0x0, but PCI_IO_RANGE_TYPE_32 is 0x1.
    
    In particular, this broke sparc64.
    
    Note: this just reverts to behaviour prior to the commit above.
    Making PCI_IO_BASE_UPPER16 and PCI_IO_LIMIT_UPPER16
    registers writeable should, and seems to, work just as well, but
    as no system seems to actually be interested in 32 bit IO,
    let's not make unnecessary changes.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci.c b/hw/pci.c
index fee27fc..6d08cef 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -633,8 +633,8 @@ static void pci_init_mask_bridge(PCIDevice *d)
     memset(d->wmask + PCI_PREF_BASE_UPPER32, 0xff, 8);
 
     /* Supported memory and i/o types */
-    d->config[PCI_IO_BASE] |= PCI_IO_RANGE_TYPE_32;
-    d->config[PCI_IO_LIMIT] |= PCI_IO_RANGE_TYPE_32;
+    d->config[PCI_IO_BASE] |= PCI_IO_RANGE_TYPE_16;
+    d->config[PCI_IO_LIMIT] |= PCI_IO_RANGE_TYPE_16;
     pci_word_test_and_set_mask(d->config + PCI_PREF_MEMORY_BASE,
                                PCI_PREF_RANGE_TYPE_64);
     pci_word_test_and_set_mask(d->config + PCI_PREF_MEMORY_LIMIT,
commit 633442ff56909214576549d34f5be1f50a67c5a6
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Tue Feb 21 15:58:59 2012 +0200

    pcie: drop functionality moved to core
    
    Now that core sets memory type correctly,
    remove this code from pcie port implementation.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pcie_port.c b/hw/pcie_port.c
index 8a36f5c..d6350e5 100644
--- a/hw/pcie_port.c
+++ b/hw/pcie_port.c
@@ -27,23 +27,13 @@ void pcie_port_init_reg(PCIDevice *d)
     pci_set_word(d->config + PCI_STATUS, 0);
     pci_set_word(d->config + PCI_SEC_STATUS, 0);
 
-    /* Unlike conventional pci bridge, some bits are hardwared to 0. */
+    /* Unlike conventional pci bridge, some bits are hardwired to 0. */
     pci_set_word(d->wmask + PCI_BRIDGE_CONTROL,
                  PCI_BRIDGE_CTL_PARITY |
                  PCI_BRIDGE_CTL_ISA |
                  PCI_BRIDGE_CTL_VGA |
                  PCI_BRIDGE_CTL_SERR |
                  PCI_BRIDGE_CTL_BUS_RESET);
-
-    /* 7.5.3.5 Prefetchable Memory Base Limit
-     * The Prefetchable Memory Base and Prefetchable Memory Limit registers
-     * must indicate that 64-bit addresses are supported, as defined in
-     * PCI-to-PCI Bridge Architecture Specification, Revision 1.2.
-     */
-    pci_word_test_and_set_mask(d->config + PCI_PREF_MEMORY_BASE,
-                               PCI_PREF_RANGE_TYPE_64);
-    pci_word_test_and_set_mask(d->config + PCI_PREF_MEMORY_LIMIT,
-                               PCI_PREF_RANGE_TYPE_64);
 }
 
 /**************************************************************************
commit 15ab7a75335108c76700bea67602017fe305350d
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Tue Feb 21 15:49:01 2012 +0200

    pci: set memory type for memory behind the bridge
    
    As we make upper bits in IO and prefetcheable memory
    registers writeable, we should declare support
    for 64 bit prefetcheable memory and 32 bit io
    in the bridge.
    
    This changes the default for apb, dec, but I'm guessing
    they got the defaults wrong by accident.
    Alternatively, we could let bridges declare lack of
    64 bit support and make the upper bits read-only zero.
    
    Reported-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci.c b/hw/pci.c
index 3ca5f4c..fee27fc 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -663,8 +663,11 @@ static void pci_init_mask_bridge(PCIDevice *d)
     pci_set_word(d->w1cmask + PCI_BRIDGE_CONTROL,
                  PCI_BRIDGE_CTL_DISCARD_STATUS);
     d->cmask[PCI_IO_BASE] |= PCI_IO_RANGE_TYPE_MASK;
+    d->cmask[PCI_IO_LIMIT] |= PCI_IO_RANGE_TYPE_MASK;
     pci_word_test_and_set_mask(d->cmask + PCI_PREF_MEMORY_BASE,
                                PCI_PREF_RANGE_TYPE_MASK);
+    pci_word_test_and_set_mask(d->cmask + PCI_PREF_MEMORY_LIMIT,
+                               PCI_PREF_RANGE_TYPE_MASK);
 }
 
 static int pci_init_multifunction(PCIBus *bus, PCIDevice *dev)
commit 4eb812f7603f57dc63f6b74e3c464a60ed5bc91b
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Sun Jul 3 16:00:09 2011 +0300

    pci: add standard bridge device
    
    This adds support for a standard pci to pci bridge,
    enabling support for more than 32 PCI devices in the system.
    Device hotplug is supported by means of SHPC controller.
    For guests with an SHPC driver, this allows robust hotplug
    and even hotplug of nested bridges, up to 31 devices
    per bridge.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index 5b97871..25400e9 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -213,7 +213,7 @@ hw-obj-$(CONFIG_VIRTIO) += virtio-console.o
 hw-obj-y += usb/libhw.o
 hw-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
 hw-obj-y += fw_cfg.o
-hw-obj-$(CONFIG_PCI) += pci.o pci_bridge.o
+hw-obj-$(CONFIG_PCI) += pci.o pci_bridge.o pci_bridge_dev.o
 hw-obj-$(CONFIG_PCI) += msix.o msi.o
 hw-obj-$(CONFIG_PCI) += shpc.o
 hw-obj-$(CONFIG_PCI) += slotid_cap.o
diff --git a/hw/pci_bridge_dev.c b/hw/pci_bridge_dev.c
new file mode 100644
index 0000000..eccaa58
--- /dev/null
+++ b/hw/pci_bridge_dev.c
@@ -0,0 +1,174 @@
+/*
+ * Standard PCI Bridge Device
+ *
+ * Copyright (c) 2011 Red Hat Inc. Author: Michael S. Tsirkin <mst at redhat.com>
+ *
+ * http://www.pcisig.com/specifications/conventional/pci_to_pci_bridge_architecture/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "pci_bridge.h"
+#include "pci_ids.h"
+#include "msi.h"
+#include "shpc.h"
+#include "slotid_cap.h"
+#include "memory.h"
+#include "pci_internals.h"
+
+#define REDHAT_PCI_VENDOR_ID 0x1b36
+#define PCI_BRIDGE_DEV_VENDOR_ID REDHAT_PCI_VENDOR_ID
+#define PCI_BRIDGE_DEV_DEVICE_ID 0x1
+
+struct PCIBridgeDev {
+    PCIBridge bridge;
+    MemoryRegion bar;
+    uint8_t chassis_nr;
+#define PCI_BRIDGE_DEV_F_MSI_REQ 0
+    uint32_t flags;
+};
+typedef struct PCIBridgeDev PCIBridgeDev;
+
+/* Mapping mandated by PCI-to-PCI Bridge architecture specification,
+ * revision 1.2 */
+/* Table 9-1: Interrupt Binding for Devices Behind a Bridge */
+static int pci_bridge_dev_map_irq_fn(PCIDevice *dev, int irq_num)
+{
+    return (irq_num + PCI_SLOT(dev->devfn)) % PCI_NUM_PINS;
+}
+
+static int pci_bridge_dev_initfn(PCIDevice *dev)
+{
+    PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
+    PCIBridgeDev *bridge_dev = DO_UPCAST(PCIBridgeDev, bridge, br);
+    int err;
+    pci_bridge_map_irq(br, NULL, pci_bridge_dev_map_irq_fn);
+    err = pci_bridge_initfn(dev);
+    if (err) {
+        goto bridge_error;
+    }
+    memory_region_init(&bridge_dev->bar, "shpc-bar", shpc_bar_size(dev));
+    err = shpc_init(dev, &br->sec_bus, &bridge_dev->bar, 0);
+    if (err) {
+        goto shpc_error;
+    }
+    err = slotid_cap_init(dev, 0, bridge_dev->chassis_nr, 0);
+    if (err) {
+        goto slotid_error;
+    }
+    if ((bridge_dev->flags & (1 << PCI_BRIDGE_DEV_F_MSI_REQ)) &&
+        msi_supported) {
+        err = msi_init(dev, 0, 1, true, true);
+        if (err < 0) {
+            goto msi_error;
+        }
+    }
+    /* TODO: spec recommends using 64 bit prefetcheable BAR.
+     * Check whether that works well. */
+    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
+		     PCI_BASE_ADDRESS_MEM_TYPE_64, &bridge_dev->bar);
+    dev->config[PCI_INTERRUPT_PIN] = 0x1;
+    return 0;
+msi_error:
+    slotid_cap_cleanup(dev);
+slotid_error:
+    shpc_cleanup(dev, &bridge_dev->bar);
+shpc_error:
+    memory_region_destroy(&bridge_dev->bar);
+bridge_error:
+    return err;
+}
+
+static int pci_bridge_dev_exitfn(PCIDevice *dev)
+{
+    PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
+    PCIBridgeDev *bridge_dev = DO_UPCAST(PCIBridgeDev, bridge, br);
+    int ret;
+    if (msi_present(dev)) {
+        msi_uninit(dev);
+    }
+    slotid_cap_cleanup(dev);
+    shpc_cleanup(dev, &bridge_dev->bar);
+    memory_region_destroy(&bridge_dev->bar);
+    ret = pci_bridge_exitfn(dev);
+    assert(!ret);
+    return 0;
+}
+
+static void pci_bridge_dev_write_config(PCIDevice *d,
+                                        uint32_t address, uint32_t val, int len)
+{
+    pci_bridge_write_config(d, address, val, len);
+    if (msi_present(d)) {
+        msi_write_config(d, address, val, len);
+    }
+    shpc_cap_write_config(d, address, val, len);
+}
+
+static void qdev_pci_bridge_dev_reset(DeviceState *qdev)
+{
+    PCIDevice *dev = DO_UPCAST(PCIDevice, qdev, qdev);
+    pci_bridge_reset(qdev);
+    if (msi_present(dev)) {
+        msi_reset(dev);
+    }
+    shpc_reset(dev);
+}
+
+static Property pci_bridge_dev_properties[] = {
+                    /* Note: 0 is not a legal chassis number. */
+    DEFINE_PROP_UINT8("chassis_nr", PCIBridgeDev, chassis_nr, 0),
+    DEFINE_PROP_BIT("msi", PCIBridgeDev, flags, PCI_BRIDGE_DEV_F_MSI_REQ, true),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static const VMStateDescription pci_bridge_dev_vmstate = {
+    .name = "pci_bridge",
+    .fields = (VMStateField[]) {
+        VMSTATE_PCI_DEVICE(bridge.dev, PCIBridgeDev),
+        SHPC_VMSTATE(bridge.dev.shpc, PCIBridgeDev),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void pci_bridge_dev_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+    k->init = pci_bridge_dev_initfn;
+    k->exit = pci_bridge_dev_exitfn;
+    k->config_write = pci_bridge_dev_write_config;
+    k->vendor_id = PCI_BRIDGE_DEV_VENDOR_ID;
+    k->device_id = PCI_BRIDGE_DEV_DEVICE_ID;
+    k->class_id = PCI_CLASS_BRIDGE_PCI;
+    k->is_bridge = 1,
+    dc->desc = "Standard PCI Bridge";
+    dc->reset = qdev_pci_bridge_dev_reset;
+    dc->props = pci_bridge_dev_properties;
+    dc->vmsd = &pci_bridge_dev_vmstate;
+}
+
+static TypeInfo pci_bridge_dev_info = {
+    .name = "pci-bridge",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCIBridgeDev),
+    .class_init = pci_bridge_dev_class_init,
+};
+
+static void pci_bridge_dev_register(void)
+{
+    type_register_static(&pci_bridge_dev_info);
+}
+
+type_init(pci_bridge_dev_register);
commit 762833b3b88b7b79af442439a8b138a04786ec3d
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Wed Feb 15 19:17:59 2012 +0200

    slotid: add slot id capability
    
    This capability makes it possible for the guest to
    report a unique chassis identifier to the user.
    
    The spec also recommends making chassis indentifier
    persist in eeprom.
    This isn't implemented.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index 1e8034c..5b97871 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -216,6 +216,7 @@ hw-obj-y += fw_cfg.o
 hw-obj-$(CONFIG_PCI) += pci.o pci_bridge.o
 hw-obj-$(CONFIG_PCI) += msix.o msi.o
 hw-obj-$(CONFIG_PCI) += shpc.o
+hw-obj-$(CONFIG_PCI) += slotid_cap.o
 hw-obj-$(CONFIG_PCI) += pci_host.o pcie_host.o
 hw-obj-$(CONFIG_PCI) += ioh3420.o xio3130_upstream.o xio3130_downstream.o
 hw-obj-y += watchdog.o
diff --git a/hw/pci.h b/hw/pci.h
index dc4d9d1..8d0aa49 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -129,6 +129,8 @@ enum {
     /* Standard hot plug controller. */
 #define QEMU_PCI_SHPC_BITNR 5
     QEMU_PCI_CAP_SHPC = (1 << QEMU_PCI_SHPC_BITNR),
+#define QEMU_PCI_SLOTID_BITNR 6
+    QEMU_PCI_CAP_SLOTID = (1 << QEMU_PCI_SLOTID_BITNR),
 };
 
 #define TYPE_PCI_DEVICE "pci-device"
diff --git a/hw/slotid_cap.c b/hw/slotid_cap.c
new file mode 100644
index 0000000..0106452
--- /dev/null
+++ b/hw/slotid_cap.c
@@ -0,0 +1,44 @@
+#include "slotid_cap.h"
+#include "pci.h"
+
+#define SLOTID_CAP_LENGTH 4
+#define SLOTID_NSLOTS_SHIFT (ffs(PCI_SID_ESR_NSLOTS) - 1)
+
+int slotid_cap_init(PCIDevice *d, int nslots,
+                    uint8_t chassis,
+                    unsigned offset)
+{
+    int cap;
+    if (!chassis) {
+        error_report("Bridge chassis not specified. Each bridge is required "
+                     "to be assigned a unique chassis id > 0.");
+        return -EINVAL;
+    }
+    if (nslots < 0 || nslots > (PCI_SID_ESR_NSLOTS >> SLOTID_NSLOTS_SHIFT)) {
+        /* TODO: error report? */
+        return -EINVAL;
+    }
+
+    cap = pci_add_capability(d, PCI_CAP_ID_SLOTID, offset, SLOTID_CAP_LENGTH);
+    if (cap < 0) {
+        return cap;
+    }
+    /* We make each chassis unique, this way each bridge is First in Chassis */
+    d->config[cap + PCI_SID_ESR] = PCI_SID_ESR_FIC |
+        (nslots << SLOTID_NSLOTS_SHIFT);
+    d->cmask[cap + PCI_SID_ESR] = 0xff;
+    d->config[cap + PCI_SID_CHASSIS_NR] = chassis;
+    /* Note: Chassis number register is non-volatile,
+       so we don't reset it. */
+    /* TODO: store in eeprom? */
+    d->wmask[cap + PCI_SID_CHASSIS_NR] = 0xff;
+
+    d->cap_present |= QEMU_PCI_CAP_SLOTID;
+    return 0;
+}
+
+void slotid_cap_cleanup(PCIDevice *d)
+{
+    /* TODO: cleanup config space? */
+    d->cap_present &= ~QEMU_PCI_CAP_SLOTID;
+}
diff --git a/hw/slotid_cap.h b/hw/slotid_cap.h
new file mode 100644
index 0000000..70db047
--- /dev/null
+++ b/hw/slotid_cap.h
@@ -0,0 +1,11 @@
+#ifndef PCI_SLOTID_CAP_H
+#define PCI_SLOTID_CAP_H
+
+#include "qemu-common.h"
+
+int slotid_cap_init(PCIDevice *dev, int nslots,
+                    uint8_t chassis,
+                    unsigned offset);
+void slotid_cap_cleanup(PCIDevice *dev);
+
+#endif
commit 1dc324d20f7404fd6a416f16c2cb9a4ec50a4dd7
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Sun Feb 12 14:12:21 2012 +0200

    shpc: standard hot plug controller
    
    This adds support for SHPC interface, as defined by PCI Standard
    Hot-Plug Controller and Subsystem Specification, Rev 1.0
    http://www.pcisig.com/specifications/conventional/pci_hot_plug/SHPC_10
    
    Only SHPC intergrated with a PCI-to-PCI bridge is supported,
    SHPC integrated with a host bridge would need more work.
    
    All main SHPC features are supported:
    - MRL sensor
    - Attention button
    - Attention indicator
    - Power indicator
    
    Wake on hotplug and serr generation are stubbed out but unused
    as we don't have interfaces to generate these events ATM.
    
    One issue that isn't completely resolved is that qemu currently
    expects an "eject" interface, which SHPC does not provide: it merely
    removes the power to device and it's up to the user to remove the device
    from slot. This patch works around that by ejecting the device
    when power is removed and power LED goes off.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index 226b01d..1e8034c 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -215,6 +215,7 @@ hw-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
 hw-obj-y += fw_cfg.o
 hw-obj-$(CONFIG_PCI) += pci.o pci_bridge.o
 hw-obj-$(CONFIG_PCI) += msix.o msi.o
+hw-obj-$(CONFIG_PCI) += shpc.o
 hw-obj-$(CONFIG_PCI) += pci_host.o pcie_host.o
 hw-obj-$(CONFIG_PCI) += ioh3420.o xio3130_upstream.o xio3130_downstream.o
 hw-obj-y += watchdog.o
diff --git a/hw/pci.h b/hw/pci.h
index 704d3f3..dc4d9d1 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -126,6 +126,9 @@ enum {
     /* command register SERR bit enabled */
 #define QEMU_PCI_CAP_SERR_BITNR 4
     QEMU_PCI_CAP_SERR = (1 << QEMU_PCI_CAP_SERR_BITNR),
+    /* Standard hot plug controller. */
+#define QEMU_PCI_SHPC_BITNR 5
+    QEMU_PCI_CAP_SHPC = (1 << QEMU_PCI_SHPC_BITNR),
 };
 
 #define TYPE_PCI_DEVICE "pci-device"
@@ -230,6 +233,9 @@ struct PCIDevice {
     /* PCI Express */
     PCIExpressDevice exp;
 
+    /* SHPC */
+    SHPCDevice *shpc;
+
     /* Location of option rom */
     char *romfile;
     bool has_rom;
diff --git a/hw/shpc.c b/hw/shpc.c
new file mode 100644
index 0000000..a5baf24
--- /dev/null
+++ b/hw/shpc.c
@@ -0,0 +1,681 @@
+#include <strings.h>
+#include <stdint.h>
+#include "range.h"
+#include "range.h"
+#include "shpc.h"
+#include "pci.h"
+#include "pci_internals.h"
+#include "msi.h"
+
+/* TODO: model power only and disabled slot states. */
+/* TODO: handle SERR and wakeups */
+/* TODO: consider enabling 66MHz support */
+
+/* TODO: remove fully only on state DISABLED and LED off.
+ * track state to properly record this. */
+
+/* SHPC Working Register Set */
+#define SHPC_BASE_OFFSET  0x00 /* 4 bytes */
+#define SHPC_SLOTS_33     0x04 /* 4 bytes. Also encodes PCI-X slots. */
+#define SHPC_SLOTS_66     0x08 /* 4 bytes. */
+#define SHPC_NSLOTS       0x0C /* 1 byte */
+#define SHPC_FIRST_DEV    0x0D /* 1 byte */
+#define SHPC_PHYS_SLOT    0x0E /* 2 byte */
+#define SHPC_PHYS_NUM_MAX 0x7ff
+#define SHPC_PHYS_NUM_UP  0x2000
+#define SHPC_PHYS_MRL     0x4000
+#define SHPC_PHYS_BUTTON  0x8000
+#define SHPC_SEC_BUS      0x10 /* 2 bytes */
+#define SHPC_SEC_BUS_33   0x0
+#define SHPC_SEC_BUS_66   0x1 /* Unused */
+#define SHPC_SEC_BUS_MASK 0x7
+#define SHPC_MSI_CTL      0x12 /* 1 byte */
+#define SHPC_PROG_IFC     0x13 /* 1 byte */
+#define SHPC_PROG_IFC_1_0 0x1
+#define SHPC_CMD_CODE     0x14 /* 1 byte */
+#define SHPC_CMD_TRGT     0x15 /* 1 byte */
+#define SHPC_CMD_TRGT_MIN 0x1
+#define SHPC_CMD_TRGT_MAX 0x1f
+#define SHPC_CMD_STATUS   0x16 /* 2 bytes */
+#define SHPC_CMD_STATUS_BUSY          0x1
+#define SHPC_CMD_STATUS_MRL_OPEN      0x2
+#define SHPC_CMD_STATUS_INVALID_CMD   0x4
+#define SHPC_CMD_STATUS_INVALID_MODE  0x8
+#define SHPC_INT_LOCATOR  0x18 /* 4 bytes */
+#define SHPC_INT_COMMAND  0x1
+#define SHPC_SERR_LOCATOR 0x1C /* 4 bytes */
+#define SHPC_SERR_INT     0x20 /* 4 bytes */
+#define SHPC_INT_DIS      0x1
+#define SHPC_SERR_DIS     0x2
+#define SHPC_CMD_INT_DIS  0x4
+#define SHPC_ARB_SERR_DIS 0x8
+#define SHPC_CMD_DETECTED 0x10000
+#define SHPC_ARB_DETECTED 0x20000
+ /* 4 bytes * slot # (start from 0) */
+#define SHPC_SLOT_REG(s)         (0x24 + (s) * 4)
+ /* 2 bytes */
+#define SHPC_SLOT_STATUS(s)       (0x0 + SHPC_SLOT_REG(s))
+
+/* Same slot state masks are used for command and status registers */
+#define SHPC_SLOT_STATE_MASK     0x03
+#define SHPC_SLOT_STATE_SHIFT \
+    (ffs(SHPC_SLOT_STATE_MASK) - 1)
+
+#define SHPC_STATE_NO       0x0
+#define SHPC_STATE_PWRONLY  0x1
+#define SHPC_STATE_ENABLED  0x2
+#define SHPC_STATE_DISABLED 0x3
+
+#define SHPC_SLOT_PWR_LED_MASK   0xC
+#define SHPC_SLOT_PWR_LED_SHIFT \
+    (ffs(SHPC_SLOT_PWR_LED_MASK) - 1)
+#define SHPC_SLOT_ATTN_LED_MASK  0x30
+#define SHPC_SLOT_ATTN_LED_SHIFT \
+    (ffs(SHPC_SLOT_ATTN_LED_MASK) - 1)
+
+#define SHPC_LED_NO     0x0
+#define SHPC_LED_ON     0x1
+#define SHPC_LED_BLINK  0x2
+#define SHPC_LED_OFF    0x3
+
+#define SHPC_SLOT_STATUS_PWR_FAULT      0x40
+#define SHPC_SLOT_STATUS_BUTTON         0x80
+#define SHPC_SLOT_STATUS_MRL_OPEN       0x100
+#define SHPC_SLOT_STATUS_66             0x200
+#define SHPC_SLOT_STATUS_PRSNT_MASK     0xC00
+#define SHPC_SLOT_STATUS_PRSNT_EMPTY    0x3
+#define SHPC_SLOT_STATUS_PRSNT_25W      0x1
+#define SHPC_SLOT_STATUS_PRSNT_15W      0x2
+#define SHPC_SLOT_STATUS_PRSNT_7_5W     0x0
+
+#define SHPC_SLOT_STATUS_PRSNT_PCIX     0x3000
+
+
+ /* 1 byte */
+#define SHPC_SLOT_EVENT_LATCH(s)        (0x2 + SHPC_SLOT_REG(s))
+ /* 1 byte */
+#define SHPC_SLOT_EVENT_SERR_INT_DIS(d, s) (0x3 + SHPC_SLOT_REG(s))
+#define SHPC_SLOT_EVENT_PRESENCE        0x01
+#define SHPC_SLOT_EVENT_ISOLATED_FAULT  0x02
+#define SHPC_SLOT_EVENT_BUTTON          0x04
+#define SHPC_SLOT_EVENT_MRL             0x08
+#define SHPC_SLOT_EVENT_CONNECTED_FAULT 0x10
+/* Bits below are used for Serr/Int disable only */
+#define SHPC_SLOT_EVENT_MRL_SERR_DIS    0x20
+#define SHPC_SLOT_EVENT_CONNECTED_FAULT_SERR_DIS 0x40
+
+#define SHPC_MIN_SLOTS        1
+#define SHPC_MAX_SLOTS        31
+#define SHPC_SIZEOF(d)    SHPC_SLOT_REG((d)->shpc->nslots)
+
+/* SHPC Slot identifiers */
+
+/* Hotplug supported at 31 slots out of the total 32.  We reserve slot 0,
+   and give the rest of them physical *and* pci numbers starting from 1, so
+   they match logical numbers.  Note: this means that multiple slots must have
+   different chassis number values, to make chassis+physical slot unique.
+   TODO: make this configurable? */
+#define SHPC_IDX_TO_LOGICAL(slot) ((slot) + 1)
+#define SHPC_LOGICAL_TO_IDX(target) ((target) - 1)
+#define SHPC_IDX_TO_PCI(slot) ((slot) + 1)
+#define SHPC_PCI_TO_IDX(pci_slot) ((pci_slot) - 1)
+#define SHPC_IDX_TO_PHYSICAL(slot) ((slot) + 1)
+
+static int roundup_pow_of_two(int x)
+{
+    x |= (x >> 1);
+    x |= (x >> 2);
+    x |= (x >> 4);
+    x |= (x >> 8);
+    x |= (x >> 16);
+    return x + 1;
+}
+
+static uint16_t shpc_get_status(SHPCDevice *shpc, int slot, uint16_t msk)
+{
+    uint8_t *status = shpc->config + SHPC_SLOT_STATUS(slot);
+    return (pci_get_word(status) & msk) >> (ffs(msk) - 1);
+}
+
+static void shpc_set_status(SHPCDevice *shpc,
+                            int slot, uint8_t value, uint16_t msk)
+{
+    uint8_t *status = shpc->config + SHPC_SLOT_STATUS(slot);
+    pci_word_test_and_clear_mask(status, msk);
+    pci_word_test_and_set_mask(status, value << (ffs(msk) - 1));
+}
+
+static void shpc_interrupt_update(PCIDevice *d)
+{
+    SHPCDevice *shpc = d->shpc;
+    int slot;
+    int level = 0;
+    uint32_t serr_int;
+    uint32_t int_locator = 0;
+
+    /* Update interrupt locator register */
+    for (slot = 0; slot < shpc->nslots; ++slot) {
+        uint8_t event = shpc->config[SHPC_SLOT_EVENT_LATCH(slot)];
+        uint8_t disable = shpc->config[SHPC_SLOT_EVENT_SERR_INT_DIS(d, slot)];
+        uint32_t mask = 1 << SHPC_IDX_TO_LOGICAL(slot);
+        if (event & ~disable) {
+            int_locator |= mask;
+        }
+    }
+    serr_int = pci_get_long(shpc->config + SHPC_SERR_INT);
+    if ((serr_int & SHPC_CMD_DETECTED) && !(serr_int & SHPC_CMD_INT_DIS)) {
+        int_locator |= SHPC_INT_COMMAND;
+    }
+    pci_set_long(shpc->config + SHPC_INT_LOCATOR, int_locator);
+    level = (!(serr_int & SHPC_INT_DIS) && int_locator) ? 1 : 0;
+    if (msi_enabled(d) && shpc->msi_requested != level)
+        msi_notify(d, 0);
+    else
+        qemu_set_irq(d->irq[0], level);
+    shpc->msi_requested = level;
+}
+
+static void shpc_set_sec_bus_speed(SHPCDevice *shpc, uint8_t speed)
+{
+    switch (speed) {
+    case SHPC_SEC_BUS_33:
+        shpc->config[SHPC_SEC_BUS] &= ~SHPC_SEC_BUS_MASK;
+        shpc->config[SHPC_SEC_BUS] |= speed;
+        break;
+    default:
+        pci_word_test_and_set_mask(shpc->config + SHPC_CMD_STATUS,
+                                   SHPC_CMD_STATUS_INVALID_MODE);
+    }
+}
+
+void shpc_reset(PCIDevice *d)
+{
+    SHPCDevice *shpc = d->shpc;
+    int nslots = shpc->nslots;
+    int i;
+    memset(shpc->config, 0, SHPC_SIZEOF(d));
+    pci_set_byte(shpc->config + SHPC_NSLOTS, nslots);
+    pci_set_long(shpc->config + SHPC_SLOTS_33, nslots);
+    pci_set_long(shpc->config + SHPC_SLOTS_66, 0);
+    pci_set_byte(shpc->config + SHPC_FIRST_DEV, SHPC_IDX_TO_PCI(0));
+    pci_set_word(shpc->config + SHPC_PHYS_SLOT,
+                 SHPC_IDX_TO_PHYSICAL(0) |
+                 SHPC_PHYS_NUM_UP |
+                 SHPC_PHYS_MRL |
+                 SHPC_PHYS_BUTTON);
+    pci_set_long(shpc->config + SHPC_SERR_INT, SHPC_INT_DIS |
+                 SHPC_SERR_DIS |
+                 SHPC_CMD_INT_DIS |
+                 SHPC_ARB_SERR_DIS);
+    pci_set_byte(shpc->config + SHPC_PROG_IFC, SHPC_PROG_IFC_1_0);
+    pci_set_word(shpc->config + SHPC_SEC_BUS, SHPC_SEC_BUS_33);
+    for (i = 0; i < shpc->nslots; ++i) {
+        pci_set_byte(shpc->config + SHPC_SLOT_EVENT_SERR_INT_DIS(d, i),
+                     SHPC_SLOT_EVENT_PRESENCE |
+                     SHPC_SLOT_EVENT_ISOLATED_FAULT |
+                     SHPC_SLOT_EVENT_BUTTON |
+                     SHPC_SLOT_EVENT_MRL |
+                     SHPC_SLOT_EVENT_CONNECTED_FAULT |
+                     SHPC_SLOT_EVENT_MRL_SERR_DIS |
+                     SHPC_SLOT_EVENT_CONNECTED_FAULT_SERR_DIS);
+        if (shpc->sec_bus->devices[PCI_DEVFN(SHPC_IDX_TO_PCI(i), 0)]) {
+            shpc_set_status(shpc, i, SHPC_STATE_ENABLED, SHPC_SLOT_STATE_MASK);
+            shpc_set_status(shpc, i, 0, SHPC_SLOT_STATUS_MRL_OPEN);
+            shpc_set_status(shpc, i, SHPC_SLOT_STATUS_PRSNT_7_5W,
+                            SHPC_SLOT_STATUS_PRSNT_MASK);
+            shpc_set_status(shpc, i, SHPC_LED_ON, SHPC_SLOT_PWR_LED_MASK);
+        } else {
+            shpc_set_status(shpc, i, SHPC_STATE_DISABLED, SHPC_SLOT_STATE_MASK);
+            shpc_set_status(shpc, i, 1, SHPC_SLOT_STATUS_MRL_OPEN);
+            shpc_set_status(shpc, i, SHPC_SLOT_STATUS_PRSNT_EMPTY,
+                            SHPC_SLOT_STATUS_PRSNT_MASK);
+            shpc_set_status(shpc, i, SHPC_LED_OFF, SHPC_SLOT_PWR_LED_MASK);
+        }
+        shpc_set_status(shpc, i, 0, SHPC_SLOT_STATUS_66);
+    }
+    shpc_set_sec_bus_speed(shpc, SHPC_SEC_BUS_33);
+    shpc->msi_requested = 0;
+    shpc_interrupt_update(d);
+}
+
+static void shpc_invalid_command(SHPCDevice *shpc)
+{
+    pci_word_test_and_set_mask(shpc->config + SHPC_CMD_STATUS,
+                               SHPC_CMD_STATUS_INVALID_CMD);
+}
+
+static void shpc_free_devices_in_slot(SHPCDevice *shpc, int slot)
+{
+    int devfn;
+    int pci_slot = SHPC_IDX_TO_PCI(slot);
+    for (devfn = PCI_DEVFN(pci_slot, 0);
+         devfn <= PCI_DEVFN(pci_slot, PCI_FUNC_MAX - 1);
+         ++devfn) {
+        PCIDevice *affected_dev = shpc->sec_bus->devices[devfn];
+        if (affected_dev) {
+            qdev_free(&affected_dev->qdev);
+        }
+    }
+}
+
+static void shpc_slot_command(SHPCDevice *shpc, uint8_t target,
+                              uint8_t state, uint8_t power, uint8_t attn)
+{
+    uint8_t current_state;
+    int slot = SHPC_LOGICAL_TO_IDX(target);
+    if (target < SHPC_CMD_TRGT_MIN || slot >= shpc->nslots) {
+        shpc_invalid_command(shpc);
+        return;
+    }
+    current_state = shpc_get_status(shpc, slot, SHPC_SLOT_STATE_MASK);
+    if (current_state == SHPC_STATE_ENABLED && state == SHPC_STATE_PWRONLY) {
+        shpc_invalid_command(shpc);
+        return;
+    }
+
+    switch (power) {
+    case SHPC_LED_NO:
+        break;
+    default:
+        /* TODO: send event to monitor */
+        shpc_set_status(shpc, slot, power, SHPC_SLOT_PWR_LED_MASK);
+    }
+    switch (attn) {
+    case SHPC_LED_NO:
+        break;
+    default:
+        /* TODO: send event to monitor */
+        shpc_set_status(shpc, slot, attn, SHPC_SLOT_ATTN_LED_MASK);
+    }
+
+    if ((current_state == SHPC_STATE_DISABLED && state == SHPC_STATE_PWRONLY) ||
+        (current_state == SHPC_STATE_DISABLED && state == SHPC_STATE_ENABLED)) {
+        shpc_set_status(shpc, slot, state, SHPC_SLOT_STATE_MASK);
+    } else if ((current_state == SHPC_STATE_ENABLED ||
+                current_state == SHPC_STATE_PWRONLY) &&
+               state == SHPC_STATE_DISABLED) {
+        shpc_set_status(shpc, slot, state, SHPC_SLOT_STATE_MASK);
+        power = shpc_get_status(shpc, slot, SHPC_SLOT_PWR_LED_MASK);
+        /* TODO: track what monitor requested. */
+        /* Look at LED to figure out whether it's ok to remove the device. */
+        if (power == SHPC_LED_OFF) {
+            shpc_free_devices_in_slot(shpc, slot);
+            shpc_set_status(shpc, slot, 1, SHPC_SLOT_STATUS_MRL_OPEN);
+            shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_EMPTY,
+                            SHPC_SLOT_STATUS_PRSNT_MASK);
+            shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |=
+                SHPC_SLOT_EVENT_BUTTON |
+                SHPC_SLOT_EVENT_MRL |
+                SHPC_SLOT_EVENT_PRESENCE;
+        }
+    }
+}
+
+static void shpc_command(SHPCDevice *shpc)
+{
+    uint8_t code = pci_get_byte(shpc->config + SHPC_CMD_CODE);
+    uint8_t speed;
+    uint8_t target;
+    uint8_t attn;
+    uint8_t power;
+    uint8_t state;
+    int i;
+
+    /* Clear status from the previous command. */
+    pci_word_test_and_clear_mask(shpc->config + SHPC_CMD_STATUS,
+                                 SHPC_CMD_STATUS_BUSY |
+                                 SHPC_CMD_STATUS_MRL_OPEN |
+                                 SHPC_CMD_STATUS_INVALID_CMD |
+                                 SHPC_CMD_STATUS_INVALID_MODE);
+    switch (code) {
+    case 0x00 ... 0x3f:
+        target = shpc->config[SHPC_CMD_TRGT] & SHPC_CMD_TRGT_MAX;
+        state = (code & SHPC_SLOT_STATE_MASK) >> SHPC_SLOT_STATE_SHIFT;
+        power = (code & SHPC_SLOT_PWR_LED_MASK) >> SHPC_SLOT_PWR_LED_SHIFT;
+        attn = (code & SHPC_SLOT_ATTN_LED_MASK) >> SHPC_SLOT_ATTN_LED_SHIFT;
+        shpc_slot_command(shpc, target, state, power, attn);
+        break;
+    case 0x40 ... 0x47:
+        speed = code & SHPC_SEC_BUS_MASK;
+        shpc_set_sec_bus_speed(shpc, speed);
+        break;
+    case 0x48:
+        /* Power only all slots */
+        /* first verify no slots are enabled */
+        for (i = 0; i < shpc->nslots; ++i) {
+            state = shpc_get_status(shpc, i, SHPC_SLOT_STATE_MASK);
+            if (state == SHPC_STATE_ENABLED) {
+                shpc_invalid_command(shpc);
+                goto done;
+            }
+        }
+        for (i = 0; i < shpc->nslots; ++i) {
+            if (!(shpc_get_status(shpc, i, SHPC_SLOT_STATUS_MRL_OPEN))) {
+                shpc_slot_command(shpc, i + SHPC_CMD_TRGT_MIN,
+                                  SHPC_STATE_PWRONLY, SHPC_LED_ON, SHPC_LED_NO);
+            } else {
+                shpc_slot_command(shpc, i + SHPC_CMD_TRGT_MIN,
+                                  SHPC_STATE_NO, SHPC_LED_OFF, SHPC_LED_NO);
+            }
+        }
+        break;
+    case 0x49:
+        /* Enable all slots */
+        /* TODO: Spec says this shall fail if some are already enabled.
+         * This doesn't make sense - why not? a spec bug? */
+        for (i = 0; i < shpc->nslots; ++i) {
+            state = shpc_get_status(shpc, i, SHPC_SLOT_STATE_MASK);
+            if (state == SHPC_STATE_ENABLED) {
+                shpc_invalid_command(shpc);
+                goto done;
+            }
+        }
+        for (i = 0; i < shpc->nslots; ++i) {
+            if (!(shpc_get_status(shpc, i, SHPC_SLOT_STATUS_MRL_OPEN))) {
+                shpc_slot_command(shpc, i + SHPC_CMD_TRGT_MIN,
+                                  SHPC_STATE_ENABLED, SHPC_LED_ON, SHPC_LED_NO);
+            } else {
+                shpc_slot_command(shpc, i + SHPC_CMD_TRGT_MIN,
+                                  SHPC_STATE_NO, SHPC_LED_OFF, SHPC_LED_NO);
+            }
+        }
+        break;
+    default:
+        shpc_invalid_command(shpc);
+        break;
+    }
+done:
+    pci_long_test_and_set_mask(shpc->config + SHPC_SERR_INT, SHPC_CMD_DETECTED);
+}
+
+static void shpc_write(PCIDevice *d, unsigned addr, uint64_t val, int l)
+{
+    SHPCDevice *shpc = d->shpc;
+    int i;
+    if (addr >= SHPC_SIZEOF(d)) {
+        return;
+    }
+    l = MIN(l, SHPC_SIZEOF(d) - addr);
+
+    /* TODO: code duplicated from pci.c */
+    for (i = 0; i < l; val >>= 8, ++i) {
+        unsigned a = addr + i;
+        uint8_t wmask = shpc->wmask[a];
+        uint8_t w1cmask = shpc->w1cmask[a];
+        assert(!(wmask & w1cmask));
+        shpc->config[a] = (shpc->config[a] & ~wmask) | (val & wmask);
+        shpc->config[a] &= ~(val & w1cmask); /* W1C: Write 1 to Clear */
+    }
+    if (ranges_overlap(addr, l, SHPC_CMD_CODE, 2)) {
+        shpc_command(shpc);
+    }
+    shpc_interrupt_update(d);
+}
+
+static uint64_t shpc_read(PCIDevice *d, unsigned addr, int l)
+{
+    uint64_t val = 0x0;
+    if (addr >= SHPC_SIZEOF(d)) {
+        return val;
+    }
+    l = MIN(l, SHPC_SIZEOF(d) - addr);
+    memcpy(&val, d->shpc->config + addr, l);
+    return val;
+}
+
+/* SHPC Bridge Capability */
+#define SHPC_CAP_LENGTH 0x08
+#define SHPC_CAP_DWORD_SELECT 0x2 /* 1 byte */
+#define SHPC_CAP_CxP 0x3 /* 1 byte: CSP, CIP */
+#define SHPC_CAP_DWORD_DATA 0x4 /* 4 bytes */
+#define SHPC_CAP_CSP_MASK 0x4
+#define SHPC_CAP_CIP_MASK 0x8
+
+static uint8_t shpc_cap_dword(PCIDevice *d)
+{
+    return pci_get_byte(d->config + d->shpc->cap + SHPC_CAP_DWORD_SELECT);
+}
+
+/* Update dword data capability register */
+static void shpc_cap_update_dword(PCIDevice *d)
+{
+    unsigned data;
+    data = shpc_read(d, shpc_cap_dword(d) * 4, 4);
+    pci_set_long(d->config  + d->shpc->cap + SHPC_CAP_DWORD_DATA, data);
+}
+
+/* Add SHPC capability to the config space for the device. */
+static int shpc_cap_add_config(PCIDevice *d)
+{
+    uint8_t *config;
+    int config_offset;
+    config_offset = pci_add_capability(d, PCI_CAP_ID_SHPC,
+                                       0, SHPC_CAP_LENGTH);
+    if (config_offset < 0) {
+        return config_offset;
+    }
+    config = d->config + config_offset;
+
+    pci_set_byte(config + SHPC_CAP_DWORD_SELECT, 0);
+    pci_set_byte(config + SHPC_CAP_CxP, 0);
+    pci_set_long(config + SHPC_CAP_DWORD_DATA, 0);
+    d->shpc->cap = config_offset;
+    /* Make dword select and data writeable. */
+    pci_set_byte(d->wmask + config_offset + SHPC_CAP_DWORD_SELECT, 0xff);
+    pci_set_long(d->wmask + config_offset + SHPC_CAP_DWORD_DATA, 0xffffffff);
+    return 0;
+}
+
+static uint64_t shpc_mmio_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
+{
+    return shpc_read(opaque, addr, size);
+}
+
+static void shpc_mmio_write(void *opaque, target_phys_addr_t addr,
+                            uint64_t val, unsigned size)
+{
+    shpc_write(opaque, addr, val, size);
+}
+
+static const MemoryRegionOps shpc_mmio_ops = {
+    .read = shpc_mmio_read,
+    .write = shpc_mmio_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        /* SHPC ECN requires dword accesses, but the original 1.0 spec doesn't.
+         * It's easier to suppport all sizes than worry about it. */
+        .min_access_size = 1,
+        .max_access_size = 4,
+    },
+};
+
+static int shpc_device_hotplug(DeviceState *qdev, PCIDevice *affected_dev,
+                               PCIHotplugState hotplug_state)
+{
+    int pci_slot = PCI_SLOT(affected_dev->devfn);
+    uint8_t state;
+    uint8_t led;
+    PCIDevice *d = DO_UPCAST(PCIDevice, qdev, qdev);
+    SHPCDevice *shpc = d->shpc;
+    int slot = SHPC_PCI_TO_IDX(pci_slot);
+    if (pci_slot < SHPC_IDX_TO_PCI(0) || slot >= shpc->nslots) {
+        error_report("Unsupported PCI slot %d for standard hotplug "
+                     "controller. Valid slots are between %d and %d.",
+                     pci_slot, SHPC_IDX_TO_PCI(0),
+                     SHPC_IDX_TO_PCI(shpc->nslots) - 1);
+        return -1;
+    }
+    /* Don't send event when device is enabled during qemu machine creation:
+     * it is present on boot, no hotplug event is necessary. We do send an
+     * event when the device is disabled later. */
+    if (hotplug_state == PCI_COLDPLUG_ENABLED) {
+        shpc_set_status(shpc, slot, 0, SHPC_SLOT_STATUS_MRL_OPEN);
+        shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_7_5W,
+                        SHPC_SLOT_STATUS_PRSNT_MASK);
+        return 0;
+    }
+    if (hotplug_state == PCI_HOTPLUG_DISABLED) {
+        shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |= SHPC_SLOT_EVENT_BUTTON;
+        state = shpc_get_status(shpc, slot, SHPC_SLOT_STATE_MASK);
+        led = shpc_get_status(shpc, slot, SHPC_SLOT_PWR_LED_MASK);
+        if (state == SHPC_STATE_DISABLED && led == SHPC_LED_OFF) {
+            shpc_free_devices_in_slot(shpc, slot);
+            shpc_set_status(shpc, slot, 1, SHPC_SLOT_STATUS_MRL_OPEN);
+            shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_EMPTY,
+                            SHPC_SLOT_STATUS_PRSNT_MASK);
+            shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |=
+                SHPC_SLOT_EVENT_MRL |
+                SHPC_SLOT_EVENT_PRESENCE;
+        }
+    } else {
+        /* This could be a cancellation of the previous removal.
+         * We check MRL state to figure out. */
+        if (shpc_get_status(shpc, slot, SHPC_SLOT_STATUS_MRL_OPEN)) {
+            shpc_set_status(shpc, slot, 0, SHPC_SLOT_STATUS_MRL_OPEN);
+            shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_7_5W,
+                            SHPC_SLOT_STATUS_PRSNT_MASK);
+            shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |=
+                SHPC_SLOT_EVENT_BUTTON |
+                SHPC_SLOT_EVENT_MRL |
+                SHPC_SLOT_EVENT_PRESENCE;
+        } else {
+            /* Press attention button to cancel removal */
+            shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |=
+                SHPC_SLOT_EVENT_BUTTON;
+        }
+    }
+    shpc_set_status(shpc, slot, 0, SHPC_SLOT_STATUS_66);
+    shpc_interrupt_update(d);
+    return 0;
+}
+
+/* Initialize the SHPC structure in bridge's BAR. */
+int shpc_init(PCIDevice *d, PCIBus *sec_bus, MemoryRegion *bar, unsigned offset)
+{
+    int i, ret;
+    int nslots = SHPC_MAX_SLOTS; /* TODO: qdev property? */
+    SHPCDevice *shpc = d->shpc = g_malloc0(sizeof(*d->shpc));
+    shpc->sec_bus = sec_bus;
+    ret = shpc_cap_add_config(d);
+    if (ret) {
+        g_free(d->shpc);
+        return ret;
+    }
+    if (nslots < SHPC_MIN_SLOTS) {
+        return 0;
+    }
+    if (nslots > SHPC_MAX_SLOTS ||
+        SHPC_IDX_TO_PCI(nslots) > PCI_SLOT_MAX) {
+        /* TODO: report an error mesage that makes sense. */
+        return -EINVAL;
+    }
+    shpc->nslots = nslots;
+    shpc->config = g_malloc0(SHPC_SIZEOF(d));
+    shpc->cmask = g_malloc0(SHPC_SIZEOF(d));
+    shpc->wmask = g_malloc0(SHPC_SIZEOF(d));
+    shpc->w1cmask = g_malloc0(SHPC_SIZEOF(d));
+
+    shpc_reset(d);
+
+    pci_set_long(shpc->config + SHPC_BASE_OFFSET, offset);
+
+    pci_set_byte(shpc->wmask + SHPC_CMD_CODE, 0xff);
+    pci_set_byte(shpc->wmask + SHPC_CMD_TRGT, SHPC_CMD_TRGT_MAX);
+    pci_set_byte(shpc->wmask + SHPC_CMD_TRGT, SHPC_CMD_TRGT_MAX);
+    pci_set_long(shpc->wmask + SHPC_SERR_INT,
+                 SHPC_INT_DIS |
+                 SHPC_SERR_DIS |
+                 SHPC_CMD_INT_DIS |
+                 SHPC_ARB_SERR_DIS);
+    pci_set_long(shpc->w1cmask + SHPC_SERR_INT,
+                 SHPC_CMD_DETECTED |
+                 SHPC_ARB_DETECTED);
+    for (i = 0; i < nslots; ++i) {
+        pci_set_byte(shpc->wmask +
+                     SHPC_SLOT_EVENT_SERR_INT_DIS(d, i),
+                     SHPC_SLOT_EVENT_PRESENCE |
+                     SHPC_SLOT_EVENT_ISOLATED_FAULT |
+                     SHPC_SLOT_EVENT_BUTTON |
+                     SHPC_SLOT_EVENT_MRL |
+                     SHPC_SLOT_EVENT_CONNECTED_FAULT |
+                     SHPC_SLOT_EVENT_MRL_SERR_DIS |
+                     SHPC_SLOT_EVENT_CONNECTED_FAULT_SERR_DIS);
+        pci_set_byte(shpc->w1cmask +
+                     SHPC_SLOT_EVENT_LATCH(i),
+                     SHPC_SLOT_EVENT_PRESENCE |
+                     SHPC_SLOT_EVENT_ISOLATED_FAULT |
+                     SHPC_SLOT_EVENT_BUTTON |
+                     SHPC_SLOT_EVENT_MRL |
+                     SHPC_SLOT_EVENT_CONNECTED_FAULT);
+    }
+
+    /* TODO: init cmask */
+    memory_region_init_io(&shpc->mmio, &shpc_mmio_ops, d, "shpc-mmio",
+                          SHPC_SIZEOF(d));
+    shpc_cap_update_dword(d);
+    memory_region_add_subregion(bar, offset, &shpc->mmio);
+    pci_bus_hotplug(sec_bus, shpc_device_hotplug, &d->qdev);
+
+    d->cap_present |= QEMU_PCI_CAP_SHPC;
+    return 0;
+}
+
+int shpc_bar_size(PCIDevice *d)
+{
+    return roundup_pow_of_two(SHPC_SLOT_REG(SHPC_MAX_SLOTS));
+}
+
+void shpc_cleanup(PCIDevice *d, MemoryRegion *bar)
+{
+    SHPCDevice *shpc = d->shpc;
+    d->cap_present &= ~QEMU_PCI_CAP_SHPC;
+    memory_region_del_subregion(bar, &shpc->mmio);
+    /* TODO: cleanup config space changes? */
+    g_free(shpc->config);
+    g_free(shpc->cmask);
+    g_free(shpc->wmask);
+    g_free(shpc->w1cmask);
+    memory_region_destroy(&shpc->mmio);
+    g_free(shpc);
+}
+
+void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
+{
+    if (!ranges_overlap(addr, l, d->shpc->cap, SHPC_CAP_LENGTH)) {
+        return;
+    }
+    if (ranges_overlap(addr, l, d->shpc->cap + SHPC_CAP_DWORD_DATA, 4)) {
+        unsigned dword_data;
+        dword_data = pci_get_long(d->shpc->config + d->shpc->cap
+                                  + SHPC_CAP_DWORD_DATA);
+        shpc_write(d, shpc_cap_dword(d) * 4, dword_data, 4);
+    }
+    /* Update cap dword data in case guest is going to read it. */
+    shpc_cap_update_dword(d);
+}
+
+static void shpc_save(QEMUFile *f, void *pv, size_t size)
+{
+    PCIDevice *d = container_of(pv, PCIDevice, shpc);
+    qemu_put_buffer(f, d->shpc->config, SHPC_SIZEOF(d));
+}
+
+static int shpc_load(QEMUFile *f, void *pv, size_t size)
+{
+    PCIDevice *d = container_of(pv, PCIDevice, shpc);
+    int ret = qemu_get_buffer(f, d->shpc->config, SHPC_SIZEOF(d));
+    if (ret != SHPC_SIZEOF(d)) {
+        return -EINVAL;
+    }
+    /* Make sure we don't lose notifications. An extra interrupt is harmless. */
+    d->shpc->msi_requested = 0;
+    shpc_interrupt_update(d);
+    return 0;
+}
+
+VMStateInfo shpc_vmstate_info = {
+    .name = "shpc",
+    .get  = shpc_load,
+    .put  = shpc_save,
+};
diff --git a/hw/shpc.h b/hw/shpc.h
new file mode 100644
index 0000000..130b71d
--- /dev/null
+++ b/hw/shpc.h
@@ -0,0 +1,48 @@
+#ifndef SHPC_H
+#define SHPC_H
+
+#include "qemu-common.h"
+#include "memory.h"
+#include "vmstate.h"
+
+struct SHPCDevice {
+    /* Capability offset in device's config space */
+    int cap;
+
+    /* # of hot-pluggable slots */
+    int nslots;
+
+    /* SHPC WRS: working register set */
+    uint8_t *config;
+
+    /* Used to enable checks on load. Note that writable bits are
+     * never checked even if set in cmask. */
+    uint8_t *cmask;
+
+    /* Used to implement R/W bytes */
+    uint8_t *wmask;
+
+    /* Used to implement RW1C(Write 1 to Clear) bytes */
+    uint8_t *w1cmask;
+
+    /* MMIO for the SHPC BAR */
+    MemoryRegion mmio;
+
+    /* Bus controlled by this SHPC */
+    PCIBus *sec_bus;
+
+    /* MSI already requested for this event */
+    int msi_requested;
+};
+
+void shpc_reset(PCIDevice *d);
+int shpc_bar_size(PCIDevice *dev);
+int shpc_init(PCIDevice *dev, PCIBus *sec_bus, MemoryRegion *bar, unsigned off);
+void shpc_cleanup(PCIDevice *dev, MemoryRegion *bar);
+void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len);
+
+extern VMStateInfo shpc_vmstate_info;
+#define SHPC_VMSTATE(_field, _type) \
+    VMSTATE_BUFFER_UNSAFE_INFO(_field, _type, 0, shpc_vmstate_info, 0)
+
+#endif
diff --git a/qemu-common.h b/qemu-common.h
index b0fdf5c..320f469 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -260,6 +260,7 @@ typedef struct SSIBus SSIBus;
 typedef struct EventNotifier EventNotifier;
 typedef struct VirtIODevice VirtIODevice;
 typedef struct QEMUSGList QEMUSGList;
+typedef struct SHPCDevice SHPCDevice;
 
 typedef uint64_t pcibus_t;
 
commit 8a3d80faf7794820da5e9666e4adf6a7d4f80f7b
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Feb 20 01:34:01 2012 +0200

    pci_bridge: user-friendly default bus name
    
    For a pci bridge device, if we don't override
    the name with custom code, the bus will be addressed as
    <id>.0, where id is the id specified by the user.
    
    Since PCI Bridge devices have a single bus each, we don't need
    the index: address the bus using the parent device name.
    This is better since this way users don't care about
    our internal bus/device distinctions.
    
    As far as I could see, we only have built-in
    bridges at this point which always override the
    name. So this change will only affect ioh3420.c.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci_bridge.c b/hw/pci_bridge.c
index fea3873..eeee8a6 100644
--- a/hw/pci_bridge.c
+++ b/hw/pci_bridge.c
@@ -314,6 +314,16 @@ int pci_bridge_initfn(PCIDevice *dev)
     pci_set_word(dev->config + PCI_SEC_STATUS,
                  PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
 
+    /*
+     * If we don't specify the name, the bus will be addressed as <id>.0, where
+     * id is the device id.
+     * Since PCI Bridge devices have a single bus each, we don't need the index:
+     * let users address the bus using the device name.
+     */
+    if (!br->bus_name && dev->qdev.id && *dev->qdev.id) {
+	    br->bus_name = dev->qdev.id;
+    }
+
     qbus_create_inplace(&sec_bus->qbus, &pci_bus_info, &dev->qdev,
                         br->bus_name);
     sec_bus->parent_dev = dev;
commit d662210a440bf90bf0f5fb5eb8abd6244478c97d
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Sun Feb 19 18:16:02 2012 +0200

    pci: make another unused extern function static
    
    Make pci_find_bus static and rename to pci_find_bus_nr to match
    functionality.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci.c b/hw/pci.c
index 691322d..3ca5f4c 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -63,6 +63,7 @@ struct BusInfo pci_bus_info = {
     }
 };
 
+static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num);
 static void pci_update_mappings(PCIDevice *d);
 static void pci_set_irq(void *opaque, int irq_num, int level);
 static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom);
@@ -558,7 +559,7 @@ PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
 
     if (!devaddr) {
         *devfnp = -1;
-        return pci_find_bus(pci_find_root_bus(0), 0);
+        return pci_find_bus_nr(pci_find_root_bus(0), 0);
     }
 
     if (pci_parse_devaddr(devaddr, &dom, &bus, &slot, NULL) < 0) {
@@ -566,7 +567,7 @@ PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
     }
 
     *devfnp = PCI_DEVFN(slot, 0);
-    return pci_find_bus(pci_find_root_bus(dom), bus);
+    return pci_find_bus_nr(pci_find_root_bus(dom), bus);
 }
 
 static void pci_init_cmask(PCIDevice *dev)
@@ -1140,7 +1141,7 @@ static void pci_for_each_device_under_bus(PCIBus *bus,
 void pci_for_each_device(PCIBus *bus, int bus_num,
                          void (*fn)(PCIBus *b, PCIDevice *d))
 {
-    bus = pci_find_bus(bus, bus_num);
+    bus = pci_find_bus_nr(bus, bus_num);
 
     if (bus) {
         pci_for_each_device_under_bus(bus, fn);
@@ -1227,7 +1228,7 @@ static PciBridgeInfo *qmp_query_pci_bridge(PCIDevice *dev, PCIBus *bus,
     info->bus.prefetchable_range->limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
 
     if (dev->config[PCI_SECONDARY_BUS] != 0) {
-        PCIBus *child_bus = pci_find_bus(bus, dev->config[PCI_SECONDARY_BUS]);
+        PCIBus *child_bus = pci_find_bus_nr(bus, dev->config[PCI_SECONDARY_BUS]);
         if (child_bus) {
             info->has_devices = true;
             info->devices = qmp_query_pci_devices(child_bus, dev->config[PCI_SECONDARY_BUS]);
@@ -1306,7 +1307,7 @@ static PciInfo *qmp_query_pci_bus(PCIBus *bus, int bus_num)
 {
     PciInfo *info = NULL;
 
-    bus = pci_find_bus(bus, bus_num);
+    bus = pci_find_bus_nr(bus, bus_num);
     if (bus) {
         info = g_malloc0(sizeof(*info));
         info->bus = bus_num;
@@ -1416,7 +1417,7 @@ static bool pci_secondary_bus_in_range(PCIDevice *dev, int bus_num)
         bus_num <= dev->config[PCI_SUBORDINATE_BUS];
 }
 
-PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
+static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num)
 {
     PCIBus *sec;
 
@@ -1452,7 +1453,7 @@ PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
 
 PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn)
 {
-    bus = pci_find_bus(bus, bus_num);
+    bus = pci_find_bus_nr(bus, bus_num);
 
     if (!bus)
         return NULL;
diff --git a/hw/pci.h b/hw/pci.h
index 403aadb..704d3f3 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -299,7 +299,6 @@ int pci_bus_num(PCIBus *s);
 void pci_for_each_device(PCIBus *bus, int bus_num, void (*fn)(PCIBus *bus, PCIDevice *d));
 PCIBus *pci_find_root_bus(int domain);
 int pci_find_domain(const PCIBus *bus);
-PCIBus *pci_find_bus(PCIBus *bus, int bus_num);
 PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn);
 int pci_qdev_find_device(const char *id, PCIDevice **pdev);
 PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr);
commit 94a09e2c846374a96719cda2b4e1312d8c4b08a7
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Wed Feb 15 23:32:00 2012 +0200

    pci: don't export an internal function
    
    Make an internal function, pci_parse_devaddr,
    static.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci.c b/hw/pci.c
index 38e1de5..691322d 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -478,7 +478,7 @@ static void pci_set_default_subsystem_id(PCIDevice *pci_dev)
  * Parse [[<domain>:]<bus>:]<slot>, return -1 on error if funcp == NULL
  *       [[<domain>:]<bus>:]<slot>.<func>, return -1 on error
  */
-int pci_parse_devaddr(const char *addr, int *domp, int *busp,
+static int pci_parse_devaddr(const char *addr, int *domp, int *busp,
                       unsigned int *slotp, unsigned int *funcp)
 {
     const char *p;
diff --git a/hw/pci.h b/hw/pci.h
index 4f19fdb..403aadb 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -304,8 +304,6 @@ PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn);
 int pci_qdev_find_device(const char *id, PCIDevice **pdev);
 PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr);
 
-int pci_parse_devaddr(const char *addr, int *domp, int *busp,
-                      unsigned int *slotp, unsigned int *funcp);
 int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
                      unsigned *slotp);
 
commit 15a7a7780675eb99c093e29deefc5d6cc371bd87
Author: Anthony PERARD <anthony.perard at citrix.com>
Date:   Fri Feb 17 17:08:36 2012 +0000

    pci_regs: Fix value of PCI_EXP_TYPE_RC_EC.
    
    Value check in PCI Express Base Specification rev 1.1
    
    Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci_regs.h b/hw/pci_regs.h
index e8357c3..6b42515 100644
--- a/hw/pci_regs.h
+++ b/hw/pci_regs.h
@@ -393,7 +393,7 @@
 #define  PCI_EXP_TYPE_DOWNSTREAM 0x6	/* Downstream Port */
 #define  PCI_EXP_TYPE_PCI_BRIDGE 0x7	/* PCI/PCI-X Bridge */
 #define  PCI_EXP_TYPE_RC_END	0x9	/* Root Complex Integrated Endpoint */
-#define  PCI_EXP_TYPE_RC_EC	0x10	/* Root Complex Event Collector */
+#define  PCI_EXP_TYPE_RC_EC     0xa     /* Root Complex Event Collector */
 #define PCI_EXP_FLAGS_SLOT	0x0100	/* Slot implemented */
 #define PCI_EXP_FLAGS_IRQ	0x3e00	/* Interrupt message number */
 #define PCI_EXP_DEVCAP		4	/* Device capabilities */
commit fdba487859bff44db21dc119ee2b1b3691c69f0f
Author: Anthony PERARD <anthony.perard at citrix.com>
Date:   Mon Feb 13 12:20:13 2012 +0000

    pci: Do not check if a bus exist in pci_parse_devaddr.
    
    Actually, pci_parse_devaddr checks if the dom/bus of the PCI address exist. But
    this should be the jobs of a caller. In fact, the two callers of this function
    will try to retrieve the PCIBus related to the devaddr and return an error if
    they cannot.
    
    Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci.c b/hw/pci.c
index bf046bf..38e1de5 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -529,10 +529,6 @@ int pci_parse_devaddr(const char *addr, int *domp, int *busp,
     if (*e)
 	return -1;
 
-    /* Note: QEMU doesn't implement domains other than 0 */
-    if (!pci_find_bus(pci_find_root_bus(dom), bus))
-	return -1;
-
     *domp = dom;
     *busp = bus;
     *slotp = slot;
commit 95be1196030c003a65052fc7b8a3394fdac690a8
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Sun Feb 12 21:02:01 2012 +0200

    pci_bridge: fix status: do not override cap bit

diff --git a/hw/pci_bridge.c b/hw/pci_bridge.c
index 1ed4339..fea3873 100644
--- a/hw/pci_bridge.c
+++ b/hw/pci_bridge.c
@@ -305,8 +305,8 @@ int pci_bridge_initfn(PCIDevice *dev)
     PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
     PCIBus *sec_bus = &br->sec_bus;
 
-    pci_set_word(dev->config + PCI_STATUS,
-                 PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
+    pci_word_test_and_set_mask(dev->config + PCI_STATUS,
+                               PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
     pci_config_set_class(dev->config, PCI_CLASS_BRIDGE_PCI);
     dev->config[PCI_HEADER_TYPE] =
         (dev->config[PCI_HEADER_TYPE] & PCI_HEADER_TYPE_MULTI_FUNCTION) |


More information about the Spice-commits mailing list