[Spice-commits] 429 commits - Changelog Makefile Makefile.hw Makefile.objs Makefile.target VERSION arch_init.c arch_init.h arm-semi.c audio/Makefile.objs audio/audio.c audio/mixeng.c audio/mixeng_template.h block.c block.h block/Makefile.objs block/iscsi.c block/qcow2-cluster.c block/qcow2.c block/qed.c block/sheepdog.c block/stream.c block/vvfat.c block_int.h blockdev.c bsd-user/Makefile.objs bsd-user/main.c cmd.c configure coroutine-sigaltstack.c cpu-all.h cpu-common.h cpu-exec.c disas.c docs/usb2.txt dump-stub.c dump.c dump.h elf.h exec-all.h exec.c fsdev/Makefile.objs gdbstub.c gdbstub.h hmp-commands.hx hmp.c hmp.h hw/9pfs hw/Makefile.objs hw/acpi_piix4.c hw/alpha hw/apic.c hw/arm hw/arm-misc.h hw/arm_boot.c hw/arm_pic.c hw/armv7m.c hw/axis_dev88.c hw/collie.c hw/cris hw/cris-boot.c hw/cris-boot.h hw/es1370.c hw/exynos4210.c hw/exynos4210.h hw/exynos4_boards.c hw/fdc.c hw/highbank.c hw/i386 hw/ide hw/integratorcp.c hw/kvm hw/leon3.c hw/lm32 hw/lm32_boards.c hw/loader.c hw/loader .h hw/m68k hw/mainstone.c hw/mc146818rtc.c hw/microblaze hw/microblaze_boot.c hw/microblaze_boot.h hw/milkymist.c hw/mips hw/mips_fulong2e.c hw/mips_jazz.c hw/mips_malta.c hw/mips_mipssim.c hw/mips_r4k.c hw/msi.h hw/msix.c hw/msix.h hw/multiboot.c hw/musicpal.c hw/nseries.c hw/omap.h hw/omap1.c hw/omap2.c hw/omap_sx1.c hw/palm.c hw/pc.c hw/pc_piix.c hw/pci-hotplug.c hw/pci.c hw/pci.h hw/petalogix_ml605_mmu.c hw/petalogix_s3adsp1800_mmu.c hw/ppc hw/ppc440_bamboo.c hw/ppc4xx_devs.c hw/ppc_newworld.c hw/ppc_oldworld.c hw/ppc_prep.c hw/ppce500_mpc8544ds.c hw/pxa.h hw/pxa2xx.c hw/pxa2xx_gpio.c hw/pxa2xx_pic.c hw/qdev-addr.c hw/qdev-monitor.c hw/qdev-properties.c hw/qdev.c hw/qdev.h hw/qxl.c hw/r2d.c hw/realview.c hw/s390-virtio-bus.c hw/s390-virtio-bus.h hw/s390-virtio.c hw/s390x hw/scsi-bus.c hw/scsi-disk.c hw/sh4 hw/spapr.c hw/sparc hw/sparc64 hw/spitz.c hw/strongarm.c hw/strongarm.h hw/sun4m.c hw/sun4u.c hw/tosa.c hw/usb hw/versatilepb.c hw/vexpress.c hw/vga.c hw/vga_int.h hw/ virtex_ml507.c hw/virtio-balloon.c hw/virtio-blk.c hw/virtio-blk.h hw/virtio-net.c hw/virtio-pci.c hw/virtio-pci.h hw/virtio-scsi.c hw/virtio-serial-bus.c hw/virtio.h hw/watchdog.c hw/xen.h hw/xen_apic.c hw/xen_common.h hw/xen_disk.c hw/xen_machine_pv.c hw/xen_platform.c hw/xilinx_zynq.c hw/xtensa hw/xtensa_lx60.c hw/xtensa_sim.c hw/z2.c include/qemu ioport-user.c kvm-all.c kvm-stub.c kvm.h libcacard/Makefile linux-headers/linux linux-user/Makefile.objs linux-user/arm linux-user/main.c linux-user/mmap.c linux-user/syscall.c m68k-semi.c main-loop.h memory_mapping-stub.c memory_mapping.c memory_mapping.h migration-tcp.c migration.c migration.h monitor.c monitor.h nbd.c net.c net.h net/Makefile.objs net/dump.c net/dump.h net/slirp.c net/slirp.h net/socket.c net/socket.h net/tap-bsd.c net/tap-win32.c net/tap.c net/tap.h net/vde.c net/vde.h pc-bios/README pc-bios/openbios-ppc pc-bios/openbios-sparc32 pc-bios/openbios-sparc64 qapi-schema-guest.json qapi-schema.json qapi/Makefile.o bjs qapi/qapi-visit-core.c qapi/qapi-visit-core.h qapi/qmp-core.h qapi/qmp-dispatch.c qapi/qmp-input-visitor.c qapi/qmp-registry.c qapi/string-output-visitor.c qemu-char.c qemu-common.h qemu-config.c qemu-config.h qemu-doc.texi qemu-ga.c qemu-img.c qemu-img.texi qemu-io.c qemu-option.c qemu-option.h qemu-options.hx qemu-sockets.c qemu-timer.c qemu_socket.h qerror.c qerror.h qga/Makefile.objs qga/commands-posix.c qga/commands.c qga/guest-agent-core.h qmp-commands.hx qom/Makefile qom/Makefile.objs qom/object.c roms/openbios rules.mak scripts/kvm scripts/qapi-commands.py slirp/Makefile.objs slirp/ip.h slirp/tcp.h slirp/tcp_output.c sysconfigs/target target-alpha/Makefile.objs target-arm/Makefile.objs target-arm/arm-semi.c target-arm/helper.c target-cris/Makefile.objs target-cris/cpu.h target-cris/translate.c target-i386/Makefile.objs target-i386/arch_dump.c target-i386/arch_memory_mapping.c target-i386/cpu-qom.h target-i386/cpu.c target-i386/cpu.h target-i386/helper.c target-i3 86/ioport-user.c target-i386/kvm.c target-lm32/Makefile.objs target-lm32/cpu.c target-lm32/cpu.h target-lm32/helper.c target-m68k/Makefile.objs target-m68k/helper.c target-m68k/m68k-semi.c target-microblaze/Makefile.objs target-microblaze/cpu.c target-microblaze/cpu.h target-microblaze/helper.c target-microblaze/translate.c target-mips/Makefile.objs target-mips/cpu.h target-mips/helper.c target-mips/translate.c target-ppc/Makefile.objs target-ppc/cpu.h target-ppc/helper.c target-s390x/Makefile.objs target-s390x/cpu.c target-s390x/cpu.h target-s390x/helper.c target-s390x/kvm.c target-sh4/Makefile.objs target-sh4/cpu.h target-sh4/translate.c target-sparc/Makefile.objs target-sparc/cpu.c target-sparc/cpu.h target-unicore32/Makefile.objs target-xtensa/Makefile.objs target-xtensa/cpu.c target-xtensa/cpu.h target-xtensa/helper.c target-xtensa/helper.h target-xtensa/op_helper.c target-xtensa/translate.c target-xtensa/xtensa-semi.c tcg/ppc tcg/ppc64 tests/Makefile tests/fdc-test.c t ests/libqtest.c tests/libqtest.h tests/qemu-iotests tests/tcg tests/test-string-output-visitor.c tests/test-visitor-serialization.c trace-events trace/simple.c ui/Makefile.objs ui/cocoa.m ui/vnc.c vl.c xen-all.c xtensa-semi.c

Gerd Hoffmann kraxel at kemper.freedesktop.org
Tue Jun 12 00:32:53 PDT 2012


 Changelog                            |    2 
 Makefile                             |   44 
 Makefile.hw                          |    7 
 Makefile.objs                        |  314 ---
 Makefile.target                      |  339 ----
 VERSION                              |    2 
 arch_init.c                          |   36 
 arch_init.h                          |    2 
 arm-semi.c                           |  509 ------
 audio/Makefile.objs                  |   14 
 audio/audio.c                        |   12 
 audio/mixeng.c                       |   36 
 audio/mixeng_template.h              |    4 
 block.c                              |  213 +-
 block.h                              |    2 
 block/Makefile.objs                  |   11 
 block/iscsi.c                        |  240 ++
 block/qcow2-cluster.c                |   23 
 block/qcow2.c                        |   13 
 block/qed.c                          |    7 
 block/sheepdog.c                     |  123 -
 block/stream.c                       |   78 
 block/vvfat.c                        |   14 
 block_int.h                          |   36 
 blockdev.c                           |   11 
 bsd-user/Makefile.objs               |    2 
 bsd-user/main.c                      |    2 
 cmd.c                                |   40 
 configure                            |   92 -
 coroutine-sigaltstack.c              |    4 
 cpu-all.h                            |    1 
 cpu-common.h                         |    4 
 cpu-exec.c                           |    9 
 disas.c                              |    2 
 docs/usb2.txt                        |   15 
 dump-stub.c                          |   64 
 dump.c                               |  873 ++++++++++
 dump.h                               |   35 
 elf.h                                |    5 
 exec-all.h                           |    2 
 exec.c                               |   44 
 fsdev/Makefile.objs                  |    9 
 gdbstub.c                            |   19 
 gdbstub.h                            |    9 
 hmp-commands.hx                      |   34 
 hmp.c                                |   54 
 hmp.h                                |    3 
 hw/9pfs/Makefile.objs                |    9 
 hw/Makefile.objs                     |  165 ++
 hw/acpi_piix4.c                      |    1 
 hw/alpha/Makefile.objs               |    4 
 hw/apic.c                            |    3 
 hw/arm-misc.h                        |    8 
 hw/arm/Makefile.objs                 |   40 
 hw/arm_boot.c                        |   21 
 hw/arm_pic.c                         |    8 
 hw/armv7m.c                          |   17 
 hw/axis_dev88.c                      |    6 
 hw/collie.c                          |    2 
 hw/cris-boot.c                       |   10 
 hw/cris-boot.h                       |    2 
 hw/cris/Makefile.objs                |   13 
 hw/es1370.c                          |   11 
 hw/exynos4210.c                      |    9 
 hw/exynos4210.h                      |    4 
 hw/exynos4_boards.c                  |    4 
 hw/fdc.c                             |   14 
 hw/highbank.c                        |   13 
 hw/i386/Makefile.objs                |   13 
 hw/ide/Makefile.objs                 |   10 
 hw/ide/ahci.c                        |    4 
 hw/integratorcp.c                    |   14 
 hw/kvm/apic.c                        |   36 
 hw/kvm/i8254.c                       |   57 
 hw/leon3.c                           |   14 
 hw/lm32/Makefile.objs                |   23 
 hw/lm32_boards.c                     |   18 
 hw/loader.c                          |    2 
 hw/loader.h                          |    3 
 hw/m68k/Makefile.objs                |    4 
 hw/mainstone.c                       |   16 
 hw/mc146818rtc.c                     |    7 
 hw/microblaze/Makefile.objs          |   14 
 hw/microblaze_boot.c                 |   16 
 hw/microblaze_boot.h                 |    4 
 hw/milkymist.c                       |   12 
 hw/mips/Makefile.objs                |    6 
 hw/mips_fulong2e.c                   |   14 
 hw/mips_jazz.c                       |   13 
 hw/mips_malta.c                      |   15 
 hw/mips_mipssim.c                    |   15 
 hw/mips_r4k.c                        |   15 
 hw/msi.h                             |    5 
 hw/msix.c                            |  121 +
 hw/msix.h                            |    6 
 hw/multiboot.c                       |   12 
 hw/musicpal.c                        |   10 
 hw/nseries.c                         |   72 
 hw/omap.h                            |    2 
 hw/omap1.c                           |   20 
 hw/omap2.c                           |    8 
 hw/omap_sx1.c                        |    6 
 hw/palm.c                            |   12 
 hw/pc.c                              |   53 
 hw/pc_piix.c                         |   18 
 hw/pci-hotplug.c                     |    8 
 hw/pci.c                             |    3 
 hw/pci.h                             |   10 
 hw/petalogix_ml605_mmu.c             |   10 
 hw/petalogix_s3adsp1800_mmu.c        |   10 
 hw/ppc/Makefile.objs                 |   31 
 hw/ppc440_bamboo.c                   |   13 
 hw/ppc4xx_devs.c                     |   13 
 hw/ppc_newworld.c                    |   13 
 hw/ppc_oldworld.c                    |   13 
 hw/ppc_prep.c                        |   13 
 hw/ppce500_mpc8544ds.c               |   21 
 hw/pxa.h                             |    4 
 hw/pxa2xx.c                          |   40 
 hw/pxa2xx_gpio.c                     |    9 
 hw/pxa2xx_pic.c                      |   32 
 hw/qdev-addr.c                       |    4 
 hw/qdev-monitor.c                    |   13 
 hw/qdev-properties.c                 |  211 +-
 hw/qdev.c                            |    5 
 hw/qdev.h                            |    4 
 hw/qxl.c                             |    8 
 hw/r2d.c                             |   18 
 hw/realview.c                        |   12 
 hw/s390-virtio-bus.c                 |   16 
 hw/s390-virtio-bus.h                 |    4 
 hw/s390-virtio.c                     |   12 
 hw/s390x/Makefile.objs               |    3 
 hw/scsi-bus.c                        |   10 
 hw/scsi-disk.c                       |   16 
 hw/sh4/Makefile.objs                 |    5 
 hw/spapr.c                           |   14 
 hw/sparc/Makefile.objs               |    8 
 hw/sparc64/Makefile.objs             |    4 
 hw/spitz.c                           |   24 
 hw/strongarm.c                       |    6 
 hw/strongarm.h                       |    2 
 hw/sun4m.c                           |   20 
 hw/sun4u.c                           |   81 
 hw/tosa.c                            |   14 
 hw/usb/Makefile.objs                 |   13 
 hw/usb/dev-network.c                 |    7 
 hw/usb/dev-storage.c                 |   71 
 hw/usb/hcd-ehci.c                    |  614 ++++---
 hw/usb/hcd-uhci.c                    |   67 
 hw/usb/hcd-xhci.c                    |  251 +--
 hw/usb/host-linux.c                  |    9 
 hw/versatilepb.c                     |   13 
 hw/vexpress.c                        |   18 
 hw/vga.c                             |    7 
 hw/vga_int.h                         |    1 
 hw/virtex_ml507.c                    |   27 
 hw/virtio-balloon.c                  |    6 
 hw/virtio-blk.c                      |  106 -
 hw/virtio-blk.h                      |   14 
 hw/virtio-net.c                      |    6 
 hw/virtio-pci.c                      |  139 +
 hw/virtio-pci.h                      |   10 
 hw/virtio-scsi.c                     |    7 
 hw/virtio-serial-bus.c               |    6 
 hw/virtio.h                          |    4 
 hw/watchdog.c                        |    2 
 hw/xen.h                             |   10 
 hw/xen_apic.c                        |    5 
 hw/xen_common.h                      |    2 
 hw/xen_disk.c                        |   56 
 hw/xen_machine_pv.c                  |    4 
 hw/xen_platform.c                    |    5 
 hw/xilinx_zynq.c                     |   10 
 hw/xtensa/Makefile.objs              |    5 
 hw/xtensa_lx60.c                     |   15 
 hw/xtensa_sim.c                      |   17 
 hw/z2.c                              |   26 
 include/qemu/object.h                |    6 
 ioport-user.c                        |   60 
 kvm-all.c                            |  256 ++-
 kvm-stub.c                           |   23 
 kvm.h                                |   18 
 libcacard/Makefile                   |   17 
 linux-headers/linux/kvm.h            |   38 
 linux-user/Makefile.objs             |    7 
 linux-user/arm/nwfpe/Makefile.objs   |    2 
 linux-user/main.c                    |    2 
 linux-user/mmap.c                    |    6 
 linux-user/syscall.c                 |    2 
 m68k-semi.c                          |  408 ----
 main-loop.h                          |    4 
 memory_mapping-stub.c                |   33 
 memory_mapping.c                     |  246 ++
 memory_mapping.h                     |   64 
 migration-tcp.c                      |   77 
 migration.c                          |   14 
 migration.h                          |    7 
 monitor.c                            |  107 -
 monitor.h                            |    4 
 nbd.c                                |    4 
 net.c                                |  104 -
 net.h                                |    6 
 net/Makefile.objs                    |   12 
 net/dump.c                           |    2 
 net/dump.h                           |    3 
 net/slirp.c                          |    5 
 net/slirp.h                          |    5 
 net/socket.c                         |    8 
 net/socket.h                         |    3 
 net/tap-bsd.c                        |    6 
 net/tap-win32.c                      |    2 
 net/tap.c                            |    9 
 net/tap.h                            |    5 
 net/vde.c                            |    2 
 net/vde.h                            |    2 
 pc-bios/README                       |    2 
 pc-bios/openbios-ppc                 |binary
 pc-bios/openbios-sparc32             |binary
 pc-bios/openbios-sparc64             |binary
 qapi-schema-guest.json               |   61 
 qapi-schema.json                     |  107 +
 qapi/Makefile.objs                   |    3 
 qapi/qapi-visit-core.c               |  139 +
 qapi/qapi-visit-core.h               |   16 
 qapi/qmp-core.h                      |   10 
 qapi/qmp-dispatch.c                  |    8 
 qapi/qmp-input-visitor.c             |   11 
 qapi/qmp-registry.c                  |    4 
 qapi/string-output-visitor.c         |    2 
 qemu-char.c                          |   26 
 qemu-common.h                        |    4 
 qemu-config.c                        |   43 
 qemu-config.h                        |    7 
 qemu-doc.texi                        |   81 
 qemu-ga.c                            |   51 
 qemu-img.c                           |   16 
 qemu-img.texi                        |   18 
 qemu-io.c                            |   10 
 qemu-option.c                        |  175 +-
 qemu-option.h                        |   11 
 qemu-options.hx                      |  171 +-
 qemu-sockets.c                       |   68 
 qemu-timer.c                         |    7 
 qemu_socket.h                        |   10 
 qerror.c                             |   24 
 qerror.h                             |   18 
 qga/Makefile.objs                    |    3 
 qga/commands-posix.c                 |  202 +-
 qga/commands.c                       |    2 
 qga/guest-agent-core.h               |    5 
 qmp-commands.hx                      |   85 -
 qom/Makefile                         |    2 
 qom/Makefile.objs                    |    4 
 qom/object.c                         |    2 
 roms/openbios                        |    2 
 rules.mak                            |   40 
 scripts/kvm/vmxcap                   |   13 
 scripts/qapi-commands.py             |   14 
 slirp/Makefile.objs                  |    3 
 slirp/ip.h                           |   20 
 slirp/tcp.h                          |   13 
 slirp/tcp_output.c                   |    1 
 sysconfigs/target/cpus-x86_64.conf   |  128 +
 sysconfigs/target/target-x86_64.conf |  128 -
 target-alpha/Makefile.objs           |    3 
 target-arm/Makefile.objs             |    6 
 target-arm/arm-semi.c                |  509 ++++++
 target-arm/helper.c                  |    7 
 target-cris/Makefile.objs            |    4 
 target-cris/cpu.h                    |   12 
 target-cris/translate.c              |  112 -
 target-i386/Makefile.objs            |    7 
 target-i386/arch_dump.c              |  449 +++++
 target-i386/arch_memory_mapping.c    |  272 +++
 target-i386/cpu-qom.h                |    4 
 target-i386/cpu.c                    |   73 
 target-i386/cpu.h                    |   18 
 target-i386/helper.c                 |   25 
 target-i386/ioport-user.c            |   60 
 target-i386/kvm.c                    |    6 
 target-lm32/Makefile.objs            |    4 
 target-lm32/cpu.c                    |    2 
 target-lm32/cpu.h                    |   12 
 target-lm32/helper.c                 |   10 
 target-m68k/Makefile.objs            |    5 
 target-m68k/helper.c                 |    5 
 target-m68k/m68k-semi.c              |  408 ++++
 target-microblaze/Makefile.objs      |    4 
 target-microblaze/cpu.c              |    1 
 target-microblaze/cpu.h              |   16 
 target-microblaze/helper.c           |    2 
 target-microblaze/translate.c        |   93 -
 target-mips/Makefile.objs            |    4 
 target-mips/cpu.h                    |   16 
 target-mips/helper.c                 |    3 
 target-mips/translate.c              |   14 
 target-ppc/Makefile.objs             |    6 
 target-ppc/cpu.h                     |   12 
 target-ppc/helper.c                  |    9 
 target-s390x/Makefile.objs           |    5 
 target-s390x/cpu.c                   |    2 
 target-s390x/cpu.h                   |   10 
 target-s390x/helper.c                |   13 
 target-s390x/kvm.c                   |   12 
 target-sh4/Makefile.objs             |    4 
 target-sh4/cpu.h                     |   12 
 target-sh4/translate.c               |    9 
 target-sparc/Makefile.objs           |    8 
 target-sparc/cpu.c                   |    9 
 target-sparc/cpu.h                   |   17 
 target-unicore32/Makefile.objs       |    4 
 target-xtensa/Makefile.objs          |    6 
 target-xtensa/cpu.c                  |    2 
 target-xtensa/cpu.h                  |   21 
 target-xtensa/helper.c               |   70 
 target-xtensa/helper.h               |   58 
 target-xtensa/op_helper.c            |  203 +-
 target-xtensa/translate.c            |   66 
 target-xtensa/xtensa-semi.c          |  223 ++
 tcg/ppc/tcg-target.c                 |   16 
 tcg/ppc64/tcg-target.c               |   44 
 tests/Makefile                       |    9 
 tests/fdc-test.c                     |  226 ++
 tests/libqtest.c                     |  123 +
 tests/libqtest.h                     |   17 
 tests/qemu-iotests/002.out           |    4 
 tests/qemu-iotests/012.out           |    2 
 tests/qemu-iotests/016.out           |   12 
 tests/qemu-iotests/017.out           | 1024 ++++++------
 tests/qemu-iotests/018.out           | 1024 ++++++------
 tests/qemu-iotests/019.out           | 1536 +++++++++---------
 tests/qemu-iotests/020.out           | 1024 ++++++------
 tests/qemu-iotests/023.out           | 2880 +++++++++++++++++------------------
 tests/qemu-iotests/027.out           |    2 
 tests/qemu-iotests/028.out           |  448 ++---
 tests/qemu-iotests/030               |   34 
 tests/qemu-iotests/030.out           |    4 
 tests/qemu-iotests/033.out           |    6 
 tests/qemu-iotests/035               |    2 
 tests/qemu-iotests/035.out           |  384 ++--
 tests/qemu-iotests/iotests.py        |   16 
 tests/tcg/test-mmap.c                |    2 
 tests/tcg/xtensa/test_mmu.S          |  221 ++
 tests/test-string-output-visitor.c   |    2 
 tests/test-visitor-serialization.c   |  784 +++++++++
 trace-events                         |   50 
 trace/simple.c                       |    5 
 ui/Makefile.objs                     |   18 
 ui/cocoa.m                           |    3 
 ui/vnc.c                             |    9 
 vl.c                                 |   53 
 xen-all.c                            |   22 
 xtensa-semi.c                        |  224 --
 354 files changed, 14566 insertions(+), 8738 deletions(-)

New commits:
commit 7677e24f3db8466c7d6014a794b1e425bc7929ba
Merge: 248bfdc... 0cdd3d1...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Jun 11 12:15:52 2012 -0500

    Merge remote-tracking branch 'qemu-kvm/uq/master' into staging
    
    * qemu-kvm/uq/master:
      kvm: i8254: Fix conversion of in-kernel to userspace state
      kvm/apic: correct short memset

commit 248bfdc9f53a85b82e3ff39c5122d8849f61ee65
Merge: e4d4081... 64c27e5...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Jun 11 12:15:51 2012 -0500

    Merge remote-tracking branch 'sstabellini/for_1.1.1' into staging
    
    * sstabellini/for_1.1.1:
      qemu/xendisk: set maximum number of grants to be used

commit e4d40816f152b0021e0bdc2413f4b72fa9ea5e00
Merge: df33219... 3edb8f9...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Jun 11 12:15:51 2012 -0500

    Merge remote-tracking branch 'afaerber-or/qom-cpu-3a' into staging
    
    * afaerber-or/qom-cpu-3a: (27 commits)
      target-s390x: Pass S390CPU to s390_cpu_restart()
      s390-virtio: Let s390_cpu_addr2state() return S390CPU
      s390-virtio: Use cpu_s390x_init() to obtain S390CPU
      target-s390x: Let cpu_s390x_init() return S390CPU
      xen_machine_pv: Use cpu_x86_init() to obtain X86CPU
      arm_pic: Pass ARMCPU to arm_pic_init_cpu()
      arm_boot: Pass ARMCPU to arm_load_kernel()
      xilinx_zynq: Use cpu_arm_init() to obtain ARMCPU
      pxa2xx_gpio: Store ARMCPU in PXA2xxGPIOInfo
      pxa2xx_pic: Store ARMCPU in PXA2xxPICState
      pxa2xx: Pass ARMCPU to pxa2xx_pic_init()
      exynos4210: Use cpu_arm_init() to store ARMCPU
      vexpress: Use cpu_arm_init() to obtain ARMCPU
      realview: Use cpu_arm_init() to obtain ARMCPU
      arm_boot: Pass ARMCPU to arm_boot_info::secondary_cpu_reset_hook()
      arm_boot: Pass ARMCPU to arm_boot_info::write_secondary_boot()
      versatilepb: Use cpu_arm_init() to obtain ARMCPU
      musicpal: Use cpu_arm_init() to obtain ARMCPU
      integratorcp: Use cpu_arm_init() to obtain ARMCPU
      strongarm: Use cpu_arm_init() to store ARMCPU in StrongARMState
      ...

commit df33219191a8f8ac672f674ec1fd4e1837d760a3
Merge: 3525c42... fa02988...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Jun 11 12:15:51 2012 -0500

    Merge remote-tracking branch 'afaerber-or/qom-next-1' into staging
    
    * afaerber-or/qom-next-1:
      target-i386: Use uint32 visitor for [x]level properties
      qdev: Remove PropertyInfo range checking
      qdev: Switch property accessors to fixed-width visitor interfaces
      qdev: Use int32_t container for devfn property
      qapi: Add String visitor coverage to serialization unit tests
      qapi: String visitor, use %f representation for floats
      qapi: Unit tests for visitor-based serialization
      qapi: Add Visitor interfaces for uint*_t and int*_t

commit 3525c42fd3b70182b1f98d74439e8aeabb565803
Merge: 39cde84... 263ddcc...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Jun 11 12:15:51 2012 -0500

    Merge remote-tracking branch 'stefanha/trivial-patches' into staging
    
    * stefanha/trivial-patches:
      configure: report missing libraries for virtfs
      trace/simple.c: fix deprecated glib2 interface
      Clarify comments of tb_invalidate_phys_[page_]range

commit 39cde84517ce1bcef294dc9e9e0940475c46fab2
Merge: dbaf26b... f020ed3...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Jun 11 12:07:00 2012 -0500

    Merge remote-tracking branch 'kraxel/usb.52' into staging
    
    * kraxel/usb.52: (37 commits)
      ehci: rework frame skipping
      ehci: adaptive wakeup rate.
      ehci: create ehci_update_frindex
      ehci: remove unused attach_poll_counter
      ehci: fix halt status handling
      ehci: update status bits in ehci_set_state
      ehci: add ehci_*_enabled() helpers
      ehci: fix reset
      ehci: kick async schedule on wakeup
      ehci: schedule async bh on async packet completion
      ehci: move async schedule to bottom half
      ehci: add async field to EHCIQueue
      ehci: tweak queue initialization
      ehci: add queuing support
      ehci: move ehci_flush_qh
      ehci: cache USBDevice in EHCIQueue
      ehci: make ehci_execute work on EHCIPacket instead of EHCIQueue
      ehci: add EHCIPacket
      xhci: trace: slots
      xhci: trace: transfers
      ...

commit 0cdd3d14447da1a04e778c219c77db8b96f9cf33
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Jun 6 16:28:42 2012 +0200

    kvm: i8254: Fix conversion of in-kernel to userspace state
    
    Due to a offset between the clock used to generate the in-kernel
    count_load_time (CLOCK_MONOTONIC) and the clock used for processing this
    in userspace (vm_clock), reading back the output of PIT channel 2 via
    port 0x61 was broken. One use cases that suffered from it was the CPU
    frequency calibration of SeaBIOS, which also affected IDE/AHCI timeouts.
    
    This fixes it by calibrating the offset between both clocks on
    kvm_pit_get and adjusting the kernel value before saving it in the
    userspace state. As the calibration only works while the vm_clock is
    running, we cache the in-kernel state across stopped phases.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/kvm/i8254.c b/hw/kvm/i8254.c
index bb5fe07..c5d3711 100644
--- a/hw/kvm/i8254.c
+++ b/hw/kvm/i8254.c
@@ -23,31 +23,63 @@
  * THE SOFTWARE.
  */
 #include "qemu-timer.h"
+#include "sysemu.h"
 #include "hw/i8254.h"
 #include "hw/i8254_internal.h"
 #include "kvm.h"
 
 #define KVM_PIT_REINJECT_BIT 0
 
+#define CALIBRATION_ROUNDS   3
+
 typedef struct KVMPITState {
     PITCommonState pit;
     LostTickPolicy lost_tick_policy;
+    bool state_valid;
 } KVMPITState;
 
-static void kvm_pit_get(PITCommonState *s)
+static int64_t abs64(int64_t v)
 {
+    return v < 0 ? -v : v;
+}
+
+static void kvm_pit_get(PITCommonState *pit)
+{
+    KVMPITState *s = DO_UPCAST(KVMPITState, pit, pit);
     struct kvm_pit_state2 kpit;
     struct kvm_pit_channel_state *kchan;
     struct PITChannelState *sc;
+    int64_t offset, clock_offset;
+    struct timespec ts;
     int i, ret;
 
+    if (s->state_valid) {
+        return;
+    }
+
+    /*
+     * Measure the delta between CLOCK_MONOTONIC, the base used for
+     * kvm_pit_channel_state::count_load_time, and vm_clock. Take the
+     * minimum of several samples to filter out scheduling noise.
+     */
+    clock_offset = INT64_MAX;
+    for (i = 0; i < CALIBRATION_ROUNDS; i++) {
+        offset = qemu_get_clock_ns(vm_clock);
+        clock_gettime(CLOCK_MONOTONIC, &ts);
+        offset -= ts.tv_nsec;
+        offset -= (int64_t)ts.tv_sec * 1000000000;
+        if (abs64(offset) < abs64(clock_offset)) {
+            clock_offset = offset;
+        }
+    }
+
     if (kvm_has_pit_state2()) {
         ret = kvm_vm_ioctl(kvm_state, KVM_GET_PIT2, &kpit);
         if (ret < 0) {
             fprintf(stderr, "KVM_GET_PIT2 failed: %s\n", strerror(ret));
             abort();
         }
-        s->channels[0].irq_disabled = kpit.flags & KVM_PIT_FLAGS_HPET_LEGACY;
+        pit->channels[0].irq_disabled = kpit.flags & KVM_PIT_FLAGS_HPET_LEGACY;
     } else {
         /*
          * kvm_pit_state2 is superset of kvm_pit_state struct,
@@ -61,7 +93,7 @@ static void kvm_pit_get(PITCommonState *s)
     }
     for (i = 0; i < 3; i++) {
         kchan = &kpit.channels[i];
-        sc = &s->channels[i];
+        sc = &pit->channels[i];
         sc->count = kchan->count;
         sc->latched_count = kchan->latched_count;
         sc->count_latched = kchan->count_latched;
@@ -74,10 +106,10 @@ static void kvm_pit_get(PITCommonState *s)
         sc->mode = kchan->mode;
         sc->bcd = kchan->bcd;
         sc->gate = kchan->gate;
-        sc->count_load_time = kchan->count_load_time;
+        sc->count_load_time = kchan->count_load_time + clock_offset;
     }
 
-    sc = &s->channels[0];
+    sc = &pit->channels[0];
     sc->next_transition_time =
         pit_get_next_transition_time(sc, sc->count_load_time);
 }
@@ -173,6 +205,19 @@ static void kvm_pit_irq_control(void *opaque, int n, int enable)
     kvm_pit_put(pit);
 }
 
+static void kvm_pit_vm_state_change(void *opaque, int running,
+                                    RunState state)
+{
+    KVMPITState *s = opaque;
+
+    if (running) {
+        s->state_valid = false;
+    } else {
+        kvm_pit_get(&s->pit);
+        s->state_valid = true;
+    }
+}
+
 static int kvm_pit_initfn(PITCommonState *pit)
 {
     KVMPITState *s = DO_UPCAST(KVMPITState, pit, pit);
@@ -215,6 +260,8 @@ static int kvm_pit_initfn(PITCommonState *pit)
 
     qdev_init_gpio_in(&pit->dev.qdev, kvm_pit_irq_control, 1);
 
+    qemu_add_vm_change_state_handler(kvm_pit_vm_state_change, s);
+
     return 0;
 }
 
commit 64c27e5b1fdb6d94bdc0bda3b1869d7383a35c65
Author: Jan Beulich <JBeulich at suse.com>
Date:   Mon Jun 11 09:52:27 2012 +0000

    qemu/xendisk: set maximum number of grants to be used
    
    Legacy (non-pvops) gntdev drivers may require this to be done when the
    number of grants intended to be used simultaneously exceeds a certain
    driver specific default limit.
    
    Signed-off-by: Jan Beulich <jbeulich at suse.com>
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 07594bc..de7e8a4 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -537,6 +537,15 @@ static void blk_bh(void *opaque)
     blk_handle_requests(blkdev);
 }
 
+/*
+ * We need to account for the grant allocations requiring contiguous
+ * chunks; the worst case number would be
+ *     max_req * max_seg + (max_req - 1) * (max_seg - 1) + 1,
+ * but in order to keep things simple just use
+ *     2 * max_req * max_seg.
+ */
+#define MAX_GRANTS(max_req, max_seg) (2 * (max_req) * (max_seg))
+
 static void blk_alloc(struct XenDevice *xendev)
 {
     struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
@@ -548,6 +557,11 @@ static void blk_alloc(struct XenDevice *xendev)
     if (xen_mode != XEN_EMULATE) {
         batch_maps = 1;
     }
+    if (xc_gnttab_set_max_grants(xendev->gnttabdev,
+            MAX_GRANTS(max_requests, BLKIF_MAX_SEGMENTS_PER_REQUEST)) < 0) {
+        xen_be_printf(xendev, 0, "xc_gnttab_set_max_grants failed: %s\n",
+                      strerror(errno));
+    }
 }
 
 static int blk_init(struct XenDevice *xendev)
commit 0614cb82ca27bdffb83864e693fc29e29182667b
Author: Jim Meyering <meyering at redhat.com>
Date:   Thu May 10 18:19:47 2012 +0200

    kvm/apic: correct short memset
    
    kvm_put_apic_state's attempt to clear *kapic before setting its
    bits cleared sizeof(void*) bytes (no more than 8) rather than the
    intended 1024 (KVM_APIC_REG_SIZE) bytes. Spotted by coverity.
    
    Signed-off-by: Jim Meyering <meyering at redhat.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/kvm/apic.c b/hw/kvm/apic.c
index 8ba4079..80e3e48 100644
--- a/hw/kvm/apic.c
+++ b/hw/kvm/apic.c
@@ -30,7 +30,7 @@ void kvm_put_apic_state(DeviceState *d, struct kvm_lapic_state *kapic)
     APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
     int i;
 
-    memset(kapic, 0, sizeof(kapic));
+    memset(kapic, 0, sizeof(*kapic));
     kvm_apic_set_reg(kapic, 0x2, s->id << 24);
     kvm_apic_set_reg(kapic, 0x8, s->tpr);
     kvm_apic_set_reg(kapic, 0xd, s->log_dest << 24);
commit 3edb8f92e8b5f18797693d8ed9fad3962e11e25d
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu May 3 04:32:00 2012 +0200

    target-s390x: Pass S390CPU to s390_cpu_restart()
    
    Needed for qemu_cpu_kick().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 2153e38..5800fd6 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -292,8 +292,10 @@ static int handle_diag(CPUS390XState *env, struct kvm_run *run, int ipb_code)
     return r;
 }
 
-static int s390_cpu_restart(CPUS390XState *env)
+static int s390_cpu_restart(S390CPU *cpu)
 {
+    CPUS390XState *env = &cpu->env;
+
     kvm_s390_interrupt(env, KVM_S390_RESTART, 0);
     s390_add_running_cpu(env);
     qemu_cpu_kick(env);
@@ -362,7 +364,7 @@ static int handle_sigp(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1)
 
     switch (order_code) {
         case SIGP_RESTART:
-            r = s390_cpu_restart(target_env);
+            r = s390_cpu_restart(target_cpu);
             break;
         case SIGP_STORE_STATUS_ADDR:
             r = s390_store_status(target_env, parameter);
commit 45fa769b32861573409bceff53251cffafcf10a9
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu May 3 04:28:14 2012 +0200

    s390-virtio: Let s390_cpu_addr2state() return S390CPU
    
    Convert ipi_states to S390CPU**.
    
    Needed for s390_cpu_restart() in handle_sigp().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index 1d38a8f..23ef35b 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -140,7 +140,8 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
     s390_virtio_device_sync(dev);
     s390_virtio_reset_idx(dev);
     if (dev->qdev.hotplugged) {
-        CPUS390XState *env = s390_cpu_addr2state(0);
+        S390CPU *cpu = s390_cpu_addr2state(0);
+        CPUS390XState *env = &cpu->env;
         s390_virtio_irq(env, VIRTIO_PARAM_DEV_ADD, dev->dev_offs);
     }
 
@@ -354,7 +355,8 @@ static void virtio_s390_notify(void *opaque, uint16_t vector)
 {
     VirtIOS390Device *dev = (VirtIOS390Device*)opaque;
     uint64_t token = s390_virtio_device_vq_token(dev, vector);
-    CPUS390XState *env = s390_cpu_addr2state(0);
+    S390CPU *cpu = s390_cpu_addr2state(0);
+    CPUS390XState *env = &cpu->env;
 
     s390_virtio_irq(env, 0, token);
 }
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index 49b3495..47eed35 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -61,9 +61,9 @@
 #define MAX_BLK_DEVS                    10
 
 static VirtIOS390Bus *s390_bus;
-static CPUS390XState **ipi_states;
+static S390CPU **ipi_states;
 
-CPUS390XState *s390_cpu_addr2state(uint16_t cpu_addr)
+S390CPU *s390_cpu_addr2state(uint16_t cpu_addr)
 {
     if (cpu_addr >= smp_cpus) {
         return NULL;
@@ -206,7 +206,7 @@ static void s390_init(ram_addr_t my_ram_size,
         cpu_model = "host";
     }
 
-    ipi_states = g_malloc(sizeof(CPUS390XState *) * smp_cpus);
+    ipi_states = g_malloc(sizeof(S390CPU *) * smp_cpus);
 
     for (i = 0; i < smp_cpus; i++) {
         S390CPU *cpu;
@@ -217,7 +217,7 @@ static void s390_init(ram_addr_t my_ram_size,
         if (!env) {
             env = tmp_env;
         }
-        ipi_states[i] = tmp_env;
+        ipi_states[i] = cpu;
         tmp_env->halted = 1;
         tmp_env->exception_index = EXCP_HLT;
         tmp_env->storage_keys = storage_keys;
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 10bfab0..c30ac3a 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -316,7 +316,7 @@ static inline void kvm_s390_interrupt_internal(CPUS390XState *env, int type,
 {
 }
 #endif
-CPUS390XState *s390_cpu_addr2state(uint16_t cpu_addr);
+S390CPU *s390_cpu_addr2state(uint16_t cpu_addr);
 void s390_add_running_cpu(CPUS390XState *env);
 unsigned s390_del_running_cpu(CPUS390XState *env);
 
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 90aad61..2153e38 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -333,6 +333,7 @@ static int handle_sigp(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1)
     uint16_t cpu_addr;
     uint8_t t;
     int r = -1;
+    S390CPU *target_cpu;
     CPUS390XState *target_env;
 
     cpu_synchronize_state(env);
@@ -353,10 +354,11 @@ static int handle_sigp(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1)
     parameter = env->regs[t] & 0x7ffffe00;
     cpu_addr = env->regs[ipa1 & 0x0f];
 
-    target_env = s390_cpu_addr2state(cpu_addr);
-    if (!target_env) {
+    target_cpu = s390_cpu_addr2state(cpu_addr);
+    if (target_cpu == NULL) {
         goto out;
     }
+    target_env = &target_cpu->env;
 
     switch (order_code) {
         case SIGP_RESTART:
commit 6fc150de80ffa9d3a7eba3e4f26793eb44347eda
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu May 3 04:16:07 2012 +0200

    s390-virtio: Use cpu_s390x_init() to obtain S390CPU
    
    Needed to store S390CPU in ipi_states[].
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index c0e19fd..49b3495 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -209,9 +209,11 @@ static void s390_init(ram_addr_t my_ram_size,
     ipi_states = g_malloc(sizeof(CPUS390XState *) * smp_cpus);
 
     for (i = 0; i < smp_cpus; i++) {
+        S390CPU *cpu;
         CPUS390XState *tmp_env;
 
-        tmp_env = cpu_init(cpu_model);
+        cpu = cpu_s390x_init(cpu_model);
+        tmp_env = &cpu->env;
         if (!env) {
             env = tmp_env;
         }
commit 564b863d8e4015d763acc6e4f010b031594fa7e5
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu May 3 04:13:04 2012 +0200

    target-s390x: Let cpu_s390x_init() return S390CPU
    
    Let cpu_init() return CPUS390XState for backwards compatibility.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
index f183213..619b202 100644
--- a/target-s390x/cpu.c
+++ b/target-s390x/cpu.c
@@ -20,7 +20,7 @@
  * <http://www.gnu.org/licenses/lgpl-2.1.html>
  */
 
-#include "cpu-qom.h"
+#include "cpu.h"
 #include "qemu-common.h"
 #include "qemu-timer.h"
 
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 2f3f394..10bfab0 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -105,6 +105,8 @@ typedef struct CPUS390XState {
     QEMUTimer *cpu_timer;
 } CPUS390XState;
 
+#include "cpu-qom.h"
+
 #if defined(CONFIG_USER_ONLY)
 static inline void cpu_clone_regs(CPUS390XState *env, target_ulong newsp)
 {
@@ -271,7 +273,7 @@ static inline int get_ilc(uint8_t opc)
 #define ILC_LATER_INC_2 0x22
 
 
-CPUS390XState *cpu_s390x_init(const char *cpu_model);
+S390CPU *cpu_s390x_init(const char *cpu_model);
 void s390x_translate_init(void);
 int cpu_s390x_exec(CPUS390XState *s);
 void cpu_s390x_close(CPUS390XState *s);
@@ -340,7 +342,7 @@ static inline void cpu_set_tls(CPUS390XState *env, target_ulong newtls)
     env->aregs[1] = newtls & 0xffffffffULL;
 }
 
-#define cpu_init cpu_s390x_init
+#define cpu_init(model) (&cpu_s390x_init(model)->env)
 #define cpu_exec cpu_s390x_exec
 #define cpu_gen_code cpu_s390x_gen_code
 #define cpu_signal_handler cpu_s390x_signal_handler
@@ -994,6 +996,4 @@ 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 a34a35b..d0a1180 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -70,7 +70,7 @@ void s390x_cpu_timer(void *opaque)
 }
 #endif
 
-CPUS390XState *cpu_s390x_init(const char *cpu_model)
+S390CPU *cpu_s390x_init(const char *cpu_model)
 {
     S390CPU *cpu;
     CPUS390XState *env;
@@ -86,7 +86,7 @@ CPUS390XState *cpu_s390x_init(const char *cpu_model)
 
     env->cpu_model_str = cpu_model;
     qemu_init_vcpu(env);
-    return env;
+    return cpu;
 }
 
 #if defined(CONFIG_USER_ONLY)
commit a0595d9eb85c64e00d03c4d696bb1028e99dfcbc
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed May 23 01:51:57 2012 +0200

    xen_machine_pv: Use cpu_x86_init() to obtain X86CPU
    
    Needed for moving halted field to CPUState.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Tested-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/hw/xen_machine_pv.c b/hw/xen_machine_pv.c
index 7eee770..4b72aa7 100644
--- a/hw/xen_machine_pv.c
+++ b/hw/xen_machine_pv.c
@@ -36,6 +36,7 @@ static void xen_init_pv(ram_addr_t ram_size,
 			const char *initrd_filename,
 			const char *cpu_model)
 {
+    X86CPU *cpu;
     CPUX86State *env;
     DriveInfo *dinfo;
     int i;
@@ -48,7 +49,8 @@ static void xen_init_pv(ram_addr_t ram_size,
         cpu_model = "qemu32";
 #endif
     }
-    env = cpu_init(cpu_model);
+    cpu = cpu_x86_init(cpu_model);
+    env = &cpu->env;
     env->halted = 1;
 
     /* Initialize backend core & drivers */
commit 4bd7466166b8c1b612c7f01a124b24ab2a0ace14
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon May 14 04:21:52 2012 +0200

    arm_pic: Pass ARMCPU to arm_pic_init_cpu()
    
    Pass it through to arm_pic_cpu_handler().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>
    Acked-by: Igor Mitsyanko <i.mitsyanko at samsung.com> (for exynos)

diff --git a/hw/arm-misc.h b/hw/arm-misc.h
index b7f4c32..1d51570 100644
--- a/hw/arm-misc.h
+++ b/hw/arm-misc.h
@@ -16,7 +16,7 @@
 /* The CPU is also modeled as an interrupt controller.  */
 #define ARM_PIC_CPU_IRQ 0
 #define ARM_PIC_CPU_FIQ 1
-qemu_irq *arm_pic_init_cpu(CPUARMState *env);
+qemu_irq *arm_pic_init_cpu(ARMCPU *cpu);
 
 /* armv7m.c */
 qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
diff --git a/hw/arm_pic.c b/hw/arm_pic.c
index 1094965..ffb4d41 100644
--- a/hw/arm_pic.c
+++ b/hw/arm_pic.c
@@ -13,7 +13,9 @@
 /* Input 0 is IRQ and input 1 is FIQ.  */
 static void arm_pic_cpu_handler(void *opaque, int irq, int level)
 {
-    CPUARMState *env = (CPUARMState *)opaque;
+    ARMCPU *cpu = opaque;
+    CPUARMState *env = &cpu->env;
+
     switch (irq) {
     case ARM_PIC_CPU_IRQ:
         if (level)
@@ -32,7 +34,7 @@ static void arm_pic_cpu_handler(void *opaque, int irq, int level)
     }
 }
 
-qemu_irq *arm_pic_init_cpu(CPUARMState *env)
+qemu_irq *arm_pic_init_cpu(ARMCPU *cpu)
 {
-    return qemu_allocate_irqs(arm_pic_cpu_handler, env, 2);
+    return qemu_allocate_irqs(arm_pic_cpu_handler, cpu, 2);
 }
diff --git a/hw/armv7m.c b/hw/armv7m.c
index 418139a..8cec78d 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -215,7 +215,7 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
     nvic = qdev_create(NULL, "armv7m_nvic");
     env->nvic = nvic;
     qdev_init_nofail(nvic);
-    cpu_pic = arm_pic_init_cpu(env);
+    cpu_pic = arm_pic_init_cpu(cpu);
     sysbus_connect_irq(sysbus_from_qdev(nvic), 0, cpu_pic[ARM_PIC_CPU_IRQ]);
     for (i = 0; i < 64; i++) {
         pic[i] = qdev_get_gpio_in(nvic, i);
diff --git a/hw/exynos4210.c b/hw/exynos4210.c
index 7dc3787..dd14d01 100644
--- a/hw/exynos4210.c
+++ b/hw/exynos4210.c
@@ -112,8 +112,9 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
             fprintf(stderr, "Unable to find CPU %d definition\n", n);
             exit(1);
         }
+
         /* Create PIC controller for each processor instance */
-        irqp = arm_pic_init_cpu(&s->cpu[n]->env);
+        irqp = arm_pic_init_cpu(s->cpu[n]);
 
         /*
          * Get GICs gpio_in cpu_irq to connect a combiner to them later.
diff --git a/hw/highbank.c b/hw/highbank.c
index a3901b0..4bdea5d 100644
--- a/hw/highbank.c
+++ b/hw/highbank.c
@@ -192,7 +192,6 @@ static void highbank_init(ram_addr_t ram_size,
                      const char *kernel_filename, const char *kernel_cmdline,
                      const char *initrd_filename, const char *cpu_model)
 {
-    CPUARMState *env = NULL;
     DeviceState *dev;
     SysBusDevice *busdev;
     qemu_irq *irqp;
@@ -215,10 +214,10 @@ static void highbank_init(ram_addr_t ram_size,
             fprintf(stderr, "Unable to find CPU definition\n");
             exit(1);
         }
-        env = &cpu->env;
+
         /* This will become a QOM property eventually */
         cpu->reset_cbar = GIC_BASE_ADDR;
-        irqp = arm_pic_init_cpu(env);
+        irqp = arm_pic_init_cpu(cpu);
         cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
     }
 
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index e927012..deacbf4 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -476,7 +476,7 @@ static void integratorcp_init(ram_addr_t ram_size,
     qdev_init_nofail(dev);
     sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000);
 
-    cpu_pic = arm_pic_init_cpu(&cpu->env);
+    cpu_pic = arm_pic_init_cpu(cpu);
     dev = sysbus_create_varargs("integrator_pic", 0x14000000,
                                 cpu_pic[ARM_PIC_CPU_IRQ],
                                 cpu_pic[ARM_PIC_CPU_FIQ], NULL);
diff --git a/hw/musicpal.c b/hw/musicpal.c
index cef847e..f14f20d 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -1538,7 +1538,7 @@ static void musicpal_init(ram_addr_t ram_size,
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
-    cpu_pic = arm_pic_init_cpu(&cpu->env);
+    cpu_pic = arm_pic_init_cpu(cpu);
 
     /* For now we use a fixed - the original - RAM size */
     memory_region_init_ram(ram, "musicpal.ram", MP_RAM_DEFAULT_SIZE);
diff --git a/hw/omap1.c b/hw/omap1.c
index a997d30..ad60cc4 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -3854,7 +3854,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
 
     omap_clkm_init(system_memory, 0xfffece00, 0xe1008000, s);
 
-    cpu_irq = arm_pic_init_cpu(&s->cpu->env);
+    cpu_irq = arm_pic_init_cpu(s->cpu);
     s->ih[0] = qdev_create(NULL, "omap-intc");
     qdev_prop_set_uint32(s->ih[0], "size", 0x100);
     qdev_prop_set_ptr(s->ih[0], "clk", omap_findclk(s, "arminth_ck"));
diff --git a/hw/omap2.c b/hw/omap2.c
index 196c4b6..4278dd1 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -2277,7 +2277,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
     s->l4 = omap_l4_init(sysmem, OMAP2_L4_BASE, 54);
 
     /* Actually mapped at any 2K boundary in the ARM11 private-peripheral if */
-    cpu_irq = arm_pic_init_cpu(&s->cpu->env);
+    cpu_irq = arm_pic_init_cpu(s->cpu);
     s->ih[0] = qdev_create(NULL, "omap2-intc");
     qdev_prop_set_uint8(s->ih[0], "revision", 0x21);
     qdev_prop_set_ptr(s->ih[0], "fclk", omap_findclk(s, "mpu_intc_fclk"));
diff --git a/hw/realview.c b/hw/realview.c
index 38085f1..19db4d0 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -94,7 +94,7 @@ static void realview_init(ram_addr_t ram_size,
             fprintf(stderr, "Unable to find CPU definition\n");
             exit(1);
         }
-        irqp = arm_pic_init_cpu(&cpu->env);
+        irqp = arm_pic_init_cpu(cpu);
         cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
     }
     env = &cpu->env;
diff --git a/hw/strongarm.c b/hw/strongarm.c
index 38b1d0c..7150eeb 100644
--- a/hw/strongarm.c
+++ b/hw/strongarm.c
@@ -1574,7 +1574,7 @@ StrongARMState *sa1110_init(MemoryRegion *sysmem,
     vmstate_register_ram_global(&s->sdram);
     memory_region_add_subregion(sysmem, SA_SDCS0, &s->sdram);
 
-    pic = arm_pic_init_cpu(&s->cpu->env);
+    pic = arm_pic_init_cpu(s->cpu);
     s->pic = sysbus_create_varargs("strongarm_pic", 0x90050000,
                     pic[ARM_PIC_CPU_IRQ], pic[ARM_PIC_CPU_FIQ], NULL);
 
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index ed54fdd..4fd5d9b 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -209,7 +209,7 @@ static void versatile_init(ram_addr_t ram_size,
     qdev_init_nofail(sysctl);
     sysbus_mmio_map(sysbus_from_qdev(sysctl), 0, 0x10000000);
 
-    cpu_pic = arm_pic_init_cpu(&cpu->env);
+    cpu_pic = arm_pic_init_cpu(cpu);
     dev = sysbus_create_varargs("pl190", 0x10140000,
                                 cpu_pic[0], cpu_pic[1], NULL);
     for (n = 0; n < 32; n++) {
diff --git a/hw/vexpress.c b/hw/vexpress.c
index 4797c6a..8072c5a 100644
--- a/hw/vexpress.c
+++ b/hw/vexpress.c
@@ -181,7 +181,7 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
             fprintf(stderr, "Unable to find CPU definition\n");
             exit(1);
         }
-        irqp = arm_pic_init_cpu(&cpu->env);
+        irqp = arm_pic_init_cpu(cpu);
         cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
     }
 
@@ -280,7 +280,7 @@ static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
             fprintf(stderr, "Unable to find CPU definition\n");
             exit(1);
         }
-        irqp = arm_pic_init_cpu(&cpu->env);
+        irqp = arm_pic_init_cpu(cpu);
         cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
     }
 
diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c
index 11026cb..7e6c273 100644
--- a/hw/xilinx_zynq.c
+++ b/hw/xilinx_zynq.c
@@ -71,7 +71,7 @@ static void zynq_init(ram_addr_t ram_size, const char *boot_device,
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
-    irqp = arm_pic_init_cpu(&cpu->env);
+    irqp = arm_pic_init_cpu(cpu);
     cpu_irq = irqp[ARM_PIC_CPU_IRQ];
 
     /* max 2GB ram */
commit 3aaa8dfae955d7bec462cc4e2fce185ef6d41b5a
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon May 14 02:39:57 2012 +0200

    arm_boot: Pass ARMCPU to arm_load_kernel()
    
    In particular this simplifies the &s->mpu->cpu->env expression again.
    
    first_cpu and ->next_cpu are expected to be QOM'ified later.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Igor Mitsyanko <i.mitsyanko at samsung.com> (for exynos)
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm-misc.h b/hw/arm-misc.h
index bbd6fd3..b7f4c32 100644
--- a/hw/arm-misc.h
+++ b/hw/arm-misc.h
@@ -59,7 +59,7 @@ struct arm_boot_info {
     target_phys_addr_t initrd_size;
     target_phys_addr_t entry;
 };
-void arm_load_kernel(CPUARMState *env, struct arm_boot_info *info);
+void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info);
 
 /* Multiplication factor to convert from system clock ticks to qemu timer
    ticks.  */
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index 8eabfb2..d0e643b 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -303,9 +303,9 @@ static void do_cpu_reset(void *opaque)
     }
 }
 
-void arm_load_kernel(CPUARMState *env, struct arm_boot_info *info)
+void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
 {
-    ARMCPU *cpu = arm_env_get_cpu(env);
+    CPUARMState *env = &cpu->env;
     int kernel_size;
     int initrd_size;
     int n;
diff --git a/hw/collie.c b/hw/collie.c
index e6f8dbf..56f89a9 100644
--- a/hw/collie.c
+++ b/hw/collie.c
@@ -54,7 +54,7 @@ static void collie_init(ram_addr_t ram_size,
     collie_binfo.kernel_cmdline = kernel_cmdline;
     collie_binfo.initrd_filename = initrd_filename;
     collie_binfo.board_id = 0x208;
-    arm_load_kernel(&s->cpu->env, &collie_binfo);
+    arm_load_kernel(s->cpu, &collie_binfo);
 }
 
 static QEMUMachine collie_machine = {
diff --git a/hw/exynos4_boards.c b/hw/exynos4_boards.c
index ea32c51..e5c2a5f 100644
--- a/hw/exynos4_boards.c
+++ b/hw/exynos4_boards.c
@@ -138,7 +138,7 @@ static void nuri_init(ram_addr_t ram_size,
     exynos4_boards_init_common(kernel_filename, kernel_cmdline,
                 initrd_filename, EXYNOS4_BOARD_NURI);
 
-    arm_load_kernel(first_cpu, &exynos4_board_binfo);
+    arm_load_kernel(arm_env_get_cpu(first_cpu), &exynos4_board_binfo);
 }
 
 static void smdkc210_init(ram_addr_t ram_size,
@@ -151,7 +151,7 @@ static void smdkc210_init(ram_addr_t ram_size,
 
     lan9215_init(SMDK_LAN9118_BASE_ADDR,
             qemu_irq_invert(s->irq_table[exynos4210_get_irq(37, 1)]));
-    arm_load_kernel(first_cpu, &exynos4_board_binfo);
+    arm_load_kernel(arm_env_get_cpu(first_cpu), &exynos4_board_binfo);
 }
 
 static QEMUMachine exynos4_machines[EXYNOS4_NUM_OF_BOARDS] = {
diff --git a/hw/highbank.c b/hw/highbank.c
index 66ff042..a3901b0 100644
--- a/hw/highbank.c
+++ b/hw/highbank.c
@@ -318,7 +318,7 @@ static void highbank_init(ram_addr_t ram_size,
     highbank_binfo.loader_start = 0;
     highbank_binfo.write_secondary_boot = hb_write_secondary;
     highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary;
-    arm_load_kernel(first_cpu, &highbank_binfo);
+    arm_load_kernel(arm_env_get_cpu(first_cpu), &highbank_binfo);
 }
 
 static QEMUMachine highbank_machine = {
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index 46fd09d..e927012 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -502,7 +502,7 @@ static void integratorcp_init(ram_addr_t ram_size,
     integrator_binfo.kernel_filename = kernel_filename;
     integrator_binfo.kernel_cmdline = kernel_cmdline;
     integrator_binfo.initrd_filename = initrd_filename;
-    arm_load_kernel(&cpu->env, &integrator_binfo);
+    arm_load_kernel(cpu, &integrator_binfo);
 }
 
 static QEMUMachine integratorcp_machine = {
diff --git a/hw/mainstone.c b/hw/mainstone.c
index 17c68f6..97687b6 100644
--- a/hw/mainstone.c
+++ b/hw/mainstone.c
@@ -168,7 +168,7 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
     mainstone_binfo.kernel_cmdline = kernel_cmdline;
     mainstone_binfo.initrd_filename = initrd_filename;
     mainstone_binfo.board_id = arm_id;
-    arm_load_kernel(&mpu->cpu->env, &mainstone_binfo);
+    arm_load_kernel(mpu->cpu, &mainstone_binfo);
 }
 
 static void mainstone_init(ram_addr_t ram_size,
diff --git a/hw/musicpal.c b/hw/musicpal.c
index b7fed39..cef847e 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -1651,7 +1651,7 @@ static void musicpal_init(ram_addr_t ram_size,
     musicpal_binfo.kernel_filename = kernel_filename;
     musicpal_binfo.kernel_cmdline = kernel_cmdline;
     musicpal_binfo.initrd_filename = initrd_filename;
-    arm_load_kernel(&cpu->env, &musicpal_binfo);
+    arm_load_kernel(cpu, &musicpal_binfo);
 }
 
 static QEMUMachine musicpal_machine = {
diff --git a/hw/nseries.c b/hw/nseries.c
index b199cb9..fcc8546 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -1329,7 +1329,7 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
         binfo->kernel_filename = kernel_filename;
         binfo->kernel_cmdline = kernel_cmdline;
         binfo->initrd_filename = initrd_filename;
-        arm_load_kernel(&s->mpu->cpu->env, binfo);
+        arm_load_kernel(s->mpu->cpu, binfo);
 
         qemu_register_reset(n8x0_boot_init, s);
     }
diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c
index b64e1eb..abca341 100644
--- a/hw/omap_sx1.c
+++ b/hw/omap_sx1.c
@@ -202,7 +202,7 @@ static void sx1_init(ram_addr_t ram_size,
         sx1_binfo.kernel_filename = kernel_filename;
         sx1_binfo.kernel_cmdline = kernel_cmdline;
         sx1_binfo.initrd_filename = initrd_filename;
-        arm_load_kernel(&mpu->cpu->env, &sx1_binfo);
+        arm_load_kernel(mpu->cpu, &sx1_binfo);
     }
 
     /* TODO: fix next line */
diff --git a/hw/palm.c b/hw/palm.c
index 1375b19..bacdc90 100644
--- a/hw/palm.c
+++ b/hw/palm.c
@@ -265,7 +265,7 @@ static void palmte_init(ram_addr_t ram_size,
         palmte_binfo.kernel_filename = kernel_filename;
         palmte_binfo.kernel_cmdline = kernel_cmdline;
         palmte_binfo.initrd_filename = initrd_filename;
-        arm_load_kernel(&mpu->cpu->env, &palmte_binfo);
+        arm_load_kernel(mpu->cpu, &palmte_binfo);
     }
 
     /* FIXME: We shouldn't really be doing this here.  The LCD controller
diff --git a/hw/realview.c b/hw/realview.c
index 583993c..38085f1 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -327,7 +327,7 @@ static void realview_init(ram_addr_t ram_size,
     realview_binfo.nb_cpus = smp_cpus;
     realview_binfo.board_id = realview_board_id[board_type];
     realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0);
-    arm_load_kernel(first_cpu, &realview_binfo);
+    arm_load_kernel(arm_env_get_cpu(first_cpu), &realview_binfo);
 }
 
 static void realview_eb_init(ram_addr_t ram_size,
diff --git a/hw/spitz.c b/hw/spitz.c
index d320633..20e7835 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -932,7 +932,7 @@ static void spitz_common_init(ram_addr_t ram_size,
     spitz_binfo.kernel_cmdline = kernel_cmdline;
     spitz_binfo.initrd_filename = initrd_filename;
     spitz_binfo.board_id = arm_id;
-    arm_load_kernel(&mpu->cpu->env, &spitz_binfo);
+    arm_load_kernel(mpu->cpu, &spitz_binfo);
     sl_bootparam_write(SL_PXA_PARAM_BASE);
 }
 
diff --git a/hw/tosa.c b/hw/tosa.c
index 8bae80d..297a8c2 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -242,7 +242,7 @@ static void tosa_init(ram_addr_t ram_size,
     tosa_binfo.kernel_cmdline = kernel_cmdline;
     tosa_binfo.initrd_filename = initrd_filename;
     tosa_binfo.board_id = 0x208;
-    arm_load_kernel(&mpu->cpu->env, &tosa_binfo);
+    arm_load_kernel(mpu->cpu, &tosa_binfo);
     sl_bootparam_write(SL_PXA_PARAM_BASE);
 }
 
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index d567af9..ed54fdd 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -339,7 +339,7 @@ static void versatile_init(ram_addr_t ram_size,
     versatile_binfo.kernel_cmdline = kernel_cmdline;
     versatile_binfo.initrd_filename = initrd_filename;
     versatile_binfo.board_id = board_id;
-    arm_load_kernel(&cpu->env, &versatile_binfo);
+    arm_load_kernel(cpu, &versatile_binfo);
 }
 
 static void vpb_init(ram_addr_t ram_size,
diff --git a/hw/vexpress.c b/hw/vexpress.c
index e957f43..4797c6a 100644
--- a/hw/vexpress.c
+++ b/hw/vexpress.c
@@ -438,7 +438,7 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard,
     vexpress_binfo.smp_loader_start = map[VE_SRAM];
     vexpress_binfo.smp_bootreg_addr = map[VE_SYSREGS] + 0x30;
     vexpress_binfo.gic_cpu_if_addr = daughterboard->gic_cpu_if_addr;
-    arm_load_kernel(first_cpu, &vexpress_binfo);
+    arm_load_kernel(arm_env_get_cpu(first_cpu), &vexpress_binfo);
 }
 
 static void vexpress_a9_init(ram_addr_t ram_size,
diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c
index 68349e2..11026cb 100644
--- a/hw/xilinx_zynq.c
+++ b/hw/xilinx_zynq.c
@@ -137,7 +137,7 @@ static void zynq_init(ram_addr_t ram_size, const char *boot_device,
     zynq_binfo.nb_cpus = 1;
     zynq_binfo.board_id = 0xd32;
     zynq_binfo.loader_start = 0;
-    arm_load_kernel(first_cpu, &zynq_binfo);
+    arm_load_kernel(arm_env_get_cpu(first_cpu), &zynq_binfo);
 }
 
 static QEMUMachine zynq_machine = {
diff --git a/hw/z2.c b/hw/z2.c
index db25cdc..289cee9 100644
--- a/hw/z2.c
+++ b/hw/z2.c
@@ -363,7 +363,7 @@ static void z2_init(ram_addr_t ram_size,
         z2_binfo.kernel_cmdline = kernel_cmdline;
         z2_binfo.initrd_filename = initrd_filename;
         z2_binfo.board_id = 0x6dd;
-        arm_load_kernel(&mpu->cpu->env, &z2_binfo);
+        arm_load_kernel(mpu->cpu, &z2_binfo);
     }
 }
 
commit 17c2f0bf37182d46d66998bf037b2cac520d2183
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon May 14 02:55:25 2012 +0200

    xilinx_zynq: Use cpu_arm_init() to obtain ARMCPU
    
    Needed for arm_load_kernel().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter A.G. Crosthwaite <peter.crosthwaite at petalogix.com>

diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c
index 7290c64..68349e2 100644
--- a/hw/xilinx_zynq.c
+++ b/hw/xilinx_zynq.c
@@ -50,7 +50,7 @@ static void zynq_init(ram_addr_t ram_size, const char *boot_device,
                         const char *kernel_filename, const char *kernel_cmdline,
                         const char *initrd_filename, const char *cpu_model)
 {
-    CPUARMState *env = NULL;
+    ARMCPU *cpu;
     MemoryRegion *address_space_mem = get_system_memory();
     MemoryRegion *ext_ram = g_new(MemoryRegion, 1);
     MemoryRegion *ocm_ram = g_new(MemoryRegion, 1);
@@ -66,12 +66,12 @@ static void zynq_init(ram_addr_t ram_size, const char *boot_device,
         cpu_model = "cortex-a9";
     }
 
-    env = cpu_init(cpu_model);
-    if (!env) {
+    cpu = cpu_arm_init(cpu_model);
+    if (!cpu) {
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
-    irqp = arm_pic_init_cpu(env);
+    irqp = arm_pic_init_cpu(&cpu->env);
     cpu_irq = irqp[ARM_PIC_CPU_IRQ];
 
     /* max 2GB ram */
commit 95d42bb5d793e3c61e684db3c0e9b714ea6cd549
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 00:23:14 2012 +0200

    pxa2xx_gpio: Store ARMCPU in PXA2xxGPIOInfo
    
    Prepares for moving halted field into CPUState.
    
    Add missing braces.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index 09a408b..3c90c9c 100644
--- a/hw/pxa2xx_gpio.c
+++ b/hw/pxa2xx_gpio.c
@@ -20,7 +20,7 @@ struct PXA2xxGPIOInfo {
     qemu_irq irq0, irq1, irqX;
     int lines;
     int ncpu;
-    CPUARMState *cpu_env;
+    ARMCPU *cpu;
 
     /* XXX: GNU C vectors are more suitable */
     uint32_t ilevel[PXA2XX_GPIO_BANKS];
@@ -118,8 +118,9 @@ static void pxa2xx_gpio_set(void *opaque, int line, int level)
         pxa2xx_gpio_irq_update(s);
 
     /* Wake-up GPIOs */
-    if (s->cpu_env->halted && (mask & ~s->dir[bank] & pxa2xx_gpio_wake[bank]))
-        cpu_interrupt(s->cpu_env, CPU_INTERRUPT_EXITTB);
+    if (s->cpu->env.halted && (mask & ~s->dir[bank] & pxa2xx_gpio_wake[bank])) {
+        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_EXITTB);
+    }
 }
 
 static void pxa2xx_gpio_handler_update(PXA2xxGPIOInfo *s) {
@@ -275,7 +276,7 @@ static int pxa2xx_gpio_initfn(SysBusDevice *dev)
 
     s = FROM_SYSBUS(PXA2xxGPIOInfo, dev);
 
-    s->cpu_env = qemu_get_cpu(s->ncpu);
+    s->cpu = arm_env_get_cpu(qemu_get_cpu(s->ncpu));
 
     qdev_init_gpio_in(&dev->qdev, pxa2xx_gpio_set, s->lines);
     qdev_init_gpio_out(&dev->qdev, s->handler, s->lines);
commit e9d872cfe16d65f36835792d6b74d6b80024c4cf
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 00:05:29 2012 +0200

    pxa2xx_pic: Store ARMCPU in PXA2xxPICState
    
    Prepares for moving halted field to CPUState.
    
    Add missing braces.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index 255cc3f..c560133 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -34,7 +34,7 @@
 typedef struct {
     SysBusDevice busdev;
     MemoryRegion iomem;
-    CPUARMState *cpu_env;
+    ARMCPU *cpu;
     uint32_t int_enabled[2];
     uint32_t int_pending[2];
     uint32_t is_fiq[2];
@@ -47,25 +47,28 @@ static void pxa2xx_pic_update(void *opaque)
     uint32_t mask[2];
     PXA2xxPICState *s = (PXA2xxPICState *) opaque;
 
-    if (s->cpu_env->halted) {
+    if (s->cpu->env.halted) {
         mask[0] = s->int_pending[0] & (s->int_enabled[0] | s->int_idle);
         mask[1] = s->int_pending[1] & (s->int_enabled[1] | s->int_idle);
-        if (mask[0] || mask[1])
-            cpu_interrupt(s->cpu_env, CPU_INTERRUPT_EXITTB);
+        if (mask[0] || mask[1]) {
+            cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_EXITTB);
+        }
     }
 
     mask[0] = s->int_pending[0] & s->int_enabled[0];
     mask[1] = s->int_pending[1] & s->int_enabled[1];
 
-    if ((mask[0] & s->is_fiq[0]) || (mask[1] & s->is_fiq[1]))
-        cpu_interrupt(s->cpu_env, CPU_INTERRUPT_FIQ);
-    else
-        cpu_reset_interrupt(s->cpu_env, CPU_INTERRUPT_FIQ);
+    if ((mask[0] & s->is_fiq[0]) || (mask[1] & s->is_fiq[1])) {
+        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_FIQ);
+    } else {
+        cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_FIQ);
+    }
 
-    if ((mask[0] & ~s->is_fiq[0]) || (mask[1] & ~s->is_fiq[1]))
-        cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
-    else
-        cpu_reset_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
+    if ((mask[0] & ~s->is_fiq[0]) || (mask[1] & ~s->is_fiq[1])) {
+        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
+    } else {
+        cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
+    }
 }
 
 /* Note: Here level means state of the signal on a pin, not
@@ -251,7 +254,7 @@ DeviceState *pxa2xx_pic_init(target_phys_addr_t base, ARMCPU *cpu)
     DeviceState *dev = qdev_create(NULL, "pxa2xx_pic");
     PXA2xxPICState *s = FROM_SYSBUS(PXA2xxPICState, sysbus_from_qdev(dev));
 
-    s->cpu_env = env;
+    s->cpu = cpu;
 
     s->int_pending[0] = 0;
     s->int_pending[1] = 0;
commit f161bcd05fca4902ce680a37314b49586b5a8b2e
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 00:01:27 2012 +0200

    pxa2xx: Pass ARMCPU to pxa2xx_pic_init()
    
    Cleans up after storing ARMCPU in PXA2xxState.
    Prepares for storing ARMCPU in PXA2xxPICState.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/pxa.h b/hw/pxa.h
index 2be006d..6a21205 100644
--- a/hw/pxa.h
+++ b/hw/pxa.h
@@ -65,7 +65,7 @@
 # define PXA2XX_INTERNAL_SIZE	0x40000
 
 /* pxa2xx_pic.c */
-DeviceState *pxa2xx_pic_init(target_phys_addr_t base, CPUARMState *env);
+DeviceState *pxa2xx_pic_init(target_phys_addr_t base, ARMCPU *cpu);
 
 /* pxa2xx_gpio.c */
 DeviceState *pxa2xx_gpio_init(target_phys_addr_t base,
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 5f8f226..7958d14 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -2081,7 +2081,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
     memory_region_add_subregion(address_space, PXA2XX_INTERNAL_BASE,
                                 &s->internal);
 
-    s->pic = pxa2xx_pic_init(0x40d00000, &s->cpu->env);
+    s->pic = pxa2xx_pic_init(0x40d00000, s->cpu);
 
     s->dma = pxa27x_dma_init(0x40000000,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_DMA));
@@ -2213,7 +2213,7 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
     memory_region_add_subregion(address_space, PXA2XX_INTERNAL_BASE,
                                 &s->internal);
 
-    s->pic = pxa2xx_pic_init(0x40d00000, &s->cpu->env);
+    s->pic = pxa2xx_pic_init(0x40d00000, s->cpu);
 
     s->dma = pxa255_dma_init(0x40000000,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_DMA));
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index a806b80..255cc3f 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -245,8 +245,9 @@ static int pxa2xx_pic_post_load(void *opaque, int version_id)
     return 0;
 }
 
-DeviceState *pxa2xx_pic_init(target_phys_addr_t base, CPUARMState *env)
+DeviceState *pxa2xx_pic_init(target_phys_addr_t base, ARMCPU *cpu)
 {
+    CPUARMState *env = &cpu->env;
     DeviceState *dev = qdev_create(NULL, "pxa2xx_pic");
     PXA2xxPICState *s = FROM_SYSBUS(PXA2xxPICState, sysbus_from_qdev(dev));
 
commit ef6cbcc584c6b044016677147da0a7c3632d0e6f
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon May 14 04:09:55 2012 +0200

    exynos4210: Use cpu_arm_init() to store ARMCPU
    
    Needed for arm_pic_init_cpu().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>
    Acked-by: Igor Mitsyanko <i.mitsyanko at samsung.com>

diff --git a/hw/exynos4210.c b/hw/exynos4210.c
index ae53837..7dc3787 100644
--- a/hw/exynos4210.c
+++ b/hw/exynos4210.c
@@ -107,13 +107,13 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
     SysBusDevice *busdev;
 
     for (n = 0; n < EXYNOS4210_NCPUS; n++) {
-        s->env[n] = cpu_init("cortex-a9");
-        if (!s->env[n]) {
+        s->cpu[n] = cpu_arm_init("cortex-a9");
+        if (!s->cpu[n]) {
             fprintf(stderr, "Unable to find CPU %d definition\n", n);
             exit(1);
         }
         /* Create PIC controller for each processor instance */
-        irqp = arm_pic_init_cpu(s->env[n]);
+        irqp = arm_pic_init_cpu(&s->cpu[n]->env);
 
         /*
          * Get GICs gpio_in cpu_irq to connect a combiner to them later.
diff --git a/hw/exynos4210.h b/hw/exynos4210.h
index b520676..b1b4609 100644
--- a/hw/exynos4210.h
+++ b/hw/exynos4210.h
@@ -83,7 +83,7 @@ typedef struct Exynos4210Irq {
 } Exynos4210Irq;
 
 typedef struct Exynos4210State {
-    CPUARMState * env[EXYNOS4210_NCPUS];
+    ARMCPU *cpu[EXYNOS4210_NCPUS];
     Exynos4210Irq irqs;
     qemu_irq *irq_table;
 
commit 64c9e29708b36caefa6b9e8e7ae48fbc93989400
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon May 14 03:58:46 2012 +0200

    vexpress: Use cpu_arm_init() to obtain ARMCPU
    
    Needed for arm_pic_init_cpu().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/vexpress.c b/hw/vexpress.c
index 18d87ac..e957f43 100644
--- a/hw/vexpress.c
+++ b/hw/vexpress.c
@@ -159,7 +159,6 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
                                   const char *cpu_model,
                                   qemu_irq *pic, uint32_t *proc_id)
 {
-    CPUARMState *env = NULL;
     MemoryRegion *sysmem = get_system_memory();
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     MemoryRegion *lowram = g_new(MemoryRegion, 1);
@@ -177,12 +176,12 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
     *proc_id = 0x0c000191;
 
     for (n = 0; n < smp_cpus; n++) {
-        env = cpu_init(cpu_model);
-        if (!env) {
+        ARMCPU *cpu = cpu_arm_init(cpu_model);
+        if (!cpu) {
             fprintf(stderr, "Unable to find CPU definition\n");
             exit(1);
         }
-        irqp = arm_pic_init_cpu(env);
+        irqp = arm_pic_init_cpu(&cpu->env);
         cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
     }
 
@@ -259,7 +258,6 @@ static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
                                    qemu_irq *pic, uint32_t *proc_id)
 {
     int n;
-    CPUARMState *env = NULL;
     MemoryRegion *sysmem = get_system_memory();
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     MemoryRegion *sram = g_new(MemoryRegion, 1);
@@ -274,13 +272,15 @@ static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
     *proc_id = 0x14000217;
 
     for (n = 0; n < smp_cpus; n++) {
+        ARMCPU *cpu;
         qemu_irq *irqp;
-        env = cpu_init(cpu_model);
-        if (!env) {
+
+        cpu = cpu_arm_init(cpu_model);
+        if (!cpu) {
             fprintf(stderr, "Unable to find CPU definition\n");
             exit(1);
         }
-        irqp = arm_pic_init_cpu(env);
+        irqp = arm_pic_init_cpu(&cpu->env);
         cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
     }
 
commit 9077f01b45ee035b8789ba8b4bc469de165bde75
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon May 14 03:50:56 2012 +0200

    realview: Use cpu_arm_init() to obtain ARMCPU
    
    Needed for arm_pic_init_cpu().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/realview.c b/hw/realview.c
index ecf4701..583993c 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -50,7 +50,8 @@ static void realview_init(ram_addr_t ram_size,
                      const char *initrd_filename, const char *cpu_model,
                      enum realview_board_type board_type)
 {
-    CPUARMState *env = NULL;
+    ARMCPU *cpu = NULL;
+    CPUARMState *env;
     MemoryRegion *sysmem = get_system_memory();
     MemoryRegion *ram_lo = g_new(MemoryRegion, 1);
     MemoryRegion *ram_hi = g_new(MemoryRegion, 1);
@@ -88,14 +89,15 @@ static void realview_init(ram_addr_t ram_size,
         break;
     }
     for (n = 0; n < smp_cpus; n++) {
-        env = cpu_init(cpu_model);
-        if (!env) {
+        cpu = cpu_arm_init(cpu_model);
+        if (!cpu) {
             fprintf(stderr, "Unable to find CPU definition\n");
             exit(1);
         }
-        irqp = arm_pic_init_cpu(env);
+        irqp = arm_pic_init_cpu(&cpu->env);
         cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
     }
+    env = &cpu->env;
     if (arm_feature(env, ARM_FEATURE_V7)) {
         if (is_mpcore) {
             proc_id = 0x0c000000;
commit 5d309320e3e419187b48b4537d403daf95835bc6
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon May 14 01:05:40 2012 +0200

    arm_boot: Pass ARMCPU to arm_boot_info::secondary_cpu_reset_hook()
    
    Adapt highbank accordingly.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm-misc.h b/hw/arm-misc.h
index 320033d..bbd6fd3 100644
--- a/hw/arm-misc.h
+++ b/hw/arm-misc.h
@@ -52,7 +52,7 @@ struct arm_boot_info {
      */
     void (*write_secondary_boot)(ARMCPU *cpu,
                                  const struct arm_boot_info *info);
-    void (*secondary_cpu_reset_hook)(CPUARMState *env,
+    void (*secondary_cpu_reset_hook)(ARMCPU *cpu,
                                      const struct arm_boot_info *info);
     /* Used internally by arm_boot.c */
     int is_linux;
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index 4955f01..8eabfb2 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -72,9 +72,11 @@ static void default_write_secondary(ARMCPU *cpu,
                        info->smp_loader_start);
 }
 
-static void default_reset_secondary(CPUARMState *env,
+static void default_reset_secondary(ARMCPU *cpu,
                                     const struct arm_boot_info *info)
 {
+    CPUARMState *env = &cpu->env;
+
     stl_phys_notdirty(info->smp_bootreg_addr, 0);
     env->regs[15] = info->smp_loader_start;
 }
@@ -295,7 +297,7 @@ static void do_cpu_reset(void *opaque)
                     }
                 }
             } else {
-                info->secondary_cpu_reset_hook(env, info);
+                info->secondary_cpu_reset_hook(cpu, info);
             }
         }
     }
diff --git a/hw/highbank.c b/hw/highbank.c
index 45ca1ad..66ff042 100644
--- a/hw/highbank.c
+++ b/hw/highbank.c
@@ -60,8 +60,10 @@ static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
     rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR);
 }
 
-static void hb_reset_secondary(CPUARMState *env, const struct arm_boot_info *info)
+static void hb_reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
 {
+    CPUARMState *env = &cpu->env;
+
     switch (info->nb_cpus) {
     case 4:
         stl_phys_notdirty(SMP_BOOT_REG + 0x30, 0);
commit 9543b0cdd64ac0ba109b92eaf00e458b6223a6a8
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon May 14 00:08:10 2012 +0200

    arm_boot: Pass ARMCPU to arm_boot_info::write_secondary_boot()
    
    Adapt exynos4210 and highbank accordingly.
    The parameter itself is unused.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>
    Acked-by: Igor Mitsyanko <i.mitsyanko at samsung.com> (for exynos)

diff --git a/hw/arm-misc.h b/hw/arm-misc.h
index 2f46e21..320033d 100644
--- a/hw/arm-misc.h
+++ b/hw/arm-misc.h
@@ -50,7 +50,7 @@ struct arm_boot_info {
      * perform any necessary CPU reset handling and set the PC for thei
      * secondary CPUs to point at this boot blob.
      */
-    void (*write_secondary_boot)(CPUARMState *env,
+    void (*write_secondary_boot)(ARMCPU *cpu,
                                  const struct arm_boot_info *info);
     void (*secondary_cpu_reset_hook)(CPUARMState *env,
                                      const struct arm_boot_info *info);
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index eb2d176..4955f01 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -59,7 +59,7 @@ static uint32_t smpboot[] = {
   0           /* bootreg: Boot register address is held here */
 };
 
-static void default_write_secondary(CPUARMState *env,
+static void default_write_secondary(ARMCPU *cpu,
                                     const struct arm_boot_info *info)
 {
     int n;
@@ -303,7 +303,7 @@ static void do_cpu_reset(void *opaque)
 
 void arm_load_kernel(CPUARMState *env, struct arm_boot_info *info)
 {
-    ARMCPU *cpu;
+    ARMCPU *cpu = arm_env_get_cpu(env);
     int kernel_size;
     int initrd_size;
     int n;
@@ -402,7 +402,7 @@ void arm_load_kernel(CPUARMState *env, struct arm_boot_info *info)
         rom_add_blob_fixed("bootloader", bootloader, sizeof(bootloader),
                            info->loader_start);
         if (info->nb_cpus > 1) {
-            info->write_secondary_boot(env, info);
+            info->write_secondary_boot(cpu, info);
         }
     }
     info->is_linux = is_linux;
diff --git a/hw/exynos4210.c b/hw/exynos4210.c
index afc4bdc..ae53837 100644
--- a/hw/exynos4210.c
+++ b/hw/exynos4210.c
@@ -65,7 +65,7 @@
 static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
                                     0x09, 0x00, 0x00, 0x00 };
 
-void exynos4210_write_secondary(CPUARMState *env,
+void exynos4210_write_secondary(ARMCPU *cpu,
         const struct arm_boot_info *info)
 {
     int n;
diff --git a/hw/exynos4210.h b/hw/exynos4210.h
index f7c7027..b520676 100644
--- a/hw/exynos4210.h
+++ b/hw/exynos4210.h
@@ -97,7 +97,7 @@ typedef struct Exynos4210State {
     MemoryRegion bootreg_mem;
 } Exynos4210State;
 
-void exynos4210_write_secondary(CPUARMState *env,
+void exynos4210_write_secondary(ARMCPU *cpu,
         const struct arm_boot_info *info);
 
 Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
diff --git a/hw/highbank.c b/hw/highbank.c
index 4d6d728..45ca1ad 100644
--- a/hw/highbank.c
+++ b/hw/highbank.c
@@ -36,7 +36,7 @@
 
 /* Board init.  */
 
-static void hb_write_secondary(CPUARMState *env, const struct arm_boot_info *info)
+static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
 {
     int n;
     uint32_t smpboot[] = {
commit 20e93374e902450fa90ddd30eb4bf7d46da9ab76
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon May 14 02:04:38 2012 +0200

    versatilepb: Use cpu_arm_init() to obtain ARMCPU
    
    Needed for arm_load_kernel().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index 7c79c54..d567af9 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -173,7 +173,7 @@ static void versatile_init(ram_addr_t ram_size,
                      const char *initrd_filename, const char *cpu_model,
                      int board_id)
 {
-    CPUARMState *env;
+    ARMCPU *cpu;
     MemoryRegion *sysmem = get_system_memory();
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     qemu_irq *cpu_pic;
@@ -189,10 +189,11 @@ static void versatile_init(ram_addr_t ram_size,
     int done_smc = 0;
     DriveInfo *dinfo;
 
-    if (!cpu_model)
+    if (!cpu_model) {
         cpu_model = "arm926";
-    env = cpu_init(cpu_model);
-    if (!env) {
+    }
+    cpu = cpu_arm_init(cpu_model);
+    if (!cpu) {
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
@@ -208,7 +209,7 @@ static void versatile_init(ram_addr_t ram_size,
     qdev_init_nofail(sysctl);
     sysbus_mmio_map(sysbus_from_qdev(sysctl), 0, 0x10000000);
 
-    cpu_pic = arm_pic_init_cpu(env);
+    cpu_pic = arm_pic_init_cpu(&cpu->env);
     dev = sysbus_create_varargs("pl190", 0x10140000,
                                 cpu_pic[0], cpu_pic[1], NULL);
     for (n = 0; n < 32; n++) {
@@ -338,7 +339,7 @@ static void versatile_init(ram_addr_t ram_size,
     versatile_binfo.kernel_cmdline = kernel_cmdline;
     versatile_binfo.initrd_filename = initrd_filename;
     versatile_binfo.board_id = board_id;
-    arm_load_kernel(env, &versatile_binfo);
+    arm_load_kernel(&cpu->env, &versatile_binfo);
 }
 
 static void vpb_init(ram_addr_t ram_size,
commit f25608e9dd0d3c1edcf3076070afb08a6d8c5fdb
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon May 14 01:54:18 2012 +0200

    musicpal: Use cpu_arm_init() to obtain ARMCPU
    
    Needed for arm_load_kernel().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/musicpal.c b/hw/musicpal.c
index c9f845a..b7fed39 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -1513,7 +1513,7 @@ static void musicpal_init(ram_addr_t ram_size,
                const char *kernel_filename, const char *kernel_cmdline,
                const char *initrd_filename, const char *cpu_model)
 {
-    CPUARMState *env;
+    ARMCPU *cpu;
     qemu_irq *cpu_pic;
     qemu_irq pic[32];
     DeviceState *dev;
@@ -1533,12 +1533,12 @@ static void musicpal_init(ram_addr_t ram_size,
     if (!cpu_model) {
         cpu_model = "arm926";
     }
-    env = cpu_init(cpu_model);
-    if (!env) {
+    cpu = cpu_arm_init(cpu_model);
+    if (!cpu) {
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
-    cpu_pic = arm_pic_init_cpu(env);
+    cpu_pic = arm_pic_init_cpu(&cpu->env);
 
     /* For now we use a fixed - the original - RAM size */
     memory_region_init_ram(ram, "musicpal.ram", MP_RAM_DEFAULT_SIZE);
@@ -1651,7 +1651,7 @@ static void musicpal_init(ram_addr_t ram_size,
     musicpal_binfo.kernel_filename = kernel_filename;
     musicpal_binfo.kernel_cmdline = kernel_cmdline;
     musicpal_binfo.initrd_filename = initrd_filename;
-    arm_load_kernel(env, &musicpal_binfo);
+    arm_load_kernel(&cpu->env, &musicpal_binfo);
 }
 
 static QEMUMachine musicpal_machine = {
commit 393a9eabb396c9ea4b45f02c72aa7fa92994e334
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon May 14 01:51:01 2012 +0200

    integratorcp: Use cpu_arm_init() to obtain ARMCPU
    
    Needed for arm_load_kernel().
    
    Add missing braces.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index 9bdb9e6..46fd09d 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -443,7 +443,7 @@ static void integratorcp_init(ram_addr_t ram_size,
                      const char *kernel_filename, const char *kernel_cmdline,
                      const char *initrd_filename, const char *cpu_model)
 {
-    CPUARMState *env;
+    ARMCPU *cpu;
     MemoryRegion *address_space_mem = get_system_memory();
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
@@ -452,13 +452,15 @@ static void integratorcp_init(ram_addr_t ram_size,
     DeviceState *dev;
     int i;
 
-    if (!cpu_model)
+    if (!cpu_model) {
         cpu_model = "arm926";
-    env = cpu_init(cpu_model);
-    if (!env) {
+    }
+    cpu = cpu_arm_init(cpu_model);
+    if (!cpu) {
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
+
     memory_region_init_ram(ram, "integrator.ram", ram_size);
     vmstate_register_ram_global(ram);
     /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
@@ -474,7 +476,7 @@ static void integratorcp_init(ram_addr_t ram_size,
     qdev_init_nofail(dev);
     sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000);
 
-    cpu_pic = arm_pic_init_cpu(env);
+    cpu_pic = arm_pic_init_cpu(&cpu->env);
     dev = sysbus_create_varargs("integrator_pic", 0x14000000,
                                 cpu_pic[ARM_PIC_CPU_IRQ],
                                 cpu_pic[ARM_PIC_CPU_FIQ], NULL);
@@ -500,7 +502,7 @@ static void integratorcp_init(ram_addr_t ram_size,
     integrator_binfo.kernel_filename = kernel_filename;
     integrator_binfo.kernel_cmdline = kernel_cmdline;
     integrator_binfo.initrd_filename = initrd_filename;
-    arm_load_kernel(env, &integrator_binfo);
+    arm_load_kernel(&cpu->env, &integrator_binfo);
 }
 
 static QEMUMachine integratorcp_machine = {
commit 8bf502e2a64f8f4ed37d9b16f367378ebf237ccb
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon May 14 01:42:57 2012 +0200

    strongarm: Use cpu_arm_init() to store ARMCPU in StrongARMState
    
    Adapt collie accordingly.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/collie.c b/hw/collie.c
index 42f4310..e6f8dbf 100644
--- a/hw/collie.c
+++ b/hw/collie.c
@@ -54,7 +54,7 @@ static void collie_init(ram_addr_t ram_size,
     collie_binfo.kernel_cmdline = kernel_cmdline;
     collie_binfo.initrd_filename = initrd_filename;
     collie_binfo.board_id = 0x208;
-    arm_load_kernel(s->env, &collie_binfo);
+    arm_load_kernel(&s->cpu->env, &collie_binfo);
 }
 
 static QEMUMachine collie_machine = {
diff --git a/hw/strongarm.c b/hw/strongarm.c
index 1b15f39..38b1d0c 100644
--- a/hw/strongarm.c
+++ b/hw/strongarm.c
@@ -1563,9 +1563,9 @@ StrongARMState *sa1110_init(MemoryRegion *sysmem,
         exit(1);
     }
 
-    s->env = cpu_init(rev);
+    s->cpu = cpu_arm_init(rev);
 
-    if (!s->env) {
+    if (!s->cpu) {
         error_report("Unable to find CPU definition");
         exit(1);
     }
@@ -1574,7 +1574,7 @@ StrongARMState *sa1110_init(MemoryRegion *sysmem,
     vmstate_register_ram_global(&s->sdram);
     memory_region_add_subregion(sysmem, SA_SDCS0, &s->sdram);
 
-    pic = arm_pic_init_cpu(s->env);
+    pic = arm_pic_init_cpu(&s->cpu->env);
     s->pic = sysbus_create_varargs("strongarm_pic", 0x90050000,
                     pic[ARM_PIC_CPU_IRQ], pic[ARM_PIC_CPU_FIQ], NULL);
 
diff --git a/hw/strongarm.h b/hw/strongarm.h
index 02acac3..d30dd6a 100644
--- a/hw/strongarm.h
+++ b/hw/strongarm.h
@@ -53,7 +53,7 @@ enum {
 };
 
 typedef struct {
-    CPUARMState *env;
+    ARMCPU *cpu;
     MemoryRegion sdram;
     DeviceState *pic;
     DeviceState *gpio;
commit 5c6f4f178ba542358c012ca033985f73e61b8ae5
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon May 14 01:25:55 2012 +0200

    z2: Rename PXA2xxState variable
    
    Avoid cpu->cpu by using "mpu" as variable name.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/z2.c b/hw/z2.c
index 9dd83ff..db25cdc 100644
--- a/hw/z2.c
+++ b/hw/z2.c
@@ -301,7 +301,7 @@ static void z2_init(ram_addr_t ram_size,
 {
     MemoryRegion *address_space_mem = get_system_memory();
     uint32_t sector_len = 0x10000;
-    PXA2xxState *cpu;
+    PXA2xxState *mpu;
     DriveInfo *dinfo;
     int be;
     void *z2_lcd;
@@ -313,7 +313,7 @@ static void z2_init(ram_addr_t ram_size,
     }
 
     /* Setup CPU & memory */
-    cpu = pxa270_init(address_space_mem, z2_binfo.ram_size, cpu_model);
+    mpu = pxa270_init(address_space_mem, z2_binfo.ram_size, cpu_model);
 
 #ifdef TARGET_WORDS_BIGENDIAN
     be = 1;
@@ -337,25 +337,25 @@ static void z2_init(ram_addr_t ram_size,
     }
 
     /* setup keypad */
-    pxa27x_register_keypad(cpu->kp, map, 0x100);
+    pxa27x_register_keypad(mpu->kp, map, 0x100);
 
     /* MMC/SD host */
-    pxa2xx_mmci_handlers(cpu->mmc,
+    pxa2xx_mmci_handlers(mpu->mmc,
         NULL,
-        qdev_get_gpio_in(cpu->gpio, Z2_GPIO_SD_DETECT));
+        qdev_get_gpio_in(mpu->gpio, Z2_GPIO_SD_DETECT));
 
     type_register_static(&zipit_lcd_info);
     type_register_static(&aer915_info);
-    z2_lcd = ssi_create_slave(cpu->ssp[1], "zipit-lcd");
-    bus = pxa2xx_i2c_bus(cpu->i2c[0]);
+    z2_lcd = ssi_create_slave(mpu->ssp[1], "zipit-lcd");
+    bus = pxa2xx_i2c_bus(mpu->i2c[0]);
     i2c_create_slave(bus, "aer915", 0x55);
     wm = i2c_create_slave(bus, "wm8750", 0x1b);
-    cpu->i2s->opaque = wm;
-    cpu->i2s->codec_out = wm8750_dac_dat;
-    cpu->i2s->codec_in = wm8750_adc_dat;
-    wm8750_data_req_set(wm, cpu->i2s->data_req, cpu->i2s);
+    mpu->i2s->opaque = wm;
+    mpu->i2s->codec_out = wm8750_dac_dat;
+    mpu->i2s->codec_in = wm8750_adc_dat;
+    wm8750_data_req_set(wm, mpu->i2s->data_req, mpu->i2s);
 
-    qdev_connect_gpio_out(cpu->gpio, Z2_GPIO_LCD_CS,
+    qdev_connect_gpio_out(mpu->gpio, Z2_GPIO_LCD_CS,
         qemu_allocate_irqs(z2_lcd_cs, z2_lcd, 1)[0]);
 
     if (kernel_filename) {
@@ -363,7 +363,7 @@ static void z2_init(ram_addr_t ram_size,
         z2_binfo.kernel_cmdline = kernel_cmdline;
         z2_binfo.initrd_filename = initrd_filename;
         z2_binfo.board_id = 0x6dd;
-        arm_load_kernel(&cpu->cpu->env, &z2_binfo);
+        arm_load_kernel(&mpu->cpu->env, &z2_binfo);
     }
 }
 
commit 8efa35e073339dcef6afc23913d2f56b10545cb4
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon May 14 01:24:05 2012 +0200

    tosa: Rename PXA2xxState variable
    
    Avoid cpu->cpu by using "mpu" as variable name.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/tosa.c b/hw/tosa.c
index d1ede8d..8bae80d 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -212,14 +212,14 @@ static void tosa_init(ram_addr_t ram_size,
 {
     MemoryRegion *address_space_mem = get_system_memory();
     MemoryRegion *rom = g_new(MemoryRegion, 1);
-    PXA2xxState *cpu;
+    PXA2xxState *mpu;
     TC6393xbState *tmio;
     DeviceState *scp0, *scp1;
 
     if (!cpu_model)
         cpu_model = "pxa255";
 
-    cpu = pxa255_init(address_space_mem, tosa_binfo.ram_size);
+    mpu = pxa255_init(address_space_mem, tosa_binfo.ram_size);
 
     memory_region_init_ram(rom, "tosa.rom", TOSA_ROM);
     vmstate_register_ram_global(rom);
@@ -227,22 +227,22 @@ static void tosa_init(ram_addr_t ram_size,
     memory_region_add_subregion(address_space_mem, 0, rom);
 
     tmio = tc6393xb_init(address_space_mem, 0x10000000,
-            qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_TC6393XB_INT));
+            qdev_get_gpio_in(mpu->gpio, TOSA_GPIO_TC6393XB_INT));
 
     scp0 = sysbus_create_simple("scoop", 0x08800000, NULL);
     scp1 = sysbus_create_simple("scoop", 0x14800040, NULL);
 
-    tosa_gpio_setup(cpu, scp0, scp1, tmio);
+    tosa_gpio_setup(mpu, scp0, scp1, tmio);
 
-    tosa_microdrive_attach(cpu);
+    tosa_microdrive_attach(mpu);
 
-    tosa_tg_init(cpu);
+    tosa_tg_init(mpu);
 
     tosa_binfo.kernel_filename = kernel_filename;
     tosa_binfo.kernel_cmdline = kernel_cmdline;
     tosa_binfo.initrd_filename = initrd_filename;
     tosa_binfo.board_id = 0x208;
-    arm_load_kernel(&cpu->cpu->env, &tosa_binfo);
+    arm_load_kernel(&mpu->cpu->env, &tosa_binfo);
     sl_bootparam_write(SL_PXA_PARAM_BASE);
 }
 
commit 2e7ad76018aefe8390e322a9132dc924ec136ce3
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon May 14 01:22:03 2012 +0200

    spitz: Rename PXA2xxState variable
    
    Avoid cpu->cpu by using "mpu" as variable name.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/spitz.c b/hw/spitz.c
index 9042d44..d320633 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -884,7 +884,7 @@ static void spitz_common_init(ram_addr_t ram_size,
                 const char *kernel_cmdline, const char *initrd_filename,
                 const char *cpu_model, enum spitz_model_e model, int arm_id)
 {
-    PXA2xxState *cpu;
+    PXA2xxState *mpu;
     DeviceState *scp0, *scp1 = NULL;
     MemoryRegion *address_space_mem = get_system_memory();
     MemoryRegion *rom = g_new(MemoryRegion, 1);
@@ -893,9 +893,9 @@ static void spitz_common_init(ram_addr_t ram_size,
         cpu_model = (model == terrier) ? "pxa270-c5" : "pxa270-c0";
 
     /* Setup CPU & memory */
-    cpu = pxa270_init(address_space_mem, spitz_binfo.ram_size, cpu_model);
+    mpu = pxa270_init(address_space_mem, spitz_binfo.ram_size, cpu_model);
 
-    sl_flash_register(cpu, (model == spitz) ? FLASH_128M : FLASH_1024M);
+    sl_flash_register(mpu, (model == spitz) ? FLASH_128M : FLASH_1024M);
 
     memory_region_init_ram(rom, "spitz.rom", SPITZ_ROM);
     vmstate_register_ram_global(rom);
@@ -903,36 +903,36 @@ static void spitz_common_init(ram_addr_t ram_size,
     memory_region_add_subregion(address_space_mem, 0, rom);
 
     /* Setup peripherals */
-    spitz_keyboard_register(cpu);
+    spitz_keyboard_register(mpu);
 
-    spitz_ssp_attach(cpu);
+    spitz_ssp_attach(mpu);
 
     scp0 = sysbus_create_simple("scoop", 0x10800000, NULL);
     if (model != akita) {
         scp1 = sysbus_create_simple("scoop", 0x08800040, NULL);
     }
 
-    spitz_scoop_gpio_setup(cpu, scp0, scp1);
+    spitz_scoop_gpio_setup(mpu, scp0, scp1);
 
-    spitz_gpio_setup(cpu, (model == akita) ? 1 : 2);
+    spitz_gpio_setup(mpu, (model == akita) ? 1 : 2);
 
-    spitz_i2c_setup(cpu);
+    spitz_i2c_setup(mpu);
 
     if (model == akita)
-        spitz_akita_i2c_setup(cpu);
+        spitz_akita_i2c_setup(mpu);
 
     if (model == terrier)
         /* A 6.0 GB microdrive is permanently sitting in CF slot 1.  */
-        spitz_microdrive_attach(cpu, 1);
+        spitz_microdrive_attach(mpu, 1);
     else if (model != akita)
         /* A 4.0 GB microdrive is permanently sitting in CF slot 0.  */
-        spitz_microdrive_attach(cpu, 0);
+        spitz_microdrive_attach(mpu, 0);
 
     spitz_binfo.kernel_filename = kernel_filename;
     spitz_binfo.kernel_cmdline = kernel_cmdline;
     spitz_binfo.initrd_filename = initrd_filename;
     spitz_binfo.board_id = arm_id;
-    arm_load_kernel(&cpu->cpu->env, &spitz_binfo);
+    arm_load_kernel(&mpu->cpu->env, &spitz_binfo);
     sl_bootparam_write(SL_PXA_PARAM_BASE);
 }
 
commit 1c88de673e38ba34f410c14e01fc2a373a01bc58
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon May 14 01:11:15 2012 +0200

    mainstone: Rename PXA2xxState variable
    
    Avoid cpu->cpu by using "mpu" as variable name.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/mainstone.c b/hw/mainstone.c
index 00a8adc..17c68f6 100644
--- a/hw/mainstone.c
+++ b/hw/mainstone.c
@@ -102,7 +102,7 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
 {
     uint32_t sector_len = 256 * 1024;
     target_phys_addr_t mainstone_flash_base[] = { MST_FLASH_0, MST_FLASH_1 };
-    PXA2xxState *cpu;
+    PXA2xxState *mpu;
     DeviceState *mst_irq;
     DriveInfo *dinfo;
     int i;
@@ -113,7 +113,7 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
         cpu_model = "pxa270-c5";
 
     /* Setup CPU & memory */
-    cpu = pxa270_init(address_space_mem, mainstone_binfo.ram_size, cpu_model);
+    mpu = pxa270_init(address_space_mem, mainstone_binfo.ram_size, cpu_model);
     memory_region_init_ram(rom, "mainstone.rom", MAINSTONE_ROM);
     vmstate_register_ram_global(rom);
     memory_region_set_readonly(rom, true);
@@ -145,19 +145,19 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
     }
 
     mst_irq = sysbus_create_simple("mainstone-fpga", MST_FPGA_PHYS,
-                    qdev_get_gpio_in(cpu->gpio, 0));
+                    qdev_get_gpio_in(mpu->gpio, 0));
 
     /* setup keypad */
     printf("map addr %p\n", &map);
-    pxa27x_register_keypad(cpu->kp, map, 0xe0);
+    pxa27x_register_keypad(mpu->kp, map, 0xe0);
 
     /* MMC/SD host */
-    pxa2xx_mmci_handlers(cpu->mmc, NULL, qdev_get_gpio_in(mst_irq, MMC_IRQ));
+    pxa2xx_mmci_handlers(mpu->mmc, NULL, qdev_get_gpio_in(mst_irq, MMC_IRQ));
 
-    pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[0],
+    pxa2xx_pcmcia_set_irq_cb(mpu->pcmcia[0],
             qdev_get_gpio_in(mst_irq, S0_IRQ),
             qdev_get_gpio_in(mst_irq, S0_CD_IRQ));
-    pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[1],
+    pxa2xx_pcmcia_set_irq_cb(mpu->pcmcia[1],
             qdev_get_gpio_in(mst_irq, S1_IRQ),
             qdev_get_gpio_in(mst_irq, S1_CD_IRQ));
 
@@ -168,7 +168,7 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
     mainstone_binfo.kernel_cmdline = kernel_cmdline;
     mainstone_binfo.initrd_filename = initrd_filename;
     mainstone_binfo.board_id = arm_id;
-    arm_load_kernel(&cpu->cpu->env, &mainstone_binfo);
+    arm_load_kernel(&mpu->cpu->env, &mainstone_binfo);
 }
 
 static void mainstone_init(ram_addr_t ram_size,
commit f1eea068de28bb4edabc378378e361c42d1e6c0d
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon May 14 01:20:13 2012 +0200

    palm: Rename omap_mpu_state_s variable
    
    Avoid cpu->cpu by using "mpu" as variable name.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/palm.c b/hw/palm.c
index 6d81829..1375b19 100644
--- a/hw/palm.c
+++ b/hw/palm.c
@@ -196,7 +196,7 @@ static void palmte_init(ram_addr_t ram_size,
                 const char *initrd_filename, const char *cpu_model)
 {
     MemoryRegion *address_space_mem = get_system_memory();
-    struct omap_mpu_state_s *cpu;
+    struct omap_mpu_state_s *mpu;
     int flash_size = 0x00800000;
     int sdram_size = palmte_binfo.ram_size;
     static uint32_t cs0val = 0xffffffff;
@@ -208,7 +208,7 @@ static void palmte_init(ram_addr_t ram_size,
     MemoryRegion *flash = g_new(MemoryRegion, 1);
     MemoryRegion *cs = g_new(MemoryRegion, 4);
 
-    cpu = omap310_mpu_init(address_space_mem, sdram_size, cpu_model);
+    mpu = omap310_mpu_init(address_space_mem, sdram_size, cpu_model);
 
     /* External Flash (EMIFS) */
     memory_region_init_ram(flash, "palmte.flash", flash_size);
@@ -230,11 +230,11 @@ static void palmte_init(ram_addr_t ram_size,
                           OMAP_CS3_SIZE);
     memory_region_add_subregion(address_space_mem, OMAP_CS3_BASE, &cs[3]);
 
-    palmte_microwire_setup(cpu);
+    palmte_microwire_setup(mpu);
 
-    qemu_add_kbd_event_handler(palmte_button_event, cpu);
+    qemu_add_kbd_event_handler(palmte_button_event, mpu);
 
-    palmte_gpio_setup(cpu);
+    palmte_gpio_setup(mpu);
 
     /* Setup initial (reset) machine state */
     if (nb_option_roms) {
@@ -265,7 +265,7 @@ static void palmte_init(ram_addr_t ram_size,
         palmte_binfo.kernel_filename = kernel_filename;
         palmte_binfo.kernel_cmdline = kernel_cmdline;
         palmte_binfo.initrd_filename = initrd_filename;
-        arm_load_kernel(&cpu->cpu->env, &palmte_binfo);
+        arm_load_kernel(&mpu->cpu->env, &palmte_binfo);
     }
 
     /* FIXME: We shouldn't really be doing this here.  The LCD controller
commit 59b91996b925d8cb7e971723ea1f3f8c38339505
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon May 14 01:17:03 2012 +0200

    omap_sx1: Rename omap_mpu_state_s variable
    
    Avoid cpu->cpu by using "mpu" as variable name.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c
index c7618c6..b64e1eb 100644
--- a/hw/omap_sx1.c
+++ b/hw/omap_sx1.c
@@ -103,7 +103,7 @@ static void sx1_init(ram_addr_t ram_size,
                 const char *initrd_filename, const char *cpu_model,
                 const int version)
 {
-    struct omap_mpu_state_s *cpu;
+    struct omap_mpu_state_s *mpu;
     MemoryRegion *address_space = get_system_memory();
     MemoryRegion *flash = g_new(MemoryRegion, 1);
     MemoryRegion *flash_1 = g_new(MemoryRegion, 1);
@@ -121,7 +121,7 @@ static void sx1_init(ram_addr_t ram_size,
         flash_size = flash2_size;
     }
 
-    cpu = omap310_mpu_init(address_space, sx1_binfo.ram_size, cpu_model);
+    mpu = omap310_mpu_init(address_space, sx1_binfo.ram_size, cpu_model);
 
     /* External Flash (EMIFS) */
     memory_region_init_ram(flash, "omap_sx1.flash0-0", flash_size);
@@ -202,7 +202,7 @@ static void sx1_init(ram_addr_t ram_size,
         sx1_binfo.kernel_filename = kernel_filename;
         sx1_binfo.kernel_cmdline = kernel_cmdline;
         sx1_binfo.initrd_filename = initrd_filename;
-        arm_load_kernel(&cpu->cpu->env, &sx1_binfo);
+        arm_load_kernel(&mpu->cpu->env, &sx1_binfo);
     }
 
     /* TODO: fix next line */
commit 518ec1342cf11169957b4f58ba23b1fdabb59d50
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun May 13 22:13:15 2012 +0200

    nseries: Rename n800_s::cpu to mpu
    
    omap_mpu_state_s::env was renamed to cpu while changing its type.
    With n800_s::cpu of type omap_mpu_state_s* this leads to s->cpu->cpu.
    
    Rename the field to "mpu" to avoid this ugliness.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/nseries.c b/hw/nseries.c
index b8c6a29..b199cb9 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -37,7 +37,7 @@
 
 /* Nokia N8x0 support */
 struct n800_s {
-    struct omap_mpu_state_s *cpu;
+    struct omap_mpu_state_s *mpu;
 
     struct rfbi_chip_s blizzard;
     struct {
@@ -135,10 +135,10 @@ static void n800_mmc_cs_cb(void *opaque, int line, int level)
 
 static void n8x0_gpio_setup(struct n800_s *s)
 {
-    qemu_irq *mmc_cs = qemu_allocate_irqs(n800_mmc_cs_cb, s->cpu->mmc, 1);
-    qdev_connect_gpio_out(s->cpu->gpio, N8X0_MMC_CS_GPIO, mmc_cs[0]);
+    qemu_irq *mmc_cs = qemu_allocate_irqs(n800_mmc_cs_cb, s->mpu->mmc, 1);
+    qdev_connect_gpio_out(s->mpu->gpio, N8X0_MMC_CS_GPIO, mmc_cs[0]);
 
-    qemu_irq_lower(qdev_get_gpio_in(s->cpu->gpio, N800_BAT_COVER_GPIO));
+    qemu_irq_lower(qdev_get_gpio_in(s->mpu->gpio, N800_BAT_COVER_GPIO));
 }
 
 #define MAEMO_CAL_HEADER(...)				\
@@ -179,8 +179,8 @@ static void n8x0_nand_setup(struct n800_s *s)
     }
     qdev_init_nofail(s->nand);
     sysbus_connect_irq(sysbus_from_qdev(s->nand), 0,
-                       qdev_get_gpio_in(s->cpu->gpio, N8X0_ONENAND_GPIO));
-    omap_gpmc_attach(s->cpu->gpmc, N8X0_ONENAND_CS,
+                       qdev_get_gpio_in(s->mpu->gpio, N8X0_ONENAND_GPIO));
+    omap_gpmc_attach(s->mpu->gpmc, N8X0_ONENAND_CS,
                      sysbus_mmio_get_region(sysbus_from_qdev(s->nand), 0));
     otp_region = onenand_raw_otp(s->nand);
 
@@ -192,13 +192,13 @@ static void n8x0_nand_setup(struct n800_s *s)
 static void n8x0_i2c_setup(struct n800_s *s)
 {
     DeviceState *dev;
-    qemu_irq tmp_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_TMP105_GPIO);
-    i2c_bus *i2c = omap_i2c_bus(s->cpu->i2c[0]);
+    qemu_irq tmp_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_TMP105_GPIO);
+    i2c_bus *i2c = omap_i2c_bus(s->mpu->i2c[0]);
 
     /* Attach a menelaus PM chip */
     dev = i2c_create_slave(i2c, "twl92230", N8X0_MENELAUS_ADDR);
     qdev_connect_gpio_out(dev, 3,
-                          qdev_get_gpio_in(s->cpu->ih[0],
+                          qdev_get_gpio_in(s->mpu->ih[0],
                                            OMAP_INT_24XX_SYS_NIRQ));
 
     qemu_system_powerdown = qdev_get_gpio_in(dev, 3);
@@ -263,8 +263,8 @@ static void n800_tsc_kbd_setup(struct n800_s *s)
     /* XXX: are the three pins inverted inside the chip between the
      * tsc and the cpu (N4111)?  */
     qemu_irq penirq = NULL;	/* NC */
-    qemu_irq kbirq = qdev_get_gpio_in(s->cpu->gpio, N800_TSC_KP_IRQ_GPIO);
-    qemu_irq dav = qdev_get_gpio_in(s->cpu->gpio, N800_TSC_TS_GPIO);
+    qemu_irq kbirq = qdev_get_gpio_in(s->mpu->gpio, N800_TSC_KP_IRQ_GPIO);
+    qemu_irq dav = qdev_get_gpio_in(s->mpu->gpio, N800_TSC_TS_GPIO);
 
     s->ts.chip = tsc2301_init(penirq, kbirq, dav);
     s->ts.opaque = s->ts.chip->opaque;
@@ -283,7 +283,7 @@ static void n800_tsc_kbd_setup(struct n800_s *s)
 
 static void n810_tsc_setup(struct n800_s *s)
 {
-    qemu_irq pintdav = qdev_get_gpio_in(s->cpu->gpio, N810_TSC_TS_GPIO);
+    qemu_irq pintdav = qdev_get_gpio_in(s->mpu->gpio, N810_TSC_TS_GPIO);
 
     s->ts.opaque = tsc2005_init(pintdav);
     s->ts.txrx = tsc2005_txrx;
@@ -375,7 +375,7 @@ static int n810_keys[0x80] = {
 
 static void n810_kbd_setup(struct n800_s *s)
 {
-    qemu_irq kbd_irq = qdev_get_gpio_in(s->cpu->gpio, N810_KEYBOARD_GPIO);
+    qemu_irq kbd_irq = qdev_get_gpio_in(s->mpu->gpio, N810_KEYBOARD_GPIO);
     int i;
 
     for (i = 0; i < 0x80; i ++)
@@ -388,7 +388,7 @@ static void n810_kbd_setup(struct n800_s *s)
 
     /* Attach the LM8322 keyboard to the I2C bus,
      * should happen in n8x0_i2c_setup and s->kbd be initialised here.  */
-    s->kbd = i2c_create_slave(omap_i2c_bus(s->cpu->i2c[0]),
+    s->kbd = i2c_create_slave(omap_i2c_bus(s->mpu->i2c[0]),
                            "lm8323", N810_LM8323_ADDR);
     qdev_connect_gpio_out(s->kbd, 0, kbd_irq);
 }
@@ -679,8 +679,8 @@ static void n8x0_spi_setup(struct n800_s *s)
     void *tsc = s->ts.opaque;
     void *mipid = mipid_init();
 
-    omap_mcspi_attach(s->cpu->mcspi[0], s->ts.txrx, tsc, 0);
-    omap_mcspi_attach(s->cpu->mcspi[0], mipid_txrx, mipid, 1);
+    omap_mcspi_attach(s->mpu->mcspi[0], s->ts.txrx, tsc, 0);
+    omap_mcspi_attach(s->mpu->mcspi[0], mipid_txrx, mipid, 1);
 }
 
 /* This task is normally performed by the bootloader.  If we're loading
@@ -735,20 +735,20 @@ static void n8x0_dss_setup(struct n800_s *s)
     s->blizzard.write = s1d13745_write;
     s->blizzard.read = s1d13745_read;
 
-    omap_rfbi_attach(s->cpu->dss, 0, &s->blizzard);
+    omap_rfbi_attach(s->mpu->dss, 0, &s->blizzard);
 }
 
 static void n8x0_cbus_setup(struct n800_s *s)
 {
-    qemu_irq dat_out = qdev_get_gpio_in(s->cpu->gpio, N8X0_CBUS_DAT_GPIO);
-    qemu_irq retu_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_RETU_GPIO);
-    qemu_irq tahvo_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_TAHVO_GPIO);
+    qemu_irq dat_out = qdev_get_gpio_in(s->mpu->gpio, N8X0_CBUS_DAT_GPIO);
+    qemu_irq retu_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_RETU_GPIO);
+    qemu_irq tahvo_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_TAHVO_GPIO);
 
     CBus *cbus = cbus_init(dat_out);
 
-    qdev_connect_gpio_out(s->cpu->gpio, N8X0_CBUS_CLK_GPIO, cbus->clk);
-    qdev_connect_gpio_out(s->cpu->gpio, N8X0_CBUS_DAT_GPIO, cbus->dat);
-    qdev_connect_gpio_out(s->cpu->gpio, N8X0_CBUS_SEL_GPIO, cbus->sel);
+    qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_CLK_GPIO, cbus->clk);
+    qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_DAT_GPIO, cbus->dat);
+    qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_SEL_GPIO, cbus->sel);
 
     cbus_attach(cbus, s->retu = retu_init(retu_irq, 1));
     cbus_attach(cbus, s->tahvo = tahvo_init(tahvo_irq, 1));
@@ -757,14 +757,14 @@ static void n8x0_cbus_setup(struct n800_s *s)
 static void n8x0_uart_setup(struct n800_s *s)
 {
     CharDriverState *radio = uart_hci_init(
-                    qdev_get_gpio_in(s->cpu->gpio, N8X0_BT_HOST_WKUP_GPIO));
+                    qdev_get_gpio_in(s->mpu->gpio, N8X0_BT_HOST_WKUP_GPIO));
 
-    qdev_connect_gpio_out(s->cpu->gpio, N8X0_BT_RESET_GPIO,
+    qdev_connect_gpio_out(s->mpu->gpio, N8X0_BT_RESET_GPIO,
                     csrhci_pins_get(radio)[csrhci_pin_reset]);
-    qdev_connect_gpio_out(s->cpu->gpio, N8X0_BT_WKUP_GPIO,
+    qdev_connect_gpio_out(s->mpu->gpio, N8X0_BT_WKUP_GPIO,
                     csrhci_pins_get(radio)[csrhci_pin_wakeup]);
 
-    omap_uart_attach(s->cpu->uart[BT_UART], radio);
+    omap_uart_attach(s->mpu->uart[BT_UART], radio);
 }
 
 static void n8x0_usb_setup(struct n800_s *s)
@@ -774,13 +774,13 @@ static void n8x0_usb_setup(struct n800_s *s)
     dev = sysbus_from_qdev(s->usb);
     qdev_init_nofail(s->usb);
     sysbus_connect_irq(dev, 0,
-                       qdev_get_gpio_in(s->cpu->gpio, N8X0_TUSB_INT_GPIO));
+                       qdev_get_gpio_in(s->mpu->gpio, N8X0_TUSB_INT_GPIO));
     /* Using the NOR interface */
-    omap_gpmc_attach(s->cpu->gpmc, N8X0_USB_ASYNC_CS,
+    omap_gpmc_attach(s->mpu->gpmc, N8X0_USB_ASYNC_CS,
                      sysbus_mmio_get_region(dev, 0));
-    omap_gpmc_attach(s->cpu->gpmc, N8X0_USB_SYNC_CS,
+    omap_gpmc_attach(s->mpu->gpmc, N8X0_USB_SYNC_CS,
                      sysbus_mmio_get_region(dev, 1));
-    qdev_connect_gpio_out(s->cpu->gpio, N8X0_TUSB_ENABLE_GPIO,
+    qdev_connect_gpio_out(s->mpu->gpio, N8X0_TUSB_ENABLE_GPIO,
                           qdev_get_gpio_in(s->usb, 0)); /* tusb_pwr */
 }
 
@@ -1023,11 +1023,11 @@ static void n8x0_boot_init(void *opaque)
     n800_dss_init(&s->blizzard);
 
     /* CPU setup */
-    s->cpu->cpu->env.GE = 0x5;
+    s->mpu->cpu->env.GE = 0x5;
 
     /* If the machine has a slided keyboard, open it */
     if (s->kbd)
-        qemu_irq_raise(qdev_get_gpio_in(s->cpu->gpio, N810_SLIDE_GPIO));
+        qemu_irq_raise(qdev_get_gpio_in(s->mpu->gpio, N810_SLIDE_GPIO));
 }
 
 #define OMAP_TAG_NOKIA_BT	0x4e01
@@ -1281,7 +1281,7 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
     int sdram_size = binfo->ram_size;
     DisplayState *ds;
 
-    s->cpu = omap2420_mpu_init(sysmem, sdram_size, cpu_model);
+    s->mpu = omap2420_mpu_init(sysmem, sdram_size, cpu_model);
 
     /* Setup peripherals
      *
@@ -1329,7 +1329,7 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
         binfo->kernel_filename = kernel_filename;
         binfo->kernel_cmdline = kernel_cmdline;
         binfo->initrd_filename = initrd_filename;
-        arm_load_kernel(&s->cpu->cpu->env, binfo);
+        arm_load_kernel(&s->mpu->cpu->env, binfo);
 
         qemu_register_reset(n8x0_boot_init, s);
     }
@@ -1338,7 +1338,7 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
         int rom_size;
         uint8_t nolo_tags[0x10000];
         /* No, wait, better start at the ROM.  */
-        s->cpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000;
+        s->mpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000;
 
         /* This is intended for loading the `secondary.bin' program from
          * Nokia images (the NOLO bootloader).  The entry point seems
commit dbaf26b3b22daae3be6a89b965e43503e7c3b912
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Jun 10 20:29:19 2012 +0000

    Revert "build: compile oslib-obj-y once"
    
    This reverts commit 25f27a4f7160d077d6992e811021b4bc3a82abc1
    because of bsd-user breakage.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.objs b/Makefile.objs
index 8e72f09..74110dd 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -22,8 +22,6 @@ oslib-obj-y = osdep.o
 oslib-obj-$(CONFIG_WIN32) += oslib-win32.o qemu-thread-win32.o
 oslib-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o
 
-universal-obj-y += $(oslib-obj-y)
-
 #######################################################################
 # coroutines
 coroutine-obj-y = qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o
@@ -64,6 +62,7 @@ common-obj-y = $(block-obj-y) blockdev.o
 common-obj-y += net.o net/
 common-obj-y += qom/
 common-obj-y += readline.o console.o cursor.o
+common-obj-y += $(oslib-obj-y)
 common-obj-$(CONFIG_WIN32) += os-win32.o
 common-obj-$(CONFIG_POSIX) += os-posix.o
 
diff --git a/Makefile.target b/Makefile.target
index 2912307..2907aad 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -96,7 +96,7 @@ ifdef CONFIG_LINUX_USER
 QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) -I$(SRC_PATH)/linux-user
 
 obj-y += linux-user/
-obj-y += gdbstub.o thunk.o user-exec.o
+obj-y += gdbstub.o thunk.o user-exec.o $(oslib-obj-y)
 
 endif #CONFIG_LINUX_USER
 
commit f492b82d673d58066a0f7856b00157fbe7860a9d
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun Jun 10 11:33:12 2012 +0400

    target-xtensa: switch to AREG0-free mode
    
    Add env parameter to every helper function that needs it, update
    'configure' script.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/configure b/configure
index 0ecb55f..dd0d2b3 100755
--- a/configure
+++ b/configure
@@ -3675,7 +3675,7 @@ symlink "$source_path/Makefile.target" "$target_dir/Makefile"
 
 
 case "$target_arch2" in
-  alpha | sparc*)
+  alpha | sparc* | xtensa*)
     echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak
   ;;
 esac
diff --git a/target-xtensa/Makefile.objs b/target-xtensa/Makefile.objs
index f8fbf91..b30e5a8 100644
--- a/target-xtensa/Makefile.objs
+++ b/target-xtensa/Makefile.objs
@@ -4,5 +4,3 @@ obj-y += core-dc233c.o
 obj-y += core-fsf.o
 obj-y += translate.o op_helper.o helper.o cpu.o
 obj-$(CONFIG_SOFTMMU) += machine.o
-
-$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-xtensa/helper.h b/target-xtensa/helper.h
index 9dd6f89..152fec0 100644
--- a/target-xtensa/helper.h
+++ b/target-xtensa/helper.h
@@ -1,39 +1,39 @@
 #include "def-helper.h"
 
-DEF_HELPER_1(exception, noreturn, i32)
-DEF_HELPER_2(exception_cause, noreturn, i32, i32)
-DEF_HELPER_3(exception_cause_vaddr, noreturn, i32, i32, i32)
-DEF_HELPER_2(debug_exception, noreturn, i32, i32)
+DEF_HELPER_2(exception, noreturn, env, i32)
+DEF_HELPER_3(exception_cause, noreturn, env, i32, i32)
+DEF_HELPER_4(exception_cause_vaddr, noreturn, env, i32, i32, i32)
+DEF_HELPER_3(debug_exception, noreturn, env, i32, i32)
 
 DEF_HELPER_FLAGS_1(nsa, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
 DEF_HELPER_FLAGS_1(nsau, TCG_CALL_CONST | TCG_CALL_PURE, 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_2(wsr_windowbase, void, env, i32)
+DEF_HELPER_4(entry, void, env, i32, i32, i32)
+DEF_HELPER_2(retw, i32, env, i32)
+DEF_HELPER_2(rotw, void, env, i32)
+DEF_HELPER_3(window_check, void, env, i32, i32)
+DEF_HELPER_1(restore_owb, void, env)
+DEF_HELPER_2(movsp, void, env, i32)
+DEF_HELPER_2(wsr_lbeg, void, env, i32)
+DEF_HELPER_2(wsr_lend, void, env, i32)
 DEF_HELPER_1(simcall, void, env)
-DEF_HELPER_0(dump_state, void)
+DEF_HELPER_1(dump_state, void, env)
 
-DEF_HELPER_2(waiti, void, i32, i32)
-DEF_HELPER_2(timer_irq, void, i32, i32)
-DEF_HELPER_1(advance_ccount, void, i32)
+DEF_HELPER_3(waiti, void, env, i32, i32)
+DEF_HELPER_3(timer_irq, void, env, i32, i32)
+DEF_HELPER_2(advance_ccount, void, env, i32)
 DEF_HELPER_1(check_interrupts, void, env)
 
-DEF_HELPER_1(wsr_rasid, void, i32)
-DEF_HELPER_FLAGS_2(rtlb0, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
-DEF_HELPER_FLAGS_2(rtlb1, TCG_CALL_CONST | TCG_CALL_PURE, 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_2(wsr_rasid, void, env, i32)
+DEF_HELPER_FLAGS_3(rtlb0, TCG_CALL_CONST | TCG_CALL_PURE, i32, env, i32, i32)
+DEF_HELPER_FLAGS_3(rtlb1, TCG_CALL_CONST | TCG_CALL_PURE, i32, env, i32, i32)
+DEF_HELPER_3(itlb, void, env, i32, i32)
+DEF_HELPER_3(ptlb, i32, env, i32, i32)
+DEF_HELPER_4(wtlb, void, env, 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)
+DEF_HELPER_2(wsr_ibreakenable, void, env, i32)
+DEF_HELPER_3(wsr_ibreaka, void, env, i32, i32)
+DEF_HELPER_3(wsr_dbreaka, void, env, i32, i32)
+DEF_HELPER_3(wsr_dbreakc, void, env, i32, i32)
 
 #include "def-helper.h"
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index 41107ff..2659c0e 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -26,12 +26,11 @@
  */
 
 #include "cpu.h"
-#include "dyngen-exec.h"
 #include "helper.h"
 #include "host-utils.h"
 
-static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
-                                uintptr_t retaddr);
+static void do_unaligned_access(CPUXtensaState *env,
+        target_ulong addr, int is_write, int is_user, uintptr_t retaddr);
 
 #define ALIGNED_ONLY
 #define MMUSUFFIX _mmu
@@ -48,7 +47,7 @@ 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(uintptr_t pc)
+static void do_restore_state(CPUXtensaState *env, uintptr_t pc)
 {
     TranslationBlock *tb;
 
@@ -58,44 +57,38 @@ static void do_restore_state(uintptr_t pc)
     }
 }
 
-static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
-                                uintptr_t retaddr)
+static void do_unaligned_access(CPUXtensaState *env,
+        target_ulong addr, int is_write, int is_user, uintptr_t retaddr)
 {
     if (xtensa_option_enabled(env->config, XTENSA_OPTION_UNALIGNED_EXCEPTION) &&
             !xtensa_option_enabled(env->config, XTENSA_OPTION_HW_ALIGNMENT)) {
-        do_restore_state(retaddr);
-        HELPER(exception_cause_vaddr)(
+        do_restore_state(env, retaddr);
+        HELPER(exception_cause_vaddr)(env,
                 env->pc, LOAD_STORE_ALIGNMENT_CAUSE, addr);
     }
 }
 
-void tlb_fill(CPUXtensaState *env1, target_ulong vaddr, int is_write, int mmu_idx,
-              uintptr_t retaddr)
+void tlb_fill(CPUXtensaState *env,
+        target_ulong vaddr, int is_write, int mmu_idx, uintptr_t retaddr)
 {
-    CPUXtensaState *saved_env = env;
-
-    env = env1;
-    {
-        uint32_t paddr;
-        uint32_t page_size;
-        unsigned access;
-        int ret = xtensa_get_physical_addr(env, true, vaddr, is_write, mmu_idx,
-                &paddr, &page_size, &access);
+    uint32_t paddr;
+    uint32_t page_size;
+    unsigned access;
+    int ret = xtensa_get_physical_addr(env, true, vaddr, is_write, mmu_idx,
+            &paddr, &page_size, &access);
 
-        qemu_log("%s(%08x, %d, %d) -> %08x, ret = %d\n", __func__,
-                vaddr, is_write, mmu_idx, paddr, ret);
+    qemu_log("%s(%08x, %d, %d) -> %08x, ret = %d\n", __func__,
+            vaddr, is_write, mmu_idx, paddr, ret);
 
-        if (ret == 0) {
-            tlb_set_page(env,
-                    vaddr & TARGET_PAGE_MASK,
-                    paddr & TARGET_PAGE_MASK,
-                    access, mmu_idx, page_size);
-        } else {
-            do_restore_state(retaddr);
-            HELPER(exception_cause_vaddr)(env->pc, ret, vaddr);
-        }
+    if (ret == 0) {
+        tlb_set_page(env,
+                vaddr & TARGET_PAGE_MASK,
+                paddr & TARGET_PAGE_MASK,
+                access, mmu_idx, page_size);
+    } else {
+        do_restore_state(env, retaddr);
+        HELPER(exception_cause_vaddr)(env, env->pc, ret, vaddr);
     }
-    env = saved_env;
 }
 
 static void tb_invalidate_virtual_addr(CPUXtensaState *env, uint32_t vaddr)
@@ -110,13 +103,13 @@ static void tb_invalidate_virtual_addr(CPUXtensaState *env, uint32_t vaddr)
     }
 }
 
-void HELPER(exception)(uint32_t excp)
+void HELPER(exception)(CPUXtensaState *env, uint32_t excp)
 {
     env->exception_index = excp;
     cpu_loop_exit(env);
 }
 
-void HELPER(exception_cause)(uint32_t pc, uint32_t cause)
+void HELPER(exception_cause)(CPUXtensaState *env, uint32_t pc, uint32_t cause)
 {
     uint32_t vector;
 
@@ -136,24 +129,24 @@ void HELPER(exception_cause)(uint32_t pc, uint32_t cause)
     env->sregs[EXCCAUSE] = cause;
     env->sregs[PS] |= PS_EXCM;
 
-    HELPER(exception)(vector);
+    HELPER(exception)(env, vector);
 }
 
-void HELPER(exception_cause_vaddr)(uint32_t pc, uint32_t cause, uint32_t vaddr)
+void HELPER(exception_cause_vaddr)(CPUXtensaState *env,
+        uint32_t pc, uint32_t cause, uint32_t vaddr)
 {
     env->sregs[EXCVADDR] = vaddr;
-    HELPER(exception_cause)(pc, cause);
+    HELPER(exception_cause)(env, pc, cause);
 }
 
-void debug_exception_env(CPUXtensaState *new_env, uint32_t cause)
+void debug_exception_env(CPUXtensaState *env, uint32_t cause)
 {
-    if (xtensa_get_cintlevel(new_env) < new_env->config->debug_level) {
-        env = new_env;
-        HELPER(debug_exception)(env->pc, cause);
+    if (xtensa_get_cintlevel(env) < env->config->debug_level) {
+        HELPER(debug_exception)(env, env->pc, cause);
     }
 }
 
-void HELPER(debug_exception)(uint32_t pc, uint32_t cause)
+void HELPER(debug_exception)(CPUXtensaState *env, uint32_t pc, uint32_t cause)
 {
     unsigned level = env->config->debug_level;
 
@@ -163,7 +156,7 @@ void HELPER(debug_exception)(uint32_t pc, uint32_t cause)
     env->sregs[EPS2 + level - 2] = env->sregs[PS];
     env->sregs[PS] = (env->sregs[PS] & ~PS_INTLEVEL) | PS_EXCM |
         (level << PS_INTLEVEL_SHIFT);
-    HELPER(exception)(EXC_DEBUG);
+    HELPER(exception)(env, EXC_DEBUG);
 }
 
 uint32_t HELPER(nsa)(uint32_t v)
@@ -232,39 +225,39 @@ void xtensa_sync_phys_from_window(CPUXtensaState *env)
     copy_phys_from_window(env, env->sregs[WINDOW_BASE] * 4, 0, 16);
 }
 
-static void rotate_window_abs(uint32_t position)
+static void rotate_window_abs(CPUXtensaState *env, uint32_t position)
 {
     xtensa_sync_phys_from_window(env);
     env->sregs[WINDOW_BASE] = windowbase_bound(position, env);
     xtensa_sync_window_from_phys(env);
 }
 
-static void rotate_window(uint32_t delta)
+static void rotate_window(CPUXtensaState *env, uint32_t delta)
 {
-    rotate_window_abs(env->sregs[WINDOW_BASE] + delta);
+    rotate_window_abs(env, env->sregs[WINDOW_BASE] + delta);
 }
 
-void HELPER(wsr_windowbase)(uint32_t v)
+void HELPER(wsr_windowbase)(CPUXtensaState *env, uint32_t v)
 {
-    rotate_window_abs(v);
+    rotate_window_abs(env, v);
 }
 
-void HELPER(entry)(uint32_t pc, uint32_t s, uint32_t imm)
+void HELPER(entry)(CPUXtensaState *env, uint32_t pc, uint32_t s, uint32_t imm)
 {
     int callinc = (env->sregs[PS] & PS_CALLINC) >> PS_CALLINC_SHIFT;
     if (s > 3 || ((env->sregs[PS] & (PS_WOE | PS_EXCM)) ^ PS_WOE) != 0) {
         qemu_log("Illegal entry instruction(pc = %08x), PS = %08x\n",
                 pc, env->sregs[PS]);
-        HELPER(exception_cause)(pc, ILLEGAL_INSTRUCTION_CAUSE);
+        HELPER(exception_cause)(env, pc, ILLEGAL_INSTRUCTION_CAUSE);
     } else {
         env->regs[(callinc << 2) | (s & 3)] = env->regs[s] - (imm << 3);
-        rotate_window(callinc);
+        rotate_window(env, callinc);
         env->sregs[WINDOW_START] |=
             windowstart_bit(env->sregs[WINDOW_BASE], env);
     }
 }
 
-void HELPER(window_check)(uint32_t pc, uint32_t w)
+void HELPER(window_check)(CPUXtensaState *env, uint32_t pc, uint32_t w)
 {
     uint32_t windowbase = windowbase_bound(env->sregs[WINDOW_BASE], env);
     uint32_t windowstart = env->sregs[WINDOW_START];
@@ -284,21 +277,21 @@ void HELPER(window_check)(uint32_t pc, uint32_t w)
     }
 
     m = windowbase_bound(windowbase + n, env);
-    rotate_window(n);
+    rotate_window(env, n);
     env->sregs[PS] = (env->sregs[PS] & ~PS_OWB) |
         (windowbase << PS_OWB_SHIFT) | PS_EXCM;
     env->sregs[EPC1] = env->pc = pc;
 
     if (windowstart & windowstart_bit(m + 1, env)) {
-        HELPER(exception)(EXC_WINDOW_OVERFLOW4);
+        HELPER(exception)(env, EXC_WINDOW_OVERFLOW4);
     } else if (windowstart & windowstart_bit(m + 2, env)) {
-        HELPER(exception)(EXC_WINDOW_OVERFLOW8);
+        HELPER(exception)(env, EXC_WINDOW_OVERFLOW8);
     } else {
-        HELPER(exception)(EXC_WINDOW_OVERFLOW12);
+        HELPER(exception)(env, EXC_WINDOW_OVERFLOW12);
     }
 }
 
-uint32_t HELPER(retw)(uint32_t pc)
+uint32_t HELPER(retw)(CPUXtensaState *env, uint32_t pc)
 {
     int n = (env->regs[0] >> 30) & 0x3;
     int m = 0;
@@ -319,13 +312,13 @@ uint32_t HELPER(retw)(uint32_t pc)
         qemu_log("Illegal retw instruction(pc = %08x), "
                 "PS = %08x, m = %d, n = %d\n",
                 pc, env->sregs[PS], m, n);
-        HELPER(exception_cause)(pc, ILLEGAL_INSTRUCTION_CAUSE);
+        HELPER(exception_cause)(env, pc, ILLEGAL_INSTRUCTION_CAUSE);
     } else {
         int owb = windowbase;
 
         ret_pc = (pc & 0xc0000000) | (env->regs[0] & 0x3fffffff);
 
-        rotate_window(-n);
+        rotate_window(env, -n);
         if (windowstart & windowstart_bit(env->sregs[WINDOW_BASE], env)) {
             env->sregs[WINDOW_START] &= ~windowstart_bit(owb, env);
         } else {
@@ -335,38 +328,38 @@ uint32_t HELPER(retw)(uint32_t pc)
             env->sregs[EPC1] = env->pc = pc;
 
             if (n == 1) {
-                HELPER(exception)(EXC_WINDOW_UNDERFLOW4);
+                HELPER(exception)(env, EXC_WINDOW_UNDERFLOW4);
             } else if (n == 2) {
-                HELPER(exception)(EXC_WINDOW_UNDERFLOW8);
+                HELPER(exception)(env, EXC_WINDOW_UNDERFLOW8);
             } else if (n == 3) {
-                HELPER(exception)(EXC_WINDOW_UNDERFLOW12);
+                HELPER(exception)(env, EXC_WINDOW_UNDERFLOW12);
             }
         }
     }
     return ret_pc;
 }
 
-void HELPER(rotw)(uint32_t imm4)
+void HELPER(rotw)(CPUXtensaState *env, uint32_t imm4)
 {
-    rotate_window(imm4);
+    rotate_window(env, imm4);
 }
 
-void HELPER(restore_owb)(void)
+void HELPER(restore_owb)(CPUXtensaState *env)
 {
-    rotate_window_abs((env->sregs[PS] & PS_OWB) >> PS_OWB_SHIFT);
+    rotate_window_abs(env, (env->sregs[PS] & PS_OWB) >> PS_OWB_SHIFT);
 }
 
-void HELPER(movsp)(uint32_t pc)
+void HELPER(movsp)(CPUXtensaState *env, uint32_t pc)
 {
     if ((env->sregs[WINDOW_START] &
             (windowstart_bit(env->sregs[WINDOW_BASE] - 3, env) |
              windowstart_bit(env->sregs[WINDOW_BASE] - 2, env) |
              windowstart_bit(env->sregs[WINDOW_BASE] - 1, env))) == 0) {
-        HELPER(exception_cause)(pc, ALLOCA_CAUSE);
+        HELPER(exception_cause)(env, pc, ALLOCA_CAUSE);
     }
 }
 
-void HELPER(wsr_lbeg)(uint32_t v)
+void HELPER(wsr_lbeg)(CPUXtensaState *env, uint32_t v)
 {
     if (env->sregs[LBEG] != v) {
         tb_invalidate_virtual_addr(env, env->sregs[LEND] - 1);
@@ -374,7 +367,7 @@ void HELPER(wsr_lbeg)(uint32_t v)
     }
 }
 
-void HELPER(wsr_lend)(uint32_t v)
+void HELPER(wsr_lend)(CPUXtensaState *env, uint32_t v)
 {
     if (env->sregs[LEND] != v) {
         tb_invalidate_virtual_addr(env, env->sregs[LEND] - 1);
@@ -383,12 +376,12 @@ void HELPER(wsr_lend)(uint32_t v)
     }
 }
 
-void HELPER(dump_state)(void)
+void HELPER(dump_state)(CPUXtensaState *env)
 {
     cpu_dump_state(env, stderr, fprintf, 0);
 }
 
-void HELPER(waiti)(uint32_t pc, uint32_t intlevel)
+void HELPER(waiti)(CPUXtensaState *env, uint32_t pc, uint32_t intlevel)
 {
     env->pc = pc;
     env->sregs[PS] = (env->sregs[PS] & ~PS_INTLEVEL) |
@@ -404,15 +397,15 @@ void HELPER(waiti)(uint32_t pc, uint32_t intlevel)
     if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT)) {
         xtensa_rearm_ccompare_timer(env);
     }
-    HELPER(exception)(EXCP_HLT);
+    HELPER(exception)(env, EXCP_HLT);
 }
 
-void HELPER(timer_irq)(uint32_t id, uint32_t active)
+void HELPER(timer_irq)(CPUXtensaState *env, uint32_t id, uint32_t active)
 {
     xtensa_timer_irq(env, id, active);
 }
 
-void HELPER(advance_ccount)(uint32_t d)
+void HELPER(advance_ccount)(CPUXtensaState *env, uint32_t d)
 {
     xtensa_advance_ccount(env, d);
 }
@@ -422,7 +415,7 @@ void HELPER(check_interrupts)(CPUXtensaState *env)
     check_interrupts(env);
 }
 
-void HELPER(wsr_rasid)(uint32_t v)
+void HELPER(wsr_rasid)(CPUXtensaState *env, uint32_t v)
 {
     v = (v & 0xffffff00) | 0x1;
     if (v != env->sregs[RASID]) {
@@ -574,7 +567,7 @@ void split_tlb_entry_spec_way(const CPUXtensaState *env, uint32_t v, bool dtlb,
  * Split TLB address into TLB way, entry index and VPN (with index).
  * See ISA, 4.6.5.5 - 4.6.5.8 for the TLB addressing format
  */
-static void split_tlb_entry_spec(uint32_t v, bool dtlb,
+static void split_tlb_entry_spec(CPUXtensaState *env, uint32_t v, bool dtlb,
         uint32_t *vpn, uint32_t *wi, uint32_t *ei)
 {
     if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
@@ -587,41 +580,42 @@ static void split_tlb_entry_spec(uint32_t v, bool dtlb,
     }
 }
 
-static xtensa_tlb_entry *get_tlb_entry(uint32_t v, bool dtlb, uint32_t *pwi)
+static xtensa_tlb_entry *get_tlb_entry(CPUXtensaState *env,
+        uint32_t v, bool dtlb, uint32_t *pwi)
 {
     uint32_t vpn;
     uint32_t wi;
     uint32_t ei;
 
-    split_tlb_entry_spec(v, dtlb, &vpn, &wi, &ei);
+    split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei);
     if (pwi) {
         *pwi = wi;
     }
     return xtensa_tlb_get_entry(env, dtlb, wi, ei);
 }
 
-uint32_t HELPER(rtlb0)(uint32_t v, uint32_t dtlb)
+uint32_t HELPER(rtlb0)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
 {
     if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
         uint32_t wi;
-        const xtensa_tlb_entry *entry = get_tlb_entry(v, dtlb, &wi);
+        const xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, &wi);
         return (entry->vaddr & get_vpn_mask(env, dtlb, wi)) | entry->asid;
     } else {
         return v & REGION_PAGE_MASK;
     }
 }
 
-uint32_t HELPER(rtlb1)(uint32_t v, uint32_t dtlb)
+uint32_t HELPER(rtlb1)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
 {
-    const xtensa_tlb_entry *entry = get_tlb_entry(v, dtlb, NULL);
+    const xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, NULL);
     return entry->paddr | entry->attr;
 }
 
-void HELPER(itlb)(uint32_t v, uint32_t dtlb)
+void HELPER(itlb)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
 {
     if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
         uint32_t wi;
-        xtensa_tlb_entry *entry = get_tlb_entry(v, dtlb, &wi);
+        xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, &wi);
         if (entry->variable && entry->asid) {
             tlb_flush_page(env, entry->vaddr);
             entry->asid = 0;
@@ -629,7 +623,7 @@ void HELPER(itlb)(uint32_t v, uint32_t dtlb)
     }
 }
 
-uint32_t HELPER(ptlb)(uint32_t v, uint32_t dtlb)
+uint32_t HELPER(ptlb)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
 {
     if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
         uint32_t wi;
@@ -646,7 +640,7 @@ uint32_t HELPER(ptlb)(uint32_t v, uint32_t dtlb)
 
         case INST_TLB_MULTI_HIT_CAUSE:
         case LOAD_STORE_TLB_MULTI_HIT_CAUSE:
-            HELPER(exception_cause_vaddr)(env->pc, res, v);
+            HELPER(exception_cause_vaddr)(env, env->pc, res, v);
             break;
         }
         return 0;
@@ -691,17 +685,17 @@ void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb,
     }
 }
 
-void HELPER(wtlb)(uint32_t p, uint32_t v, uint32_t dtlb)
+void HELPER(wtlb)(CPUXtensaState *env, uint32_t p, uint32_t v, uint32_t dtlb)
 {
     uint32_t vpn;
     uint32_t wi;
     uint32_t ei;
-    split_tlb_entry_spec(v, dtlb, &vpn, &wi, &ei);
+    split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei);
     xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, p);
 }
 
 
-void HELPER(wsr_ibreakenable)(uint32_t v)
+void HELPER(wsr_ibreakenable)(CPUXtensaState *env, uint32_t v)
 {
     uint32_t change = v ^ env->sregs[IBREAKENABLE];
     unsigned i;
@@ -714,7 +708,7 @@ void HELPER(wsr_ibreakenable)(uint32_t v)
     env->sregs[IBREAKENABLE] = v & ((1 << env->config->nibreak) - 1);
 }
 
-void HELPER(wsr_ibreaka)(uint32_t i, uint32_t v)
+void HELPER(wsr_ibreaka)(CPUXtensaState *env, uint32_t i, uint32_t v)
 {
     if (env->sregs[IBREAKENABLE] & (1 << i) && env->sregs[IBREAKA + i] != v) {
         tb_invalidate_virtual_addr(env, env->sregs[IBREAKA + i]);
@@ -723,7 +717,8 @@ void HELPER(wsr_ibreaka)(uint32_t i, uint32_t v)
     env->sregs[IBREAKA + i] = v;
 }
 
-static void set_dbreak(unsigned i, uint32_t dbreaka, uint32_t dbreakc)
+static void set_dbreak(CPUXtensaState *env, unsigned i, uint32_t dbreaka,
+        uint32_t dbreakc)
 {
     int flags = BP_CPU | BP_STOP_BEFORE_ACCESS;
     uint32_t mask = dbreakc | ~DBREAKC_MASK;
@@ -751,22 +746,22 @@ static void set_dbreak(unsigned i, uint32_t dbreaka, uint32_t dbreakc)
     }
 }
 
-void HELPER(wsr_dbreaka)(uint32_t i, uint32_t v)
+void HELPER(wsr_dbreaka)(CPUXtensaState *env, uint32_t i, uint32_t v)
 {
     uint32_t dbreakc = env->sregs[DBREAKC + i];
 
     if ((dbreakc & DBREAKC_SB_LB) &&
             env->sregs[DBREAKA + i] != v) {
-        set_dbreak(i, v, dbreakc);
+        set_dbreak(env, i, v, dbreakc);
     }
     env->sregs[DBREAKA + i] = v;
 }
 
-void HELPER(wsr_dbreakc)(uint32_t i, uint32_t v)
+void HELPER(wsr_dbreakc)(CPUXtensaState *env, uint32_t i, uint32_t v)
 {
     if ((env->sregs[DBREAKC + i] ^ v) & (DBREAKC_SB_LB | DBREAKC_MASK)) {
         if (v & DBREAKC_SB_LB) {
-            set_dbreak(i, env->sregs[DBREAKA + i], v);
+            set_dbreak(env, i, env->sregs[DBREAKA + i], v);
         } else {
             if (env->cpu_watchpoint[i]) {
                 cpu_watchpoint_remove_by_ref(env, env->cpu_watchpoint[i]);
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index a542a31..b883e6b 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -254,7 +254,7 @@ static void gen_advance_ccount(DisasContext *dc)
     if (dc->ccount_delta > 0) {
         TCGv_i32 tmp = tcg_const_i32(dc->ccount_delta);
         dc->ccount_delta = 0;
-        gen_helper_advance_ccount(tmp);
+        gen_helper_advance_ccount(cpu_env, tmp);
         tcg_temp_free(tmp);
     }
 }
@@ -268,7 +268,7 @@ static void gen_exception(DisasContext *dc, int excp)
 {
     TCGv_i32 tmp = tcg_const_i32(excp);
     gen_advance_ccount(dc);
-    gen_helper_exception(tmp);
+    gen_helper_exception(cpu_env, tmp);
     tcg_temp_free(tmp);
 }
 
@@ -277,7 +277,7 @@ static void gen_exception_cause(DisasContext *dc, uint32_t cause)
     TCGv_i32 tpc = tcg_const_i32(dc->pc);
     TCGv_i32 tcause = tcg_const_i32(cause);
     gen_advance_ccount(dc);
-    gen_helper_exception_cause(tpc, tcause);
+    gen_helper_exception_cause(cpu_env, tpc, tcause);
     tcg_temp_free(tpc);
     tcg_temp_free(tcause);
     if (cause == ILLEGAL_INSTRUCTION_CAUSE ||
@@ -292,7 +292,7 @@ static void gen_exception_cause_vaddr(DisasContext *dc, uint32_t cause,
     TCGv_i32 tpc = tcg_const_i32(dc->pc);
     TCGv_i32 tcause = tcg_const_i32(cause);
     gen_advance_ccount(dc);
-    gen_helper_exception_cause_vaddr(tpc, tcause, vaddr);
+    gen_helper_exception_cause_vaddr(cpu_env, tpc, tcause, vaddr);
     tcg_temp_free(tpc);
     tcg_temp_free(tcause);
 }
@@ -302,7 +302,7 @@ static void gen_debug_exception(DisasContext *dc, uint32_t cause)
     TCGv_i32 tpc = tcg_const_i32(dc->pc);
     TCGv_i32 tcause = tcg_const_i32(cause);
     gen_advance_ccount(dc);
-    gen_helper_debug_exception(tpc, tcause);
+    gen_helper_debug_exception(cpu_env, tpc, tcause);
     tcg_temp_free(tpc);
     tcg_temp_free(tcause);
     if (cause & (DEBUGCAUSE_IB | DEBUGCAUSE_BI | DEBUGCAUSE_BN)) {
@@ -460,13 +460,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_helper_wsr_lbeg(cpu_env, 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_helper_wsr_lend(cpu_env, s);
     gen_jumpi_check_loop_end(dc, 0);
 }
 
@@ -499,7 +499,7 @@ static void gen_wsr_acchi(DisasContext *dc, uint32_t sr, TCGv_i32 s)
 
 static void gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
-    gen_helper_wsr_windowbase(v);
+    gen_helper_wsr_windowbase(cpu_env, v);
     reset_used_window(dc);
 }
 
@@ -516,7 +516,7 @@ static void gen_wsr_ptevaddr(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 
 static void gen_wsr_rasid(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
-    gen_helper_wsr_rasid(v);
+    gen_helper_wsr_rasid(cpu_env, v);
     /* This can change tb->flags, so exit tb */
     gen_jumpi_check_loop_end(dc, -1);
 }
@@ -528,7 +528,7 @@ static void gen_wsr_tlbcfg(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 
 static void gen_wsr_ibreakenable(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
-    gen_helper_wsr_ibreakenable(v);
+    gen_helper_wsr_ibreakenable(cpu_env, v);
     gen_jumpi_check_loop_end(dc, 0);
 }
 
@@ -538,7 +538,7 @@ static void gen_wsr_ibreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 
     if (id < dc->config->nibreak) {
         TCGv_i32 tmp = tcg_const_i32(id);
-        gen_helper_wsr_ibreaka(tmp, v);
+        gen_helper_wsr_ibreaka(cpu_env, tmp, v);
         tcg_temp_free(tmp);
         gen_jumpi_check_loop_end(dc, 0);
     }
@@ -550,7 +550,7 @@ static void gen_wsr_dbreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 
     if (id < dc->config->ndbreak) {
         TCGv_i32 tmp = tcg_const_i32(id);
-        gen_helper_wsr_dbreaka(tmp, v);
+        gen_helper_wsr_dbreaka(cpu_env, tmp, v);
         tcg_temp_free(tmp);
     }
 }
@@ -561,7 +561,7 @@ static void gen_wsr_dbreakc(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 
     if (id < dc->config->ndbreak) {
         TCGv_i32 tmp = tcg_const_i32(id);
-        gen_helper_wsr_dbreakc(tmp, v);
+        gen_helper_wsr_dbreakc(cpu_env, tmp, v);
         tcg_temp_free(tmp);
     }
 }
@@ -714,7 +714,7 @@ static void gen_waiti(DisasContext *dc, uint32_t imm4)
     TCGv_i32 pc = tcg_const_i32(dc->next_pc);
     TCGv_i32 intlevel = tcg_const_i32(imm4);
     gen_advance_ccount(dc);
-    gen_helper_waiti(pc, intlevel);
+    gen_helper_waiti(cpu_env, pc, intlevel);
     tcg_temp_free(pc);
     tcg_temp_free(intlevel);
 }
@@ -731,7 +731,7 @@ static void gen_window_check1(DisasContext *dc, unsigned r1)
 
         dc->used_window = r1 / 4;
         gen_advance_ccount(dc);
-        gen_helper_window_check(pc, w);
+        gen_helper_window_check(cpu_env, pc, w);
 
         tcg_temp_free(w);
         tcg_temp_free(pc);
@@ -851,8 +851,8 @@ static void disas_xtensa_insn(DisasContext *dc)
 
 #define RSR_SR (b1)
 
-    uint8_t b0 = ldub_code(dc->pc);
-    uint8_t b1 = ldub_code(dc->pc + 1);
+    uint8_t b0 = cpu_ldub_code(cpu_single_env, dc->pc);
+    uint8_t b1 = cpu_ldub_code(cpu_single_env, dc->pc + 1);
     uint8_t b2 = 0;
 
     static const uint32_t B4CONST[] = {
@@ -868,7 +868,7 @@ static void disas_xtensa_insn(DisasContext *dc)
         HAS_OPTION(XTENSA_OPTION_CODE_DENSITY);
     } else {
         dc->next_pc = dc->pc + 3;
-        b2 = ldub_code(dc->pc + 2);
+        b2 = cpu_ldub_code(cpu_single_env, dc->pc + 2);
     }
 
     switch (OP0) {
@@ -905,7 +905,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                             {
                                 TCGv_i32 tmp = tcg_const_i32(dc->pc);
                                 gen_advance_ccount(dc);
-                                gen_helper_retw(tmp, tmp);
+                                gen_helper_retw(tmp, cpu_env, tmp);
                                 gen_jump(dc, tmp);
                                 tcg_temp_free(tmp);
                             }
@@ -953,7 +953,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                     {
                         TCGv_i32 pc = tcg_const_i32(dc->pc);
                         gen_advance_ccount(dc);
-                        gen_helper_movsp(pc);
+                        gen_helper_movsp(cpu_env, pc);
                         tcg_gen_mov_i32(cpu_R[RRR_T], cpu_R[RRR_S]);
                         tcg_temp_free(pc);
                     }
@@ -1033,7 +1033,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                                             cpu_SR[WINDOW_START], tmp);
                                 }
 
-                                gen_helper_restore_owb();
+                                gen_helper_restore_owb(cpu_env);
                                 gen_helper_check_interrupts(cpu_env);
                                 gen_jump(dc, cpu_SR[EPC1]);
 
@@ -1221,7 +1221,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                     {
                         TCGv_i32 tmp = tcg_const_i32(
                                 RRR_T | ((RRR_T & 8) ? 0xfffffff0 : 0));
-                        gen_helper_rotw(tmp);
+                        gen_helper_rotw(cpu_env, tmp);
                         tcg_temp_free(tmp);
                         reset_used_window(dc);
                     }
@@ -1257,28 +1257,32 @@ static void disas_xtensa_insn(DisasContext *dc)
 
                     switch (RRR_R & 7) {
                     case 3: /*RITLB0*/ /*RDTLB0*/
-                        gen_helper_rtlb0(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
+                        gen_helper_rtlb0(cpu_R[RRR_T],
+                                cpu_env, cpu_R[RRR_S], dtlb);
                         break;
 
                     case 4: /*IITLB*/ /*IDTLB*/
-                        gen_helper_itlb(cpu_R[RRR_S], dtlb);
+                        gen_helper_itlb(cpu_env, cpu_R[RRR_S], dtlb);
                         /* This could change memory mapping, so exit tb */
                         gen_jumpi_check_loop_end(dc, -1);
                         break;
 
                     case 5: /*PITLB*/ /*PDTLB*/
                         tcg_gen_movi_i32(cpu_pc, dc->pc);
-                        gen_helper_ptlb(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
+                        gen_helper_ptlb(cpu_R[RRR_T],
+                                cpu_env, cpu_R[RRR_S], dtlb);
                         break;
 
                     case 6: /*WITLB*/ /*WDTLB*/
-                        gen_helper_wtlb(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
+                        gen_helper_wtlb(
+                                cpu_env, cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
                         /* This could change memory mapping, so exit tb */
                         gen_jumpi_check_loop_end(dc, -1);
                         break;
 
                     case 7: /*RITLB1*/ /*RDTLB1*/
-                        gen_helper_rtlb1(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
+                        gen_helper_rtlb1(cpu_R[RRR_T],
+                                cpu_env, cpu_R[RRR_S], dtlb);
                         break;
 
                     default:
@@ -2246,7 +2250,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                     TCGv_i32 s = tcg_const_i32(BRI12_S);
                     TCGv_i32 imm = tcg_const_i32(BRI12_IMM12);
                     gen_advance_ccount(dc);
-                    gen_helper_entry(pc, s, imm);
+                    gen_helper_entry(cpu_env, pc, s, imm);
                     tcg_temp_free(imm);
                     tcg_temp_free(s);
                     tcg_temp_free(pc);
@@ -2280,7 +2284,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
                         tcg_gen_subi_i32(cpu_SR[LCOUNT], cpu_R[RRI8_S], 1);
                         tcg_gen_movi_i32(cpu_SR[LBEG], dc->next_pc);
-                        gen_helper_wsr_lend(tmp);
+                        gen_helper_wsr_lend(cpu_env, tmp);
                         tcg_temp_free(tmp);
 
                         if (BRI8_R > 8) {
@@ -2449,7 +2453,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 {
                     TCGv_i32 tmp = tcg_const_i32(dc->pc);
                     gen_advance_ccount(dc);
-                    gen_helper_retw(tmp, tmp);
+                    gen_helper_retw(tmp, cpu_env, tmp);
                     gen_jump(dc, tmp);
                     tcg_temp_free(tmp);
                 }
commit e8de1ea849176812765bf30514f66c5450a1edc6
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun Jun 10 11:33:11 2012 +0400

    target-xtensa: add attributes to helper functions
    
    Mark exception generating functions 'noreturn' and pure constant
    functions as such.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-xtensa/helper.h b/target-xtensa/helper.h
index 48a741e..9dd6f89 100644
--- a/target-xtensa/helper.h
+++ b/target-xtensa/helper.h
@@ -1,12 +1,12 @@
 #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(exception, noreturn, i32)
+DEF_HELPER_2(exception_cause, noreturn, i32, i32)
+DEF_HELPER_3(exception_cause_vaddr, noreturn, i32, i32, i32)
+DEF_HELPER_2(debug_exception, noreturn, i32, i32)
 
-DEF_HELPER_1(nsa, i32, i32)
-DEF_HELPER_1(nsau, i32, i32)
+DEF_HELPER_FLAGS_1(nsa, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+DEF_HELPER_FLAGS_1(nsau, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
 DEF_HELPER_1(wsr_windowbase, void, i32)
 DEF_HELPER_3(entry, void, i32, i32, i32)
 DEF_HELPER_1(retw, i32, i32)
@@ -25,8 +25,8 @@ 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_FLAGS_2(rtlb0, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(rtlb1, TCG_CALL_CONST | TCG_CALL_PURE, 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)
commit 9ed3a188fff6ffc33dcadce6061c708b2fb3b0b2
Author: Peter Portante <peter.portante at redhat.com>
Date:   Sun Jun 10 11:33:10 2012 +0400

    target-xtensa: remove unnecessary include of dyngen-exec.h
    
    Signed-off-by: Peter Portante <peter.portante at redhat.com>
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-xtensa/xtensa-semi.c b/target-xtensa/xtensa-semi.c
index b7c8c34..1c8a19e 100644
--- a/target-xtensa/xtensa-semi.c
+++ b/target-xtensa/xtensa-semi.c
@@ -30,7 +30,6 @@
 #include <string.h>
 #include <stddef.h>
 #include "cpu.h"
-#include "dyngen-exec.h"
 #include "helper.h"
 #include "qemu-log.h"
 
commit d865f307399441919d6646545b7735e57920da04
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Mon May 28 03:18:33 2012 +0400

    target-xtensa: fix CCOUNT for conditional branches
    
    Taken conditional branches fail to update CCOUNT register because
    accumulated ccount_delta is reset during translation of non-taken
    branch. To fix it only update CCOUNT once per conditional branch
    instruction translation.
    
    This fixes guest linux freeze on LTP waitpid06 test.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 521c0e6..a542a31 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -388,6 +388,7 @@ static bool gen_check_loop_end(DisasContext *dc, int slot)
             dc->next_pc == dc->lend) {
         int label = gen_new_label();
 
+        gen_advance_ccount(dc);
         tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_SR[LCOUNT], 0, label);
         tcg_gen_subi_i32(cpu_SR[LCOUNT], cpu_SR[LCOUNT], 1);
         gen_jumpi(dc, dc->lbeg, slot);
@@ -410,6 +411,7 @@ static void gen_brcond(DisasContext *dc, TCGCond cond,
 {
     int label = gen_new_label();
 
+    gen_advance_ccount(dc);
     tcg_gen_brcond_i32(cond, t0, t1, label);
     gen_jumpi_check_loop_end(dc, 0);
     gen_set_label(label);
commit 9d70c4b7b8a580959cc4f739e7c9a04964d00d46
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun May 27 20:21:08 2012 +0400

    exec: fix TB invalidation after breakpoint insertion/deletion
    
    tb_invalidate_phys_addr has to be called with the exact physical address of
    the breakpoint we add/remove, not just the page's base address.
    Otherwise we easily fail to flush the right TB.
    
    This breakage was introduced by the commit f3705d5329 "memory: make
    phys_page_find() return an unadjusted".
    
    This appeared to work for some guest architectures because their
    cpu_get_phys_page_debug implementation returns full translated physical
    address, not just the base of the TARGET_PAGE_SIZE-sized page.
    
    Reported-by: TeLeMan <geleman at gmail.com>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/exec.c b/exec.c
index 1b65859..a587e7a 100644
--- a/exec.c
+++ b/exec.c
@@ -1492,7 +1492,8 @@ void tb_invalidate_phys_addr(target_phys_addr_t addr)
 
 static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
 {
-    tb_invalidate_phys_addr(cpu_get_phys_page_debug(env, pc));
+    tb_invalidate_phys_addr(cpu_get_phys_page_debug(env, pc) |
+            (pc & ~TARGET_PAGE_MASK));
 }
 #endif
 #endif /* TARGET_HAS_ICE */
commit c305e32f4336e29fd3f86fc32ffce7b00e5bd9e1
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun May 27 18:34:54 2012 +0400

    target-xtensa: add MMU pagewalking tests
    
    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_mmu.S b/tests/tcg/xtensa/test_mmu.S
index 52d5774..5d87fbb 100644
--- a/tests/tcg/xtensa/test_mmu.S
+++ b/tests/tcg/xtensa/test_mmu.S
@@ -293,26 +293,219 @@ test store_prohibited
     assert  eq, a2, a3
 test_end
 
-test dtlb_autoload
-    set_vector kernel, 0
-
-    movi    a2, 0xd4000000
+/* Set up page table entry vaddr->paddr, ring=pte_ring, attr=pte_attr
+ * and DTLB way 7 to cover this PTE, ring=pt_ring, attr=pt_attr
+ */
+.macro pt_setup pt_ring, pt_attr, pte_ring, vaddr, paddr, pte_attr
+    movi    a2, 0x80000000
     wsr     a2, ptevaddr
-    movi    a3, 0x00001013
-    s32i    a3, a2, 4
+
+    movi    a3, 0x80000007 | (((\vaddr) >> 10) & 0xfffff000) /* way 7 */
+    movi    a4, 0x04000003 | ((\pt_ring) << 4) /* PADDR 64M */
+    wdtlb   a4, a3
+    isync
+
+    movi    a3, ((\paddr) & 0xfffff000) | ((\pte_ring) << 4) | (\pte_attr)
+    movi    a1, ((\vaddr) >> 12) << 2
+    add     a2, a1, a2
+    s32i    a3, a2, 0
+
+    movi    a3, 0x80000007 | (((\vaddr) >> 10) & 0xfffff000) /* way 7 */
+    movi    a4, 0x04000000 | ((\pt_ring) << 4) | (\pt_attr) /* PADDR 64M */
+    wdtlb   a4, a3
+    isync
+
+    movi    a3, (\vaddr)
+.endm
+
+/* out: PS.RING=ring, PS.EXCM=excm, a3=vaddr */
+.macro go_ring ring, excm, vaddr
+    movi    a3, 10f
+    pitlb   a3, a3
+    ritlb1  a2, a3
+    movi    a1, 0x10
+    or      a2, a2, a1
+    movi    a1, 0x000ff000
+    and     a3, a3, a1
+    movi    a1, 4
+    or      a3, a3, a1
+    witlb   a2, a3
+    movi    a3, 10f
+    movi    a1, 0x000fffff
+    and     a1, a3, a1
+
+    movi    a2, 0
+    wsr     a2, excvaddr
+
+    movi    a3, \vaddr
+    movi    a2, 0x4000f | ((\ring) << 6) | ((\excm) << 4)
+    jx      a1
+10:
+    wsr     a2, ps
+    isync
+.endm
+
+/* in: a3 -- virtual address to test */
+.macro assert_auto_tlb
+    movi    a2, 0x4000f
+    wsr     a2, ps
+    isync
+    pdtlb   a2, a3
+    movi    a1, 0xfffff01f
+    and     a2, a2, a1
+    movi    a1, 0xfffff000
+    and     a1, a1, a3
+    xor     a1, a1, a2
+    assert  gei, a1, 0x10
+    movi    a2, 0x14
+    assert  lt, a1, a2
+.endm
+
+/* in: a3 -- virtual address to test */
+.macro assert_no_auto_tlb
+    movi    a2, 0x4000f
+    wsr     a2, ps
+    isync
     pdtlb   a2, a3
     movi    a1, 0x10
     and     a1, a1, a2
     assert  eqi, a1, 0
-    l8ui    a1, a3, 0
-    pdtlb   a2, a3
-    movi    a1, 0xfffff010
-    and     a1, a1, a2
-    movi    a3, 0x00001010
-    assert  eq, a1, a3
-    movi    a1, 0xf
+.endm
+
+.macro assert_sr sr, v
+    rsr     a2, \sr
+    movi    a1, (\v)
+    assert  eq, a1, a2
+.endm
+
+.macro assert_epc1_1m vaddr
+    movi    a2, (\vaddr)
+    movi    a1, 0xfffff
     and     a1, a1, a2
-    assert  lti, a1, 4
+    rsr     a2, epc1
+    assert  eq, a1, a2
+.endm
+
+test dtlb_autoload
+    set_vector kernel, 0
+
+    pt_setup    0, 3, 1, 0x1000, 0x1000, 3
+    assert_no_auto_tlb
+
+    l8ui    a1, a3, 0
+
+    rsr     a2, excvaddr
+    assert  eq, a2, a3
+
+    assert_auto_tlb
+test_end
+
+test autoload_load_store_privilege
+    set_vector kernel, 0
+    set_vector double, 2f
+
+    pt_setup    0, 3, 0, 0x2000, 0x2000, 3
+    movi    a3, 0x2004
+    assert_no_auto_tlb
+
+    movi    a2, 0x4005f    /* ring 1 + excm => cring == 0 */
+    wsr     a2, ps
+    isync
+1:
+    l32e    a2, a3, -4     /* ring used */
+    test_fail
+2:
+    rsr     a2, excvaddr
+    addi    a1, a3, -4
+    assert  eq, a1, a2
+
+    assert_auto_tlb
+    assert_sr depc, 1b
+    assert_sr exccause, 26
+test_end
+
+test autoload_pte_load_prohibited
+    set_vector kernel, 2f
+
+    pt_setup    0, 3, 0, 0x3000, 0, 0xc
+    assert_no_auto_tlb
+1:
+    l32i    a2, a3, 0
+    test_fail
+2:
+    rsr     a2, excvaddr
+    assert  eq, a2, a3
+
+    assert_auto_tlb
+    assert_sr epc1, 1b
+    assert_sr exccause, 28
+test_end
+
+test autoload_pt_load_prohibited
+    set_vector kernel, 2f
+
+    pt_setup    0, 0xc, 0, 0x4000, 0x4000, 3
+    assert_no_auto_tlb
+1:
+    l32i    a2, a3, 0
+    test_fail
+2:
+    rsr     a2, excvaddr
+    assert  eq, a2, a3
+
+    assert_no_auto_tlb
+    assert_sr epc1, 1b
+    assert_sr exccause, 24
+test_end
+
+test autoload_pt_privilege
+    set_vector  kernel, 2f
+    pt_setup    0, 3, 1, 0x5000, 0, 3
+    go_ring     1, 0, 0x5001
+
+    l8ui    a2, a3, 0
+1:
+    syscall
+2:
+    rsr     a2, excvaddr
+    assert  eq, a2, a3
+
+    assert_auto_tlb
+    assert_epc1_1m 1b
+    assert_sr exccause, 1
+test_end
+
+test autoload_pte_privilege
+    set_vector  kernel, 2f
+    pt_setup    0, 3, 0, 0x6000, 0, 3
+    go_ring     1, 0, 0x6001
+1:
+    l8ui    a2, a3, 0
+    syscall
+2:
+    rsr     a2, excvaddr
+    assert  eq, a2, a3
+
+    assert_auto_tlb
+    assert_epc1_1m 1b
+    assert_sr exccause, 26
+test_end
+
+test autoload_3_level_pt
+    set_vector  kernel, 2f
+    pt_setup    1, 3, 1, 0x00400000, 0, 3
+    pt_setup    1, 3, 1, 0x80001000, 0x2000000, 3
+    go_ring     1, 0, 0x00400001
+1:
+    l8ui    a2, a3, 0
+    syscall
+2:
+    rsr     a2, excvaddr
+    assert  eq, a2, a3
+
+    assert_no_auto_tlb
+    assert_epc1_1m 1b
+    assert_sr exccause, 24
 test_end
 
 test_suite_end
commit 57705a676c65e6ecacc44c23b192f3d7ed2cdedd
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun May 27 18:34:53 2012 +0400

    target-xtensa: control page table lookup explicitly
    
    Hardware pagetable walking may not be nested. Stop guessing and pass
    explicit flag to the get_physical_addr_mmu function that controls page
    table lookup.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index ea4bf73..044ce18 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -447,7 +447,8 @@ static int get_pte(CPUXtensaState *env, uint32_t vaddr, uint32_t *pte);
 
 static int get_physical_addr_mmu(CPUXtensaState *env, bool update_tlb,
         uint32_t vaddr, int is_write, int mmu_idx,
-        uint32_t *paddr, uint32_t *page_size, unsigned *access)
+        uint32_t *paddr, uint32_t *page_size, unsigned *access,
+        bool may_lookup_pt)
 {
     bool dtlb = is_write != 2;
     uint32_t wi;
@@ -460,8 +461,7 @@ static int get_physical_addr_mmu(CPUXtensaState *env, bool update_tlb,
     int ret = xtensa_tlb_lookup(env, vaddr, dtlb, &wi, &ei, &ring);
 
     if ((ret == INST_TLB_MISS_CAUSE || ret == LOAD_STORE_TLB_MISS_CAUSE) &&
-            (mmu_idx != 0 || ((vaddr ^ env->sregs[PTEVADDR]) & 0xffc00000)) &&
-            get_pte(env, vaddr, &pte) == 0) {
+            may_lookup_pt && get_pte(env, vaddr, &pte) == 0) {
         ring = (pte >> 4) & 0x3;
         wi = 0;
         split_tlb_entry_spec_way(env, vaddr, dtlb, &vpn, wi, &ei);
@@ -515,7 +515,7 @@ static int get_pte(CPUXtensaState *env, uint32_t vaddr, uint32_t *pte)
     uint32_t pt_vaddr =
         (env->sregs[PTEVADDR] | (vaddr >> 10)) & 0xfffffffc;
     int ret = get_physical_addr_mmu(env, false, pt_vaddr, 0, 0,
-            &paddr, &page_size, &access);
+            &paddr, &page_size, &access, false);
 
     qemu_log("%s: trying autorefill(%08x) -> %08x\n", __func__,
             vaddr, ret ? ~0 : paddr);
@@ -563,7 +563,7 @@ int xtensa_get_physical_addr(CPUXtensaState *env, bool update_tlb,
 {
     if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
         return get_physical_addr_mmu(env, update_tlb,
-                vaddr, is_write, mmu_idx, paddr, page_size, access);
+                vaddr, is_write, mmu_idx, paddr, page_size, access, true);
     } else if (xtensa_option_bits_enabled(env->config,
                 XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_PROTECTION) |
                 XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_TRANSLATION))) {
commit ae4e7982e6db8b88e90db74779f4693bc2c636a8
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun May 27 18:34:52 2012 +0400

    target-xtensa: update autorefill TLB entries conditionally
    
    This is to avoid interference of internal QEMU helpers
    (cpu_get_phys_page_debug, tb_invalidate_virtual_addr) with guest-visible
    TLB state.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index c2ca509..f7db116 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -386,7 +386,7 @@ void xtensa_tlb_set_entry_mmu(const CPUXtensaState *env,
         unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte);
 void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb,
         unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte);
-int xtensa_get_physical_addr(CPUXtensaState *env,
+int xtensa_get_physical_addr(CPUXtensaState *env, bool update_tlb,
         uint32_t vaddr, int is_write, int mmu_idx,
         uint32_t *paddr, uint32_t *page_size, unsigned *access);
 void reset_mmu(CPUXtensaState *env);
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index 04c4f60..ea4bf73 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -130,11 +130,11 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUXtensaState *env, target_ulong add
     uint32_t page_size;
     unsigned access;
 
-    if (xtensa_get_physical_addr(env, addr, 0, 0,
+    if (xtensa_get_physical_addr(env, false, addr, 0, 0,
                 &paddr, &page_size, &access) == 0) {
         return paddr;
     }
-    if (xtensa_get_physical_addr(env, addr, 2, 0,
+    if (xtensa_get_physical_addr(env, false, addr, 2, 0,
                 &paddr, &page_size, &access) == 0) {
         return paddr;
     }
@@ -443,10 +443,9 @@ static bool is_access_granted(unsigned access, int is_write)
     }
 }
 
-static int autorefill_mmu(CPUXtensaState *env, uint32_t vaddr, bool dtlb,
-        uint32_t *wi, uint32_t *ei, uint8_t *ring);
+static int get_pte(CPUXtensaState *env, uint32_t vaddr, uint32_t *pte);
 
-static int get_physical_addr_mmu(CPUXtensaState *env,
+static int get_physical_addr_mmu(CPUXtensaState *env, bool update_tlb,
         uint32_t vaddr, int is_write, int mmu_idx,
         uint32_t *paddr, uint32_t *page_size, unsigned *access)
 {
@@ -454,19 +453,38 @@ static int get_physical_addr_mmu(CPUXtensaState *env,
     uint32_t wi;
     uint32_t ei;
     uint8_t ring;
+    uint32_t vpn;
+    uint32_t pte;
+    const xtensa_tlb_entry *entry = NULL;
+    xtensa_tlb_entry tmp_entry;
     int ret = xtensa_tlb_lookup(env, vaddr, dtlb, &wi, &ei, &ring);
 
     if ((ret == INST_TLB_MISS_CAUSE || ret == LOAD_STORE_TLB_MISS_CAUSE) &&
             (mmu_idx != 0 || ((vaddr ^ env->sregs[PTEVADDR]) & 0xffc00000)) &&
-            autorefill_mmu(env, vaddr, dtlb, &wi, &ei, &ring) == 0) {
+            get_pte(env, vaddr, &pte) == 0) {
+        ring = (pte >> 4) & 0x3;
+        wi = 0;
+        split_tlb_entry_spec_way(env, vaddr, dtlb, &vpn, wi, &ei);
+
+        if (update_tlb) {
+            wi = ++env->autorefill_idx & 0x3;
+            xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, pte);
+            env->sregs[EXCVADDR] = vaddr;
+            qemu_log("%s: autorefill(%08x): %08x -> %08x\n",
+                    __func__, vaddr, vpn, pte);
+        } else {
+            xtensa_tlb_set_entry_mmu(env, &tmp_entry, dtlb, wi, ei, vpn, pte);
+            entry = &tmp_entry;
+        }
         ret = 0;
     }
     if (ret != 0) {
         return ret;
     }
 
-    const xtensa_tlb_entry *entry =
-        xtensa_tlb_get_entry(env, dtlb, wi, ei);
+    if (entry == NULL) {
+        entry = xtensa_tlb_get_entry(env, dtlb, wi, ei);
+    }
 
     if (ring < mmu_idx) {
         return dtlb ?
@@ -489,31 +507,21 @@ static int get_physical_addr_mmu(CPUXtensaState *env,
     return 0;
 }
 
-static int autorefill_mmu(CPUXtensaState *env, uint32_t vaddr, bool dtlb,
-        uint32_t *wi, uint32_t *ei, uint8_t *ring)
+static int get_pte(CPUXtensaState *env, uint32_t vaddr, uint32_t *pte)
 {
     uint32_t paddr;
     uint32_t page_size;
     unsigned access;
     uint32_t pt_vaddr =
         (env->sregs[PTEVADDR] | (vaddr >> 10)) & 0xfffffffc;
-    int ret = get_physical_addr_mmu(env, pt_vaddr, 0, 0,
+    int ret = get_physical_addr_mmu(env, false, pt_vaddr, 0, 0,
             &paddr, &page_size, &access);
 
     qemu_log("%s: trying autorefill(%08x) -> %08x\n", __func__,
             vaddr, ret ? ~0 : paddr);
 
     if (ret == 0) {
-        uint32_t vpn;
-        uint32_t pte = ldl_phys(paddr);
-
-        *ring = (pte >> 4) & 0x3;
-        *wi = (++env->autorefill_idx) & 0x3;
-        split_tlb_entry_spec_way(env, vaddr, dtlb, &vpn, *wi, ei);
-        xtensa_tlb_set_entry(env, dtlb, *wi, *ei, vpn, pte);
-        env->sregs[EXCVADDR] = vaddr;
-        qemu_log("%s: autorefill(%08x): %08x -> %08x\n",
-                __func__, vaddr, vpn, pte);
+        *pte = ldl_phys(paddr);
     }
     return ret;
 }
@@ -549,13 +557,13 @@ static int get_physical_addr_region(CPUXtensaState *env,
  *
  * \return 0 if ok, exception cause code otherwise
  */
-int xtensa_get_physical_addr(CPUXtensaState *env,
+int xtensa_get_physical_addr(CPUXtensaState *env, bool update_tlb,
         uint32_t vaddr, int is_write, int mmu_idx,
         uint32_t *paddr, uint32_t *page_size, unsigned *access)
 {
     if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
-        return get_physical_addr_mmu(env, vaddr, is_write, mmu_idx,
-                paddr, page_size, access);
+        return get_physical_addr_mmu(env, update_tlb,
+                vaddr, is_write, mmu_idx, paddr, page_size, access);
     } else if (xtensa_option_bits_enabled(env->config,
                 XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_PROTECTION) |
                 XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_TRANSLATION))) {
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index 663bb6d..41107ff 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -79,7 +79,7 @@ void tlb_fill(CPUXtensaState *env1, target_ulong vaddr, int is_write, int mmu_id
         uint32_t paddr;
         uint32_t page_size;
         unsigned access;
-        int ret = xtensa_get_physical_addr(env, vaddr, is_write, mmu_idx,
+        int ret = xtensa_get_physical_addr(env, true, vaddr, is_write, mmu_idx,
                 &paddr, &page_size, &access);
 
         qemu_log("%s(%08x, %d, %d) -> %08x, ret = %d\n", __func__,
@@ -103,7 +103,7 @@ 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,
+    int ret = xtensa_get_physical_addr(env, false, vaddr, 2, 0,
             &paddr, &page_size, &access);
     if (ret == 0) {
         tb_invalidate_phys_addr(paddr);
commit 16bde77a298acfe15f5e948aceff550d0cb173e8
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun May 27 18:34:51 2012 +0400

    target-xtensa: extract TLB entry setting method
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 81f7833..c2ca509 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -381,6 +381,9 @@ void split_tlb_entry_spec_way(const CPUXtensaState *env, uint32_t v, bool dtlb,
         uint32_t *vpn, uint32_t wi, uint32_t *ei);
 int xtensa_tlb_lookup(const CPUXtensaState *env, uint32_t addr, bool dtlb,
         uint32_t *pwi, uint32_t *pei, uint8_t *pring);
+void xtensa_tlb_set_entry_mmu(const CPUXtensaState *env,
+        xtensa_tlb_entry *entry, bool dtlb,
+        unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte);
 void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb,
         unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte);
 int xtensa_get_physical_addr(CPUXtensaState *env,
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index ce61157..663bb6d 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -655,6 +655,16 @@ uint32_t HELPER(ptlb)(uint32_t v, uint32_t dtlb)
     }
 }
 
+void xtensa_tlb_set_entry_mmu(const CPUXtensaState *env,
+        xtensa_tlb_entry *entry, bool dtlb,
+        unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte)
+{
+    entry->vaddr = vpn;
+    entry->paddr = pte & xtensa_tlb_get_addr_mask(env, dtlb, wi);
+    entry->asid = (env->sregs[RASID] >> ((pte >> 1) & 0x18)) & 0xff;
+    entry->attr = pte & 0xf;
+}
+
 void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb,
         unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte)
 {
@@ -665,10 +675,7 @@ void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb,
             if (entry->asid) {
                 tlb_flush_page(env, entry->vaddr);
             }
-            entry->vaddr = vpn;
-            entry->paddr = pte & xtensa_tlb_get_addr_mask(env, dtlb, wi);
-            entry->asid = (env->sregs[RASID] >> ((pte >> 1) & 0x18)) & 0xff;
-            entry->attr = pte & 0xf;
+            xtensa_tlb_set_entry_mmu(env, entry, dtlb, wi, ei, vpn, pte);
             tlb_flush_page(env, entry->vaddr);
         } else {
             qemu_log("%s %d, %d, %d trying to set immutable entry\n",
commit 39e7d37f0f25823c00d1105e8eb9b61182fd349c
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun May 27 18:34:50 2012 +0400

    target-xtensa: update EXCVADDR in case of page table lookup
    
    According to ISA, 4.4.2.6, EXCVADDR may be changed by any TLB miss, even
    if the miss is handled entirely by processor hardware.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index 5e7e72e..04c4f60 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -511,6 +511,7 @@ static int autorefill_mmu(CPUXtensaState *env, uint32_t vaddr, bool dtlb,
         *wi = (++env->autorefill_idx) & 0x3;
         split_tlb_entry_spec_way(env, vaddr, dtlb, &vpn, *wi, ei);
         xtensa_tlb_set_entry(env, dtlb, *wi, *ei, vpn, pte);
+        env->sregs[EXCVADDR] = vaddr;
         qemu_log("%s: autorefill(%08x): %08x -> %08x\n",
                 __func__, vaddr, vpn, pte);
     }
commit e323bdeff28f3bd647bf02cc9df57971eff3e258
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun May 27 18:34:49 2012 +0400

    target-xtensa: flush TLB page for new MMU mapping
    
    Both old and new mappings need flushing because their VPN may be
    different in MMU case.
    
    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 364dc19..ce61157 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -669,6 +669,7 @@ void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb,
             entry->paddr = pte & xtensa_tlb_get_addr_mask(env, dtlb, wi);
             entry->asid = (env->sregs[RASID] >> ((pte >> 1) & 0x18)) & 0xff;
             entry->attr = pte & 0xf;
+            tlb_flush_page(env, entry->vaddr);
         } else {
             qemu_log("%s %d, %d, %d trying to set immutable entry\n",
                     __func__, dtlb, wi, ei);
commit bbbc0e244e35cdc159f559e9d47e5941a1b35745
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Jun 7 15:45:35 2012 +0200

    w32: Fix broken build (missing include file)
    
    dump.c was recently added to the code. It unconditionally
    includes sys/procfs which is not available with MinGW (w32, w64).
    
    It looks like this file is not needed at all (tested on Linux),
    so I removed it completely.
    
    Some other include statements are also redundant because they are
    already included in qemu-common, therefore they were removed, too.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/dump.c b/dump.c
index f5c7283..4412d7a 100644
--- a/dump.c
+++ b/dump.c
@@ -12,10 +12,7 @@
  */
 
 #include "qemu-common.h"
-#include <unistd.h>
 #include "elf.h"
-#include <sys/procfs.h>
-#include <glib.h>
 #include "cpu.h"
 #include "cpu-all.h"
 #include "targphys.h"
@@ -23,7 +20,6 @@
 #include "kvm.h"
 #include "dump.h"
 #include "sysemu.h"
-#include "bswap.h"
 #include "memory_mapping.h"
 #include "error.h"
 #include "qmp-commands.h"
commit 3294ce1893620aecf0d2a693c7177a0f84129422
Author: Michael Tokarev <mjt at tls.msk.ru>
Date:   Sat Jun 2 23:43:33 2012 +0400

    do not include <libutil.h> needlessly or if it doesn't exist
    
    <libutil.h> and <util.h> on *BSD (some have one, some another)
    were #included just for openpty() declaration.  The only file
    where this function is actually used is qemu-char.c.
    
    In vl.c and net/tap-bsd.c, none of functions declared in libutil.h
    (login logout logwtmp timdomain openpty forkpty uu_lock realhostname
    fparseln and a few others depending on version) are used.
    
    Initially the code which is currently in qemu-char.c was in vl.c,
    it has been removed into separate file in commit 0e82f34d077dc2542
    Fri Oct 31 18:44:40 2008, but the #includes were left in vl.c.
    So with vl.c, we just remove includes - libutil.h, util.h and
    pty.h (which declares only openpty() and forkpty()) from there.
    
    The code in net/tap-bsd.c, which come from net/tap.c, had this
    
    commit 5281d757efa6e40d74ce124be048b08d43887555
    Author: Mark McLoughlin <markmc at redhat.com>
    Date:   Thu Oct 22 17:49:07 2009 +0100
    
        net: split all the tap code out into net/tap.c
    
    Note this commit not only moved stuff out of net.c to net/tap.c,
    but also rewrote large portions of the tap code, and added these
    completely unnecessary #includes -- as usual, I question why such
    a misleading commit messages are allowed.
    
    Again, no functions defined in libutil.h or util.h on *BSD are
    used by neither net/tap.c nor net/tap-bsd.c.  Removing them.
    
    And finally, the only real user for these #includes, qemu-char.c,
    which actually uses openpty().  There, the #ifdef logic is wrong.
    A GLIBC-based system has <pty.h>, even if it is a variant of *BSD.
    So __GLIBC__ should be checked first, and instead of trying to
    include <libutil.h> or <util.h>, we include <pty.h>.  If it is not
    GLIBC-based, we check for variations between <*util.h> as before.
    
    This patch fixes build of qemu 1.1 on Debian/kFreebsd (well, one
    of the two problems): it is a distribution with a FreeBSD kernel,
    so it #defines at least __FreeBSD_kernel__, but since it is based
    on GLIBC, it has <pty.h>, but current version does not have neither
    <util.h> nor <libutil.h>, which the code tries to include 3 times
    but uses only once.
    
    Signed-off-By: Michael Tokarev <mjt at tls.msk.ru>
    Cc: Aurelien Jarno <aurelien at aurel32.net>
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/net/tap-bsd.c b/net/tap-bsd.c
index 4b6b3a4..937a94b 100644
--- a/net/tap-bsd.c
+++ b/net/tap-bsd.c
@@ -33,12 +33,6 @@
 #include <net/if_tap.h>
 #endif
 
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
-#include <libutil.h>
-#else
-#include <util.h>
-#endif
-
 int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required)
 {
     int fd;
diff --git a/qemu-char.c b/qemu-char.c
index 0bd903f..c2aaaee 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -56,19 +56,19 @@
 #include <sys/select.h>
 #ifdef CONFIG_BSD
 #include <sys/stat.h>
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-#include <libutil.h>
-#include <dev/ppbus/ppi.h>
-#include <dev/ppbus/ppbconf.h>
 #if defined(__GLIBC__)
 #include <pty.h>
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+#include <libutil.h>
+#else
+#include <util.h>
 #endif
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#include <dev/ppbus/ppi.h>
+#include <dev/ppbus/ppbconf.h>
 #elif defined(__DragonFly__)
-#include <libutil.h>
 #include <dev/misc/ppi/ppi.h>
 #include <bus/ppbus/ppbconf.h>
-#else
-#include <util.h>
 #endif
 #else
 #ifdef __linux__
diff --git a/vl.c b/vl.c
index 1485426..204d85b 100644
--- a/vl.c
+++ b/vl.c
@@ -51,14 +51,12 @@
 #ifdef CONFIG_BSD
 #include <sys/stat.h>
 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
-#include <libutil.h>
 #include <sys/sysctl.h>
 #else
 #include <util.h>
 #endif
 #else
 #ifdef __linux__
-#include <pty.h>
 #include <malloc.h>
 
 #include <linux/ppdev.h>
@@ -81,10 +79,6 @@
 #endif
 #endif
 
-#if defined(__OpenBSD__)
-#include <util.h>
-#endif
-
 #if defined(CONFIG_VDE)
 #include <libvdeplug.h>
 #endif
commit 7c760cbceaf6c5da1cfb4ee6019c6fecf0008d1a
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Sat Jun 9 03:43:05 2012 +0200

    target-ppc: Unbreak kvm_ppc.c build
    
    The file is located in target-ppc/, not hw/.
    
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Cc: Paolo Bonzini <pbonzini at redhat.com>
    Cc: Anthony Liguori <anthony at codemonkey.ws>
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index 842e7b9..d0ef8a2 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -18,7 +18,6 @@ obj-y += ppc440_bamboo.o
 obj-y += ppce500_mpc8544ds.o mpc8544_guts.o ppce500_spin.o
 # PowerPC 440 Xilinx ML507 reference board.
 obj-y += virtex_ml507.o
-obj-$(CONFIG_KVM) += kvm_ppc.o
 # PowerPC OpenPIC
 obj-y += openpic.o
 obj-$(CONFIG_FDT) += ../device_tree.o
diff --git a/target-ppc/Makefile.objs b/target-ppc/Makefile.objs
index 95ed340..f781610 100644
--- a/target-ppc/Makefile.objs
+++ b/target-ppc/Makefile.objs
@@ -1,6 +1,6 @@
 obj-y += translate.o op_helper.o helper.o
 obj-$(CONFIG_SOFTMMU) += machine.o
-obj-$(CONFIG_KVM) += kvm.o
+obj-$(CONFIG_KVM) += kvm.o kvm_ppc.o
 obj-y += op_helper.o helper.o
 
 $(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
commit 7baa82079f089dd2c6f42b11c39ba0fd9f1ab85d
Author: Stefan Weil <sw at weilnetz.de>
Date:   Fri Jun 8 19:57:25 2012 +0200

    dump: Fix build breakage (missing sys/procfs.h)
    
    sys/procfs is not available everywhere (MingW does not have it).
    
    Remove this and more unused or redundant include statements.
    This fixes the broken build.
    
    qerror.h was previously included indirectly.
    Add an explicit include statement for it because it is needed.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/dump-stub.c b/dump-stub.c
index 4c8bedb..165c005 100644
--- a/dump-stub.c
+++ b/dump-stub.c
@@ -12,22 +12,9 @@
  */
 
 #include "qemu-common.h"
-#include <unistd.h>
-#include "elf.h"
-#include <sys/procfs.h>
-#include <glib.h>
-#include "cpu.h"
-#include "cpu-all.h"
-#include "targphys.h"
-#include "monitor.h"
-#include "kvm.h"
 #include "dump.h"
-#include "sysemu.h"
-#include "bswap.h"
-#include "memory_mapping.h"
-#include "error.h"
+#include "qerror.h"
 #include "qmp-commands.h"
-#include "gdbstub.h"
 
 /* we need this function in hmp.c */
 void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
commit fa0298872e13939283bd0568e5326a1aa674c4ca
Author: Andreas Färber <afaerber at suse.de>
Date:   Tue May 1 23:33:13 2012 +0200

    target-i386: Use uint32 visitor for [x]level properties
    
    This simplifies the code and resolves TODOs.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Michael Roth <mdroth at linux.vnet.ibm.com>

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 388bc5c..0b61162 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -723,66 +723,32 @@ static void x86_cpuid_get_level(Object *obj, Visitor *v, void *opaque,
                                 const char *name, Error **errp)
 {
     X86CPU *cpu = X86_CPU(obj);
-    int64_t value;
 
-    value = cpu->env.cpuid_level;
-    /* TODO Use visit_type_uint32() once available */
-    visit_type_int(v, &value, name, errp);
+    visit_type_uint32(v, &cpu->env.cpuid_level, name, errp);
 }
 
 static void x86_cpuid_set_level(Object *obj, Visitor *v, void *opaque,
                                 const char *name, Error **errp)
 {
     X86CPU *cpu = X86_CPU(obj);
-    const int64_t min = 0;
-    const int64_t max = UINT32_MAX;
-    int64_t value;
-
-    /* TODO Use visit_type_uint32() once available */
-    visit_type_int(v, &value, name, errp);
-    if (error_is_set(errp)) {
-        return;
-    }
-    if (value < min || value > max) {
-        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
-                  name ? name : "null", value, min, max);
-        return;
-    }
 
-    cpu->env.cpuid_level = value;
+    visit_type_uint32(v, &cpu->env.cpuid_level, name, errp);
 }
 
 static void x86_cpuid_get_xlevel(Object *obj, Visitor *v, void *opaque,
                                  const char *name, Error **errp)
 {
     X86CPU *cpu = X86_CPU(obj);
-    int64_t value;
 
-    value = cpu->env.cpuid_xlevel;
-    /* TODO Use visit_type_uint32() once available */
-    visit_type_int(v, &value, name, errp);
+    visit_type_uint32(v, &cpu->env.cpuid_xlevel, name, errp);
 }
 
 static void x86_cpuid_set_xlevel(Object *obj, Visitor *v, void *opaque,
                                  const char *name, Error **errp)
 {
     X86CPU *cpu = X86_CPU(obj);
-    const int64_t min = 0;
-    const int64_t max = UINT32_MAX;
-    int64_t value;
-
-    /* TODO Use visit_type_uint32() once available */
-    visit_type_int(v, &value, name, errp);
-    if (error_is_set(errp)) {
-        return;
-    }
-    if (value < min || value > max) {
-        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
-                  name ? name : "null", value, min, max);
-        return;
-    }
 
-    cpu->env.cpuid_xlevel = value;
+    visit_type_uint32(v, &cpu->env.cpuid_xlevel, name, errp);
 }
 
 static char *x86_cpuid_get_vendor(Object *obj, Error **errp)
commit 27712df95d85e76e9d41a0a4ee2acd0ad8a9cc6d
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Apr 12 15:32:26 2012 +0200

    qdev: Remove PropertyInfo range checking
    
    Range checking in PropertyInfo is now used only for pci_devfn
    properties and some error reporting.  Remove all code that implements
    it in the various property types, and the now unused fields.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    [AF: Fix blocksize min/max for 32-bit hosts by using const int64_t.]
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 553b0d1..9ae3187 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -91,34 +91,20 @@ static void set_uint8(Object *obj, Visitor *v, void *opaque,
 {
     DeviceState *dev = DEVICE(obj);
     Property *prop = opaque;
-    uint8_t value, *ptr = qdev_get_prop_ptr(dev, prop);
-    Error *local_err = NULL;
+    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
 
     if (dev->state != DEV_STATE_CREATED) {
         error_set(errp, QERR_PERMISSION_DENIED);
         return;
     }
 
-    visit_type_uint8(v, &value, name, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
-        return;
-    }
-    if (value >= prop->info->min && value <= prop->info->max) {
-        *ptr = value;
-    } else {
-        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
-                  dev->id?:"", name, (int64_t)value, prop->info->min,
-                  prop->info->max);
-    }
+    visit_type_uint8(v, ptr, name, errp);
 }
 
 PropertyInfo qdev_prop_uint8 = {
     .name  = "uint8",
     .get   = get_uint8,
     .set   = set_uint8,
-    .min   = 0,
-    .max   = 255,
 };
 
 /* --- 8bit hex value --- */
@@ -153,8 +139,6 @@ PropertyInfo qdev_prop_hex8 = {
     .print = print_hex8,
     .get   = get_uint8,
     .set   = set_uint8,
-    .min   = 0,
-    .max   = 255,
 };
 
 /* --- 16bit integer --- */
@@ -174,34 +158,20 @@ static void set_uint16(Object *obj, Visitor *v, void *opaque,
 {
     DeviceState *dev = DEVICE(obj);
     Property *prop = opaque;
-    uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
-    Error *local_err = NULL;
+    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
 
     if (dev->state != DEV_STATE_CREATED) {
         error_set(errp, QERR_PERMISSION_DENIED);
         return;
     }
 
-    visit_type_uint16(v, &value, name, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
-        return;
-    }
-    if (value >= prop->info->min && value <= prop->info->max) {
-        *ptr = value;
-    } else {
-        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
-                  dev->id?:"", name, (int64_t)value, prop->info->min,
-                  prop->info->max);
-    }
+    visit_type_uint16(v, ptr, name, errp);
 }
 
 PropertyInfo qdev_prop_uint16 = {
     .name  = "uint16",
     .get   = get_uint16,
     .set   = set_uint16,
-    .min   = 0,
-    .max   = 65535,
 };
 
 /* --- 32bit integer --- */
@@ -211,10 +181,9 @@ static void get_uint32(Object *obj, Visitor *v, void *opaque,
 {
     DeviceState *dev = DEVICE(obj);
     Property *prop = opaque;
-    uint32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
+    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
 
-    value = *ptr;
-    visit_type_uint32(v, &value, name, errp);
+    visit_type_uint32(v, ptr, name, errp);
 }
 
 static void set_uint32(Object *obj, Visitor *v, void *opaque,
@@ -222,26 +191,14 @@ static void set_uint32(Object *obj, Visitor *v, void *opaque,
 {
     DeviceState *dev = DEVICE(obj);
     Property *prop = opaque;
-    uint32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
-    Error *local_err = NULL;
+    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
 
     if (dev->state != DEV_STATE_CREATED) {
         error_set(errp, QERR_PERMISSION_DENIED);
         return;
     }
 
-    visit_type_uint32(v, &value, name, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
-        return;
-    }
-    if (value >= prop->info->min && value <= prop->info->max) {
-        *ptr = value;
-    } else {
-        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
-                  dev->id?:"", name, (int64_t)value, prop->info->min,
-                  prop->info->max);
-    }
+    visit_type_uint32(v, ptr, name, errp);
 }
 
 static void get_int32(Object *obj, Visitor *v, void *opaque,
@@ -259,42 +216,26 @@ static void set_int32(Object *obj, Visitor *v, void *opaque,
 {
     DeviceState *dev = DEVICE(obj);
     Property *prop = opaque;
-    int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
-    Error *local_err = NULL;
+    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
 
     if (dev->state != DEV_STATE_CREATED) {
         error_set(errp, QERR_PERMISSION_DENIED);
         return;
     }
 
-    visit_type_int32(v, &value, name, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
-        return;
-    }
-    if (value >= prop->info->min && value <= prop->info->max) {
-        *ptr = value;
-    } else {
-        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
-                  dev->id?:"", name, (int64_t)value, prop->info->min,
-                  prop->info->max);
-    }
+    visit_type_int32(v, ptr, name, errp);
 }
 
 PropertyInfo qdev_prop_uint32 = {
     .name  = "uint32",
     .get   = get_uint32,
     .set   = set_uint32,
-    .min   = 0,
-    .max   = 0xFFFFFFFFULL,
 };
 
 PropertyInfo qdev_prop_int32 = {
     .name  = "int32",
     .get   = get_int32,
     .set   = set_int32,
-    .min   = -0x80000000LL,
-    .max   = 0x7FFFFFFFLL,
 };
 
 /* --- 32bit hex value --- */
@@ -329,8 +270,6 @@ PropertyInfo qdev_prop_hex32 = {
     .print = print_hex32,
     .get   = get_uint32,
     .set   = set_uint32,
-    .min   = 0,
-    .max   = 0xFFFFFFFFULL,
 };
 
 /* --- 64bit integer --- */
@@ -853,7 +792,7 @@ static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
 {
     DeviceState *dev = DEVICE(obj);
     Property *prop = opaque;
-    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
+    int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
     unsigned int slot, fn, n;
     Error *local_err = NULL;
     char *str;
@@ -866,7 +805,17 @@ static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
     visit_type_str(v, &str, name, &local_err);
     if (local_err) {
         error_free(local_err);
-        return set_int32(obj, v, opaque, name, errp);
+        local_err = NULL;
+        visit_type_int32(v, &value, name, &local_err);
+        if (local_err) {
+            error_propagate(errp, local_err);
+        } else if (value < -1 || value > 255) {
+            error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
+                      "pci_devfn");
+        } else {
+            *ptr = value;
+        }
+        return;
     }
 
     if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
@@ -904,8 +853,6 @@ PropertyInfo qdev_prop_pci_devfn = {
     .print = print_pci_devfn,
     .get   = get_int32,
     .set   = set_pci_devfn,
-    .min   = -1,
-    .max   = 255,
 };
 
 /* --- blocksize --- */
@@ -917,6 +864,8 @@ static void set_blocksize(Object *obj, Visitor *v, void *opaque,
     Property *prop = opaque;
     uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
     Error *local_err = NULL;
+    const int64_t min = 512;
+    const int64_t max = 32768;
 
     if (dev->state != DEV_STATE_CREATED) {
         error_set(errp, QERR_PERMISSION_DENIED);
@@ -928,10 +877,9 @@ static void set_blocksize(Object *obj, Visitor *v, void *opaque,
         error_propagate(errp, local_err);
         return;
     }
-    if (value < prop->info->min || value > prop->info->max) {
+    if (value < min || value > max) {
         error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
-                  dev->id?:"", name, (int64_t)value, prop->info->min,
-                  prop->info->max);
+                  dev->id?:"", name, (int64_t)value, min, max);
         return;
     }
 
@@ -949,8 +897,6 @@ PropertyInfo qdev_prop_blocksize = {
     .name  = "blocksize",
     .get   = get_uint16,
     .set   = set_blocksize,
-    .min   = 512,
-    .max   = 65024,
 };
 
 /* --- public helpers --- */
diff --git a/hw/qdev.h b/hw/qdev.h
index d07da45..5386b16 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -122,8 +122,6 @@ struct PropertyInfo {
     const char *name;
     const char *legacy_name;
     const char **enum_table;
-    int64_t min;
-    int64_t max;
     int (*parse)(DeviceState *dev, Property *prop, const char *str);
     int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
     ObjectPropertyAccessor *get;
commit c08fb2ac000b636a8426e69d93f7340274d76c9e
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Wed Feb 22 12:26:37 2012 -0600

    qdev: Switch property accessors to fixed-width visitor interfaces
    
    This introduces {get,set}_uint{8,16,32,64}() functions for the
    respective qdev types.
    TADDR and VLAN are switched to explicit int64, BLOCKSIZE to uint16.
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/qdev-addr.c b/hw/qdev-addr.c
index 0bb16c7..b711b6b 100644
--- a/hw/qdev-addr.c
+++ b/hw/qdev-addr.c
@@ -27,7 +27,7 @@ static void get_taddr(Object *obj, Visitor *v, void *opaque,
     int64_t value;
 
     value = *ptr;
-    visit_type_int(v, &value, name, errp);
+    visit_type_int64(v, &value, name, errp);
 }
 
 static void set_taddr(Object *obj, Visitor *v, void *opaque,
@@ -44,7 +44,7 @@ static void set_taddr(Object *obj, Visitor *v, void *opaque,
         return;
     }
 
-    visit_type_int(v, &value, name, &local_err);
+    visit_type_int64(v, &value, name, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
         return;
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index d109f89..553b0d1 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -76,33 +76,30 @@ PropertyInfo qdev_prop_bit = {
 
 /* --- 8bit integer --- */
 
-static void get_int8(Object *obj, Visitor *v, void *opaque,
-                     const char *name, Error **errp)
+static void get_uint8(Object *obj, Visitor *v, void *opaque,
+                      const char *name, Error **errp)
 {
     DeviceState *dev = DEVICE(obj);
     Property *prop = opaque;
-    int8_t *ptr = qdev_get_prop_ptr(dev, prop);
-    int64_t value;
+    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
 
-    value = *ptr;
-    visit_type_int(v, &value, name, errp);
+    visit_type_uint8(v, ptr, name, errp);
 }
 
-static void set_int8(Object *obj, Visitor *v, void *opaque,
-                     const char *name, Error **errp)
+static void set_uint8(Object *obj, Visitor *v, void *opaque,
+                      const char *name, Error **errp)
 {
     DeviceState *dev = DEVICE(obj);
     Property *prop = opaque;
-    int8_t *ptr = qdev_get_prop_ptr(dev, prop);
+    uint8_t value, *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);
+    visit_type_uint8(v, &value, name, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
         return;
@@ -111,15 +108,15 @@ static void set_int8(Object *obj, Visitor *v, void *opaque,
         *ptr = value;
     } else {
         error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
-                  dev->id?:"", name, value, prop->info->min,
+                  dev->id?:"", name, (int64_t)value, prop->info->min,
                   prop->info->max);
     }
 }
 
 PropertyInfo qdev_prop_uint8 = {
     .name  = "uint8",
-    .get   = get_int8,
-    .set   = set_int8,
+    .get   = get_uint8,
+    .set   = set_uint8,
     .min   = 0,
     .max   = 255,
 };
@@ -154,41 +151,38 @@ PropertyInfo qdev_prop_hex8 = {
     .legacy_name  = "hex8",
     .parse = parse_hex8,
     .print = print_hex8,
-    .get   = get_int8,
-    .set   = set_int8,
+    .get   = get_uint8,
+    .set   = set_uint8,
     .min   = 0,
     .max   = 255,
 };
 
 /* --- 16bit integer --- */
 
-static void get_int16(Object *obj, Visitor *v, void *opaque,
-                      const char *name, Error **errp)
+static void get_uint16(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);
-    int64_t value;
+    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
 
-    value = *ptr;
-    visit_type_int(v, &value, name, errp);
+    visit_type_uint16(v, ptr, name, errp);
 }
 
-static void set_int16(Object *obj, Visitor *v, void *opaque,
-                      const char *name, Error **errp)
+static void set_uint16(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);
+    uint16_t value, *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);
+    visit_type_uint16(v, &value, name, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
         return;
@@ -197,31 +191,67 @@ static void set_int16(Object *obj, Visitor *v, void *opaque,
         *ptr = value;
     } else {
         error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
-                  dev->id?:"", name, value, prop->info->min,
+                  dev->id?:"", name, (int64_t)value, prop->info->min,
                   prop->info->max);
     }
 }
 
 PropertyInfo qdev_prop_uint16 = {
     .name  = "uint16",
-    .get   = get_int16,
-    .set   = set_int16,
+    .get   = get_uint16,
+    .set   = set_uint16,
     .min   = 0,
     .max   = 65535,
 };
 
 /* --- 32bit integer --- */
 
+static void get_uint32(Object *obj, Visitor *v, void *opaque,
+                       const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    uint32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
+
+    value = *ptr;
+    visit_type_uint32(v, &value, name, errp);
+}
+
+static void set_uint32(Object *obj, Visitor *v, void *opaque,
+                       const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    uint32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
+    Error *local_err = NULL;
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    visit_type_uint32(v, &value, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+    if (value >= prop->info->min && value <= prop->info->max) {
+        *ptr = value;
+    } else {
+        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
+                  dev->id?:"", name, (int64_t)value, prop->info->min,
+                  prop->info->max);
+    }
+}
+
 static void get_int32(Object *obj, Visitor *v, void *opaque,
                       const char *name, Error **errp)
 {
     DeviceState *dev = DEVICE(obj);
     Property *prop = opaque;
     int32_t *ptr = qdev_get_prop_ptr(dev, prop);
-    int64_t value;
 
-    value = *ptr;
-    visit_type_int(v, &value, name, errp);
+    visit_type_int32(v, ptr, name, errp);
 }
 
 static void set_int32(Object *obj, Visitor *v, void *opaque,
@@ -229,16 +259,15 @@ static void set_int32(Object *obj, Visitor *v, void *opaque,
 {
     DeviceState *dev = DEVICE(obj);
     Property *prop = opaque;
-    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
+    int32_t value, *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);
+    visit_type_int32(v, &value, name, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
         return;
@@ -247,15 +276,15 @@ static void set_int32(Object *obj, Visitor *v, void *opaque,
         *ptr = value;
     } else {
         error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
-                  dev->id?:"", name, value, prop->info->min,
+                  dev->id?:"", name, (int64_t)value, prop->info->min,
                   prop->info->max);
     }
 }
 
 PropertyInfo qdev_prop_uint32 = {
     .name  = "uint32",
-    .get   = get_int32,
-    .set   = set_int32,
+    .get   = get_uint32,
+    .set   = set_uint32,
     .min   = 0,
     .max   = 0xFFFFFFFFULL,
 };
@@ -298,43 +327,43 @@ PropertyInfo qdev_prop_hex32 = {
     .legacy_name  = "hex32",
     .parse = parse_hex32,
     .print = print_hex32,
-    .get   = get_int32,
-    .set   = set_int32,
+    .get   = get_uint32,
+    .set   = set_uint32,
     .min   = 0,
     .max   = 0xFFFFFFFFULL,
 };
 
 /* --- 64bit integer --- */
 
-static void get_int64(Object *obj, Visitor *v, void *opaque,
-                      const char *name, Error **errp)
+static void get_uint64(Object *obj, Visitor *v, void *opaque,
+                       const char *name, Error **errp)
 {
     DeviceState *dev = DEVICE(obj);
     Property *prop = opaque;
-    int64_t *ptr = qdev_get_prop_ptr(dev, prop);
+    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
 
-    visit_type_int(v, ptr, name, errp);
+    visit_type_uint64(v, ptr, name, errp);
 }
 
-static void set_int64(Object *obj, Visitor *v, void *opaque,
-                      const char *name, Error **errp)
+static void set_uint64(Object *obj, Visitor *v, void *opaque,
+                       const char *name, Error **errp)
 {
     DeviceState *dev = DEVICE(obj);
     Property *prop = opaque;
-    int64_t *ptr = qdev_get_prop_ptr(dev, prop);
+    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
 
     if (dev->state != DEV_STATE_CREATED) {
         error_set(errp, QERR_PERMISSION_DENIED);
         return;
     }
 
-    visit_type_int(v, ptr, name, errp);
+    visit_type_uint64(v, ptr, name, errp);
 }
 
 PropertyInfo qdev_prop_uint64 = {
     .name  = "uint64",
-    .get   = get_int64,
-    .set   = set_int64,
+    .get   = get_uint64,
+    .set   = set_uint64,
 };
 
 /* --- 64bit hex value --- */
@@ -367,8 +396,8 @@ PropertyInfo qdev_prop_hex64 = {
     .legacy_name  = "hex64",
     .parse = parse_hex64,
     .print = print_hex64,
-    .get   = get_int64,
-    .set   = set_int64,
+    .get   = get_uint64,
+    .set   = set_uint64,
 };
 
 /* --- string --- */
@@ -645,7 +674,7 @@ static void get_vlan(Object *obj, Visitor *v, void *opaque,
     int64_t id;
 
     id = *ptr ? (*ptr)->id : -1;
-    visit_type_int(v, &id, name, errp);
+    visit_type_int64(v, &id, name, errp);
 }
 
 static void set_vlan(Object *obj, Visitor *v, void *opaque,
@@ -663,7 +692,7 @@ static void set_vlan(Object *obj, Visitor *v, void *opaque,
         return;
     }
 
-    visit_type_int(v, &id, name, &local_err);
+    visit_type_int64(v, &id, name, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
         return;
@@ -886,23 +915,22 @@ static void set_blocksize(Object *obj, Visitor *v, void *opaque,
 {
     DeviceState *dev = DEVICE(obj);
     Property *prop = opaque;
-    int16_t *ptr = qdev_get_prop_ptr(dev, prop);
+    uint16_t value, *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);
+    visit_type_uint16(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,
+                  dev->id?:"", name, (int64_t)value, prop->info->min,
                   prop->info->max);
         return;
     }
@@ -910,7 +938,7 @@ static void set_blocksize(Object *obj, Visitor *v, void *opaque,
     /* 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);
+                  dev->id?:"", name, (int64_t)value);
         return;
     }
 
@@ -919,7 +947,7 @@ static void set_blocksize(Object *obj, Visitor *v, void *opaque,
 
 PropertyInfo qdev_prop_blocksize = {
     .name  = "blocksize",
-    .get   = get_int16,
+    .get   = get_uint16,
     .set   = set_blocksize,
     .min   = 512,
     .max   = 65024,
commit 09f1bbcd834c63da35b3fe190fcd9a20d7b04f07
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Sun Mar 4 13:38:27 2012 -0600

    qdev: Use int32_t container for devfn property
    
    Valid range for devfn is -1 to 255 (-1 for automatic assignment). We do
    not currently validate this due to devfn being stored as a uint32_t.
    This can lead to segfaults and other strange behavior.
    
    We could technically just cast it to int32_t to implement the checking,
    but this will not work for visitor-based setting where we may do additional
    bounds-checking based on target container type, which is int32_t for this
    case.
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/pci.c b/hw/pci.c
index c1ebdde..127b7ac 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1537,7 +1537,7 @@ PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction,
     DeviceState *dev;
 
     dev = qdev_create(&bus->qbus, name);
-    qdev_prop_set_uint32(dev, "addr", devfn);
+    qdev_prop_set_int32(dev, "addr", devfn);
     qdev_prop_set_bit(dev, "multifunction", multifunction);
     return PCI_DEVICE(dev);
 }
diff --git a/hw/pci.h b/hw/pci.h
index c3cacce..7f223c0 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -197,7 +197,7 @@ struct PCIDevice {
 
     /* the following fields are read only */
     PCIBus *bus;
-    uint32_t devfn;
+    int32_t devfn;
     char name[64];
     PCIIORegion io_regions[PCI_NUM_REGIONS];
 
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index b7b5597..d109f89 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -824,7 +824,7 @@ static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
 {
     DeviceState *dev = DEVICE(obj);
     Property *prop = opaque;
-    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
+    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
     unsigned int slot, fn, n;
     Error *local_err = NULL;
     char *str;
@@ -860,7 +860,7 @@ invalid:
 
 static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
 {
-    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
+    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
 
     if (*ptr == -1) {
         return snprintf(dest, len, "<unset>");
@@ -875,11 +875,8 @@ PropertyInfo qdev_prop_pci_devfn = {
     .print = print_pci_devfn,
     .get   = get_int32,
     .set   = set_pci_devfn,
-    /* FIXME: this should be -1...255, but the address is stored
-     * into an uint32_t rather than int32_t.
-     */
-    .min   = 0,
-    .max   = 0xFFFFFFFFULL,
+    .min   = -1,
+    .max   = 255,
 };
 
 /* --- blocksize --- */
diff --git a/hw/qdev.h b/hw/qdev.h
index 4e90119..d07da45 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -267,7 +267,7 @@ extern PropertyInfo qdev_prop_blocksize;
 #define DEFINE_PROP_HEX64(_n, _s, _f, _d)                       \
     DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex64, uint64_t)
 #define DEFINE_PROP_PCI_DEVFN(_n, _s, _f, _d)                   \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_pci_devfn, uint32_t)
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_pci_devfn, int32_t)
 
 #define DEFINE_PROP_PTR(_n, _s, _f)             \
     DEFINE_PROP(_n, _s, _f, qdev_prop_ptr, void*)
commit 0d30b0a2d338cd5f463a0fd3942d19f70eb6db56
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Wed Feb 22 10:16:31 2012 -0600

    qapi: Add String visitor coverage to serialization unit tests
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/tests/test-visitor-serialization.c b/tests/test-visitor-serialization.c
index 6ef57d0..b8ad16f 100644
--- a/tests/test-visitor-serialization.c
+++ b/tests/test-visitor-serialization.c
@@ -19,6 +19,8 @@
 #include "qemu-objects.h"
 #include "qapi/qmp-input-visitor.h"
 #include "qapi/qmp-output-visitor.h"
+#include "qapi/string-input-visitor.h"
+#include "qapi/string-output-visitor.h"
 
 typedef struct PrimitiveType {
     union {
@@ -666,6 +668,37 @@ static void qmp_cleanup(void *datap)
     qmp_input_visitor_cleanup(d->qiv);
 }
 
+typedef struct StringSerializeData {
+    StringOutputVisitor *sov;
+    StringInputVisitor *siv;
+} StringSerializeData;
+
+static void string_serialize(void *native_in, void **datap,
+                             VisitorFunc visit, Error **errp)
+{
+    StringSerializeData *d = g_malloc0(sizeof(*d));
+
+    d->sov = string_output_visitor_new();
+    visit(string_output_get_visitor(d->sov), &native_in, errp);
+    *datap = d;
+}
+
+static void string_deserialize(void **native_out, void *datap,
+                               VisitorFunc visit, Error **errp)
+{
+    StringSerializeData *d = datap;
+
+    d->siv = string_input_visitor_new(string_output_get_string(d->sov));
+    visit(string_input_get_visitor(d->siv), native_out, errp);
+}
+
+static void string_cleanup(void *datap)
+{
+    StringSerializeData *d = datap;
+    string_output_visitor_cleanup(d->sov);
+    string_input_visitor_cleanup(d->siv);
+}
+
 /* visitor registration, test harness */
 
 /* note: to function interchangeably as a serialization mechanism your
@@ -680,6 +713,13 @@ static const SerializeOps visitors[] = {
         .cleanup = qmp_cleanup,
         .caps = VCAP_PRIMITIVES | VCAP_STRUCTURES | VCAP_LISTS
     },
+    {
+        .type = "String",
+        .serialize = string_serialize,
+        .deserialize = string_deserialize,
+        .cleanup = string_cleanup,
+        .caps = VCAP_PRIMITIVES
+    },
     { NULL }
 };
 
commit 173bbb754f53e8bfc8e4d488f2ed66fe1072ed69
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Mon Apr 30 09:33:30 2012 -0500

    qapi: String visitor, use %f representation for floats
    
    Currently string-output-visitor formats floats as %g, which is nice in
    that trailing 0's are automatically truncated, but otherwise this causes
    some issues:
    
     - it uses 6 significant figures instead of 6 decimal places, which
       means something like 155777.5 (which even has an exact floating point
       representation) will be rounded to 155778 when converted to a string.
    
     - output will be presented in scientific notation when the normalized
       form requires a 10^x multiplier. Not a huge deal, but arguably less
       readable for command-line arguments.
    
     - due to using scientific notation for numbers requiring more than 6
       significant figures, instead of hard-defined decimal places, it
       fails a lot of the test-visitor-serialization unit tests for floats.
    
    Instead, let's just use %f, which is what the QJSON and the QMP visitors
    use.
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/qapi/string-output-visitor.c b/qapi/string-output-visitor.c
index 92b0305..34e525e 100644
--- a/qapi/string-output-visitor.c
+++ b/qapi/string-output-visitor.c
@@ -52,7 +52,7 @@ static void print_type_number(Visitor *v, double *obj, const char *name,
                               Error **errp)
 {
     StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
-    string_output_set(sov, g_strdup_printf("%g", *obj));
+    string_output_set(sov, g_strdup_printf("%f", *obj));
 }
 
 char *string_output_get_string(StringOutputVisitor *sov)
diff --git a/tests/test-string-output-visitor.c b/tests/test-string-output-visitor.c
index 22909b8..608f14a 100644
--- a/tests/test-string-output-visitor.c
+++ b/tests/test-string-output-visitor.c
@@ -84,7 +84,7 @@ static void test_visitor_out_number(TestOutputVisitorData *data,
 
     str = string_output_get_string(data->sov);
     g_assert(str != NULL);
-    g_assert_cmpstr(str, ==, "3.14");
+    g_assert_cmpstr(str, ==, "3.140000");
     g_free(str);
 }
 
commit 2d496105397b8eca905f9a53c40e2faaac7bfa6b
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Feb 21 21:05:07 2012 -0600

    qapi: Unit tests for visitor-based serialization
    
    Currently we test our visitors individually, and seperately for input
    vs. output. This is useful for validating internal representations
    against the native C types and vice-versa, and other visitor-specific
    testing, but it doesn't cover the potential use-case of using visitor
    pairs for serialization/deserialization very well, and makes it
    hard to easily extend the coverage for different C types / boundary
    conditions.
    
    To cover that we add a set of unit tests that takes a number of native C
    values, passes them into an output visitor, extracts the values with an
    input visitor, then compares the result to the original.
    
    Plugging in new visitors to the test harness only requires a user to
    implement the SerializeOps interface and add it to a list.
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/tests/Makefile b/tests/Makefile
index 2e754c3..d66ab19 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -13,6 +13,7 @@ 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-unit-y += tests/test-visitor-serialization$(EXESUF)
 
 check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
 
@@ -31,7 +32,7 @@ test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.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
+	tests/test-qmp-commands.o tests/test-visitor-serialization.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
@@ -64,6 +65,7 @@ tests/test-qmp-output-visitor$(EXESUF): tests/test-qmp-output-visitor.o $(test-q
 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)
+tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(test-qapi-obj-y)
 
 tests/rtc-test$(EXESUF): tests/rtc-test.o $(trace-obj-y)
 tests/m48t59-test$(EXESUF): tests/m48t59-test.o $(trace-obj-y)
diff --git a/tests/test-visitor-serialization.c b/tests/test-visitor-serialization.c
new file mode 100644
index 0000000..6ef57d0
--- /dev/null
+++ b/tests/test-visitor-serialization.c
@@ -0,0 +1,744 @@
+/*
+ * Unit-tests for visitor-based serialization
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ *  Michael Roth <mdroth at linux.vnet.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 <glib.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <float.h>
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "qemu-objects.h"
+#include "qapi/qmp-input-visitor.h"
+#include "qapi/qmp-output-visitor.h"
+
+typedef struct PrimitiveType {
+    union {
+        const char *string;
+        bool boolean;
+        double number;
+        int64_t integer;
+        uint8_t u8;
+        uint16_t u16;
+        uint32_t u32;
+        uint64_t u64;
+        int8_t s8;
+        int16_t s16;
+        int32_t s32;
+        int64_t s64;
+        intmax_t max;
+    } value;
+    enum {
+        PTYPE_STRING = 0,
+        PTYPE_BOOLEAN,
+        PTYPE_NUMBER,
+        PTYPE_INTEGER,
+        PTYPE_U8,
+        PTYPE_U16,
+        PTYPE_U32,
+        PTYPE_U64,
+        PTYPE_S8,
+        PTYPE_S16,
+        PTYPE_S32,
+        PTYPE_S64,
+        PTYPE_EOL,
+    } type;
+    const char *description;
+} PrimitiveType;
+
+/* test helpers */
+
+static void visit_primitive_type(Visitor *v, void **native, Error **errp)
+{
+    PrimitiveType *pt = *native;
+    switch(pt->type) {
+    case PTYPE_STRING:
+        visit_type_str(v, (char **)&pt->value.string, NULL, errp);
+        break;
+    case PTYPE_BOOLEAN:
+        visit_type_bool(v, &pt->value.boolean, NULL, errp);
+        break;
+    case PTYPE_NUMBER:
+        visit_type_number(v, &pt->value.number, NULL, errp);
+        break;
+    case PTYPE_INTEGER:
+        visit_type_int(v, &pt->value.integer, NULL, errp);
+        break;
+    case PTYPE_U8:
+        visit_type_uint8(v, &pt->value.u8, NULL, errp);
+        break;
+    case PTYPE_U16:
+        visit_type_uint16(v, &pt->value.u16, NULL, errp);
+        break;
+    case PTYPE_U32:
+        visit_type_uint32(v, &pt->value.u32, NULL, errp);
+        break;
+    case PTYPE_U64:
+        visit_type_uint64(v, &pt->value.u64, NULL, errp);
+        break;
+    case PTYPE_S8:
+        visit_type_int8(v, &pt->value.s8, NULL, errp);
+        break;
+    case PTYPE_S16:
+        visit_type_int16(v, &pt->value.s16, NULL, errp);
+        break;
+    case PTYPE_S32:
+        visit_type_int32(v, &pt->value.s32, NULL, errp);
+        break;
+    case PTYPE_S64:
+        visit_type_int64(v, &pt->value.s64, NULL, errp);
+        break;
+    case PTYPE_EOL:
+        g_assert(false);
+    }
+}
+
+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, NULL, 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 TestStruct *struct_create(void)
+{
+    TestStruct *ts = g_malloc0(sizeof(*ts));
+    ts->integer = -42;
+    ts->boolean = true;
+    ts->string = strdup("test string");
+    return ts;
+}
+
+static void struct_compare(TestStruct *ts1, TestStruct *ts2)
+{
+    g_assert(ts1);
+    g_assert(ts2);
+    g_assert_cmpint(ts1->integer, ==, ts2->integer);
+    g_assert(ts1->boolean == ts2->boolean);
+    g_assert_cmpstr(ts1->string, ==, ts2->string);
+}
+
+static void struct_cleanup(TestStruct *ts)
+{
+    g_free(ts->string);
+    g_free(ts);
+}
+
+static void visit_struct(Visitor *v, void **native, Error **errp)
+{
+    visit_type_TestStruct(v, (TestStruct **)native, NULL, errp);
+}
+
+static UserDefNested *nested_struct_create(void)
+{
+    UserDefNested *udnp = g_malloc0(sizeof(*udnp));
+    udnp->string0 = strdup("test_string0");
+    udnp->dict1.string1 = strdup("test_string1");
+    udnp->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
+    udnp->dict1.dict2.userdef1->integer = 42;
+    udnp->dict1.dict2.userdef1->string = strdup("test_string");
+    udnp->dict1.dict2.string2 = strdup("test_string2");
+    udnp->dict1.has_dict3 = true;
+    udnp->dict1.dict3.userdef2 = g_malloc0(sizeof(UserDefOne));
+    udnp->dict1.dict3.userdef2->integer = 43;
+    udnp->dict1.dict3.userdef2->string = strdup("test_string");
+    udnp->dict1.dict3.string3 = strdup("test_string3");
+    return udnp;
+}
+
+static void nested_struct_compare(UserDefNested *udnp1, UserDefNested *udnp2)
+{
+    g_assert(udnp1);
+    g_assert(udnp2);
+    g_assert_cmpstr(udnp1->string0, ==, udnp2->string0);
+    g_assert_cmpstr(udnp1->dict1.string1, ==, udnp2->dict1.string1);
+    g_assert_cmpint(udnp1->dict1.dict2.userdef1->integer, ==,
+                    udnp2->dict1.dict2.userdef1->integer);
+    g_assert_cmpstr(udnp1->dict1.dict2.userdef1->string, ==,
+                    udnp2->dict1.dict2.userdef1->string);
+    g_assert_cmpstr(udnp1->dict1.dict2.string2, ==, udnp2->dict1.dict2.string2);
+    g_assert(udnp1->dict1.has_dict3 == udnp2->dict1.has_dict3);
+    g_assert_cmpint(udnp1->dict1.dict3.userdef2->integer, ==,
+                    udnp2->dict1.dict3.userdef2->integer);
+    g_assert_cmpstr(udnp1->dict1.dict3.userdef2->string, ==,
+                    udnp2->dict1.dict3.userdef2->string);
+    g_assert_cmpstr(udnp1->dict1.dict3.string3, ==, udnp2->dict1.dict3.string3);
+}
+
+static void nested_struct_cleanup(UserDefNested *udnp)
+{
+    qapi_free_UserDefNested(udnp);
+}
+
+static void visit_nested_struct(Visitor *v, void **native, Error **errp)
+{
+    visit_type_UserDefNested(v, (UserDefNested **)native, NULL, errp);
+}
+
+static void visit_nested_struct_list(Visitor *v, void **native, Error **errp)
+{
+    visit_type_UserDefNestedList(v, (UserDefNestedList **)native, NULL, errp);
+}
+
+/* test cases */
+
+typedef void (*VisitorFunc)(Visitor *v, void **native, Error **errp);
+
+typedef enum VisitorCapabilities {
+    VCAP_PRIMITIVES = 1,
+    VCAP_STRUCTURES = 2,
+    VCAP_LISTS = 4,
+} VisitorCapabilities;
+
+typedef struct SerializeOps {
+    void (*serialize)(void *native_in, void **datap,
+                      VisitorFunc visit, Error **errp);
+    void (*deserialize)(void **native_out, void *datap,
+                            VisitorFunc visit, Error **errp);
+    void (*cleanup)(void *datap);
+    const char *type;
+    VisitorCapabilities caps;
+} SerializeOps;
+
+typedef struct TestArgs {
+    const SerializeOps *ops;
+    void *test_data;
+} TestArgs;
+
+#define FLOAT_STRING_PRECISION 6 /* corresponding to n in %.nf formatting */
+static gsize calc_float_string_storage(double value)
+{
+    int whole_value = value;
+    gsize i = 0;
+    do {
+        i++;
+    } while (whole_value /= 10);
+    return i + 2 + FLOAT_STRING_PRECISION;
+}
+
+static void test_primitives(gconstpointer opaque)
+{
+    TestArgs *args = (TestArgs *) opaque;
+    const SerializeOps *ops = args->ops;
+    PrimitiveType *pt = args->test_data;
+    PrimitiveType *pt_copy = g_malloc0(sizeof(*pt_copy));
+    Error *err = NULL;
+    void *serialize_data;
+    char *double1, *double2;
+
+    pt_copy->type = pt->type;
+    ops->serialize(pt, &serialize_data, visit_primitive_type, &err);
+    ops->deserialize((void **)&pt_copy, serialize_data, visit_primitive_type, &err);
+
+    g_assert(err == NULL);
+    g_assert(pt_copy != NULL);
+    if (pt->type == PTYPE_STRING) {
+        g_assert_cmpstr(pt->value.string, ==, pt_copy->value.string);
+    } else if (pt->type == PTYPE_NUMBER) {
+        /* we serialize with %f for our reference visitors, so rather than fuzzy
+         * floating math to test "equality", just compare the formatted values
+         */
+        double1 = g_malloc0(calc_float_string_storage(pt->value.number));
+        double2 = g_malloc0(calc_float_string_storage(pt_copy->value.number));
+        g_assert_cmpstr(double1, ==, double2);
+        g_free(double1);
+        g_free(double2);
+    } else if (pt->type == PTYPE_BOOLEAN) {
+        g_assert_cmpint(!!pt->value.max, ==, !!pt->value.max);
+    } else {
+        g_assert_cmpint(pt->value.max, ==, pt_copy->value.max);
+    }
+
+    ops->cleanup(serialize_data);
+    g_free(args);
+}
+
+static void test_struct(gconstpointer opaque)
+{
+    TestArgs *args = (TestArgs *) opaque;
+    const SerializeOps *ops = args->ops;
+    TestStruct *ts = struct_create();
+    TestStruct *ts_copy = NULL;
+    Error *err = NULL;
+    void *serialize_data;
+
+    ops->serialize(ts, &serialize_data, visit_struct, &err);
+    ops->deserialize((void **)&ts_copy, serialize_data, visit_struct, &err); 
+
+    g_assert(err == NULL);
+    struct_compare(ts, ts_copy);
+
+    struct_cleanup(ts);
+    struct_cleanup(ts_copy);
+
+    ops->cleanup(serialize_data);
+    g_free(args);
+}
+
+static void test_nested_struct(gconstpointer opaque)
+{
+    TestArgs *args = (TestArgs *) opaque;
+    const SerializeOps *ops = args->ops;
+    UserDefNested *udnp = nested_struct_create();
+    UserDefNested *udnp_copy = NULL;
+    Error *err = NULL;
+    void *serialize_data;
+    
+    ops->serialize(udnp, &serialize_data, visit_nested_struct, &err);
+    ops->deserialize((void **)&udnp_copy, serialize_data, visit_nested_struct, &err); 
+
+    g_assert(err == NULL);
+    nested_struct_compare(udnp, udnp_copy);
+
+    nested_struct_cleanup(udnp);
+    nested_struct_cleanup(udnp_copy);
+
+    ops->cleanup(serialize_data);
+    g_free(args);
+}
+
+static void test_nested_struct_list(gconstpointer opaque)
+{
+    TestArgs *args = (TestArgs *) opaque;
+    const SerializeOps *ops = args->ops;
+    UserDefNestedList *listp = NULL, *tmp, *tmp_copy, *listp_copy = NULL;
+    Error *err = NULL;
+    void *serialize_data;
+    int i = 0;
+
+    for (i = 0; i < 8; i++) {
+        tmp = g_malloc0(sizeof(UserDefNestedList));
+        tmp->value = nested_struct_create();
+        tmp->next = listp;
+        listp = tmp;
+    }
+    
+    ops->serialize(listp, &serialize_data, visit_nested_struct_list, &err);
+    ops->deserialize((void **)&listp_copy, serialize_data,
+                     visit_nested_struct_list, &err); 
+
+    g_assert(err == NULL);
+
+    tmp = listp;
+    tmp_copy = listp_copy;
+    while (listp_copy) {
+        g_assert(listp);
+        nested_struct_compare(listp->value, listp_copy->value);
+        listp = listp->next;
+        listp_copy = listp_copy->next;
+    }
+
+    qapi_free_UserDefNestedList(tmp);
+    qapi_free_UserDefNestedList(tmp_copy);
+
+    ops->cleanup(serialize_data);
+    g_free(args);
+}
+
+PrimitiveType pt_values[] = {
+    /* string tests */
+    {
+        .description = "string_empty",
+        .type = PTYPE_STRING,
+        .value.string = "",
+    },
+    {
+        .description = "string_whitespace",
+        .type = PTYPE_STRING,
+        .value.string = "a b  c\td",
+    },
+    {
+        .description = "string_newlines",
+        .type = PTYPE_STRING,
+        .value.string = "a\nb\n",
+    },
+    {
+        .description = "string_commas",
+        .type = PTYPE_STRING,
+        .value.string = "a,b, c,d",
+    },
+    {
+        .description = "string_single_quoted",
+        .type = PTYPE_STRING,
+        .value.string = "'a b',cd",
+    },
+    {
+        .description = "string_double_quoted",
+        .type = PTYPE_STRING,
+        .value.string = "\"a b\",cd",
+    },
+    /* boolean tests */
+    {
+        .description = "boolean_true1",
+        .type = PTYPE_BOOLEAN,
+        .value.boolean = true,
+    },
+    {
+        .description = "boolean_true2",
+        .type = PTYPE_BOOLEAN,
+        .value.boolean = 8,
+    },
+    {
+        .description = "boolean_true3",
+        .type = PTYPE_BOOLEAN,
+        .value.boolean = -1,
+    },
+    {
+        .description = "boolean_false1",
+        .type = PTYPE_BOOLEAN,
+        .value.boolean = false,
+    },
+    {
+        .description = "boolean_false2",
+        .type = PTYPE_BOOLEAN,
+        .value.boolean = 0,
+    },
+    /* number tests (double) */
+    /* note: we format these to %.6f before comparing, since that's how
+     * we serialize them and it doesn't make sense to check precision
+     * beyond that.
+     */
+    {
+        .description = "number_sanity1",
+        .type = PTYPE_NUMBER,
+        .value.number = -1,
+    },
+    {
+        .description = "number_sanity2",
+        .type = PTYPE_NUMBER,
+        .value.number = 3.14159265,
+    },
+    {
+        .description = "number_min",
+        .type = PTYPE_NUMBER,
+        .value.number = DBL_MIN,
+    },
+    {
+        .description = "number_max",
+        .type = PTYPE_NUMBER,
+        .value.number = DBL_MAX,
+    },
+    /* integer tests (int64) */
+    {
+        .description = "integer_sanity1",
+        .type = PTYPE_INTEGER,
+        .value.integer = -1,
+    },
+    {
+        .description = "integer_sanity2",
+        .type = PTYPE_INTEGER,
+        .value.integer = INT64_MAX / 2 + 1,
+    },
+    {
+        .description = "integer_min",
+        .type = PTYPE_INTEGER,
+        .value.integer = INT64_MIN,
+    },
+    {
+        .description = "integer_max",
+        .type = PTYPE_INTEGER,
+        .value.integer = INT64_MAX,
+    },
+    /* uint8 tests */
+    {
+        .description = "uint8_sanity1",
+        .type = PTYPE_U8,
+        .value.u8 = 1,
+    },
+    {
+        .description = "uint8_sanity2",
+        .type = PTYPE_U8,
+        .value.u8 = UINT8_MAX / 2 + 1,
+    },
+    {
+        .description = "uint8_min",
+        .type = PTYPE_U8,
+        .value.u8 = 0,
+    },
+    {
+        .description = "uint8_max",
+        .type = PTYPE_U8,
+        .value.u8 = UINT8_MAX,
+    },
+    /* uint16 tests */
+    {
+        .description = "uint16_sanity1",
+        .type = PTYPE_U16,
+        .value.u16 = 1,
+    },
+    {
+        .description = "uint16_sanity2",
+        .type = PTYPE_U16,
+        .value.u16 = UINT16_MAX / 2 + 1,
+    },
+    {
+        .description = "uint16_min",
+        .type = PTYPE_U16,
+        .value.u16 = 0,
+    },
+    {
+        .description = "uint16_max",
+        .type = PTYPE_U16,
+        .value.u16 = UINT16_MAX,
+    },
+    /* uint32 tests */
+    {
+        .description = "uint32_sanity1",
+        .type = PTYPE_U32,
+        .value.u32 = 1,
+    },
+    {
+        .description = "uint32_sanity2",
+        .type = PTYPE_U32,
+        .value.u32 = UINT32_MAX / 2 + 1,
+    },
+    {
+        .description = "uint32_min",
+        .type = PTYPE_U32,
+        .value.u32 = 0,
+    },
+    {
+        .description = "uint32_max",
+        .type = PTYPE_U32,
+        .value.u32 = UINT32_MAX,
+    },
+    /* uint64 tests */
+    {
+        .description = "uint64_sanity1",
+        .type = PTYPE_U64,
+        .value.u64 = 1,
+    },
+    {
+        .description = "uint64_sanity2",
+        .type = PTYPE_U64,
+        .value.u64 = UINT64_MAX / 2 + 1,
+    },
+    {
+        .description = "uint64_min",
+        .type = PTYPE_U64,
+        .value.u64 = 0,
+    },
+    {
+        .description = "uint64_max",
+        .type = PTYPE_U64,
+        .value.u64 = UINT64_MAX,
+    },
+    /* int8 tests */
+    {
+        .description = "int8_sanity1",
+        .type = PTYPE_S8,
+        .value.s8 = -1,
+    },
+    {
+        .description = "int8_sanity2",
+        .type = PTYPE_S8,
+        .value.s8 = INT8_MAX / 2 + 1,
+    },
+    {
+        .description = "int8_min",
+        .type = PTYPE_S8,
+        .value.s8 = INT8_MIN,
+    },
+    {
+        .description = "int8_max",
+        .type = PTYPE_S8,
+        .value.s8 = INT8_MAX,
+    },
+    /* int16 tests */
+    {
+        .description = "int16_sanity1",
+        .type = PTYPE_S16,
+        .value.s16 = -1,
+    },
+    {
+        .description = "int16_sanity2",
+        .type = PTYPE_S16,
+        .value.s16 = INT16_MAX / 2 + 1,
+    },
+    {
+        .description = "int16_min",
+        .type = PTYPE_S16,
+        .value.s16 = INT16_MIN,
+    },
+    {
+        .description = "int16_max",
+        .type = PTYPE_S16,
+        .value.s16 = INT16_MAX,
+    },
+    /* int32 tests */
+    {
+        .description = "int32_sanity1",
+        .type = PTYPE_S32,
+        .value.s32 = -1,
+    },
+    {
+        .description = "int32_sanity2",
+        .type = PTYPE_S32,
+        .value.s32 = INT32_MAX / 2 + 1,
+    },
+    {
+        .description = "int32_min",
+        .type = PTYPE_S32,
+        .value.s32 = INT32_MIN,
+    },
+    {
+        .description = "int32_max",
+        .type = PTYPE_S32,
+        .value.s32 = INT32_MAX,
+    },
+    /* int64 tests */
+    {
+        .description = "int64_sanity1",
+        .type = PTYPE_S64,
+        .value.s64 = -1,
+    },
+    {
+        .description = "int64_sanity2",
+        .type = PTYPE_S64,
+        .value.s64 = INT64_MAX / 2 + 1,
+    },
+    {
+        .description = "int64_min",
+        .type = PTYPE_S64,
+        .value.s64 = INT64_MIN,
+    },
+    {
+        .description = "int64_max",
+        .type = PTYPE_S64,
+        .value.s64 = INT64_MAX,
+    },
+    { .type = PTYPE_EOL }
+};
+
+/* visitor-specific op implementations */
+
+typedef struct QmpSerializeData {
+    QmpOutputVisitor *qov;
+    QmpInputVisitor *qiv;
+} QmpSerializeData;
+
+static void qmp_serialize(void *native_in, void **datap,
+                          VisitorFunc visit, Error **errp)
+{
+    QmpSerializeData *d = g_malloc0(sizeof(*d));
+
+    d->qov = qmp_output_visitor_new();
+    visit(qmp_output_get_visitor(d->qov), &native_in, errp);
+    *datap = d;
+}
+
+static void qmp_deserialize(void **native_out, void *datap,
+                            VisitorFunc visit, Error **errp)
+{
+    QmpSerializeData *d = datap;
+    QString *output_json = qobject_to_json(qmp_output_get_qobject(d->qov));
+    QObject *obj = qobject_from_json(qstring_get_str(output_json));
+
+    QDECREF(output_json);
+    d->qiv = qmp_input_visitor_new(obj);
+    visit(qmp_input_get_visitor(d->qiv), native_out, errp);
+}
+
+static void qmp_cleanup(void *datap)
+{
+    QmpSerializeData *d = datap;
+    qmp_output_visitor_cleanup(d->qov);
+    qmp_input_visitor_cleanup(d->qiv);
+}
+
+/* visitor registration, test harness */
+
+/* note: to function interchangeably as a serialization mechanism your
+ * visitor test implementation should pass the test cases for all visitor
+ * capabilities: primitives, structures, and lists
+ */
+static const SerializeOps visitors[] = {
+    {
+        .type = "QMP",
+        .serialize = qmp_serialize,
+        .deserialize = qmp_deserialize,
+        .cleanup = qmp_cleanup,
+        .caps = VCAP_PRIMITIVES | VCAP_STRUCTURES | VCAP_LISTS
+    },
+    { NULL }
+};
+
+static void add_visitor_type(const SerializeOps *ops)
+{
+    char testname_prefix[128];
+    char testname[128];
+    TestArgs *args;
+    int i = 0;
+
+    sprintf(testname_prefix, "/visitor/serialization/%s", ops->type);
+
+    if (ops->caps & VCAP_PRIMITIVES) {
+        while (pt_values[i].type != PTYPE_EOL) {
+            sprintf(testname, "%s/primitives/%s", testname_prefix,
+                    pt_values[i].description);
+            args = g_malloc0(sizeof(*args));
+            args->ops = ops;
+            args->test_data = &pt_values[i];
+            g_test_add_data_func(testname, args, test_primitives);
+            i++;
+        }
+    }
+
+    if (ops->caps & VCAP_STRUCTURES) {
+        sprintf(testname, "%s/struct", testname_prefix);
+        args = g_malloc0(sizeof(*args));
+        args->ops = ops;
+        args->test_data = NULL;
+        g_test_add_data_func(testname, args, test_struct);
+
+        sprintf(testname, "%s/nested_struct", testname_prefix);
+        args = g_malloc0(sizeof(*args));
+        args->ops = ops;
+        args->test_data = NULL;
+        g_test_add_data_func(testname, args, test_nested_struct);
+    }
+
+    if (ops->caps & VCAP_LISTS) {
+        sprintf(testname, "%s/nested_struct_list", testname_prefix);
+        args = g_malloc0(sizeof(*args));
+        args->ops = ops;
+        args->test_data = NULL;
+        g_test_add_data_func(testname, args, test_nested_struct_list);
+    }
+}
+
+int main(int argc, char **argv)
+{
+    int i = 0;
+
+    g_test_init(&argc, &argv, NULL);
+
+    while (visitors[i].type != NULL) {
+        add_visitor_type(&visitors[i]);
+        i++;
+    }
+
+    g_test_run();
+
+    return 0;
+}
commit 4e27e819bea0ea6c8108dc7e9fa48afd6ec13c46
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Thu Aug 25 10:44:50 2011 -0500

    qapi: Add Visitor interfaces for uint*_t and int*_t
    
    This adds visitor interfaces for fixed-width integers types.
    Implementing these in visitors is optional, otherwise we fall back to
    visit_type_int() (int64_t) with some additional bounds checking to avoid
    integer overflows for cases where the value fetched exceeds the bounds
    of our target C type.
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    [LE: exclude negative values in uint*_t Visitor interfaces]
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    [AF: Merged fix by Laszlo]
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 9c64e0a..3777f85 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -599,13 +599,6 @@ static const MemoryRegionOps cmos_ops = {
     .old_portio = cmos_portio
 };
 
-// FIXME add int32 visitor
-static void visit_type_int32(Visitor *v, int *value, const char *name, Error **errp)
-{
-    int64_t val = *value;
-    visit_type_int(v, &val, name, errp);
-}
-
 static void rtc_get_date(Object *obj, Visitor *v, void *opaque,
                          const char *name, Error **errp)
 {
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index a4e088c..ffffbf7 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -97,6 +97,145 @@ void visit_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp)
     }
 }
 
+void visit_type_uint8(Visitor *v, uint8_t *obj, const char *name, Error **errp)
+{
+    int64_t value;
+    if (!error_is_set(errp)) {
+        if (v->type_uint8) {
+            v->type_uint8(v, obj, name, errp);
+        } else {
+            value = *obj;
+            v->type_int(v, &value, name, errp);
+            if (value < 0 || value > UINT8_MAX) {
+                error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
+                          "uint8_t");
+                return;
+            }
+            *obj = value;
+        }
+    }
+}
+
+void visit_type_uint16(Visitor *v, uint16_t *obj, const char *name, Error **errp)
+{
+    int64_t value;
+    if (!error_is_set(errp)) {
+        if (v->type_uint16) {
+            v->type_uint16(v, obj, name, errp);
+        } else {
+            value = *obj;
+            v->type_int(v, &value, name, errp);
+            if (value < 0 || value > UINT16_MAX) {
+                error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
+                          "uint16_t");
+                return;
+            }
+            *obj = value;
+        }
+    }
+}
+
+void visit_type_uint32(Visitor *v, uint32_t *obj, const char *name, Error **errp)
+{
+    int64_t value;
+    if (!error_is_set(errp)) {
+        if (v->type_uint32) {
+            v->type_uint32(v, obj, name, errp);
+        } else {
+            value = *obj;
+            v->type_int(v, &value, name, errp);
+            if (value < 0 || value > UINT32_MAX) {
+                error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
+                          "uint32_t");
+                return;
+            }
+            *obj = value;
+        }
+    }
+}
+
+void visit_type_uint64(Visitor *v, uint64_t *obj, const char *name, Error **errp)
+{
+    int64_t value;
+    if (!error_is_set(errp)) {
+        if (v->type_uint64) {
+            v->type_uint64(v, obj, name, errp);
+        } else {
+            value = *obj;
+            v->type_int(v, &value, name, errp);
+            *obj = value;
+        }
+    }
+}
+
+void visit_type_int8(Visitor *v, int8_t *obj, const char *name, Error **errp)
+{
+    int64_t value;
+    if (!error_is_set(errp)) {
+        if (v->type_int8) {
+            v->type_int8(v, obj, name, errp);
+        } else {
+            value = *obj;
+            v->type_int(v, &value, name, errp);
+            if (value < INT8_MIN || value > INT8_MAX) {
+                error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
+                          "int8_t");
+                return;
+            }
+            *obj = value;
+        }
+    }
+}
+
+void visit_type_int16(Visitor *v, int16_t *obj, const char *name, Error **errp)
+{
+    int64_t value;
+    if (!error_is_set(errp)) {
+        if (v->type_int16) {
+            v->type_int16(v, obj, name, errp);
+        } else {
+            value = *obj;
+            v->type_int(v, &value, name, errp);
+            if (value < INT16_MIN || value > INT16_MAX) {
+                error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
+                          "int16_t");
+                return;
+            }
+            *obj = value;
+        }
+    }
+}
+
+void visit_type_int32(Visitor *v, int32_t *obj, const char *name, Error **errp)
+{
+    int64_t value;
+    if (!error_is_set(errp)) {
+        if (v->type_int32) {
+            v->type_int32(v, obj, name, errp);
+        } else {
+            value = *obj;
+            v->type_int(v, &value, name, errp);
+            if (value < INT32_MIN || value > INT32_MAX) {
+                error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
+                          "int32_t");
+                return;
+            }
+            *obj = value;
+        }
+    }
+}
+
+void visit_type_int64(Visitor *v, int64_t *obj, const char *name, Error **errp)
+{
+    if (!error_is_set(errp)) {
+        if (v->type_int64) {
+            v->type_int64(v, obj, name, errp);
+        } else {
+            v->type_int(v, obj, name, errp);
+        }
+    }
+}
+
 void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp)
 {
     if (!error_is_set(errp)) {
diff --git a/qapi/qapi-visit-core.h b/qapi/qapi-visit-core.h
index e850746..a19d70c 100644
--- a/qapi/qapi-visit-core.h
+++ b/qapi/qapi-visit-core.h
@@ -52,6 +52,14 @@ struct Visitor
     void (*start_handle)(Visitor *v, void **obj, const char *kind,
                          const char *name, Error **errp);
     void (*end_handle)(Visitor *v, Error **errp);
+    void (*type_uint8)(Visitor *v, uint8_t *obj, const char *name, Error **errp);
+    void (*type_uint16)(Visitor *v, uint16_t *obj, const char *name, Error **errp);
+    void (*type_uint32)(Visitor *v, uint32_t *obj, const char *name, Error **errp);
+    void (*type_uint64)(Visitor *v, uint64_t *obj, const char *name, Error **errp);
+    void (*type_int8)(Visitor *v, int8_t *obj, const char *name, Error **errp);
+    void (*type_int16)(Visitor *v, int16_t *obj, const char *name, Error **errp);
+    void (*type_int32)(Visitor *v, int32_t *obj, const char *name, Error **errp);
+    void (*type_int64)(Visitor *v, int64_t *obj, const char *name, Error **errp);
 };
 
 void visit_start_handle(Visitor *v, void **obj, const char *kind,
@@ -69,6 +77,14 @@ void visit_end_optional(Visitor *v, Error **errp);
 void visit_type_enum(Visitor *v, int *obj, const char *strings[],
                      const char *kind, const char *name, Error **errp);
 void visit_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp);
+void visit_type_uint8(Visitor *v, uint8_t *obj, const char *name, Error **errp);
+void visit_type_uint16(Visitor *v, uint16_t *obj, const char *name, Error **errp);
+void visit_type_uint32(Visitor *v, uint32_t *obj, const char *name, Error **errp);
+void visit_type_uint64(Visitor *v, uint64_t *obj, const char *name, Error **errp);
+void visit_type_int8(Visitor *v, int8_t *obj, const char *name, Error **errp);
+void visit_type_int16(Visitor *v, int16_t *obj, const char *name, Error **errp);
+void visit_type_int32(Visitor *v, int32_t *obj, const char *name, Error **errp);
+void visit_type_int64(Visitor *v, int64_t *obj, const char *name, Error **errp);
 void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp);
 void visit_type_str(Visitor *v, char **obj, const char *name, Error **errp);
 void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp);
commit 263ddcc81bf45d475ef86100a8567b3fb2129b8d
Author: Harsh Prateek Bora <harsh at linux.vnet.ibm.com>
Date:   Fri Jun 8 03:20:43 2012 +0530

    configure: report missing libraries for virtfs
    
    Signed-off-by: Harsh Prateek Bora <harsh at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/configure b/configure
index 76dd57f..e8f0172 100755
--- a/configure
+++ b/configure
@@ -2915,7 +2915,8 @@ if test "$softmmu" = yes ; then
       tools="$tools fsdev/virtfs-proxy-helper\$(EXESUF)"
     else
       if test "$virtfs" = yes; then
-        feature_not_found "virtfs"
+        echo "VirtFS is supported only on Linux and requires libcap-devel and libattr-devel"
+        exit 1
       fi
       virtfs=no
     fi
commit 0d665005c7fd3800f1ae590701f60fe7e4c9a57a
Author: Harsh Prateek Bora <harsh at linux.vnet.ibm.com>
Date:   Fri Jun 8 03:20:42 2012 +0530

    trace/simple.c: fix deprecated glib2 interface
    
    Signed-off-by: Harsh Prateek Bora <harsh at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/trace/simple.c b/trace/simple.c
index 33ae486..b4a3c6e 100644
--- a/trace/simple.c
+++ b/trace/simple.c
@@ -161,8 +161,11 @@ static void trace(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3,
     }
 
     timestamp = get_clock();
-
+#if GLIB_CHECK_VERSION(2, 30, 0)
+    idx = g_atomic_int_add((gint *)&trace_idx, 1) % TRACE_BUF_LEN;
+#else
     idx = g_atomic_int_exchange_and_add((gint *)&trace_idx, 1) % TRACE_BUF_LEN;
+#endif
     trace_buf[idx] = (TraceRecord){
         .event = event,
         .timestamp_ns = timestamp,
commit 8e0fdce32d5d2b2e8a67a30537d169bb263ca5e1
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed May 23 23:41:53 2012 -0300

    Clarify comments of tb_invalidate_phys_[page_]range
    
    They could suggest that all TBs of the page containing the range would
    be invalidated.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/exec.c b/exec.c
index 1b65859..eacaf3c 100644
--- a/exec.c
+++ b/exec.c
@@ -1076,11 +1076,11 @@ TranslationBlock *tb_gen_code(CPUArchState *env,
 }
 
 /*
- * invalidate all TBs which intersect with the target physical pages
- * starting in range [start;end[. NOTE: start and end may refer to
- * different physical pages. 'is_cpu_write_access' should be true if called
- * from a real cpu write access: the virtual CPU will exit the current
- * TB if code is modified inside this TB.
+ * Invalidate all TBs which intersect with the target physical address range
+ * [start;end[. NOTE: start and end may refer to *different* physical pages.
+ * 'is_cpu_write_access' should be true if called from a real cpu write
+ * access: the virtual CPU will exit the current TB if code is modified inside
+ * this TB.
  */
 void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end,
                               int is_cpu_write_access)
@@ -1092,11 +1092,13 @@ void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end,
     }
 }
 
-/* invalidate all TBs which intersect with the target physical page
-   starting in range [start;end[. NOTE: start and end must refer to
-   the same physical page. 'is_cpu_write_access' should be true if called
-   from a real cpu write access: the virtual CPU will exit the current
-   TB if code is modified inside this TB. */
+/*
+ * Invalidate all TBs which intersect with the target physical address range
+ * [start;end[. NOTE: start and end must refer to the *same* physical page.
+ * 'is_cpu_write_access' should be true if called from a real cpu write
+ * access: the virtual CPU will exit the current TB if code is modified inside
+ * this TB.
+ */
 void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
                                    int is_cpu_write_access)
 {
commit fa79c914efd35cb60e0bc18512c03690c48b13e2
Merge: 083dbf4... 2dee8d5...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Jun 7 17:21:40 2012 +0800

    Merge remote-tracking branch 'bonzini/nested-makefiles-3' into staging
    
    * bonzini/nested-makefiles-3: (29 commits)
      build: do not create directories at configure time
      configure: ensure directory exists when creating symlink
      build: compile oslib-obj-y once
      build: limit usage of vpath
      build: libcacard Makefile cleanups
      build: move device tree to per-target Makefile.objs
      build: move per-target hw/ objects to nested Makefile.objs
      build: convert libhw to nested Makefile.objs
      build: move target-independent hw/ objects to nested Makefile.objs
      build: move qga/ objects to nested Makefile.objs
      build: move qapi/ objects to nested Makefile.objs
      build: move slirp/ objects to nested Makefile.objs
      build: move audio/ objects to nested Makefile.objs
      build: move ui/ objects to nested Makefile.objs
      build: move fsdev/ objects to nested Makefile.objs
      build: move net/ objects to nested Makefile.objs
      build: move block/ objects to nested Makefile.objs
      build: adapt qom/Makefile and move it to Makefile.objs
      build: move rules for nesting to Makefile.objs
      build: move other target-*/ objects to nested Makefile.objs
      ...

commit 083dbf489d1b0592e910ecfb90b3858c23e49ab7
Author: Peter A. G. Crosthwaite <peter.crosthwaite at petalogix.com>
Date:   Tue Jun 5 12:31:04 2012 +1000

    target-microblaze: fix swx build breakage
    
    The lazy initialisation of r_check was throwing an error on --enable-debug.
    Removed the lazy initialisation of r_check and swx_addr.
    
    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/translate.c b/target-microblaze/translate.c
index 02b2dc6..c0a6bfd 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1105,7 +1105,7 @@ static void gen_store(DisasContext *dc, TCGv addr, TCGv val,
 
 static void dec_store(DisasContext *dc)
 {
-    TCGv t, *addr, swx_addr, r_check = 0;
+    TCGv t, *addr, swx_addr, r_check;
     int swx_skip = 0;
     unsigned int size, rev = 0, ex = 0;
 
@@ -1129,9 +1129,9 @@ static void dec_store(DisasContext *dc)
     sync_jmpstate(dc);
     addr = compute_ldst_addr(dc, &t);
 
+    r_check = tcg_temp_new();
+    swx_addr = tcg_temp_local_new();
     if (ex) { /* swx */
-        r_check = tcg_temp_new();
-        swx_addr = tcg_temp_local_new();
 
         /* Force addr into the swx_addr. */
         tcg_gen_mov_tl(swx_addr, *addr);
@@ -1221,11 +1221,12 @@ static void dec_store(DisasContext *dc)
         gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
                             tcg_const_tl(1), tcg_const_tl(size - 1));
     }
+
     if (ex) {
         gen_set_label(swx_skip);
-        tcg_temp_free(r_check);
-        tcg_temp_free(swx_addr);
     }
+    tcg_temp_free(r_check);
+    tcg_temp_free(swx_addr);
 
     if (addr == &t)
         tcg_temp_free(t);
commit f020ed36fef7780e81a94543ae6388d8dc144ab6
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri May 25 08:13:55 2012 +0200

    ehci: rework frame skipping
    
    Move the framecount check out of the loop and use the new
    ehci_update_frindex function to skip frames if needed.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index d97c539..5298204 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -2315,9 +2315,8 @@ static void ehci_frame_timer(void *opaque)
     int schedules = 0;
     int64_t expire_time, t_now;
     uint64_t ns_elapsed;
-    int frames;
+    int frames, skipped_frames;
     int i;
-    int skipped_frames = 0;
 
     t_now = qemu_get_clock_ns(vm_clock);
     ns_elapsed = t_now - ehci->last_run_ns;
@@ -2327,15 +2326,17 @@ static void ehci_frame_timer(void *opaque)
         schedules++;
         expire_time = t_now + (get_ticks_per_sec() / FRAME_TIMER_FREQ);
 
+        if (frames > ehci->maxframes) {
+            skipped_frames = frames - ehci->maxframes;
+            ehci_update_frindex(ehci, skipped_frames);
+            ehci->last_run_ns += FRAME_TIMER_NS * skipped_frames;
+            frames -= skipped_frames;
+            DPRINTF("WARNING - EHCI skipped %d frames\n", skipped_frames);
+        }
+
         for (i = 0; i < frames; i++) {
             ehci_update_frindex(ehci, 1);
-
-            if (frames - i > ehci->maxframes) {
-                skipped_frames++;
-            } else {
-                ehci_advance_periodic_state(ehci);
-            }
-
+            ehci_advance_periodic_state(ehci);
             ehci->last_run_ns += FRAME_TIMER_NS;
         }
     } else {
@@ -2348,12 +2349,6 @@ static void ehci_frame_timer(void *opaque)
         ehci->last_run_ns += FRAME_TIMER_NS * frames;
     }
 
-#if 0
-    if (skipped_frames) {
-        DPRINTF("WARNING - EHCI skipped %d frames\n", skipped_frames);
-    }
-#endif
-
     /*  Async is not inside loop since it executes everything it can once
      *  called
      */
commit 3a21532626bb5c3ecb0f916843f75ccce6501a9d
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu May 24 13:34:02 2012 +0200

    ehci: adaptive wakeup rate.
    
    Adapt the frame timer sleeps according to the actual needs.  With the
    periodic schedule being active we'll have to wakeup 1000 times per
    second and go check for work.  In case only the async schedule is active
    we can be more lazy though.  When idle ehci will increate the sleep time
    step by step, so qemu has to wake up less frequently.  When we'll see
    transactions on the bus or the guest fiddles with the schedule
    enable/disable bits we'll return to a 1000 Hz wakeup rate and full
    speed.  With both schedules disabled we stop wakeups altogether.
    
    This patch also drops the freq property (configures wakeup rate
    manually) which is obsoleted by this patch.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index c15dbee..d97c539 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -386,7 +386,6 @@ struct EHCIState {
     int companion_count;
 
     /* properties */
-    uint32_t freq;
     uint32_t maxframes;
 
     /*
@@ -430,6 +429,7 @@ struct EHCIState {
     QEMUSGList isgl;
 
     uint64_t last_run_ns;
+    uint32_t async_stepdown;
 };
 
 #define SET_LAST_RUN_CLOCK(s) \
@@ -776,6 +776,7 @@ static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr,
 static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
 {
     EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
+    uint64_t maxage = FRAME_TIMER_NS * ehci->maxframes * 4;
     EHCIQueue *q, *tmp;
 
     QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
@@ -784,8 +785,7 @@ static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
             q->ts = ehci->last_run_ns;
             continue;
         }
-        if (!flush && ehci->last_run_ns < q->ts + 250000000) {
-            /* allow 0.25 sec idle */
+        if (!flush && ehci->last_run_ns < q->ts + maxage) {
             continue;
         }
         ehci_free_queue(q);
@@ -1151,11 +1151,12 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
 
         if (((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & val) !=
             ((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & s->usbcmd)) {
-            if (!ehci_enabled(s)) {
-                qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
+            if (s->pstate == EST_INACTIVE) {
                 SET_LAST_RUN_CLOCK(s);
             }
             ehci_update_halt(s);
+            s->async_stepdown = 0;
+            qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
         }
 
         /* not supporting dynamic frame list size at the moment */
@@ -2146,10 +2147,16 @@ static void ehci_advance_state(EHCIState *ehci, int async)
 
         case EST_EXECUTE:
             again = ehci_state_execute(q);
+            if (async) {
+                ehci->async_stepdown = 0;
+            }
             break;
 
         case EST_EXECUTING:
             assert(q != NULL);
+            if (async) {
+                ehci->async_stepdown = 0;
+            }
             again = ehci_state_executing(q);
             break;
 
@@ -2305,6 +2312,7 @@ static void ehci_update_frindex(EHCIState *ehci, int frames)
 static void ehci_frame_timer(void *opaque)
 {
     EHCIState *ehci = opaque;
+    int schedules = 0;
     int64_t expire_time, t_now;
     uint64_t ns_elapsed;
     int frames;
@@ -2312,21 +2320,32 @@ static void ehci_frame_timer(void *opaque)
     int skipped_frames = 0;
 
     t_now = qemu_get_clock_ns(vm_clock);
-    expire_time = t_now + (get_ticks_per_sec() / ehci->freq);
-
     ns_elapsed = t_now - ehci->last_run_ns;
     frames = ns_elapsed / FRAME_TIMER_NS;
 
-    for (i = 0; i < frames; i++) {
-        ehci_update_frindex(ehci, 1);
+    if (ehci_periodic_enabled(ehci) || ehci->pstate != EST_INACTIVE) {
+        schedules++;
+        expire_time = t_now + (get_ticks_per_sec() / FRAME_TIMER_FREQ);
 
-        if (frames - i > ehci->maxframes) {
-            skipped_frames++;
-        } else {
-            ehci_advance_periodic_state(ehci);
-        }
+        for (i = 0; i < frames; i++) {
+            ehci_update_frindex(ehci, 1);
 
-        ehci->last_run_ns += FRAME_TIMER_NS;
+            if (frames - i > ehci->maxframes) {
+                skipped_frames++;
+            } else {
+                ehci_advance_periodic_state(ehci);
+            }
+
+            ehci->last_run_ns += FRAME_TIMER_NS;
+        }
+    } else {
+        if (ehci->async_stepdown < ehci->maxframes / 2) {
+            ehci->async_stepdown++;
+        }
+        expire_time = t_now + (get_ticks_per_sec()
+                               * ehci->async_stepdown / FRAME_TIMER_FREQ);
+        ehci_update_frindex(ehci, frames);
+        ehci->last_run_ns += FRAME_TIMER_NS * frames;
     }
 
 #if 0
@@ -2338,9 +2357,12 @@ static void ehci_frame_timer(void *opaque)
     /*  Async is not inside loop since it executes everything it can once
      *  called
      */
-    qemu_bh_schedule(ehci->async_bh);
+    if (ehci_async_enabled(ehci) || ehci->astate != EST_INACTIVE) {
+        schedules++;
+        qemu_bh_schedule(ehci->async_bh);
+    }
 
-    if (ehci_enabled(ehci)) {
+    if (schedules) {
         qemu_mod_timer(ehci->frame_timer, expire_time);
     }
 }
@@ -2379,7 +2401,6 @@ static const VMStateDescription vmstate_ehci = {
 };
 
 static Property ehci_properties[] = {
-    DEFINE_PROP_UINT32("freq",      EHCIState, freq, FRAME_TIMER_FREQ),
     DEFINE_PROP_UINT32("maxframes", EHCIState, maxframes, 128),
     DEFINE_PROP_END_OF_LIST(),
 };
commit 6ceced0b2ed52cdfb474d144dce54bf9afa613ce
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu May 24 13:28:32 2012 +0200

    ehci: create ehci_update_frindex
    
    Factor out code from ehci_frame_timer.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index ee7420f..c15dbee 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -2280,6 +2280,28 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
     }
 }
 
+static void ehci_update_frindex(EHCIState *ehci, int frames)
+{
+    int i;
+
+    if (!ehci_enabled(ehci)) {
+        return;
+    }
+
+    for (i = 0; i < frames; i++) {
+        ehci->frindex += 8;
+
+        if (ehci->frindex == 0x00002000) {
+            ehci_set_interrupt(ehci, USBSTS_FLR);
+        }
+
+        if (ehci->frindex == 0x00004000) {
+            ehci_set_interrupt(ehci, USBSTS_FLR);
+            ehci->frindex = 0;
+        }
+    }
+}
+
 static void ehci_frame_timer(void *opaque)
 {
     EHCIState *ehci = opaque;
@@ -2296,18 +2318,7 @@ static void ehci_frame_timer(void *opaque)
     frames = ns_elapsed / FRAME_TIMER_NS;
 
     for (i = 0; i < frames; i++) {
-        if (ehci_enabled(ehci)) {
-            ehci->frindex += 8;
-
-            if (ehci->frindex == 0x00002000) {
-                ehci_set_interrupt(ehci, USBSTS_FLR);
-            }
-
-            if (ehci->frindex == 0x00004000) {
-                ehci_set_interrupt(ehci, USBSTS_FLR);
-                ehci->frindex = 0;
-            }
-        }
+        ehci_update_frindex(ehci, 1);
 
         if (frames - i > ehci->maxframes) {
             skipped_frames++;
commit 863b474163085a3df13e2c6bf8e696486f3a0c66
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu May 24 16:48:04 2012 +0200

    ehci: remove unused attach_poll_counter
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index f77a26d..ee7420f 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -415,7 +415,6 @@ struct EHCIState {
      */
     QEMUTimer *frame_timer;
     QEMUBH *async_bh;
-    int attach_poll_counter;
     int astate;                        // Current state in asynchronous schedule
     int pstate;                        // Current state in periodic schedule
     USBPort ports[NB_PORTS];
@@ -984,7 +983,6 @@ static void ehci_reset(void *opaque)
 
     s->astate = EST_INACTIVE;
     s->pstate = EST_INACTIVE;
-    s->attach_poll_counter = 0;
 
     for(i = 0; i < NB_PORTS; i++) {
         if (s->companion_ports[i]) {
commit daf25307b4f8c5c13b3a15059fbf9df55823bb72
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu May 24 12:53:43 2012 +0200

    ehci: fix halt status handling
    
    When the enable bits for controller / async schedule / periodic schedule
    change just make sure we kick the frame timer and let
    ehci_advance_periodic_state and ehci_advance_async_state handle the
    controller state changes.
    
    This will make ehci set USBSTS_HALT when the controller shutdown is
    actually done, once both schedules are in inactive state and the
    USBSTS_PSS and USBSTS_ASS bits are clear.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 0a550f9..f77a26d 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -586,6 +586,17 @@ static inline void ehci_commit_interrupt(EHCIState *s)
     s->usbsts_pending = 0;
 }
 
+static void ehci_update_halt(EHCIState *s)
+{
+    if (s->usbcmd & USBCMD_RUNSTOP) {
+        ehci_clear_usbsts(s, USBSTS_HALT);
+    } else {
+        if (s->astate == EST_INACTIVE && s->pstate == EST_INACTIVE) {
+            ehci_set_usbsts(s, USBSTS_HALT);
+        }
+    }
+}
+
 static void ehci_set_state(EHCIState *s, int async, int state)
 {
     if (async) {
@@ -593,6 +604,7 @@ static void ehci_set_state(EHCIState *s, int async, int state)
         s->astate = state;
         if (s->astate == EST_INACTIVE) {
             ehci_clear_usbsts(s, USBSTS_ASS);
+            ehci_update_halt(s);
         } else {
             ehci_set_usbsts(s, USBSTS_ASS);
         }
@@ -601,6 +613,7 @@ static void ehci_set_state(EHCIState *s, int async, int state)
         s->pstate = state;
         if (s->pstate == EST_INACTIVE) {
             ehci_clear_usbsts(s, USBSTS_PSS);
+            ehci_update_halt(s);
         } else {
             ehci_set_usbsts(s, USBSTS_PSS);
         }
@@ -1138,21 +1151,15 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
             break;
         }
 
-        if ((val & USBCMD_RUNSTOP) && !(s->usbcmd & USBCMD_RUNSTOP)) {
-            qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
-            SET_LAST_RUN_CLOCK(s);
-            ehci_clear_usbsts(s, USBSTS_HALT);
-        }
-
-        if (!(val & USBCMD_RUNSTOP) && (s->usbcmd & USBCMD_RUNSTOP)) {
-            qemu_del_timer(s->frame_timer);
-            qemu_bh_cancel(s->async_bh);
-            ehci_queues_rip_all(s, 0);
-            ehci_queues_rip_all(s, 1);
-            ehci_set_usbsts(s, USBSTS_HALT);
+        if (((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & val) !=
+            ((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & s->usbcmd)) {
+            if (!ehci_enabled(s)) {
+                qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
+                SET_LAST_RUN_CLOCK(s);
+            }
+            ehci_update_halt(s);
         }
 
-
         /* not supporting dynamic frame list size at the moment */
         if ((val & USBCMD_FLS) && !(s->usbcmd & USBCMD_FLS)) {
             fprintf(stderr, "attempt to set frame list size -- value %d\n",
@@ -2291,7 +2298,7 @@ static void ehci_frame_timer(void *opaque)
     frames = ns_elapsed / FRAME_TIMER_NS;
 
     for (i = 0; i < frames; i++) {
-        if ( !(ehci->usbsts & USBSTS_HALT)) {
+        if (ehci_enabled(ehci)) {
             ehci->frindex += 8;
 
             if (ehci->frindex == 0x00002000) {
@@ -2324,7 +2331,9 @@ static void ehci_frame_timer(void *opaque)
      */
     qemu_bh_schedule(ehci->async_bh);
 
-    qemu_mod_timer(ehci->frame_timer, expire_time);
+    if (ehci_enabled(ehci)) {
+        qemu_mod_timer(ehci->frame_timer, expire_time);
+    }
 }
 
 static void ehci_async_bh(void *opaque)
commit b53f685d63e1928c0cee669703a8b30f604e6a6e
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu May 24 12:34:18 2012 +0200

    ehci: update status bits in ehci_set_state
    
    Update the status register in the ehci_set_state function, to make sure
    the guest-visible register is in sync with our internal schedule state.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index d9c0f0f..0a550f9 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -591,9 +591,19 @@ static void ehci_set_state(EHCIState *s, int async, int state)
     if (async) {
         trace_usb_ehci_state("async", state2str(state));
         s->astate = state;
+        if (s->astate == EST_INACTIVE) {
+            ehci_clear_usbsts(s, USBSTS_ASS);
+        } else {
+            ehci_set_usbsts(s, USBSTS_ASS);
+        }
     } else {
         trace_usb_ehci_state("periodic", state2str(state));
         s->pstate = state;
+        if (s->pstate == EST_INACTIVE) {
+            ehci_clear_usbsts(s, USBSTS_PSS);
+        } else {
+            ehci_set_usbsts(s, USBSTS_PSS);
+        }
     }
 }
 
@@ -2170,14 +2180,12 @@ static void ehci_advance_async_state(EHCIState *ehci)
         if (!ehci_async_enabled(ehci)) {
             break;
         }
-        ehci_set_usbsts(ehci, USBSTS_ASS);
         ehci_set_state(ehci, async, EST_ACTIVE);
         // No break, fall through to ACTIVE
 
     case EST_ACTIVE:
         if (!ehci_async_enabled(ehci)) {
             ehci_queues_rip_all(ehci, async);
-            ehci_clear_usbsts(ehci, USBSTS_ASS);
             ehci_set_state(ehci, async, EST_INACTIVE);
             break;
         }
@@ -2229,7 +2237,6 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
     switch(ehci_get_state(ehci, async)) {
     case EST_INACTIVE:
         if (!(ehci->frindex & 7) && ehci_periodic_enabled(ehci)) {
-            ehci_set_usbsts(ehci, USBSTS_PSS);
             ehci_set_state(ehci, async, EST_ACTIVE);
             // No break, fall through to ACTIVE
         } else
@@ -2238,7 +2245,6 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
     case EST_ACTIVE:
         if (!(ehci->frindex & 7) && !ehci_periodic_enabled(ehci)) {
             ehci_queues_rip_all(ehci, async);
-            ehci_clear_usbsts(ehci, USBSTS_PSS);
             ehci_set_state(ehci, async, EST_INACTIVE);
             break;
         }
commit ec807d12bdd5c740b4266fbd423b4f8b964e597a
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu May 24 12:31:34 2012 +0200

    ehci: add ehci_*_enabled() helpers
    
    Add helper functions to query whenever the async / periodic schedule
    is enabled or not.  Put them into use too.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 3b602b0..d9c0f0f 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -667,6 +667,21 @@ static void ehci_trace_sitd(EHCIState *s, target_phys_addr_t addr,
                         (bool)(sitd->results & SITD_RESULTS_ACTIVE));
 }
 
+static inline bool ehci_enabled(EHCIState *s)
+{
+    return s->usbcmd & USBCMD_RUNSTOP;
+}
+
+static inline bool ehci_async_enabled(EHCIState *s)
+{
+    return ehci_enabled(s) && (s->usbcmd & USBCMD_ASE);
+}
+
+static inline bool ehci_periodic_enabled(EHCIState *s)
+{
+    return ehci_enabled(s) && (s->usbcmd & USBCMD_PSE);
+}
+
 /* packet management */
 
 static EHCIPacket *ehci_alloc_packet(EHCIQueue *q)
@@ -1160,7 +1175,7 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
         break;
 
     case PERIODICLISTBASE:
-        if ((s->usbcmd & USBCMD_PSE) && (s->usbcmd & USBCMD_RUNSTOP)) {
+        if (ehci_periodic_enabled(s)) {
             fprintf(stderr,
               "ehci: PERIODIC list base register set while periodic schedule\n"
               "      is enabled and HC is enabled\n");
@@ -1168,7 +1183,7 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
         break;
 
     case ASYNCLISTADDR:
-        if ((s->usbcmd & USBCMD_ASE) && (s->usbcmd & USBCMD_RUNSTOP)) {
+        if (ehci_async_enabled(s)) {
             fprintf(stderr,
               "ehci: ASYNC list address register set while async schedule\n"
               "      is enabled and HC is enabled\n");
@@ -2152,7 +2167,7 @@ static void ehci_advance_async_state(EHCIState *ehci)
 
     switch(ehci_get_state(ehci, async)) {
     case EST_INACTIVE:
-        if (!(ehci->usbcmd & USBCMD_ASE)) {
+        if (!ehci_async_enabled(ehci)) {
             break;
         }
         ehci_set_usbsts(ehci, USBSTS_ASS);
@@ -2160,7 +2175,7 @@ static void ehci_advance_async_state(EHCIState *ehci)
         // No break, fall through to ACTIVE
 
     case EST_ACTIVE:
-        if ( !(ehci->usbcmd & USBCMD_ASE)) {
+        if (!ehci_async_enabled(ehci)) {
             ehci_queues_rip_all(ehci, async);
             ehci_clear_usbsts(ehci, USBSTS_ASS);
             ehci_set_state(ehci, async, EST_INACTIVE);
@@ -2213,7 +2228,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
 
     switch(ehci_get_state(ehci, async)) {
     case EST_INACTIVE:
-        if ( !(ehci->frindex & 7) && (ehci->usbcmd & USBCMD_PSE)) {
+        if (!(ehci->frindex & 7) && ehci_periodic_enabled(ehci)) {
             ehci_set_usbsts(ehci, USBSTS_PSS);
             ehci_set_state(ehci, async, EST_ACTIVE);
             // No break, fall through to ACTIVE
@@ -2221,7 +2236,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
             break;
 
     case EST_ACTIVE:
-        if ( !(ehci->frindex & 7) && !(ehci->usbcmd & USBCMD_PSE)) {
+        if (!(ehci->frindex & 7) && !ehci_periodic_enabled(ehci)) {
             ehci_queues_rip_all(ehci, async);
             ehci_clear_usbsts(ehci, USBSTS_PSS);
             ehci_set_state(ehci, async, EST_INACTIVE);
commit 7046530c36fa3a3f87692bdb54556f5d891a9c03
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu May 24 12:04:50 2012 +0200

    ehci: fix reset
    
    Check for the reset bit first when processing USBCMD register writes.
    Also break out of the switch, there is no need to check the other bits.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index f8ed80d..3b602b0 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -1107,6 +1107,12 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
     /* Do any register specific pre-write processing here.  */
     switch(addr) {
     case USBCMD:
+        if (val & USBCMD_HCRESET) {
+            ehci_reset(s);
+            val = s->usbcmd;
+            break;
+        }
+
         if ((val & USBCMD_RUNSTOP) && !(s->usbcmd & USBCMD_RUNSTOP)) {
             qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
             SET_LAST_RUN_CLOCK(s);
@@ -1121,10 +1127,6 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
             ehci_set_usbsts(s, USBSTS_HALT);
         }
 
-        if (val & USBCMD_HCRESET) {
-            ehci_reset(s);
-            val = s->usbcmd;
-        }
 
         /* not supporting dynamic frame list size at the moment */
         if ((val & USBCMD_FLS) && !(s->usbcmd & USBCMD_FLS)) {
commit 0f588df8b3688b00e77aabaa32e26ece5f19bd39
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue May 22 17:24:59 2012 +0200

    ehci: kick async schedule on wakeup
    
    Kick async schedule when we get a wakeup
    notification from a usb device.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 8b2dfed..f8ed80d 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -852,6 +852,8 @@ static void ehci_wakeup(USBPort *port)
         USBPort *companion = s->companion_ports[port->index];
         if (companion->ops->wakeup) {
             companion->ops->wakeup(companion);
+        } else {
+            qemu_bh_schedule(s->async_bh);
         }
     }
 }
commit ae710b99050a347cc7ef93e1873bf08c9a97b6be
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri May 11 11:31:56 2012 +0200

    ehci: schedule async bh on async packet completion
    
    When a packet completes which happens to be part of the async schedule
    kick the async bottom half for processing,
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 16627d3..8b2dfed 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -1327,6 +1327,10 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
     assert(p->async == EHCI_ASYNC_INFLIGHT);
     p->async = EHCI_ASYNC_FINISHED;
     p->usb_status = packet->result;
+
+    if (p->queue->async) {
+        qemu_bh_schedule(p->queue->ehci->async_bh);
+    }
 }
 
 static void ehci_execute_complete(EHCIQueue *q)
commit 0fb3e299bdc0f21e0a0ff7d19276a87e0825d651
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri May 11 11:19:11 2012 +0200

    ehci: move async schedule to bottom half
    
    This way we can kick the async schedule independant from the
    periodic frame timer.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index f363f14..16627d3 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -414,6 +414,7 @@ struct EHCIState {
      *  Internal states, shadow registers, etc
      */
     QEMUTimer *frame_timer;
+    QEMUBH *async_bh;
     int attach_poll_counter;
     int astate;                        // Current state in asynchronous schedule
     int pstate;                        // Current state in periodic schedule
@@ -959,6 +960,7 @@ static void ehci_reset(void *opaque)
     ehci_queues_rip_all(s, 0);
     ehci_queues_rip_all(s, 1);
     qemu_del_timer(s->frame_timer);
+    qemu_bh_cancel(s->async_bh);
 }
 
 static uint32_t ehci_mem_readb(void *ptr, target_phys_addr_t addr)
@@ -1111,6 +1113,7 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
 
         if (!(val & USBCMD_RUNSTOP) && (s->usbcmd & USBCMD_RUNSTOP)) {
             qemu_del_timer(s->frame_timer);
+            qemu_bh_cancel(s->async_bh);
             ehci_queues_rip_all(s, 0);
             ehci_queues_rip_all(s, 1);
             ehci_set_usbsts(s, USBSTS_HALT);
@@ -2290,11 +2293,16 @@ static void ehci_frame_timer(void *opaque)
     /*  Async is not inside loop since it executes everything it can once
      *  called
      */
-    ehci_advance_async_state(ehci);
+    qemu_bh_schedule(ehci->async_bh);
 
     qemu_mod_timer(ehci->frame_timer, expire_time);
 }
 
+static void ehci_async_bh(void *opaque)
+{
+    EHCIState *ehci = opaque;
+    ehci_advance_async_state(ehci);
+}
 
 static const MemoryRegionOps ehci_mem_ops = {
     .old_mmio = {
@@ -2430,6 +2438,7 @@ static int usb_ehci_initfn(PCIDevice *dev)
     }
 
     s->frame_timer = qemu_new_timer_ns(vm_clock, ehci_frame_timer, s);
+    s->async_bh = qemu_bh_new(ehci_async_bh, s);
     QTAILQ_INIT(&s->aqueues);
     QTAILQ_INIT(&s->pqueues);
 
commit ae0138a8eab27c9816b2f1b6a47b2cf1c580a1ca
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri May 11 09:05:15 2012 +0200

    ehci: add async field to EHCIQueue
    
    Keep track whenever a EHCIQueue is part of the async or periodic
    schedule.  This way we don't have to pass around the async flag
    everywhere but can look it up from the EHCIQueue struct when needed.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index aa67af6..f363f14 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -364,6 +364,7 @@ struct EHCIQueue {
     QTAILQ_ENTRY(EHCIQueue) next;
     uint32_t seen;
     uint64_t ts;
+    int async;
 
     /* cached data from guest - needs to be flushed
      * when guest removes an entry (doorbell, handshake sequence)
@@ -700,15 +701,16 @@ static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, uint32_t addr, int async)
     q = g_malloc0(sizeof(*q));
     q->ehci = ehci;
     q->qhaddr = addr;
+    q->async = async;
     QTAILQ_INIT(&q->packets);
     QTAILQ_INSERT_HEAD(head, q, next);
     trace_usb_ehci_queue_action(q, "alloc");
     return q;
 }
 
-static void ehci_free_queue(EHCIQueue *q, int async)
+static void ehci_free_queue(EHCIQueue *q)
 {
-    EHCIQueueHead *head = async ? &q->ehci->aqueues : &q->ehci->pqueues;
+    EHCIQueueHead *head = q->async ? &q->ehci->aqueues : &q->ehci->pqueues;
     EHCIPacket *p;
 
     trace_usb_ehci_queue_action(q, "free");
@@ -748,7 +750,7 @@ static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
             /* allow 0.25 sec idle */
             continue;
         }
-        ehci_free_queue(q, async);
+        ehci_free_queue(q);
     }
 }
 
@@ -761,7 +763,7 @@ static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async)
         if (q->dev != dev) {
             continue;
         }
-        ehci_free_queue(q, async);
+        ehci_free_queue(q);
     }
 }
 
@@ -771,7 +773,7 @@ static void ehci_queues_rip_all(EHCIState *ehci, int async)
     EHCIQueue *q, *tmp;
 
     QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
-        ehci_free_queue(q, async);
+        ehci_free_queue(q);
     }
 }
 
@@ -1806,7 +1808,7 @@ static int ehci_state_fetchsitd(EHCIState *ehci, int async)
 }
 
 /* Section 4.10.2 - paragraph 3 */
-static int ehci_state_advqueue(EHCIQueue *q, int async)
+static int ehci_state_advqueue(EHCIQueue *q)
 {
 #if 0
     /* TO-DO: 4.10.2 - paragraph 2
@@ -1825,27 +1827,27 @@ static int ehci_state_advqueue(EHCIQueue *q, int async)
     if (((q->qh.token & QTD_TOKEN_TBYTES_MASK) != 0) &&
         (NLPTR_TBIT(q->qh.altnext_qtd) == 0)) {
         q->qtdaddr = q->qh.altnext_qtd;
-        ehci_set_state(q->ehci, async, EST_FETCHQTD);
+        ehci_set_state(q->ehci, q->async, EST_FETCHQTD);
 
     /*
      *  next qTD is valid
      */
     } else if (NLPTR_TBIT(q->qh.next_qtd) == 0) {
         q->qtdaddr = q->qh.next_qtd;
-        ehci_set_state(q->ehci, async, EST_FETCHQTD);
+        ehci_set_state(q->ehci, q->async, EST_FETCHQTD);
 
     /*
      *  no valid qTD, try next QH
      */
     } else {
-        ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+        ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
     }
 
     return 1;
 }
 
 /* Section 4.10.2 - paragraph 4 */
-static int ehci_state_fetchqtd(EHCIQueue *q, int async)
+static int ehci_state_fetchqtd(EHCIQueue *q)
 {
     EHCIqtd qtd;
     EHCIPacket *p;
@@ -1865,41 +1867,41 @@ static int ehci_state_fetchqtd(EHCIQueue *q, int async)
         ehci_qh_do_overlay(q);
         ehci_flush_qh(q);
         if (p->async == EHCI_ASYNC_INFLIGHT) {
-            ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+            ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
         } else {
-            ehci_set_state(q->ehci, async, EST_EXECUTING);
+            ehci_set_state(q->ehci, q->async, EST_EXECUTING);
         }
         again = 1;
     } else if (qtd.token & QTD_TOKEN_ACTIVE) {
         p = ehci_alloc_packet(q);
         p->qtdaddr = q->qtdaddr;
         p->qtd = qtd;
-        ehci_set_state(q->ehci, async, EST_EXECUTE);
+        ehci_set_state(q->ehci, q->async, EST_EXECUTE);
         again = 1;
     } else {
-        ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+        ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
         again = 1;
     }
 
     return again;
 }
 
-static int ehci_state_horizqh(EHCIQueue *q, int async)
+static int ehci_state_horizqh(EHCIQueue *q)
 {
     int again = 0;
 
-    if (ehci_get_fetch_addr(q->ehci, async) != q->qh.next) {
-        ehci_set_fetch_addr(q->ehci, async, q->qh.next);
-        ehci_set_state(q->ehci, async, EST_FETCHENTRY);
+    if (ehci_get_fetch_addr(q->ehci, q->async) != q->qh.next) {
+        ehci_set_fetch_addr(q->ehci, q->async, q->qh.next);
+        ehci_set_state(q->ehci, q->async, EST_FETCHENTRY);
         again = 1;
     } else {
-        ehci_set_state(q->ehci, async, EST_ACTIVE);
+        ehci_set_state(q->ehci, q->async, EST_ACTIVE);
     }
 
     return again;
 }
 
-static void ehci_fill_queue(EHCIPacket *p, int async)
+static void ehci_fill_queue(EHCIPacket *p)
 {
     EHCIQueue *q = p->queue;
     EHCIqtd qtd = p->qtd;
@@ -1928,7 +1930,7 @@ static void ehci_fill_queue(EHCIPacket *p, int async)
     }
 }
 
-static int ehci_state_execute(EHCIQueue *q, int async)
+static int ehci_state_execute(EHCIQueue *q)
 {
     EHCIPacket *p = QTAILQ_FIRST(&q->packets);
     int again = 0;
@@ -1944,16 +1946,16 @@ static int ehci_state_execute(EHCIQueue *q, int async)
     // TODO write back ptr to async list when done or out of time
     // TODO Windows does not seem to ever set the MULT field
 
-    if (!async) {
+    if (!q->async) {
         int transactCtr = get_field(q->qh.epcap, QH_EPCAP_MULT);
         if (!transactCtr) {
-            ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+            ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
             again = 1;
             goto out;
         }
     }
 
-    if (async) {
+    if (q->async) {
         ehci_set_usbsts(q->ehci, USBSTS_REC);
     }
 
@@ -1966,20 +1968,20 @@ static int ehci_state_execute(EHCIQueue *q, int async)
         ehci_flush_qh(q);
         trace_usb_ehci_packet_action(p->queue, p, "async");
         p->async = EHCI_ASYNC_INFLIGHT;
-        ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+        ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
         again = 1;
-        ehci_fill_queue(p, async);
+        ehci_fill_queue(p);
         goto out;
     }
 
-    ehci_set_state(q->ehci, async, EST_EXECUTING);
+    ehci_set_state(q->ehci, q->async, EST_EXECUTING);
     again = 1;
 
 out:
     return again;
 }
 
-static int ehci_state_executing(EHCIQueue *q, int async)
+static int ehci_state_executing(EHCIQueue *q)
 {
     EHCIPacket *p = QTAILQ_FIRST(&q->packets);
     int again = 0;
@@ -1997,7 +1999,7 @@ static int ehci_state_executing(EHCIQueue *q, int async)
     }
 
     // 4.10.3
-    if (!async) {
+    if (!q->async) {
         int transactCtr = get_field(q->qh.epcap, QH_EPCAP_MULT);
         transactCtr--;
         set_field(&q->qh.epcap, transactCtr, QH_EPCAP_MULT);
@@ -2007,9 +2009,9 @@ static int ehci_state_executing(EHCIQueue *q, int async)
 
     /* 4.10.5 */
     if (p->usb_status == USB_RET_NAK) {
-        ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+        ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
     } else {
-        ehci_set_state(q->ehci, async, EST_WRITEBACK);
+        ehci_set_state(q->ehci, q->async, EST_WRITEBACK);
     }
 
     again = 1;
@@ -2020,7 +2022,7 @@ out:
 }
 
 
-static int ehci_state_writeback(EHCIQueue *q, int async)
+static int ehci_state_writeback(EHCIQueue *q)
 {
     EHCIPacket *p = QTAILQ_FIRST(&q->packets);
     int again = 0;
@@ -2043,10 +2045,10 @@ static int ehci_state_writeback(EHCIQueue *q, int async)
      * bit is clear.
      */
     if (q->qh.token & QTD_TOKEN_HALT) {
-        ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+        ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
         again = 1;
     } else {
-        ehci_set_state(q->ehci, async, EST_ADVANCEQUEUE);
+        ehci_set_state(q->ehci, q->async, EST_ADVANCEQUEUE);
         again = 1;
     }
     return again;
@@ -2056,8 +2058,7 @@ static int ehci_state_writeback(EHCIQueue *q, int async)
  * This is the state machine that is common to both async and periodic
  */
 
-static void ehci_advance_state(EHCIState *ehci,
-                               int async)
+static void ehci_advance_state(EHCIState *ehci, int async)
 {
     EHCIQueue *q = NULL;
     int again;
@@ -2074,7 +2075,12 @@ static void ehci_advance_state(EHCIState *ehci,
 
         case EST_FETCHQH:
             q = ehci_state_fetchqh(ehci, async);
-            again = q ? 1 : 0;
+            if (q != NULL) {
+                assert(q->async == async);
+                again = 1;
+            } else {
+                again = 0;
+            }
             break;
 
         case EST_FETCHITD:
@@ -2086,29 +2092,29 @@ static void ehci_advance_state(EHCIState *ehci,
             break;
 
         case EST_ADVANCEQUEUE:
-            again = ehci_state_advqueue(q, async);
+            again = ehci_state_advqueue(q);
             break;
 
         case EST_FETCHQTD:
-            again = ehci_state_fetchqtd(q, async);
+            again = ehci_state_fetchqtd(q);
             break;
 
         case EST_HORIZONTALQH:
-            again = ehci_state_horizqh(q, async);
+            again = ehci_state_horizqh(q);
             break;
 
         case EST_EXECUTE:
-            again = ehci_state_execute(q, async);
+            again = ehci_state_execute(q);
             break;
 
         case EST_EXECUTING:
             assert(q != NULL);
-            again = ehci_state_executing(q, async);
+            again = ehci_state_executing(q);
             break;
 
         case EST_WRITEBACK:
             assert(q != NULL);
-            again = ehci_state_writeback(q, async);
+            again = ehci_state_writeback(q);
             break;
 
         default:
commit 8f6d5e26b1a2c4e87810b2798f005566a20cfea7
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri May 11 08:56:49 2012 +0200

    ehci: tweak queue initialization
    
    Little tweak for the queue initialization, set the QH address in the
    allocation function.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index ccaa947..aa67af6 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -692,13 +692,14 @@ static void ehci_free_packet(EHCIPacket *p)
 
 /* queue management */
 
-static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async)
+static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, uint32_t addr, int async)
 {
     EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
     EHCIQueue *q;
 
     q = g_malloc0(sizeof(*q));
     q->ehci = ehci;
+    q->qhaddr = addr;
     QTAILQ_INIT(&q->packets);
     QTAILQ_INSERT_HEAD(head, q, next);
     trace_usb_ehci_queue_action(q, "alloc");
@@ -1672,12 +1673,11 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
     entry = ehci_get_fetch_addr(ehci, async);
     q = ehci_find_queue_by_qh(ehci, entry, async);
     if (NULL == q) {
-        q = ehci_alloc_queue(ehci, async);
+        q = ehci_alloc_queue(ehci, entry, async);
     }
     p = QTAILQ_FIRST(&q->packets);
-    q->qhaddr = entry;
-    q->seen++;
 
+    q->seen++;
     if (q->seen > 1) {
         /* we are going in circles -- stop processing */
         ehci_set_state(ehci, async, EST_ACTIVE);
commit 773dc9cdfd4a2c55f0f3343b8e120011d96831e5
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu May 10 14:12:38 2012 +0200

    ehci: add queuing support
    
    Add packet queuing.  Follow the qTD chain to see if there are more
    packets we can submit.  Improves performance on larger transfers,
    especially with usb-host, as we don't have to wait for a packet to
    finish before sending the next one to the host for processing.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index f21b4be..ccaa947 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -671,10 +671,6 @@ static EHCIPacket *ehci_alloc_packet(EHCIQueue *q)
 {
     EHCIPacket *p;
 
-#if 1
-    /* temporary, we don't handle multiple packets per queue (yet) */
-    assert(QTAILQ_EMPTY(&q->packets));
-#endif
     p = g_new0(EHCIPacket, 1);
     p->queue = q;
     usb_packet_init(&p->packet);
@@ -1394,7 +1390,7 @@ static void ehci_execute_complete(EHCIQueue *q)
 
 // 4.10.3
 
-static int ehci_execute(EHCIPacket *p)
+static int ehci_execute(EHCIPacket *p, const char *action)
 {
     USBEndpoint *ep;
     int ret;
@@ -1437,6 +1433,7 @@ static int ehci_execute(EHCIPacket *p)
     usb_packet_setup(&p->packet, p->pid, ep);
     usb_packet_map(&p->packet, &p->sgl);
 
+    trace_usb_ehci_packet_action(p->queue, p, action);
     ret = usb_handle_packet(p->queue->dev, &p->packet);
     DPRINTF("submit: qh %x next %x qtd %x pid %x len %zd "
             "(total %d) endp %x ret %d\n",
@@ -1713,7 +1710,7 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
     }
     if (p && p->async == EHCI_ASYNC_FINISHED) {
         /* I/O finished -- continue processing queue */
-        trace_usb_ehci_queue_action(q, "resume");
+        trace_usb_ehci_packet_action(p->queue, p, "complete");
         ehci_set_state(ehci, async, EST_EXECUTING);
         goto out;
     }
@@ -1858,7 +1855,22 @@ static int ehci_state_fetchqtd(EHCIQueue *q, int async)
                sizeof(EHCIqtd) >> 2);
     ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), &qtd);
 
-    if (qtd.token & QTD_TOKEN_ACTIVE) {
+    p = QTAILQ_FIRST(&q->packets);
+    while (p != NULL && p->qtdaddr != q->qtdaddr) {
+        /* should not happen (guest bug) */
+        ehci_free_packet(p);
+        p = QTAILQ_FIRST(&q->packets);
+    }
+    if (p != NULL) {
+        ehci_qh_do_overlay(q);
+        ehci_flush_qh(q);
+        if (p->async == EHCI_ASYNC_INFLIGHT) {
+            ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+        } else {
+            ehci_set_state(q->ehci, async, EST_EXECUTING);
+        }
+        again = 1;
+    } else if (qtd.token & QTD_TOKEN_ACTIVE) {
         p = ehci_alloc_packet(q);
         p->qtdaddr = q->qtdaddr;
         p->qtd = qtd;
@@ -1887,6 +1899,35 @@ static int ehci_state_horizqh(EHCIQueue *q, int async)
     return again;
 }
 
+static void ehci_fill_queue(EHCIPacket *p, int async)
+{
+    EHCIQueue *q = p->queue;
+    EHCIqtd qtd = p->qtd;
+    uint32_t qtdaddr;
+
+    for (;;) {
+        if (NLPTR_TBIT(qtd.altnext) == 0) {
+            break;
+        }
+        if (NLPTR_TBIT(qtd.next) != 0) {
+            break;
+        }
+        qtdaddr = qtd.next;
+        get_dwords(q->ehci, NLPTR_GET(qtdaddr),
+                   (uint32_t *) &qtd, sizeof(EHCIqtd) >> 2);
+        ehci_trace_qtd(q, NLPTR_GET(qtdaddr), &qtd);
+        if (!(qtd.token & QTD_TOKEN_ACTIVE)) {
+            break;
+        }
+        p = ehci_alloc_packet(q);
+        p->qtdaddr = qtdaddr;
+        p->qtd = qtd;
+        p->usb_status = ehci_execute(p, "queue");
+        assert(p->usb_status = USB_RET_ASYNC);
+        p->async = EHCI_ASYNC_INFLIGHT;
+    }
+}
+
 static int ehci_state_execute(EHCIQueue *q, int async)
 {
     EHCIPacket *p = QTAILQ_FIRST(&q->packets);
@@ -1916,17 +1957,18 @@ static int ehci_state_execute(EHCIQueue *q, int async)
         ehci_set_usbsts(q->ehci, USBSTS_REC);
     }
 
-    p->usb_status = ehci_execute(p);
+    p->usb_status = ehci_execute(p, "process");
     if (p->usb_status == USB_RET_PROCERR) {
         again = -1;
         goto out;
     }
     if (p->usb_status == USB_RET_ASYNC) {
         ehci_flush_qh(q);
-        trace_usb_ehci_queue_action(q, "suspend");
+        trace_usb_ehci_packet_action(p->queue, p, "async");
         p->async = EHCI_ASYNC_INFLIGHT;
         ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
         again = 1;
+        ehci_fill_queue(p, async);
         goto out;
     }
 
commit cd6657156e99a5c8a5d1b64ab818288d48c1295f
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu May 10 14:13:41 2012 +0200

    ehci: move ehci_flush_qh
    
    Move ehci_flush_qh() function up in the source code.
    No code change.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index d7131bd..f21b4be 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -1553,6 +1553,24 @@ static int ehci_process_itd(EHCIState *ehci,
     return 0;
 }
 
+
+/*
+ *  Write the qh back to guest physical memory.  This step isn't
+ *  in the EHCI spec but we need to do it since we don't share
+ *  physical memory with our guest VM.
+ *
+ *  The first three dwords are read-only for the EHCI, so skip them
+ *  when writing back the qh.
+ */
+static void ehci_flush_qh(EHCIQueue *q)
+{
+    uint32_t *qh = (uint32_t *) &q->qh;
+    uint32_t dwords = sizeof(EHCIqh) >> 2;
+    uint32_t addr = NLPTR_GET(q->qhaddr);
+
+    put_dwords(q->ehci, addr + 3 * sizeof(uint32_t), qh + 3, dwords - 3);
+}
+
 /*  This state is the entry point for asynchronous schedule
  *  processing.  Entry here consitutes a EHCI start event state (4.8.5)
  */
@@ -1869,23 +1887,6 @@ static int ehci_state_horizqh(EHCIQueue *q, int async)
     return again;
 }
 
-/*
- *  Write the qh back to guest physical memory.  This step isn't
- *  in the EHCI spec but we need to do it since we don't share
- *  physical memory with our guest VM.
- *
- *  The first three dwords are read-only for the EHCI, so skip them
- *  when writing back the qh.
- */
-static void ehci_flush_qh(EHCIQueue *q)
-{
-    uint32_t *qh = (uint32_t *) &q->qh;
-    uint32_t dwords = sizeof(EHCIqh) >> 2;
-    uint32_t addr = NLPTR_GET(q->qhaddr);
-
-    put_dwords(q->ehci, addr + 3 * sizeof(uint32_t), qh + 3, dwords - 3);
-}
-
 static int ehci_state_execute(EHCIQueue *q, int async)
 {
     EHCIPacket *p = QTAILQ_FIRST(&q->packets);
commit e59928b3d148f97658e804fa724cdaa75dc8935a
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu May 10 12:18:45 2012 +0200

    ehci: cache USBDevice in EHCIQueue
    
    Keep a USBDevice pointer in EHCIQueue so we don't have to lookup the
    device on each usb packet submission.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index a7cf282..d7131bd 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -371,6 +371,7 @@ struct EHCIQueue {
     EHCIqh qh;             /* copy of current QH (being worked on) */
     uint32_t qhaddr;       /* address QH read from                 */
     uint32_t qtdaddr;      /* address QTD read from                */
+    USBDevice *dev;
     QTAILQ_HEAD(, EHCIPacket) packets;
 };
 
@@ -758,11 +759,9 @@ static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async)
 {
     EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
     EHCIQueue *q, *tmp;
-    int addr;
 
     QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
-        addr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR);
-        if (addr != dev->addr) {
+        if (q->dev != dev) {
             continue;
         }
         ehci_free_queue(q, async);
@@ -1397,11 +1396,9 @@ static void ehci_execute_complete(EHCIQueue *q)
 
 static int ehci_execute(EHCIPacket *p)
 {
-    USBDevice *dev;
     USBEndpoint *ep;
     int ret;
     int endp;
-    int devadr;
 
     if (!(p->qtd.token & QTD_TOKEN_ACTIVE)) {
         fprintf(stderr, "Attempting to execute inactive qtd\n");
@@ -1435,16 +1432,12 @@ static int ehci_execute(EHCIPacket *p)
     }
 
     endp = get_field(p->queue->qh.epchar, QH_EPCHAR_EP);
-    devadr = get_field(p->queue->qh.epchar, QH_EPCHAR_DEVADDR);
-
-    /* TODO: associating device with ehci port */
-    dev = ehci_find_device(p->queue->ehci, devadr);
-    ep = usb_ep_get(dev, p->pid, endp);
+    ep = usb_ep_get(p->queue->dev, p->pid, endp);
 
     usb_packet_setup(&p->packet, p->pid, ep);
     usb_packet_map(&p->packet, &p->sgl);
 
-    ret = usb_handle_packet(dev, &p->packet);
+    ret = usb_handle_packet(p->queue->dev, &p->packet);
     DPRINTF("submit: qh %x next %x qtd %x pid %x len %zd "
             "(total %d) endp %x ret %d\n",
             q->qhaddr, q->qh.next, q->qtdaddr, q->pid,
@@ -1658,7 +1651,7 @@ out:
 static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
 {
     EHCIPacket *p;
-    uint32_t entry;
+    uint32_t entry, devaddr;
     EHCIQueue *q;
 
     entry = ehci_get_fetch_addr(ehci, async);
@@ -1681,6 +1674,20 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
                (uint32_t *) &q->qh, sizeof(EHCIqh) >> 2);
     ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &q->qh);
 
+    devaddr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR);
+    if (q->dev != NULL && q->dev->addr != devaddr) {
+        if (!QTAILQ_EMPTY(&q->packets)) {
+            /* should not happen (guest bug) */
+            while ((p = QTAILQ_FIRST(&q->packets)) != NULL) {
+                ehci_free_packet(p);
+            }
+        }
+        q->dev = NULL;
+    }
+    if (q->dev == NULL) {
+        q->dev = ehci_find_device(q->ehci, devaddr);
+    }
+
     if (p && p->async == EHCI_ASYNC_INFLIGHT) {
         /* I/O still in progress -- skip queue */
         ehci_set_state(ehci, async, EST_HORIZONTALQH);
commit 4224558f87371f87929df1064ddb733104fe5f15
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu May 10 12:10:47 2012 +0200

    ehci: make ehci_execute work on EHCIPacket instead of EHCIQueue
    
    This way it is possible to use ehci_execute to submit others than the
    first EHCIPacket of the EHCIQueue.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 03ae09f..a7cf282 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -1395,30 +1395,26 @@ static void ehci_execute_complete(EHCIQueue *q)
 
 // 4.10.3
 
-static int ehci_execute(EHCIQueue *q)
+static int ehci_execute(EHCIPacket *p)
 {
-    EHCIPacket *p = QTAILQ_FIRST(&q->packets);
     USBDevice *dev;
     USBEndpoint *ep;
     int ret;
     int endp;
     int devadr;
 
-    assert(p != NULL);
-    assert(p->qtdaddr == q->qtdaddr);
-
-    if ( !(q->qh.token & QTD_TOKEN_ACTIVE)) {
-        fprintf(stderr, "Attempting to execute inactive QH\n");
+    if (!(p->qtd.token & QTD_TOKEN_ACTIVE)) {
+        fprintf(stderr, "Attempting to execute inactive qtd\n");
         return USB_RET_PROCERR;
     }
 
-    p->tbytes = (q->qh.token & QTD_TOKEN_TBYTES_MASK) >> QTD_TOKEN_TBYTES_SH;
+    p->tbytes = (p->qtd.token & QTD_TOKEN_TBYTES_MASK) >> QTD_TOKEN_TBYTES_SH;
     if (p->tbytes > BUFF_SIZE) {
         fprintf(stderr, "Request for more bytes than allowed\n");
         return USB_RET_PROCERR;
     }
 
-    p->pid = (q->qh.token & QTD_TOKEN_PID_MASK) >> QTD_TOKEN_PID_SH;
+    p->pid = (p->qtd.token & QTD_TOKEN_PID_MASK) >> QTD_TOKEN_PID_SH;
     switch (p->pid) {
     case 0:
         p->pid = USB_TOKEN_OUT;
@@ -1438,11 +1434,11 @@ static int ehci_execute(EHCIQueue *q)
         return USB_RET_PROCERR;
     }
 
-    endp = get_field(q->qh.epchar, QH_EPCHAR_EP);
-    devadr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR);
+    endp = get_field(p->queue->qh.epchar, QH_EPCHAR_EP);
+    devadr = get_field(p->queue->qh.epchar, QH_EPCHAR_DEVADDR);
 
     /* TODO: associating device with ehci port */
-    dev = ehci_find_device(q->ehci, devadr);
+    dev = ehci_find_device(p->queue->ehci, devadr);
     ep = usb_ep_get(dev, p->pid, endp);
 
     usb_packet_setup(&p->packet, p->pid, ep);
@@ -1912,7 +1908,7 @@ static int ehci_state_execute(EHCIQueue *q, int async)
         ehci_set_usbsts(q->ehci, USBSTS_REC);
     }
 
-    p->usb_status = ehci_execute(q);
+    p->usb_status = ehci_execute(p);
     if (p->usb_status == USB_RET_PROCERR) {
         again = -1;
         goto out;
commit eb36a88e6b3a93001ba224aab5e631d251acae65
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed May 9 17:06:36 2012 +0200

    ehci: add EHCIPacket
    
    Add a separate EHCIPacket struct and move fields over from EHCIQueue.
    Preparing for supporting multiple packets per queue being in flight at
    the same time.  No functional changes yet.
    
    Fix some codestyle issues along the way.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index e759c99..03ae09f 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -334,6 +334,7 @@ typedef struct EHCIfstn {
     uint32_t backptr;                 // Standard next link pointer
 } EHCIfstn;
 
+typedef struct EHCIPacket EHCIPacket;
 typedef struct EHCIQueue EHCIQueue;
 typedef struct EHCIState EHCIState;
 
@@ -343,6 +344,21 @@ enum async_state {
     EHCI_ASYNC_FINISHED,
 };
 
+struct EHCIPacket {
+    EHCIQueue *queue;
+    QTAILQ_ENTRY(EHCIPacket) next;
+
+    EHCIqtd qtd;           /* copy of current QTD (being worked on) */
+    uint32_t qtdaddr;      /* address QTD read from                 */
+
+    USBPacket packet;
+    QEMUSGList sgl;
+    int pid;
+    uint32_t tbytes;
+    enum async_state async;
+    int usb_status;
+};
+
 struct EHCIQueue {
     EHCIState *ehci;
     QTAILQ_ENTRY(EHCIQueue) next;
@@ -352,17 +368,10 @@ struct EHCIQueue {
     /* cached data from guest - needs to be flushed
      * when guest removes an entry (doorbell, handshake sequence)
      */
-    EHCIqh qh;             // copy of current QH (being worked on)
-    uint32_t qhaddr;       // address QH read from
-    EHCIqtd qtd;           // copy of current QTD (being worked on)
-    uint32_t qtdaddr;      // address QTD read from
-
-    USBPacket packet;
-    QEMUSGList sgl;
-    int pid;
-    uint32_t tbytes;
-    enum async_state async;
-    int usb_status;
+    EHCIqh qh;             /* copy of current QH (being worked on) */
+    uint32_t qhaddr;       /* address QH read from                 */
+    uint32_t qtdaddr;      /* address QTD read from                */
+    QTAILQ_HEAD(, EHCIPacket) packets;
 };
 
 typedef QTAILQ_HEAD(EHCIQueueHead, EHCIQueue) EHCIQueueHead;
@@ -655,6 +664,35 @@ static void ehci_trace_sitd(EHCIState *s, target_phys_addr_t addr,
                         (bool)(sitd->results & SITD_RESULTS_ACTIVE));
 }
 
+/* packet management */
+
+static EHCIPacket *ehci_alloc_packet(EHCIQueue *q)
+{
+    EHCIPacket *p;
+
+#if 1
+    /* temporary, we don't handle multiple packets per queue (yet) */
+    assert(QTAILQ_EMPTY(&q->packets));
+#endif
+    p = g_new0(EHCIPacket, 1);
+    p->queue = q;
+    usb_packet_init(&p->packet);
+    QTAILQ_INSERT_TAIL(&q->packets, p, next);
+    trace_usb_ehci_packet_action(p->queue, p, "alloc");
+    return p;
+}
+
+static void ehci_free_packet(EHCIPacket *p)
+{
+    trace_usb_ehci_packet_action(p->queue, p, "free");
+    if (p->async == EHCI_ASYNC_INFLIGHT) {
+        usb_cancel_packet(&p->packet);
+    }
+    QTAILQ_REMOVE(&p->queue->packets, p, next);
+    usb_packet_cleanup(&p->packet);
+    g_free(p);
+}
+
 /* queue management */
 
 static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async)
@@ -664,7 +702,7 @@ static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async)
 
     q = g_malloc0(sizeof(*q));
     q->ehci = ehci;
-    usb_packet_init(&q->packet);
+    QTAILQ_INIT(&q->packets);
     QTAILQ_INSERT_HEAD(head, q, next);
     trace_usb_ehci_queue_action(q, "alloc");
     return q;
@@ -673,9 +711,11 @@ static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async)
 static void ehci_free_queue(EHCIQueue *q, int async)
 {
     EHCIQueueHead *head = async ? &q->ehci->aqueues : &q->ehci->pqueues;
+    EHCIPacket *p;
+
     trace_usb_ehci_queue_action(q, "free");
-    if (q->async == EHCI_ASYNC_INFLIGHT) {
-        usb_cancel_packet(&q->packet);
+    while ((p = QTAILQ_FIRST(&q->packets)) != NULL) {
+        ehci_free_packet(p);
     }
     QTAILQ_REMOVE(head, q, next);
     g_free(q);
@@ -718,10 +758,11 @@ static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async)
 {
     EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
     EHCIQueue *q, *tmp;
+    int addr;
 
     QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
-        if (!usb_packet_is_inflight(&q->packet) ||
-            q->packet.ep->dev != dev) {
+        addr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR);
+        if (addr != dev->addr) {
             continue;
         }
         ehci_free_queue(q, async);
@@ -1169,21 +1210,25 @@ static inline int put_dwords(EHCIState *ehci, uint32_t addr,
 
 static int ehci_qh_do_overlay(EHCIQueue *q)
 {
+    EHCIPacket *p = QTAILQ_FIRST(&q->packets);
     int i;
     int dtoggle;
     int ping;
     int eps;
     int reload;
 
+    assert(p != NULL);
+    assert(p->qtdaddr == q->qtdaddr);
+
     // remember values in fields to preserve in qh after overlay
 
     dtoggle = q->qh.token & QTD_TOKEN_DTOGGLE;
     ping    = q->qh.token & QTD_TOKEN_PING;
 
-    q->qh.current_qtd = q->qtdaddr;
-    q->qh.next_qtd    = q->qtd.next;
-    q->qh.altnext_qtd = q->qtd.altnext;
-    q->qh.token       = q->qtd.token;
+    q->qh.current_qtd = p->qtdaddr;
+    q->qh.next_qtd    = p->qtd.next;
+    q->qh.altnext_qtd = p->qtd.altnext;
+    q->qh.token       = p->qtd.token;
 
 
     eps = get_field(q->qh.epchar, QH_EPCHAR_EPS);
@@ -1196,7 +1241,7 @@ static int ehci_qh_do_overlay(EHCIQueue *q)
     set_field(&q->qh.altnext_qtd, reload, QH_ALTNEXT_NAKCNT);
 
     for (i = 0; i < 5; i++) {
-        q->qh.bufptr[i] = q->qtd.bufptr[i];
+        q->qh.bufptr[i] = p->qtd.bufptr[i];
     }
 
     if (!(q->qh.epchar & QH_EPCHAR_DTC)) {
@@ -1214,15 +1259,15 @@ static int ehci_qh_do_overlay(EHCIQueue *q)
     return 0;
 }
 
-static int ehci_init_transfer(EHCIQueue *q)
+static int ehci_init_transfer(EHCIPacket *p)
 {
     uint32_t cpage, offset, bytes, plen;
     dma_addr_t page;
 
-    cpage  = get_field(q->qh.token, QTD_TOKEN_CPAGE);
-    bytes  = get_field(q->qh.token, QTD_TOKEN_TBYTES);
-    offset = q->qh.bufptr[0] & ~QTD_BUFPTR_MASK;
-    pci_dma_sglist_init(&q->sgl, &q->ehci->dev, 5);
+    cpage  = get_field(p->qtd.token, QTD_TOKEN_CPAGE);
+    bytes  = get_field(p->qtd.token, QTD_TOKEN_TBYTES);
+    offset = p->qtd.bufptr[0] & ~QTD_BUFPTR_MASK;
+    pci_dma_sglist_init(&p->sgl, &p->queue->ehci->dev, 5);
 
     while (bytes > 0) {
         if (cpage > 4) {
@@ -1230,7 +1275,7 @@ static int ehci_init_transfer(EHCIQueue *q)
             return USB_RET_PROCERR;
         }
 
-        page  = q->qh.bufptr[cpage] & QTD_BUFPTR_MASK;
+        page  = p->qtd.bufptr[cpage] & QTD_BUFPTR_MASK;
         page += offset;
         plen  = bytes;
         if (plen > 4096 - offset) {
@@ -1239,7 +1284,7 @@ static int ehci_init_transfer(EHCIQueue *q)
             cpage++;
         }
 
-        qemu_sglist_add(&q->sgl, page, plen);
+        qemu_sglist_add(&p->sgl, page, plen);
         bytes -= plen;
     }
     return 0;
@@ -1249,8 +1294,6 @@ static void ehci_finish_transfer(EHCIQueue *q, int status)
 {
     uint32_t cpage, offset;
 
-    qemu_sglist_destroy(&q->sgl);
-
     if (status > 0) {
         /* update cpage & offset */
         cpage  = get_field(q->qh.token, QTD_TOKEN_CPAGE);
@@ -1268,7 +1311,7 @@ static void ehci_finish_transfer(EHCIQueue *q, int status)
 
 static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
 {
-    EHCIQueue *q;
+    EHCIPacket *p;
     EHCIState *s = port->opaque;
     uint32_t portsc = s->portsc[port->index];
 
@@ -1278,23 +1321,27 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
         return;
     }
 
-    q = container_of(packet, EHCIQueue, packet);
-    trace_usb_ehci_queue_action(q, "wakeup");
-    assert(q->async == EHCI_ASYNC_INFLIGHT);
-    q->async = EHCI_ASYNC_FINISHED;
-    q->usb_status = packet->result;
+    p = container_of(packet, EHCIPacket, packet);
+    trace_usb_ehci_packet_action(p->queue, p, "wakeup");
+    assert(p->async == EHCI_ASYNC_INFLIGHT);
+    p->async = EHCI_ASYNC_FINISHED;
+    p->usb_status = packet->result;
 }
 
 static void ehci_execute_complete(EHCIQueue *q)
 {
-    assert(q->async != EHCI_ASYNC_INFLIGHT);
-    q->async = EHCI_ASYNC_NONE;
+    EHCIPacket *p = QTAILQ_FIRST(&q->packets);
+
+    assert(p != NULL);
+    assert(p->qtdaddr == q->qtdaddr);
+    assert(p->async != EHCI_ASYNC_INFLIGHT);
+    p->async = EHCI_ASYNC_NONE;
 
     DPRINTF("execute_complete: qhaddr 0x%x, next %x, qtdaddr 0x%x, status %d\n",
             q->qhaddr, q->qh.next, q->qtdaddr, q->usb_status);
 
-    if (q->usb_status < 0) {
-        switch(q->usb_status) {
+    if (p->usb_status < 0) {
+        switch (p->usb_status) {
         case USB_RET_IOERROR:
         case USB_RET_NODEV:
             q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_XACTERR);
@@ -1314,28 +1361,29 @@ static void ehci_execute_complete(EHCIQueue *q)
             break;
         default:
             /* should not be triggerable */
-            fprintf(stderr, "USB invalid response %d to handle\n", q->usb_status);
+            fprintf(stderr, "USB invalid response %d\n", p->usb_status);
             assert(0);
             break;
         }
-    } else if ((q->usb_status > q->tbytes) && (q->pid == USB_TOKEN_IN)) {
-        q->usb_status = USB_RET_BABBLE;
+    } else if ((p->usb_status > p->tbytes) && (p->pid == USB_TOKEN_IN)) {
+        p->usb_status = USB_RET_BABBLE;
         q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_BABBLE);
         ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
     } else {
         // TODO check 4.12 for splits
 
-        if (q->tbytes && q->pid == USB_TOKEN_IN) {
-            q->tbytes -= q->usb_status;
+        if (p->tbytes && p->pid == USB_TOKEN_IN) {
+            p->tbytes -= p->usb_status;
         } else {
-            q->tbytes = 0;
+            p->tbytes = 0;
         }
 
-        DPRINTF("updating tbytes to %d\n", q->tbytes);
-        set_field(&q->qh.token, q->tbytes, QTD_TOKEN_TBYTES);
+        DPRINTF("updating tbytes to %d\n", p->tbytes);
+        set_field(&q->qh.token, p->tbytes, QTD_TOKEN_TBYTES);
     }
-    ehci_finish_transfer(q, q->usb_status);
-    usb_packet_unmap(&q->packet);
+    ehci_finish_transfer(q, p->usb_status);
+    qemu_sglist_destroy(&p->sgl);
+    usb_packet_unmap(&p->packet);
 
     q->qh.token ^= QTD_TOKEN_DTOGGLE;
     q->qh.token &= ~QTD_TOKEN_ACTIVE;
@@ -1349,32 +1397,44 @@ static void ehci_execute_complete(EHCIQueue *q)
 
 static int ehci_execute(EHCIQueue *q)
 {
+    EHCIPacket *p = QTAILQ_FIRST(&q->packets);
     USBDevice *dev;
     USBEndpoint *ep;
     int ret;
     int endp;
     int devadr;
 
+    assert(p != NULL);
+    assert(p->qtdaddr == q->qtdaddr);
+
     if ( !(q->qh.token & QTD_TOKEN_ACTIVE)) {
         fprintf(stderr, "Attempting to execute inactive QH\n");
         return USB_RET_PROCERR;
     }
 
-    q->tbytes = (q->qh.token & QTD_TOKEN_TBYTES_MASK) >> QTD_TOKEN_TBYTES_SH;
-    if (q->tbytes > BUFF_SIZE) {
+    p->tbytes = (q->qh.token & QTD_TOKEN_TBYTES_MASK) >> QTD_TOKEN_TBYTES_SH;
+    if (p->tbytes > BUFF_SIZE) {
         fprintf(stderr, "Request for more bytes than allowed\n");
         return USB_RET_PROCERR;
     }
 
-    q->pid = (q->qh.token & QTD_TOKEN_PID_MASK) >> QTD_TOKEN_PID_SH;
-    switch(q->pid) {
-        case 0: q->pid = USB_TOKEN_OUT; break;
-        case 1: q->pid = USB_TOKEN_IN; break;
-        case 2: q->pid = USB_TOKEN_SETUP; break;
-        default: fprintf(stderr, "bad token\n"); break;
+    p->pid = (q->qh.token & QTD_TOKEN_PID_MASK) >> QTD_TOKEN_PID_SH;
+    switch (p->pid) {
+    case 0:
+        p->pid = USB_TOKEN_OUT;
+        break;
+    case 1:
+        p->pid = USB_TOKEN_IN;
+        break;
+    case 2:
+        p->pid = USB_TOKEN_SETUP;
+        break;
+    default:
+        fprintf(stderr, "bad token\n");
+        break;
     }
 
-    if (ehci_init_transfer(q) != 0) {
+    if (ehci_init_transfer(p) != 0) {
         return USB_RET_PROCERR;
     }
 
@@ -1383,12 +1443,12 @@ static int ehci_execute(EHCIQueue *q)
 
     /* TODO: associating device with ehci port */
     dev = ehci_find_device(q->ehci, devadr);
-    ep = usb_ep_get(dev, q->pid, endp);
+    ep = usb_ep_get(dev, p->pid, endp);
 
-    usb_packet_setup(&q->packet, q->pid, ep);
-    usb_packet_map(&q->packet, &q->sgl);
+    usb_packet_setup(&p->packet, p->pid, ep);
+    usb_packet_map(&p->packet, &p->sgl);
 
-    ret = usb_handle_packet(dev, &q->packet);
+    ret = usb_handle_packet(dev, &p->packet);
     DPRINTF("submit: qh %x next %x qtd %x pid %x len %zd "
             "(total %d) endp %x ret %d\n",
             q->qhaddr, q->qh.next, q->qtdaddr, q->pid,
@@ -1601,6 +1661,7 @@ out:
 
 static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
 {
+    EHCIPacket *p;
     uint32_t entry;
     EHCIQueue *q;
 
@@ -1609,6 +1670,7 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
     if (NULL == q) {
         q = ehci_alloc_queue(ehci, async);
     }
+    p = QTAILQ_FIRST(&q->packets);
     q->qhaddr = entry;
     q->seen++;
 
@@ -1623,12 +1685,12 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
                (uint32_t *) &q->qh, sizeof(EHCIqh) >> 2);
     ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &q->qh);
 
-    if (q->async == EHCI_ASYNC_INFLIGHT) {
+    if (p && p->async == EHCI_ASYNC_INFLIGHT) {
         /* I/O still in progress -- skip queue */
         ehci_set_state(ehci, async, EST_HORIZONTALQH);
         goto out;
     }
-    if (q->async == EHCI_ASYNC_FINISHED) {
+    if (p && p->async == EHCI_ASYNC_FINISHED) {
         /* I/O finished -- continue processing queue */
         trace_usb_ehci_queue_action(q, "resume");
         ehci_set_state(ehci, async, EST_EXECUTING);
@@ -1767,13 +1829,18 @@ static int ehci_state_advqueue(EHCIQueue *q, int async)
 /* Section 4.10.2 - paragraph 4 */
 static int ehci_state_fetchqtd(EHCIQueue *q, int async)
 {
+    EHCIqtd qtd;
+    EHCIPacket *p;
     int again = 0;
 
-    get_dwords(q->ehci, NLPTR_GET(q->qtdaddr), (uint32_t *) &q->qtd,
+    get_dwords(q->ehci, NLPTR_GET(q->qtdaddr), (uint32_t *) &qtd,
                sizeof(EHCIqtd) >> 2);
-    ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), &q->qtd);
+    ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), &qtd);
 
-    if (q->qtd.token & QTD_TOKEN_ACTIVE) {
+    if (qtd.token & QTD_TOKEN_ACTIVE) {
+        p = ehci_alloc_packet(q);
+        p->qtdaddr = q->qtdaddr;
+        p->qtd = qtd;
         ehci_set_state(q->ehci, async, EST_EXECUTE);
         again = 1;
     } else {
@@ -1818,8 +1885,12 @@ static void ehci_flush_qh(EHCIQueue *q)
 
 static int ehci_state_execute(EHCIQueue *q, int async)
 {
+    EHCIPacket *p = QTAILQ_FIRST(&q->packets);
     int again = 0;
 
+    assert(p != NULL);
+    assert(p->qtdaddr == q->qtdaddr);
+
     if (ehci_qh_do_overlay(q) != 0) {
         return -1;
     }
@@ -1841,15 +1912,15 @@ static int ehci_state_execute(EHCIQueue *q, int async)
         ehci_set_usbsts(q->ehci, USBSTS_REC);
     }
 
-    q->usb_status = ehci_execute(q);
-    if (q->usb_status == USB_RET_PROCERR) {
+    p->usb_status = ehci_execute(q);
+    if (p->usb_status == USB_RET_PROCERR) {
         again = -1;
         goto out;
     }
-    if (q->usb_status == USB_RET_ASYNC) {
+    if (p->usb_status == USB_RET_ASYNC) {
         ehci_flush_qh(q);
         trace_usb_ehci_queue_action(q, "suspend");
-        q->async = EHCI_ASYNC_INFLIGHT;
+        p->async = EHCI_ASYNC_INFLIGHT;
         ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
         again = 1;
         goto out;
@@ -1864,13 +1935,17 @@ out:
 
 static int ehci_state_executing(EHCIQueue *q, int async)
 {
+    EHCIPacket *p = QTAILQ_FIRST(&q->packets);
     int again = 0;
 
+    assert(p != NULL);
+    assert(p->qtdaddr == q->qtdaddr);
+
     ehci_execute_complete(q);
-    if (q->usb_status == USB_RET_ASYNC) {
+    if (p->usb_status == USB_RET_ASYNC) {
         goto out;
     }
-    if (q->usb_status == USB_RET_PROCERR) {
+    if (p->usb_status == USB_RET_PROCERR) {
         again = -1;
         goto out;
     }
@@ -1885,7 +1960,7 @@ static int ehci_state_executing(EHCIQueue *q, int async)
     }
 
     /* 4.10.5 */
-    if (q->usb_status == USB_RET_NAK) {
+    if (p->usb_status == USB_RET_NAK) {
         ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
     } else {
         ehci_set_state(q->ehci, async, EST_WRITEBACK);
@@ -1901,12 +1976,17 @@ out:
 
 static int ehci_state_writeback(EHCIQueue *q, int async)
 {
+    EHCIPacket *p = QTAILQ_FIRST(&q->packets);
     int again = 0;
 
     /*  Write back the QTD from the QH area */
-    ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), (EHCIqtd*) &q->qh.next_qtd);
-    put_dwords(q->ehci, NLPTR_GET(q->qtdaddr), (uint32_t *) &q->qh.next_qtd,
+    assert(p != NULL);
+    assert(p->qtdaddr == q->qtdaddr);
+
+    ehci_trace_qtd(q, NLPTR_GET(p->qtdaddr), (EHCIqtd *) &q->qh.next_qtd);
+    put_dwords(q->ehci, NLPTR_GET(p->qtdaddr), (uint32_t *) &q->qh.next_qtd,
                sizeof(EHCIqtd) >> 2);
+    ehci_free_packet(p);
 
     /*
      * EHCI specs say go horizontal here.
diff --git a/trace-events b/trace-events
index 293eddb..f70523c 100644
--- a/trace-events
+++ b/trace-events
@@ -257,6 +257,7 @@ usb_ehci_port_detach(uint32_t port) "detach port #%d"
 usb_ehci_port_reset(uint32_t port, int enable) "reset port #%d - %d"
 usb_ehci_data(int rw, uint32_t cpage, uint32_t offset, uint32_t addr, uint32_t len, uint32_t bufpos) "write %d, cpage %d, offset 0x%03x, addr 0x%08x, len %d, bufpos %d"
 usb_ehci_queue_action(void *q, const char *action) "q %p: %s"
+usb_ehci_packet_action(void *q, void *p, const char *action) "q %p p %p: %s"
 
 # hw/usb/hcd-uhci.c
 usb_uhci_reset(void) "=== RESET ==="
commit 348f10374ac50b2e4511764fc5fae7cacef95ffa
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri May 11 15:15:27 2012 +0200

    xhci: trace: slots
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 7e823da..6c2ff02 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -1750,8 +1750,8 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
 
 static TRBCCode xhci_enable_slot(XHCIState *xhci, unsigned int slotid)
 {
+    trace_usb_xhci_slot_enable(slotid);
     assert(slotid >= 1 && slotid <= MAXSLOTS);
-    DPRINTF("xhci_enable_slot(%d)\n", slotid);
     xhci->slots[slotid-1].enabled = 1;
     xhci->slots[slotid-1].port = 0;
     memset(xhci->slots[slotid-1].eps, 0, sizeof(XHCIEPContext*)*31);
@@ -1763,8 +1763,8 @@ static TRBCCode xhci_disable_slot(XHCIState *xhci, unsigned int slotid)
 {
     int i;
 
+    trace_usb_xhci_slot_disable(slotid);
     assert(slotid >= 1 && slotid <= MAXSLOTS);
-    DPRINTF("xhci_disable_slot(%d)\n", slotid);
 
     for (i = 1; i <= 31; i++) {
         if (xhci->slots[slotid-1].eps[i-1]) {
@@ -1790,8 +1790,8 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
     int i;
     TRBCCode res;
 
+    trace_usb_xhci_slot_address(slotid);
     assert(slotid >= 1 && slotid <= MAXSLOTS);
-    DPRINTF("xhci_address_slot(%d)\n", slotid);
 
     dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high);
     pci_dma_read(&xhci->pci_dev, dcbaap + 8*slotid, &poctx, sizeof(poctx));
@@ -1877,8 +1877,8 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid,
     int i;
     TRBCCode res;
 
+    trace_usb_xhci_slot_configure(slotid);
     assert(slotid >= 1 && slotid <= MAXSLOTS);
-    DPRINTF("xhci_configure_slot(%d)\n", slotid);
 
     ictx = xhci_mask64(pictx);
     octx = xhci->slots[slotid-1].ctx;
@@ -1965,8 +1965,8 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid,
     uint32_t islot_ctx[4];
     uint32_t slot_ctx[4];
 
+    trace_usb_xhci_slot_evaluate(slotid);
     assert(slotid >= 1 && slotid <= MAXSLOTS);
-    DPRINTF("xhci_evaluate_slot(%d)\n", slotid);
 
     ictx = xhci_mask64(pictx);
     octx = xhci->slots[slotid-1].ctx;
@@ -2028,8 +2028,8 @@ static TRBCCode xhci_reset_slot(XHCIState *xhci, unsigned int slotid)
     dma_addr_t octx;
     int i;
 
+    trace_usb_xhci_slot_reset(slotid);
     assert(slotid >= 1 && slotid <= MAXSLOTS);
-    DPRINTF("xhci_reset_slot(%d)\n", slotid);
 
     octx = xhci->slots[slotid-1].ctx;
 
diff --git a/trace-events b/trace-events
index 74f661c..293eddb 100644
--- a/trace-events
+++ b/trace-events
@@ -306,6 +306,12 @@ usb_xhci_irq_intx(uint32_t level) "level %d"
 usb_xhci_irq_msi(uint32_t nr) "nr %d"
 usb_xhci_queue_event(uint32_t idx, const char *name, uint64_t param, uint32_t status, uint32_t control) "idx %d, %s, p %016" PRIx64 ", s %08x, c 0x%08x"
 usb_xhci_fetch_trb(uint64_t addr, const char *name, uint64_t param, uint32_t status, uint32_t control) "addr %016" PRIx64 ", %s, p %016" PRIx64 ", s %08x, c 0x%08x"
+usb_xhci_slot_enable(uint32_t slotid) "slotid %d"
+usb_xhci_slot_disable(uint32_t slotid) "slotid %d"
+usb_xhci_slot_address(uint32_t slotid) "slotid %d"
+usb_xhci_slot_configure(uint32_t slotid) "slotid %d"
+usb_xhci_slot_evaluate(uint32_t slotid) "slotid %d"
+usb_xhci_slot_reset(uint32_t slotid) "slotid %d"
 usb_xhci_ep_enable(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
 usb_xhci_ep_disable(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
 usb_xhci_ep_kick(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
commit 97df650bb9b4952e6e93ec3466086645714d5ddd
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri May 11 14:27:08 2012 +0200

    xhci: trace: transfers
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index c50e407..7e823da 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -1402,12 +1402,14 @@ static int xhci_setup_packet(XHCITransfer *xfer, USBDevice *dev)
 static int xhci_complete_packet(XHCITransfer *xfer, int ret)
 {
     if (ret == USB_RET_ASYNC) {
+        trace_usb_xhci_xfer_async(xfer);
         xfer->running_async = 1;
         xfer->running_retry = 0;
         xfer->complete = 0;
         xfer->cancelled = 0;
         return 0;
     } else if (ret == USB_RET_NAK) {
+        trace_usb_xhci_xfer_nak(xfer);
         xfer->running_async = 0;
         xfer->running_retry = 1;
         xfer->complete = 0;
@@ -1422,10 +1424,12 @@ static int xhci_complete_packet(XHCITransfer *xfer, int ret)
     if (ret >= 0) {
         xfer->status = CC_SUCCESS;
         xhci_xfer_data(xfer, xfer->data, ret, xfer->in_xfer, 0, 1);
+        trace_usb_xhci_xfer_success(xfer, ret);
         return 0;
     }
 
     /* error */
+    trace_usb_xhci_xfer_error(xfer, ret);
     switch (ret) {
     case USB_RET_NODEV:
         xfer->status = CC_USB_TRANSACTION_ERROR;
@@ -1461,11 +1465,12 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
     USBDevice *dev;
     int ret;
 
-    DPRINTF("xhci_fire_ctl_transfer(slot=%d)\n", xfer->slotid);
-
     trb_setup = &xfer->trbs[0];
     trb_status = &xfer->trbs[xfer->trb_count-1];
 
+    trace_usb_xhci_xfer_start(xfer, xfer->slotid, xfer->epid,
+                              trb_setup->parameter >> 48);
+
     /* at most one Event Data TRB allowed after STATUS */
     if (TRB_TYPE(*trb_status) == TR_EVDATA && xfer->trb_count > 2) {
         trb_status--;
@@ -1606,15 +1611,14 @@ static int xhci_fire_transfer(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext
     unsigned int length = 0;
     XHCITRB *trb;
 
-    DPRINTF("xhci_fire_transfer(slotid=%d,epid=%d)\n", xfer->slotid, xfer->epid);
-
     for (i = 0; i < xfer->trb_count; i++) {
         trb = &xfer->trbs[i];
         if (TRB_TYPE(*trb) == TR_NORMAL || TRB_TYPE(*trb) == TR_ISOCH) {
             length += trb->status & 0x1ffff;
         }
     }
-    DPRINTF("xhci: total TD length=%d\n", length);
+
+    trace_usb_xhci_xfer_start(xfer, xfer->slotid, xfer->epid, length);
 
     if (!epctx->has_bg) {
         xfer->data_length = length;
@@ -1670,15 +1674,13 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
         XHCITransfer *xfer = epctx->retry;
         int result;
 
-        DPRINTF("xhci: retry nack'ed transfer ...\n");
+        trace_usb_xhci_xfer_retry(xfer);
         assert(xfer->running_retry);
         xhci_setup_packet(xfer, xfer->packet.ep->dev);
         result = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
         if (result == USB_RET_NAK) {
-            DPRINTF("xhci: ... xfer still nacked\n");
             return;
         }
-        DPRINTF("xhci: ... result %d\n", result);
         xhci_complete_packet(xfer, result);
         assert(!xfer->running_retry);
         epctx->retry = NULL;
diff --git a/trace-events b/trace-events
index 74fdf6a..74f661c 100644
--- a/trace-events
+++ b/trace-events
@@ -311,6 +311,12 @@ usb_xhci_ep_disable(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
 usb_xhci_ep_kick(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
 usb_xhci_ep_stop(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
 usb_xhci_ep_reset(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
+usb_xhci_xfer_start(void *xfer, uint32_t slotid, uint32_t epid, uint32_t length) "%p: slotid %d, epid %d, length %d"
+usb_xhci_xfer_async(void *xfer) "%p"
+usb_xhci_xfer_nak(void *xfer) "%p"
+usb_xhci_xfer_retry(void *xfer) "%p"
+usb_xhci_xfer_success(void *xfer, uint32_t bytes) "%p: len %d"
+usb_xhci_xfer_error(void *xfer, uint32_t ret) "%p: ret %d"
 
 # hw/usb/desc.c
 usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"
commit c1f6b49326fee1c39f1db70fdb1e2a1df60318a2
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri May 11 14:26:15 2012 +0200

    xhci: trace: endpoints
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 08fdf94..c50e407 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -842,11 +842,10 @@ static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid,
     dma_addr_t dequeue;
     int i;
 
+    trace_usb_xhci_ep_enable(slotid, epid);
     assert(slotid >= 1 && slotid <= MAXSLOTS);
     assert(epid >= 1 && epid <= 31);
 
-    DPRINTF("xhci_enable_ep(%d, %d)\n", slotid, epid);
-
     slot = &xhci->slots[slotid-1];
     if (slot->eps[epid-1]) {
         fprintf(stderr, "xhci: slot %d ep %d already enabled!\n", slotid, epid);
@@ -961,11 +960,10 @@ static TRBCCode xhci_disable_ep(XHCIState *xhci, unsigned int slotid,
     XHCISlot *slot;
     XHCIEPContext *epctx;
 
+    trace_usb_xhci_ep_disable(slotid, epid);
     assert(slotid >= 1 && slotid <= MAXSLOTS);
     assert(epid >= 1 && epid <= 31);
 
-    DPRINTF("xhci_disable_ep(%d, %d)\n", slotid, epid);
-
     slot = &xhci->slots[slotid-1];
 
     if (!slot->eps[epid-1]) {
@@ -991,8 +989,7 @@ static TRBCCode xhci_stop_ep(XHCIState *xhci, unsigned int slotid,
     XHCISlot *slot;
     XHCIEPContext *epctx;
 
-    DPRINTF("xhci_stop_ep(%d, %d)\n", slotid, epid);
-
+    trace_usb_xhci_ep_stop(slotid, epid);
     assert(slotid >= 1 && slotid <= MAXSLOTS);
 
     if (epid < 1 || epid > 31) {
@@ -1026,10 +1023,9 @@ static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigned int slotid,
     XHCIEPContext *epctx;
     USBDevice *dev;
 
+    trace_usb_xhci_ep_reset(slotid, epid);
     assert(slotid >= 1 && slotid <= MAXSLOTS);
 
-    DPRINTF("xhci_reset_ep(%d, %d)\n", slotid, epid);
-
     if (epid < 1 || epid > 31) {
         fprintf(stderr, "xhci: bad ep %d\n", epid);
         return CC_TRB_ERROR;
@@ -1654,9 +1650,9 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
     int length;
     int i;
 
+    trace_usb_xhci_ep_kick(slotid, epid);
     assert(slotid >= 1 && slotid <= MAXSLOTS);
     assert(epid >= 1 && epid <= 31);
-    DPRINTF("xhci_kick_ep(%d, %d)\n", slotid, epid);
 
     if (!xhci->slots[slotid-1].enabled) {
         fprintf(stderr, "xhci: xhci_kick_ep for disabled slot %d\n", slotid);
@@ -1698,21 +1694,14 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
     while (1) {
         XHCITransfer *xfer = &epctx->transfers[epctx->next_xfer];
         if (xfer->running_async || xfer->running_retry || xfer->backgrounded) {
-            DPRINTF("xhci: ep is busy (#%d,%d,%d,%d)\n",
-                    epctx->next_xfer, xfer->running_async,
-                    xfer->running_retry, xfer->backgrounded);
             break;
-        } else {
-            DPRINTF("xhci: ep: using #%d\n", epctx->next_xfer);
         }
         length = xhci_ring_chain_length(xhci, &epctx->ring);
         if (length < 0) {
-            DPRINTF("xhci: incomplete TD (%d TRBs)\n", -length);
             break;
         } else if (length == 0) {
             break;
         }
-        DPRINTF("xhci: fetching %d-TRB TD\n", length);
         if (xfer->trbs && xfer->trb_alloced < length) {
             xfer->trb_count = 0;
             xfer->trb_alloced = 0;
@@ -1747,7 +1736,6 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
         }
 
         if (epctx->state == EP_HALTED) {
-            DPRINTF("xhci: ep halted, stopping schedule\n");
             break;
         }
         if (xfer->running_retry) {
diff --git a/trace-events b/trace-events
index 09ed109..74fdf6a 100644
--- a/trace-events
+++ b/trace-events
@@ -306,6 +306,11 @@ usb_xhci_irq_intx(uint32_t level) "level %d"
 usb_xhci_irq_msi(uint32_t nr) "nr %d"
 usb_xhci_queue_event(uint32_t idx, const char *name, uint64_t param, uint32_t status, uint32_t control) "idx %d, %s, p %016" PRIx64 ", s %08x, c 0x%08x"
 usb_xhci_fetch_trb(uint64_t addr, const char *name, uint64_t param, uint32_t status, uint32_t control) "addr %016" PRIx64 ", %s, p %016" PRIx64 ", s %08x, c 0x%08x"
+usb_xhci_ep_enable(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
+usb_xhci_ep_disable(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
+usb_xhci_ep_kick(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
+usb_xhci_ep_stop(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
+usb_xhci_ep_reset(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
 
 # hw/usb/desc.c
 usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"
commit 0703a4a7a67999dfda1a67cb7e0a6b4d2aefb239
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri May 11 14:23:42 2012 +0200

    xhci: trace: ring fetch
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 6890888..08fdf94 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -701,10 +701,8 @@ static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb,
         le32_to_cpus(&trb->status);
         le32_to_cpus(&trb->control);
 
-        DPRINTF("xhci: TRB fetched [" DMA_ADDR_FMT "]: "
-                "%016" PRIx64 " %08x %08x %s\n",
-                ring->dequeue, trb->parameter, trb->status, trb->control,
-                trb_name(trb));
+        trace_usb_xhci_fetch_trb(ring->dequeue, trb_name(trb),
+                                 trb->parameter, trb->status, trb->control);
 
         if ((trb->control & TRB_C) != ring->ccs) {
             return 0;
@@ -743,10 +741,6 @@ static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring)
         le32_to_cpus(&trb.status);
         le32_to_cpus(&trb.control);
 
-        DPRINTF("xhci: TRB peeked [" DMA_ADDR_FMT "]: "
-                "%016" PRIx64 " %08x %08x\n",
-                dequeue, trb.parameter, trb.status, trb.control);
-
         if ((trb.control & TRB_C) != ccs) {
             return -length;
         }
diff --git a/trace-events b/trace-events
index 974e5a3..09ed109 100644
--- a/trace-events
+++ b/trace-events
@@ -305,6 +305,7 @@ usb_xhci_doorbell_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x"
 usb_xhci_irq_intx(uint32_t level) "level %d"
 usb_xhci_irq_msi(uint32_t nr) "nr %d"
 usb_xhci_queue_event(uint32_t idx, const char *name, uint64_t param, uint32_t status, uint32_t control) "idx %d, %s, p %016" PRIx64 ", s %08x, c 0x%08x"
+usb_xhci_fetch_trb(uint64_t addr, const char *name, uint64_t param, uint32_t status, uint32_t control) "addr %016" PRIx64 ", %s, p %016" PRIx64 ", s %08x, c 0x%08x"
 
 # hw/usb/desc.c
 usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"
commit 7acd279f835e9f3b82e98df53b8ff97e2d922bb0
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri May 11 13:25:09 2012 +0200

    xhci: trace: irq + events
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 43875aa..6890888 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -422,7 +422,6 @@ typedef struct XHCIEvRingSeg {
     uint32_t rsvd;
 } XHCIEvRingSeg;
 
-#ifdef DEBUG_XHCI
 static const char *TRBType_names[] = {
     [TRB_RESERVED]                     = "TRB_RESERVED",
     [TR_NORMAL]                        = "TR_NORMAL",
@@ -474,7 +473,6 @@ static const char *trb_name(XHCITRB *trb)
     return lookup_name(TRB_TYPE(*trb), TRBType_names,
                        ARRAY_SIZE(TRBType_names));
 }
-#endif
 
 static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
                          unsigned int epid);
@@ -506,14 +504,13 @@ static void xhci_irq_update(XHCIState *xhci)
         level = 1;
     }
 
-    DPRINTF("xhci_irq_update(): %d\n", level);
-
     if (xhci->msi && msi_enabled(&xhci->pci_dev)) {
         if (level) {
-            DPRINTF("xhci_irq_update(): MSI signal\n");
+            trace_usb_xhci_irq_msi(0);
             msi_notify(&xhci->pci_dev, 0);
         }
     } else {
+        trace_usb_xhci_irq_intx(level);
         qemu_set_irq(xhci->irq, level);
     }
 }
@@ -543,9 +540,8 @@ static void xhci_write_event(XHCIState *xhci, XHCIEvent *event)
     }
     ev_trb.control = cpu_to_le32(ev_trb.control);
 
-    DPRINTF("xhci_write_event(): [%d] %016"PRIx64" %08x %08x %s\n",
-            xhci->er_ep_idx, ev_trb.parameter, ev_trb.status, ev_trb.control,
-            trb_name(&ev_trb));
+    trace_usb_xhci_queue_event(xhci->er_ep_idx, trb_name(&ev_trb),
+                               ev_trb.parameter, ev_trb.status, ev_trb.control);
 
     addr = xhci->er_start + TRB_SIZE*xhci->er_ep_idx;
     pci_dma_write(&xhci->pci_dev, addr, &ev_trb, TRB_SIZE);
diff --git a/trace-events b/trace-events
index 1b2db05..974e5a3 100644
--- a/trace-events
+++ b/trace-events
@@ -302,6 +302,9 @@ usb_xhci_oper_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x"
 usb_xhci_port_write(uint32_t port, uint32_t off, uint32_t val) "port %d, off 0x%04x, val 0x%08x"
 usb_xhci_runtime_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x"
 usb_xhci_doorbell_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x"
+usb_xhci_irq_intx(uint32_t level) "level %d"
+usb_xhci_irq_msi(uint32_t nr) "nr %d"
+usb_xhci_queue_event(uint32_t idx, const char *name, uint64_t param, uint32_t status, uint32_t control) "idx %d, %s, p %016" PRIx64 ", s %08x, c 0x%08x"
 
 # hw/usb/desc.c
 usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"
commit fc0ddaca33c3b4b9bf52cb15b62bdb17b84d9fa8
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri May 11 14:54:57 2012 +0200

    xhci: trace: run+stop
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 84d714a..43875aa 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -813,14 +813,13 @@ static void xhci_er_reset(XHCIState *xhci)
 
 static void xhci_run(XHCIState *xhci)
 {
-    DPRINTF("xhci_run()\n");
-
+    trace_usb_xhci_run();
     xhci->usbsts &= ~USBSTS_HCH;
 }
 
 static void xhci_stop(XHCIState *xhci)
 {
-    DPRINTF("xhci_stop()\n");
+    trace_usb_xhci_stop();
     xhci->usbsts |= USBSTS_HCH;
     xhci->crcr_low &= ~CRCR_CRR;
 }
diff --git a/trace-events b/trace-events
index b70b161..1b2db05 100644
--- a/trace-events
+++ b/trace-events
@@ -291,6 +291,8 @@ usb_uhci_td_complete(uint32_t qh, uint32_t td) "qh 0x%x, td 0x%x"
 
 # hw/usb/hcd-xhci.c
 usb_xhci_reset(void) "=== RESET ==="
+usb_xhci_run(void) ""
+usb_xhci_stop(void) ""
 usb_xhci_cap_read(uint32_t off, uint32_t val) "off 0x%04x, ret 0x%08x"
 usb_xhci_oper_read(uint32_t off, uint32_t val) "off 0x%04x, ret 0x%08x"
 usb_xhci_port_read(uint32_t port, uint32_t off, uint32_t val) "port %d, off 0x%04x, ret 0x%08x"
commit 2d754a10e4c43e9d83013ac83f8df7d1c856f0a0
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri May 11 12:49:31 2012 +0200

    xhci: trace: mmio reads+writes
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 4bc1e0e..84d714a 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -23,6 +23,7 @@
 #include "hw/usb.h"
 #include "hw/pci.h"
 #include "hw/msi.h"
+#include "trace.h"
 
 //#define DEBUG_XHCI
 //#define DEBUG_DATA
@@ -2301,7 +2302,7 @@ static void xhci_reset(DeviceState *dev)
     XHCIState *xhci = DO_UPCAST(XHCIState, pci_dev.qdev, dev);
     int i;
 
-    DPRINTF("xhci: full reset\n");
+    trace_usb_xhci_reset();
     if (!(xhci->usbsts & USBSTS_HCH)) {
         fprintf(stderr, "xhci: reset while running!\n");
     }
@@ -2342,77 +2343,98 @@ static void xhci_reset(DeviceState *dev)
 
 static uint32_t xhci_cap_read(XHCIState *xhci, uint32_t reg)
 {
-    DPRINTF("xhci_cap_read(0x%x)\n", reg);
+    uint32_t ret;
 
     switch (reg) {
     case 0x00: /* HCIVERSION, CAPLENGTH */
-        return 0x01000000 | LEN_CAP;
+        ret = 0x01000000 | LEN_CAP;
+        break;
     case 0x04: /* HCSPARAMS 1 */
-        return (MAXPORTS<<24) | (MAXINTRS<<8) | MAXSLOTS;
+        ret = (MAXPORTS<<24) | (MAXINTRS<<8) | MAXSLOTS;
+        break;
     case 0x08: /* HCSPARAMS 2 */
-        return 0x0000000f;
+        ret = 0x0000000f;
+        break;
     case 0x0c: /* HCSPARAMS 3 */
-        return 0x00000000;
+        ret = 0x00000000;
+        break;
     case 0x10: /* HCCPARAMS */
-#if TARGET_PHYS_ADDR_BITS > 32
-        return 0x00081001;
-#else
-        return 0x00081000;
-#endif
+        if (sizeof(dma_addr_t) == 4) {
+            ret = 0x00081000;
+        } else {
+            ret = 0x00081001;
+        }
+        break;
     case 0x14: /* DBOFF */
-        return OFF_DOORBELL;
+        ret = OFF_DOORBELL;
+        break;
     case 0x18: /* RTSOFF */
-        return OFF_RUNTIME;
+        ret = OFF_RUNTIME;
+        break;
 
     /* extended capabilities */
     case 0x20: /* Supported Protocol:00 */
-#if USB3_PORTS > 0
-        return 0x02000402; /* USB 2.0 */
-#else
-        return 0x02000002; /* USB 2.0 */
-#endif
+        ret = 0x02000402; /* USB 2.0 */
+        break;
     case 0x24: /* Supported Protocol:04 */
-        return 0x20425455; /* "USB " */
+        ret = 0x20425455; /* "USB " */
+        break;
     case 0x28: /* Supported Protocol:08 */
-        return 0x00000001 | (USB2_PORTS<<8);
+        ret = 0x00000001 | (USB2_PORTS<<8);
+        break;
     case 0x2c: /* Supported Protocol:0c */
-        return 0x00000000; /* reserved */
-#if USB3_PORTS > 0
+        ret = 0x00000000; /* reserved */
+        break;
     case 0x30: /* Supported Protocol:00 */
-        return 0x03000002; /* USB 3.0 */
+        ret = 0x03000002; /* USB 3.0 */
+        break;
     case 0x34: /* Supported Protocol:04 */
-        return 0x20425455; /* "USB " */
+        ret = 0x20425455; /* "USB " */
+        break;
     case 0x38: /* Supported Protocol:08 */
-        return 0x00000000 | (USB2_PORTS+1) | (USB3_PORTS<<8);
+        ret = 0x00000000 | (USB2_PORTS+1) | (USB3_PORTS<<8);
+        break;
     case 0x3c: /* Supported Protocol:0c */
-        return 0x00000000; /* reserved */
-#endif
+        ret = 0x00000000; /* reserved */
+        break;
     default:
         fprintf(stderr, "xhci_cap_read: reg %d unimplemented\n", reg);
+        ret = 0;
     }
-    return 0;
+
+    trace_usb_xhci_cap_read(reg, ret);
+    return ret;
 }
 
 static uint32_t xhci_port_read(XHCIState *xhci, uint32_t reg)
 {
     uint32_t port = reg >> 4;
+    uint32_t ret;
+
     if (port >= MAXPORTS) {
         fprintf(stderr, "xhci_port_read: port %d out of bounds\n", port);
-        return 0;
+        ret = 0;
+        goto out;
     }
 
     switch (reg & 0xf) {
     case 0x00: /* PORTSC */
-        return xhci->ports[port].portsc;
+        ret = xhci->ports[port].portsc;
+        break;
     case 0x04: /* PORTPMSC */
     case 0x08: /* PORTLI */
-        return 0;
+        ret = 0;
+        break;
     case 0x0c: /* reserved */
     default:
         fprintf(stderr, "xhci_port_read (port %d): reg 0x%x unimplemented\n",
                 port, reg);
-        return 0;
+        ret = 0;
     }
+
+out:
+    trace_usb_xhci_port_read(port, reg & 0x0f, ret);
+    return ret;
 }
 
 static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val)
@@ -2420,6 +2442,8 @@ static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val)
     uint32_t port = reg >> 4;
     uint32_t portsc;
 
+    trace_usb_xhci_port_write(port, reg & 0x0f, val);
+
     if (port >= MAXPORTS) {
         fprintf(stderr, "xhci_port_read: port %d out of bounds\n", port);
         return;
@@ -2457,7 +2481,7 @@ static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val)
 
 static uint32_t xhci_oper_read(XHCIState *xhci, uint32_t reg)
 {
-    DPRINTF("xhci_oper_read(0x%x)\n", reg);
+    uint32_t ret;
 
     if (reg >= 0x400) {
         return xhci_port_read(xhci, reg - 0x400);
@@ -2465,38 +2489,50 @@ static uint32_t xhci_oper_read(XHCIState *xhci, uint32_t reg)
 
     switch (reg) {
     case 0x00: /* USBCMD */
-        return xhci->usbcmd;
+        ret = xhci->usbcmd;
+        break;
     case 0x04: /* USBSTS */
-        return xhci->usbsts;
+        ret = xhci->usbsts;
+        break;
     case 0x08: /* PAGESIZE */
-        return 1; /* 4KiB */
+        ret = 1; /* 4KiB */
+        break;
     case 0x14: /* DNCTRL */
-        return xhci->dnctrl;
+        ret = xhci->dnctrl;
+        break;
     case 0x18: /* CRCR low */
-        return xhci->crcr_low & ~0xe;
+        ret = xhci->crcr_low & ~0xe;
+        break;
     case 0x1c: /* CRCR high */
-        return xhci->crcr_high;
+        ret = xhci->crcr_high;
+        break;
     case 0x30: /* DCBAAP low */
-        return xhci->dcbaap_low;
+        ret = xhci->dcbaap_low;
+        break;
     case 0x34: /* DCBAAP high */
-        return xhci->dcbaap_high;
+        ret = xhci->dcbaap_high;
+        break;
     case 0x38: /* CONFIG */
-        return xhci->config;
+        ret = xhci->config;
+        break;
     default:
         fprintf(stderr, "xhci_oper_read: reg 0x%x unimplemented\n", reg);
+        ret = 0;
     }
-    return 0;
+
+    trace_usb_xhci_oper_read(reg, ret);
+    return ret;
 }
 
 static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val)
 {
-    DPRINTF("xhci_oper_write(0x%x, 0x%08x)\n", reg, val);
-
     if (reg >= 0x400) {
         xhci_port_write(xhci, reg - 0x400, val);
         return;
     }
 
+    trace_usb_xhci_oper_write(reg, val);
+
     switch (reg) {
     case 0x00: /* USBCMD */
         if ((val & USBCMD_RS) && !(xhci->usbcmd & USBCMD_RS)) {
@@ -2552,35 +2588,46 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val)
 
 static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg)
 {
-    DPRINTF("xhci_runtime_read(0x%x)\n", reg);
+    uint32_t ret;
 
     switch (reg) {
     case 0x00: /* MFINDEX */
         fprintf(stderr, "xhci_runtime_read: MFINDEX not yet implemented\n");
-        return xhci->mfindex;
+        ret = xhci->mfindex;
+        break;
     case 0x20: /* IMAN */
-        return xhci->iman;
+        ret = xhci->iman;
+        break;
     case 0x24: /* IMOD */
-        return xhci->imod;
+        ret = xhci->imod;
+        break;
     case 0x28: /* ERSTSZ */
-        return xhci->erstsz;
+        ret = xhci->erstsz;
+        break;
     case 0x30: /* ERSTBA low */
-        return xhci->erstba_low;
+        ret = xhci->erstba_low;
+        break;
     case 0x34: /* ERSTBA high */
-        return xhci->erstba_high;
+        ret = xhci->erstba_high;
+        break;
     case 0x38: /* ERDP low */
-        return xhci->erdp_low;
+        ret = xhci->erdp_low;
+        break;
     case 0x3c: /* ERDP high */
-        return xhci->erdp_high;
+        ret = xhci->erdp_high;
+        break;
     default:
         fprintf(stderr, "xhci_runtime_read: reg 0x%x unimplemented\n", reg);
+        ret = 0;
     }
-    return 0;
+
+    trace_usb_xhci_runtime_read(reg, ret);
+    return ret;
 }
 
 static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val)
 {
-    DPRINTF("xhci_runtime_write(0x%x, 0x%08x)\n", reg, val);
+    trace_usb_xhci_runtime_read(reg, val);
 
     switch (reg) {
     case 0x20: /* IMAN */
@@ -2623,14 +2670,14 @@ static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val)
 
 static uint32_t xhci_doorbell_read(XHCIState *xhci, uint32_t reg)
 {
-    DPRINTF("xhci_doorbell_read(0x%x)\n", reg);
     /* doorbells always read as 0 */
+    trace_usb_xhci_doorbell_read(reg, 0);
     return 0;
 }
 
 static void xhci_doorbell_write(XHCIState *xhci, uint32_t reg, uint32_t val)
 {
-    DPRINTF("xhci_doorbell_write(0x%x, 0x%08x)\n", reg, val);
+    trace_usb_xhci_doorbell_write(reg, val);
 
     if (!xhci_running(xhci)) {
         fprintf(stderr, "xhci: wrote doorbell while xHC stopped or paused\n");
diff --git a/trace-events b/trace-events
index dd057bc..b70b161 100644
--- a/trace-events
+++ b/trace-events
@@ -289,6 +289,18 @@ usb_uhci_td_nextqh(uint32_t qh, uint32_t td) "qh 0x%x, td 0x%x"
 usb_uhci_td_async(uint32_t qh, uint32_t td) "qh 0x%x, td 0x%x"
 usb_uhci_td_complete(uint32_t qh, uint32_t td) "qh 0x%x, td 0x%x"
 
+# hw/usb/hcd-xhci.c
+usb_xhci_reset(void) "=== RESET ==="
+usb_xhci_cap_read(uint32_t off, uint32_t val) "off 0x%04x, ret 0x%08x"
+usb_xhci_oper_read(uint32_t off, uint32_t val) "off 0x%04x, ret 0x%08x"
+usb_xhci_port_read(uint32_t port, uint32_t off, uint32_t val) "port %d, off 0x%04x, ret 0x%08x"
+usb_xhci_runtime_read(uint32_t off, uint32_t val) "off 0x%04x, ret 0x%08x"
+usb_xhci_doorbell_read(uint32_t off, uint32_t val) "off 0x%04x, ret 0x%08x"
+usb_xhci_oper_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x"
+usb_xhci_port_write(uint32_t port, uint32_t off, uint32_t val) "port %d, off 0x%04x, val 0x%08x"
+usb_xhci_runtime_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x"
+usb_xhci_doorbell_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x"
+
 # hw/usb/desc.c
 usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"
 usb_desc_device_qualifier(int addr, int len, int ret) "dev %d query device qualifier, len %d, ret %d"
commit 64619739c4cf32db60b5c9599e98ececd7640060
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri May 11 11:36:37 2012 -0300

    xhci: Clean up reset function
    
    Properly register reset function via the device class.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 5cf1a64..4bc1e0e 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -2296,9 +2296,9 @@ static void xhci_update_port(XHCIState *xhci, XHCIPort *port, int is_detach)
     }
 }
 
-static void xhci_reset(void *opaque)
+static void xhci_reset(DeviceState *dev)
 {
-    XHCIState *xhci = opaque;
+    XHCIState *xhci = DO_UPCAST(XHCIState, pci_dev.qdev, dev);
     int i;
 
     DPRINTF("xhci: full reset\n");
@@ -2506,7 +2506,7 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val)
         }
         xhci->usbcmd = val & 0xc0f;
         if (val & USBCMD_HCRST) {
-            xhci_reset(xhci);
+            xhci_reset(&xhci->pci_dev.qdev);
         }
         xhci_irq_update(xhci);
         break;
@@ -2831,8 +2831,6 @@ static void usb_xhci_init(XHCIState *xhci, DeviceState *dev)
     for (i = 0; i < MAXSLOTS; i++) {
         xhci->slots[i].enabled = 0;
     }
-
-    qemu_register_reset(xhci_reset, xhci);
 }
 
 static int usb_xhci_initfn(struct PCIDevice *dev)
@@ -2895,6 +2893,7 @@ static void xhci_class_init(ObjectClass *klass, void *data)
 
     dc->vmsd    = &vmstate_xhci;
     dc->props   = xhci_properties;
+    dc->reset   = xhci_reset;
     k->init         = usb_xhci_initfn;
     k->vendor_id    = PCI_VENDOR_ID_NEC;
     k->device_id    = PCI_DEVICE_ID_NEC_UPD720200;
commit 5de88b1d4679b560f1350aa4559342ba6a8d69ef
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon May 14 13:56:40 2012 +0200

    usb-storage: migration support
    
    With all scsi migration support bits in place the
    final step is pretty simple ;)
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index 5b9a286..097d7b4 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -506,6 +506,17 @@ static void usb_msd_password_cb(void *opaque, int err)
         qdev_unplug(&s->dev.qdev, NULL);
 }
 
+static void *usb_msd_load_request(QEMUFile *f, SCSIRequest *req)
+{
+    MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
+
+    /* nothing to load, just store req in our state struct */
+    assert(s->req == NULL);
+    scsi_req_ref(req);
+    s->req = req;
+    return NULL;
+}
+
 static const struct SCSIBusInfo usb_msd_scsi_info = {
     .tcq = false,
     .max_target = 0,
@@ -513,7 +524,8 @@ static const struct SCSIBusInfo usb_msd_scsi_info = {
 
     .transfer_data = usb_msd_transfer_data,
     .complete = usb_msd_command_complete,
-    .cancel = usb_msd_request_cancelled
+    .cancel = usb_msd_request_cancelled,
+    .load_request = usb_msd_load_request,
 };
 
 static int usb_msd_initfn(USBDevice *dev)
@@ -633,11 +645,18 @@ static USBDevice *usb_msd_init(USBBus *bus, const char *filename)
 
 static const VMStateDescription vmstate_usb_msd = {
     .name = "usb-storage",
-    .unmigratable = 1, /* FIXME: handle transactions which are in flight */
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (VMStateField []) {
         VMSTATE_USB_DEVICE(dev, MSDState),
+        VMSTATE_UINT32(mode, MSDState),
+        VMSTATE_UINT32(scsi_len, MSDState),
+        VMSTATE_UINT32(scsi_off, MSDState),
+        VMSTATE_UINT32(data_len, MSDState),
+        VMSTATE_UINT32(csw.sig, MSDState),
+        VMSTATE_UINT32(csw.tag, MSDState),
+        VMSTATE_UINT32(csw.residue, MSDState),
+        VMSTATE_UINT8(csw.status, MSDState),
         VMSTATE_END_OF_LIST()
     }
 };
commit 1dc903673aa3afee296aaa4664404fc5d373b79a
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed May 16 15:03:40 2012 +0200

    usb-storage: add scsi_off, remove scsi_buf
    
    Repace the running buffer pointer (scsi_buf) with a buffer offset
    field (scsi_off).  The later is alot easier to live-migrate.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index 924a86f..5b9a286 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -48,8 +48,8 @@ struct usb_msd_csw {
 typedef struct {
     USBDevice dev;
     enum USBMSDMode mode;
+    uint32_t scsi_off;
     uint32_t scsi_len;
-    uint8_t *scsi_buf;
     uint32_t data_len;
     struct usb_msd_csw csw;
     SCSIRequest *req;
@@ -178,9 +178,9 @@ static void usb_msd_copy_data(MSDState *s, USBPacket *p)
     len = p->iov.size - p->result;
     if (len > s->scsi_len)
         len = s->scsi_len;
-    usb_packet_copy(p, s->scsi_buf, len);
+    usb_packet_copy(p, scsi_req_get_buf(s->req) + s->scsi_off, len);
     s->scsi_len -= len;
-    s->scsi_buf += len;
+    s->scsi_off += len;
     s->data_len -= len;
     if (s->scsi_len == 0 || s->data_len == 0) {
         scsi_req_continue(s->req);
@@ -219,7 +219,7 @@ static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
 
     assert((s->mode == USB_MSDM_DATAOUT) == (req->cmd.mode == SCSI_XFER_TO_DEV));
     s->scsi_len = len;
-    s->scsi_buf = scsi_req_get_buf(req);
+    s->scsi_off = 0;
     if (p) {
         usb_msd_copy_data(s, p);
         p = s->packet;
commit 1e6ed80b90e3d9632532b4c496d26b0d101ced6b
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue May 22 14:30:20 2012 +0200

    usb-storage: add usb_msd_packet_complete()
    
    Factor out packet completion to a separate function which
    cares to get the MSDState->packet update right.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index e6652f9..924a86f 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -200,6 +200,18 @@ static void usb_msd_send_status(MSDState *s, USBPacket *p)
     memset(&s->csw, 0, sizeof(s->csw));
 }
 
+static void usb_msd_packet_complete(MSDState *s)
+{
+    USBPacket *p = s->packet;
+
+    /* Set s->packet to NULL before calling usb_packet_complete
+       because another request may be issued before
+       usb_packet_complete returns.  */
+    DPRINTF("Packet complete %p\n", p);
+    s->packet = NULL;
+    usb_packet_complete(&s->dev, p);
+}
+
 static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
 {
     MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
@@ -212,12 +224,7 @@ static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
         usb_msd_copy_data(s, p);
         p = s->packet;
         if (p && p->result == p->iov.size) {
-            /* Set s->packet to NULL before calling usb_packet_complete
-               because another request may be issued before
-               usb_packet_complete returns.  */
-            DPRINTF("Packet complete %p\n", p);
-            s->packet = NULL;
-            usb_packet_complete(&s->dev, p);
+            usb_msd_packet_complete(s);
         }
     }
 }
@@ -250,8 +257,7 @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t r
                 s->mode = USB_MSDM_CSW;
             }
         }
-        s->packet = NULL;
-        usb_packet_complete(&s->dev, p);
+        usb_msd_packet_complete(s);
     } else if (s->data_len == 0) {
         s->mode = USB_MSDM_CSW;
     }
@@ -281,10 +287,8 @@ static void usb_msd_handle_reset(USBDevice *dev)
     assert(s->req == NULL);
 
     if (s->packet) {
-        USBPacket *p = s->packet;
-        s->packet = NULL;
-        p->result = USB_RET_STALL;
-        usb_packet_complete(dev, p);
+        s->packet->result = USB_RET_STALL;
+        usb_msd_packet_complete(s);
     }
 
     s->mode = USB_MSDM_CBW;
commit 0659879e6e537c511147d4da71934bf9d367de50
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon May 14 14:00:02 2012 +0200

    usb-storage: remove MSDState->residue
    
    We have the field twice, once in MSDState directly and one in the status
    word struct.  Drop one.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index a96c0b9..e6652f9 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -51,7 +51,6 @@ typedef struct {
     uint32_t scsi_len;
     uint8_t *scsi_buf;
     uint32_t data_len;
-    uint32_t residue;
     struct usb_msd_csw csw;
     SCSIRequest *req;
     SCSIBus bus;
@@ -229,11 +228,10 @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t r
     USBPacket *p = s->packet;
 
     DPRINTF("Command complete %d tag 0x%x\n", status, req->tag);
-    s->residue = s->data_len;
 
     s->csw.sig = cpu_to_le32(0x53425355);
     s->csw.tag = cpu_to_le32(req->tag);
-    s->csw.residue = cpu_to_le32(s->residue);
+    s->csw.residue = cpu_to_le32(s->data_len);
     s->csw.status = status != 0;
 
     if (s->packet) {
@@ -378,7 +376,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
             }
             DPRINTF("Command tag 0x%x flags %08x len %d data %d\n",
                     tag, cbw.flags, cbw.cmd_len, s->data_len);
-            s->residue = 0;
+            assert(le32_to_cpu(s->csw.residue) == 0);
             s->scsi_len = 0;
             s->req = scsi_req_new(s->scsi_dev, tag, 0, cbw.cmd, NULL);
             scsi_req_enqueue(s->req);
@@ -397,7 +395,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
             if (s->scsi_len) {
                 usb_msd_copy_data(s, p);
             }
-            if (s->residue) {
+            if (le32_to_cpu(s->csw.residue)) {
                 int len = p->iov.size - p->result;
                 if (len) {
                     usb_packet_skip(p, len);
@@ -458,7 +456,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
             if (s->scsi_len) {
                 usb_msd_copy_data(s, p);
             }
-            if (s->residue) {
+            if (le32_to_cpu(s->csw.residue)) {
                 int len = p->iov.size - p->result;
                 if (len) {
                     usb_packet_skip(p, len);
commit 18eef3bc4eb80fee2cf4a9f18cb87784854d30c1
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed May 16 14:20:03 2012 +0200

    scsi: prepare migration code for usb-storage support
    
    usb-storage can't handle requests in one go as the data transfer can be
    splitted into lots of usb packets.  Because of that there can be
    normal in-flight requests at savevm time and we need to handle that.
    With other scsi hba's this happens only in case i/o is stopped due to
    errors and there are pending requests which need to be restarted
    (req->retry = true).
    
    So, first we need to save req->retry and then handle the req->retry =
    false case.  Write requests are handled fine already.  For read requests
    we have to save the buffer as we will not restart the request (and thus
    not refill the buffer) on the target host.
    
    Cc: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index f10f3ec..4a79821 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -1507,10 +1507,9 @@ static void put_scsi_requests(QEMUFile *f, void *pv, size_t size)
     QTAILQ_FOREACH(req, &s->requests, next) {
         assert(!req->io_canceled);
         assert(req->status == -1);
-        assert(req->retry);
         assert(req->enqueued);
 
-        qemu_put_sbyte(f, 1);
+        qemu_put_sbyte(f, req->retry ? 1 : 2);
         qemu_put_buffer(f, req->cmd.buf, sizeof(req->cmd.buf));
         qemu_put_be32s(f, &req->tag);
         qemu_put_be32s(f, &req->lun);
@@ -1528,8 +1527,9 @@ static int get_scsi_requests(QEMUFile *f, void *pv, size_t size)
 {
     SCSIDevice *s = pv;
     SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus);
+    int8_t sbyte;
 
-    while (qemu_get_sbyte(f)) {
+    while ((sbyte = qemu_get_sbyte(f)) > 0) {
         uint8_t buf[SCSI_CMD_BUF_SIZE];
         uint32_t tag;
         uint32_t lun;
@@ -1539,6 +1539,7 @@ static int get_scsi_requests(QEMUFile *f, void *pv, size_t size)
         qemu_get_be32s(f, &tag);
         qemu_get_be32s(f, &lun);
         req = scsi_req_new(s, tag, lun, buf, NULL);
+        req->retry = (sbyte == 1);
         if (bus->info->load_request) {
             req->hba_private = bus->info->load_request(f, req);
         }
@@ -1547,7 +1548,6 @@ static int get_scsi_requests(QEMUFile *f, void *pv, size_t size)
         }
 
         /* Just restart it later.  */
-        req->retry = true;
         scsi_req_enqueue_internal(req);
 
         /* At this point, the request will be kept alive by the reference
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 045c764..1691491 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -132,8 +132,14 @@ static void scsi_disk_save_request(QEMUFile *f, SCSIRequest *req)
     qemu_put_be64s(f, &r->sector);
     qemu_put_be32s(f, &r->sector_count);
     qemu_put_be32s(f, &r->buflen);
-    if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
-        qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len);
+    if (r->buflen) {
+        if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
+            qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len);
+        } else if (!req->retry) {
+            uint32_t len = r->iov.iov_len;
+            qemu_put_be32s(f, &len);
+            qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len);
+        }
     }
 }
 
@@ -148,6 +154,12 @@ static void scsi_disk_load_request(QEMUFile *f, SCSIRequest *req)
         scsi_init_iovec(r, r->buflen);
         if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
             qemu_get_buffer(f, r->iov.iov_base, r->iov.iov_len);
+        } else if (!r->req.retry) {
+            uint32_t len;
+            qemu_get_be32s(f, &len);
+            r->iov.iov_len = len;
+            assert(r->iov.iov_len <= r->buflen);
+            qemu_get_buffer(f, r->iov.iov_base, r->iov.iov_len);
         }
     }
 
commit 973002c11460efd3c17fe61a76711a103e30e1f9
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri May 25 12:53:47 2012 +0200

    uhci: fix irq routing
    
    The multifunction ich9 ehci controller with uhci companions uses a
    different interrupt pin for each function.  The three uhci devices
    get pins A, B and C, whereas ehci uses pin D.  This way the guest
    can assign different IRQ lines to each controller.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 3ea388c..9871e24 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -138,6 +138,7 @@ struct UHCIState {
 
     /* Interrupts that should be raised at the end of the current frame.  */
     uint32_t pending_int_mask;
+    int irq_pin;
 
     /* Active packets */
     QTAILQ_HEAD(, UHCIQueue) queues;
@@ -340,7 +341,7 @@ static void uhci_update_irq(UHCIState *s)
     } else {
         level = 0;
     }
-    qemu_set_irq(s->dev.irq[3], level);
+    qemu_set_irq(s->dev.irq[s->irq_pin], level);
 }
 
 static void uhci_reset(void *opaque)
@@ -1184,15 +1185,31 @@ static USBBusOps uhci_bus_ops = {
 
 static int usb_uhci_common_initfn(PCIDevice *dev)
 {
+    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
     UHCIState *s = DO_UPCAST(UHCIState, dev, dev);
     uint8_t *pci_conf = s->dev.config;
     int i;
 
     pci_conf[PCI_CLASS_PROG] = 0x00;
     /* TODO: reset value should be 0. */
-    pci_conf[PCI_INTERRUPT_PIN] = 4; /* interrupt pin D */
     pci_conf[USB_SBRN] = USB_RELEASE_1; // release number
 
+    switch (pc->device_id) {
+    case PCI_DEVICE_ID_INTEL_82801I_UHCI1:
+        s->irq_pin = 0;  /* A */
+        break;
+    case PCI_DEVICE_ID_INTEL_82801I_UHCI2:
+        s->irq_pin = 1;  /* B */
+        break;
+    case PCI_DEVICE_ID_INTEL_82801I_UHCI3:
+        s->irq_pin = 2;  /* C */
+        break;
+    default:
+        s->irq_pin = 3;  /* D */
+        break;
+    }
+    pci_config_set_interrupt_pin(pci_conf, s->irq_pin + 1);
+
     if (s->masterbus) {
         USBPort *ports[NB_PORTS];
         for(i = 0; i < NB_PORTS; i++) {
commit 5852d3bfe16c85d4dabc4e0d21658fc680a756e5
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon May 14 14:02:14 2012 +0200

    uhci: zap uhci_pre_save
    
    Cancel transactions before saving vmstate is pretty pointless and just
    causes disruptions.  We need to cancel them before *loading* vmstate,
    but in that case uhci_reset() handles it already and no special action
    is needed.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 2e7c8f9..3ea388c 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -376,13 +376,6 @@ static void uhci_reset(void *opaque)
     uhci_update_irq(s);
 }
 
-static void uhci_pre_save(void *opaque)
-{
-    UHCIState *s = opaque;
-
-    uhci_async_cancel_all(s);
-}
-
 static const VMStateDescription vmstate_uhci_port = {
     .name = "uhci port",
     .version_id = 1,
@@ -399,7 +392,6 @@ static const VMStateDescription vmstate_uhci = {
     .version_id = 2,
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
-    .pre_save = uhci_pre_save,
     .fields      = (VMStateField []) {
         VMSTATE_PCI_DEVICE(dev, UHCIState),
         VMSTATE_UINT8_EQUAL(num_ports_vmstate, UHCIState),
commit 7dd0dfd7f744b35bcf7b3b0fb7601bd9e88c064f
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri May 11 12:57:34 2012 +0200

    uhci: fix trace format strings
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/trace-events b/trace-events
index 560e57b..dd057bc 100644
--- a/trace-events
+++ b/trace-events
@@ -266,10 +266,10 @@ usb_uhci_frame_start(uint32_t num) "nr %d"
 usb_uhci_frame_stop_bandwidth(void) ""
 usb_uhci_frame_loop_stop_idle(void) ""
 usb_uhci_frame_loop_continue(void) ""
-usb_uhci_mmio_readw(uint32_t addr, uint32_t val) "addr %04x, ret 0x04%x"
-usb_uhci_mmio_writew(uint32_t addr, uint32_t val) "addr %04x, val 0x04%x"
-usb_uhci_mmio_readl(uint32_t addr, uint32_t val) "addr %04x, ret 0x08%x"
-usb_uhci_mmio_writel(uint32_t addr, uint32_t val) "addr %04x, val 0x08%x"
+usb_uhci_mmio_readw(uint32_t addr, uint32_t val) "addr 0x%04x, ret 0x%04x"
+usb_uhci_mmio_writew(uint32_t addr, uint32_t val) "addr 0x%04x, val 0x%04x"
+usb_uhci_mmio_readl(uint32_t addr, uint32_t val) "addr 0x%04x, ret 0x%08x"
+usb_uhci_mmio_writel(uint32_t addr, uint32_t val) "addr 0x%04x, val 0x%08x"
 usb_uhci_queue_add(uint32_t token) "token 0x%x"
 usb_uhci_queue_del(uint32_t token) "token 0x%x"
 usb_uhci_packet_add(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x"
commit 40141d12de84b67528354ec88075f66f5afd0cc7
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri May 11 10:02:53 2012 +0200

    uhci: make bandwidth tunable
    
    Add a property for the uhci bandwidth.  Can be used to make uhci
    emulation run faster than real hardware.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 91bcc7e..2e7c8f9 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -133,6 +133,7 @@ struct UHCIState {
     QEMUTimer *frame_timer;
     QEMUBH *bh;
     uint32_t frame_bytes;
+    uint32_t frame_bandwidth;
     UHCIPort ports[NB_PORTS];
 
     /* Interrupts that should be raised at the end of the current frame.  */
@@ -908,7 +909,7 @@ static void uhci_async_complete(USBPort *port, USBPacket *packet)
         uhci_async_free(async);
     } else {
         async->done = 1;
-        if (s->frame_bytes < 1280) {
+        if (s->frame_bytes < s->frame_bandwidth) {
             qemu_bh_schedule(s->bh);
         }
     }
@@ -1007,7 +1008,7 @@ static void uhci_process_frame(UHCIState *s)
     qhdb_reset(&qhdb);
 
     for (cnt = FRAME_MAX_LOOPS; is_valid(link) && cnt; cnt--) {
-        if (s->frame_bytes >= 1280) {
+        if (s->frame_bytes >= s->frame_bandwidth) {
             /* We've reached the usb 1.1 bandwidth, which is
                1280 bytes/frame, stop processing */
             trace_usb_uhci_frame_stop_bandwidth();
@@ -1258,6 +1259,7 @@ static int usb_uhci_exit(PCIDevice *dev)
 static Property uhci_properties[] = {
     DEFINE_PROP_STRING("masterbus", UHCIState, masterbus),
     DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0),
+    DEFINE_PROP_UINT32("bandwidth", UHCIState, frame_bandwidth, 1280),
     DEFINE_PROP_END_OF_LIST(),
 };
 
commit 9a16c5950d9ce38671a1ac259dcde3e707767922
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri May 11 09:33:07 2012 +0200

    uhci: use bottom half
    
    Schedule bottom half on completion of async packets instead of calling
    uhci_process_frame directly.  This way we run uhci_process_frame only
    once in case multiple packets finish in a row.  Also check whenever
    there is bandwidth left before scheduling uhci_process_frame.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 48ad35c..91bcc7e 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -131,6 +131,7 @@ struct UHCIState {
     uint8_t status2; /* bit 0 and 1 are used to generate UHCI_STS_USBINT */
     int64_t expire_time;
     QEMUTimer *frame_timer;
+    QEMUBH *bh;
     uint32_t frame_bytes;
     UHCIPort ports[NB_PORTS];
 
@@ -370,6 +371,7 @@ static void uhci_reset(void *opaque)
     }
 
     uhci_async_cancel_all(s);
+    qemu_bh_cancel(s->bh);
     uhci_update_irq(s);
 }
 
@@ -906,7 +908,9 @@ static void uhci_async_complete(USBPort *port, USBPacket *packet)
         uhci_async_free(async);
     } else {
         async->done = 1;
-        uhci_process_frame(s);
+        if (s->frame_bytes < 1280) {
+            qemu_bh_schedule(s->bh);
+        }
     }
 }
 
@@ -1113,6 +1117,12 @@ out:
     s->pending_int_mask |= int_mask;
 }
 
+static void uhci_bh(void *opaque)
+{
+    UHCIState *s = opaque;
+    uhci_process_frame(s);
+}
+
 static void uhci_frame_timer(void *opaque)
 {
     UHCIState *s = opaque;
@@ -1120,6 +1130,7 @@ static void uhci_frame_timer(void *opaque)
     /* prepare the timer for the next frame */
     s->expire_time += (get_ticks_per_sec() / FRAME_TIMER_FREQ);
     s->frame_bytes = 0;
+    qemu_bh_cancel(s->bh);
 
     if (!(s->cmd & UHCI_CMD_RS)) {
         /* Full stop */
@@ -1206,6 +1217,7 @@ static int usb_uhci_common_initfn(PCIDevice *dev)
                               USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
         }
     }
+    s->bh = qemu_bh_new(uhci_bh, s);
     s->frame_timer = qemu_new_timer_ns(vm_clock, uhci_frame_timer, s);
     s->num_ports_vmstate = NB_PORTS;
     QTAILQ_INIT(&s->queues);
commit 4aed20e2d70f4353164399a173f20c3ab435b4eb
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri May 11 09:18:05 2012 +0200

    uhci: fix bandwidth management
    
    uhci_process_frame() can be invoked multiple times per frame, so
    accounting usb bandwith in a local variable doesn't fly, use a variable
    in UHCIState instead.  Also check the limit more frequently.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 9e211a0..48ad35c 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -131,6 +131,7 @@ struct UHCIState {
     uint8_t status2; /* bit 0 and 1 are used to generate UHCI_STS_USBINT */
     int64_t expire_time;
     QEMUTimer *frame_timer;
+    uint32_t frame_bytes;
     UHCIPort ports[NB_PORTS];
 
     /* Interrupts that should be raised at the end of the current frame.  */
@@ -985,7 +986,7 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td)
 static void uhci_process_frame(UHCIState *s)
 {
     uint32_t frame_addr, link, old_td_ctrl, val, int_mask;
-    uint32_t curr_qh, td_count = 0, bytes_count = 0;
+    uint32_t curr_qh, td_count = 0;
     int cnt, ret;
     UHCI_TD td;
     UHCI_QH qh;
@@ -1002,6 +1003,12 @@ static void uhci_process_frame(UHCIState *s)
     qhdb_reset(&qhdb);
 
     for (cnt = FRAME_MAX_LOOPS; is_valid(link) && cnt; cnt--) {
+        if (s->frame_bytes >= 1280) {
+            /* We've reached the usb 1.1 bandwidth, which is
+               1280 bytes/frame, stop processing */
+            trace_usb_uhci_frame_stop_bandwidth();
+            break;
+        }
         if (is_qh(link)) {
             /* QH */
             trace_usb_uhci_qh_load(link & ~0xf);
@@ -1011,18 +1018,12 @@ static void uhci_process_frame(UHCIState *s)
                  * We're going in circles. Which is not a bug because
                  * HCD is allowed to do that as part of the BW management.
                  *
-                 * Stop processing here if
-                 *  (a) no transaction has been done since we've been
-                 *      here last time, or
-                 *  (b) we've reached the usb 1.1 bandwidth, which is
-                 *      1280 bytes/frame.
+                 * Stop processing here if no transaction has been done
+                 * since we've been here last time.
                  */
                 if (td_count == 0) {
                     trace_usb_uhci_frame_loop_stop_idle();
                     break;
-                } else if (bytes_count >= 1280) {
-                    trace_usb_uhci_frame_loop_stop_bandwidth();
-                    break;
                 } else {
                     trace_usb_uhci_frame_loop_continue();
                     td_count = 0;
@@ -1085,7 +1086,7 @@ static void uhci_process_frame(UHCIState *s)
             trace_usb_uhci_td_complete(curr_qh & ~0xf, link & ~0xf);
             link = td.link;
             td_count++;
-            bytes_count += (td.ctrl & 0x7ff) + 1;
+            s->frame_bytes += (td.ctrl & 0x7ff) + 1;
 
             if (curr_qh) {
                 /* update QH element link */
@@ -1118,6 +1119,7 @@ static void uhci_frame_timer(void *opaque)
 
     /* prepare the timer for the next frame */
     s->expire_time += (get_ticks_per_sec() / FRAME_TIMER_FREQ);
+    s->frame_bytes = 0;
 
     if (!(s->cmd & UHCI_CMD_RS)) {
         /* Full stop */
diff --git a/trace-events b/trace-events
index 45c6bc1..560e57b 100644
--- a/trace-events
+++ b/trace-events
@@ -263,8 +263,8 @@ usb_uhci_reset(void) "=== RESET ==="
 usb_uhci_schedule_start(void) ""
 usb_uhci_schedule_stop(void) ""
 usb_uhci_frame_start(uint32_t num) "nr %d"
+usb_uhci_frame_stop_bandwidth(void) ""
 usb_uhci_frame_loop_stop_idle(void) ""
-usb_uhci_frame_loop_stop_bandwidth(void) ""
 usb_uhci_frame_loop_continue(void) ""
 usb_uhci_mmio_readw(uint32_t addr, uint32_t val) "addr %04x, ret 0x04%x"
 usb_uhci_mmio_writew(uint32_t addr, uint32_t val) "addr %04x, val 0x04%x"
commit 2dee8d54c62abb0a46578ad21cc25782b83e3773
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Jun 4 09:15:43 2012 +0200

    build: do not create directories at configure time
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/configure b/configure
index cbcbcb1..0ecb55f 100755
--- a/configure
+++ b/configure
@@ -3671,26 +3671,6 @@ if [ "$TARGET_BASE_ARCH" = "" ]; then
   TARGET_BASE_ARCH=$TARGET_ARCH
 fi
 
-mkdir -p $target_dir/fpu
-mkdir -p $target_dir/tcg
-mkdir -p $target_dir/9pfs
-mkdir -p $target_dir/hw
-mkdir -p $target_dir/hw/ide
-mkdir -p $target_dir/hw/usb
-mkdir -p $target_dir/hw/9pfs
-mkdir -p $target_dir/hw/kvm
-mkdir -p $target_dir/hw/$TARGET_ARCH
-mkdir -p $target_dir/hw/$TARGET_BASE_ARCH
-mkdir -p $target_dir/target-$TARGET_BASE_ARCH
-if test "$target_linux_user" = yes; then
-  mkdir -p $target_dir/linux-user
-fi
-if test "$target_bsd_user" = yes; then
-  mkdir -p $target_dir/bsd-user
-fi
-if test "$target" = "arm-linux-user" -o "$target" = "armeb-linux-user" -o "$target" = "arm-bsd-user" -o "$target" = "armeb-bsd-user" ; then
-  mkdir -p $target_dir/linux-user/arm/nwfpe
-fi
 symlink "$source_path/Makefile.target" "$target_dir/Makefile"
 
 
@@ -3955,12 +3935,9 @@ 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 tests/tcg/lm32"
-DIRS="$DIRS slirp audio block net pc-bios/optionrom"
-DIRS="$DIRS pc-bios/spapr-rtas"
+DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas"
 DIRS="$DIRS roms/seabios roms/vgabios"
-DIRS="$DIRS fsdev ui hw hw/usb"
-DIRS="$DIRS qapi qapi-generated"
-DIRS="$DIRS qga trace qom"
+DIRS="$DIRS qapi-generated"
 DIRS="$DIRS libcacard libcacard/libcacard libcacard/trace"
 FILES="Makefile tests/tcg/Makefile qdict-test-data.txt"
 FILES="$FILES tests/tcg/cris/Makefile tests/tcg/cris/.gdbinit"
@@ -3999,19 +3976,11 @@ done
 
 for hwlib in 32 64; do
   d=libhw$hwlib
-  mkdir -p $d
-  mkdir -p $d/hw
-  mkdir -p $d/hw/ide
-  mkdir -p $d/hw/usb
   symlink "$source_path/Makefile.hw" "$d/Makefile"
-  mkdir -p $d/hw/9pfs
   echo "QEMU_CFLAGS+=-DTARGET_PHYS_ADDR_BITS=$hwlib" > $d/config.mak
 done
 
 d=libuser
-mkdir -p $d
-mkdir -p $d/trace
-mkdir -p $d/qom
 symlink "$source_path/Makefile.user" "$d/Makefile"
 
 if test "$docs" = "yes" ; then
diff --git a/rules.mak b/rules.mak
index f65283c..4bc5e52 100644
--- a/rules.mak
+++ b/rules.mak
@@ -111,4 +111,5 @@ endef
 define unnest-vars
 $(call unnest-vars-1)
 $(foreach var,$(nested-vars),$(eval $(var) := $(filter-out %/, $($(var)))))
+$(shell mkdir -p $(sort $(foreach var,$(nested-vars),$(dir $($(var))))))
 endef
commit ec5b06d717bc49d8ad4dc5e9760e8f1f2a2a371c
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Jun 6 16:57:00 2012 +0800

    configure: ensure directory exists when creating symlink
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/configure b/configure
index cd5e8b3..cbcbcb1 100755
--- a/configure
+++ b/configure
@@ -42,6 +42,7 @@ compile_prog() {
 # symbolically link $1 to $2.  Portable version of "ln -sf".
 symlink() {
   rm -rf "$2"
+  mkdir -p "$(dirname "$2")"
   ln -s "$1" "$2"
 }
 
@@ -3454,14 +3455,12 @@ if test -f ${config_host_ld}~ ; then
 fi
 
 for d in libdis libdis-user; do
-    mkdir -p $d
     symlink "$source_path/Makefile.dis" "$d/Makefile"
     echo > $d/config.mak
 done
 
 # use included Linux headers
 if test "$linux" = "yes" ; then
-  mkdir -p linux-headers
   case "$cpu" in
   i386|x86_64)
     symlink "$source_path/linux-headers/asm-x86" linux-headers/asm
commit 25f27a4f7160d077d6992e811021b4bc3a82abc1
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue May 29 16:32:10 2012 +0200

    build: compile oslib-obj-y once
    
    There is no difference in oslib-obj-y between user-mode and system
    targets.  There used to be when user-mode could optionally be
    compiled with PIE.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index 74110dd..8e72f09 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -22,6 +22,8 @@ oslib-obj-y = osdep.o
 oslib-obj-$(CONFIG_WIN32) += oslib-win32.o qemu-thread-win32.o
 oslib-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o
 
+universal-obj-y += $(oslib-obj-y)
+
 #######################################################################
 # coroutines
 coroutine-obj-y = qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o
@@ -62,7 +64,6 @@ common-obj-y = $(block-obj-y) blockdev.o
 common-obj-y += net.o net/
 common-obj-y += qom/
 common-obj-y += readline.o console.o cursor.o
-common-obj-y += $(oslib-obj-y)
 common-obj-$(CONFIG_WIN32) += os-win32.o
 common-obj-$(CONFIG_POSIX) += os-posix.o
 
diff --git a/Makefile.target b/Makefile.target
index 2907aad..2912307 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -96,7 +96,7 @@ ifdef CONFIG_LINUX_USER
 QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) -I$(SRC_PATH)/linux-user
 
 obj-y += linux-user/
-obj-y += gdbstub.o thunk.o user-exec.o $(oslib-obj-y)
+obj-y += gdbstub.o thunk.o user-exec.o
 
 endif #CONFIG_LINUX_USER
 
commit fec90ff0bd522a65beb330ab5ca45a40b2f14f10
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue May 29 11:49:50 2012 +0200

    build: limit usage of vpath
    
    All paths are now explicitly given, and the object tree mimics
    the source tree, so there is no need to apply special vpaths.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile b/Makefile
index 1d34b95..32550cb 100644
--- a/Makefile
+++ b/Makefile
@@ -33,7 +33,7 @@ configure: ;
 .PHONY: all clean cscope distclean dvi html info install install-doc \
 	pdf recurse-all speed tar tarbin test build-all
 
-$(call set-vpath, $(SRC_PATH):$(SRC_PATH)/hw)
+$(call set-vpath, $(SRC_PATH))
 
 LIBS+=-lz $(LIBS_TOOLS)
 
diff --git a/Makefile.target b/Makefile.target
index 555894d..2907aad 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -8,12 +8,11 @@ ifneq ($(HWDIR),)
 include $(HWDIR)/config.mak
 endif
 
-TARGET_PATH=$(SRC_PATH)/target-$(TARGET_BASE_ARCH)
-$(call set-vpath, $(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw)
+$(call set-vpath, $(SRC_PATH))
 ifdef CONFIG_LINUX
 QEMU_CFLAGS += -I../linux-headers
 endif
-QEMU_CFLAGS += -I.. -I$(TARGET_PATH) -DNEED_CPU_H
+QEMU_CFLAGS += -I.. -I$(SRC_PATH)/target-$(TARGET_BASE_ARCH) -DNEED_CPU_H
 
 QEMU_CFLAGS+=-I$(SRC_PATH)/include
 
commit 00c705fb92bc6e69e955aeac3614e05ca02feacd
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue May 29 11:40:24 2012 +0200

    build: libcacard Makefile cleanups
    
    Build vscclient from toplevel Makefile, limit usage of vpath.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile b/Makefile
index a10005a..1d34b95 100644
--- a/Makefile
+++ b/Makefile
@@ -147,6 +147,10 @@ libcacard.la: $(oslib-obj-y) qemu-timer-common.o $(addsuffix .lo, $(basename $(t
 install-libcacard: libcacard.la
 	$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C libcacard V="$(V)" TARGET_DIR="$*/" install-libcacard,)
 endif
+
+vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) qemu-timer-common.o libcacard/vscclient.o
+	$(call quiet-command,$(CC) -o $@ $^ $(libcacard_libs) $(LIBS),"  LINK  $@")
+
 ######################################################################
 
 qemu-img.o: qemu-img-cmds.h
diff --git a/Makefile.objs b/Makefile.objs
index ae3770a..74110dd 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -198,7 +198,13 @@ $(trace-obj-y): $(GENERATED_HEADERS)
 ######################################################################
 # smartcard
 
-libcacard-y = cac.o event.o vcard.o vreader.o vcard_emul_nss.o vcard_emul_type.o card_7816.o
+libcacard-y += libcacard/cac.o libcacard/event.o
+libcacard-y += libcacard/vcard.o libcacard/vreader.o
+libcacard-y += libcacard/vcard_emul_nss.o
+libcacard-y += libcacard/vcard_emul_type.o
+libcacard-y += libcacard/card_7816.o
+
+common-obj-$(CONFIG_SMARTCARD_NSS) += $(libcacard-y)
 
 ######################################################################
 # qapi
diff --git a/Makefile.target b/Makefile.target
index 3dfdf92..555894d 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -164,16 +164,10 @@ all-obj-y = $(obj-y)
 all-obj-y += $(addprefix ../, $(universal-obj-y))
 
 ifdef CONFIG_SOFTMMU
-
 all-obj-y += $(addprefix ../, $(common-obj-y))
 all-obj-y += $(addprefix ../libdis/, $(libdis-y))
 all-obj-y += $(addprefix $(HWDIR)/, $(hw-obj-y))
 all-obj-y += $(addprefix ../, $(trace-obj-y))
-
-# libcacard needs qemu-thread support, and besides is only needed by devices
-# so not requires with linux-user / bsd-user targets
-all-obj-$(CONFIG_SMARTCARD_NSS) += $(addprefix ../libcacard/, $(libcacard-y))
-
 else
 all-obj-y += $(addprefix ../libuser/, $(user-obj-y))
 all-obj-y += $(addprefix ../libdis-user/, $(libdis-y))
diff --git a/configure b/configure
index e50ad0b..cd5e8b3 100755
--- a/configure
+++ b/configure
@@ -2927,6 +2927,9 @@ if test "$softmmu" = yes ; then
     fi
   fi
 fi
+if test "$smartcard_nss" = "yes" ; then
+  tools="vscclient\$(EXESUF) $tools"
+fi
 
 # Mac OS X ships with a broken assembler
 roms=
@@ -3959,9 +3962,10 @@ DIRS="$DIRS roms/seabios roms/vgabios"
 DIRS="$DIRS fsdev ui hw hw/usb"
 DIRS="$DIRS qapi qapi-generated"
 DIRS="$DIRS qga trace qom"
+DIRS="$DIRS libcacard libcacard/libcacard libcacard/trace"
 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 tests/tcg/lm32/Makefile libcacard/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"
@@ -4005,12 +4009,6 @@ for hwlib in 32 64; do
   echo "QEMU_CFLAGS+=-DTARGET_PHYS_ADDR_BITS=$hwlib" > $d/config.mak
 done
 
-if [ "$source_path" != `pwd` ]; then
-    # out of tree build
-    mkdir -p libcacard
-    symlink "$source_path/libcacard/Makefile" libcacard/Makefile
-fi
-
 d=libuser
 mkdir -p $d
 mkdir -p $d/trace
diff --git a/libcacard/Makefile b/libcacard/Makefile
index c6a896a..fdc2873 100644
--- a/libcacard/Makefile
+++ b/libcacard/Makefile
@@ -2,29 +2,23 @@
 -include $(SRC_PATH)/Makefile.objs
 -include $(SRC_PATH)/rules.mak
 
-libcacard_srcpath=$(SRC_PATH)/libcacard
 libcacard_includedir=$(includedir)/cacard
 
-$(call set-vpath, $(SRC_PATH):$(libcacard_srcpath))
-
-# objects linked against normal qemu binaries, not compiled with libtool
-QEMU_OBJS=$(addprefix ../,$(oslib-obj-y) qemu-timer-common.o $(trace-obj-y))
+$(call set-vpath, $(SRC_PATH))
 
 # objects linked into a shared library, built with libtool with -fPIC if required
-QEMU_OBJS_LIB=$(addsuffix .lo,$(basename $(QEMU_OBJS)))
+QEMU_OBJS=$(oslib-obj-y) qemu-timer-common.o $(trace-obj-y)
+QEMU_OBJS_LIB=$(patsubst %.o,%.lo,$(QEMU_OBJS))
 
 QEMU_CFLAGS+=-I../
 
-libcacard.lib-y=$(addsuffix .lo,$(basename $(libcacard-y)))
-
-vscclient: $(libcacard-y) $(QEMU_OBJS) vscclient.o
-	$(call quiet-command,$(CC) -o $@ $^ $(libcacard_libs) $(LIBS),"  LINK  $@")
+libcacard.lib-y=$(patsubst %.o,%.lo,$(libcacard-y))
 
 clean:
 	rm -f *.o */*.o *.d */*.d *.a */*.a *~ */*~ vscclient *.lo .libs/* *.la *.pc
 	rm -Rf .libs
 
-all: vscclient
+all: libcacard.la libcacard.pc
 # Dummy command so that make thinks it has done something
 	@true
 
@@ -41,6 +35,7 @@ else
 libcacard.la: $(libcacard.lib-y) $(QEMU_OBJS_LIB)
 	$(call quiet-command,$(LIBTOOL) --mode=link --quiet --tag=CC $(CC) -rpath $(libdir) -o $@ $^ $(libcacard_libs),"  lt LINK $@")
 
+libcacard_srcpath=$(SRC_PATH)/libcacard
 libcacard.pc: $(libcacard_srcpath)/libcacard.pc.in
 	sed -e 's|@LIBDIR@|$(libdir)|' \
 		-e 's|@INCLUDEDIR@|$(libcacard_includedir)|' \
commit 49ac9e0a8cfb737d6da9c0b056c062e3dec0ba45
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue May 29 17:50:03 2012 +0200

    build: move device tree to per-target Makefile.objs
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.target b/Makefile.target
index 5635043..3dfdf92 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -149,13 +149,6 @@ else
 obj-y += hw/$(TARGET_BASE_ARCH)/
 endif
 
-# Device tree
-ifeq ($(CONFIG_FDT), y)
-obj-$(TARGET_ARM) += device_tree.o
-obj-$(TARGET_MICROBLAZE) += device_tree.o
-obj-$(TARGET_PPC) += device_tree.o
-endif
-
 main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
 
 GENERATED_HEADERS += hmp-commands.h qmp-commands-old.h
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 92b4f1e..a0ff6a6 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -35,5 +35,6 @@ obj-y += vexpress.o
 obj-y += strongarm.o
 obj-y += collie.o
 obj-y += pl041.o lm4549.o
+obj-$(CONFIG_FDT) += ../device_tree.o
 
 obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/microblaze/Makefile.objs b/hw/microblaze/Makefile.objs
index 4172442..020f7b6 100644
--- a/hw/microblaze/Makefile.objs
+++ b/hw/microblaze/Makefile.objs
@@ -9,5 +9,6 @@ obj-y += xilinx_uartlite.o
 obj-y += xilinx_ethlite.o
 obj-y += xilinx_axidma.o
 obj-y += xilinx_axienet.o
+obj-$(CONFIG_FDT) += ../device_tree.o
 
 obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index 5b09849..842e7b9 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -21,6 +21,7 @@ obj-y += virtex_ml507.o
 obj-$(CONFIG_KVM) += kvm_ppc.o
 # PowerPC OpenPIC
 obj-y += openpic.o
+obj-$(CONFIG_FDT) += ../device_tree.o
 
 # Xilinx PPC peripherals
 obj-y += xilinx_intc.o
commit c353f261946ddbd814b333ae2440712b486977fd
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue May 29 11:49:34 2012 +0200

    build: move per-target hw/ objects to nested Makefile.objs
    
    This completes the move to nested Makefiles for virtio and a few
    other files that were not part of obj-TARGET-y, but still were
    compiled separately for each target.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.hw b/Makefile.hw
index 155a0c3..2bcbaff 100644
--- a/Makefile.hw
+++ b/Makefile.hw
@@ -19,7 +19,8 @@ all: $(hw-obj-y)
 	@true
 
 clean:
-	rm -f *.o */*.o *.d */*.d *.a */*.a *~ */*~ */*/*.d
+	rm -f $(addsuffix /*.o, $(dir $(sort $(hw-obj-y))))
+	rm -f $(addsuffix /*.d, $(dir $(sort $(hw-obj-y))))
 
 # Include automatically generated dependency files
--include $(wildcard *.d */*.d */*/*.d)
+-include $(patsubst %.o, %.d, $(hw-obj-y))
diff --git a/Makefile.target b/Makefile.target
index f1d5fe2..5635043 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -1,11 +1,5 @@
 # -*- Mode: makefile -*-
 
-CONFIG_NO_PCI = $(if $(subst n,,$(CONFIG_PCI)),n,y)
-CONFIG_NO_KVM = $(if $(subst n,,$(CONFIG_KVM)),n,y)
-CONFIG_NO_XEN = $(if $(subst n,,$(CONFIG_XEN)),n,y)
-CONFIG_NO_GET_MEMORY_MAPPING = $(if $(subst n,,$(CONFIG_HAVE_GET_MEMORY_MAPPING)),n,y)
-CONFIG_NO_CORE_DUMP = $(if $(subst n,,$(CONFIG_HAVE_CORE_DUMP)),n,y)
-
 include ../config-host.mak
 include config-devices.mak
 include config-target.mak
@@ -122,19 +116,16 @@ endif #CONFIG_BSD_USER
 #########################################################
 # System emulator target
 ifdef CONFIG_SOFTMMU
+CONFIG_NO_PCI = $(if $(subst n,,$(CONFIG_PCI)),n,y)
+CONFIG_NO_KVM = $(if $(subst n,,$(CONFIG_KVM)),n,y)
+CONFIG_NO_XEN = $(if $(subst n,,$(CONFIG_XEN)),n,y)
+CONFIG_NO_GET_MEMORY_MAPPING = $(if $(subst n,,$(CONFIG_HAVE_GET_MEMORY_MAPPING)),n,y)
+CONFIG_NO_CORE_DUMP = $(if $(subst n,,$(CONFIG_HAVE_CORE_DUMP)),n,y)
 
 obj-y += arch_init.o cpus.o monitor.o gdbstub.o balloon.o ioport.o
-# virtio has to be here due to weird dependency between PCI and virtio-net.
-# need to fix this properly
-obj-$(CONFIG_NO_PCI) += pci-stub.o
-obj-$(CONFIG_VIRTIO) += virtio.o virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
-obj-$(CONFIG_VIRTIO) += virtio-scsi.o
-obj-y += vhost_net.o
-obj-$(CONFIG_VHOST_NET) += vhost.o
-obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o
+obj-y += hw/
 obj-$(CONFIG_KVM) += kvm-all.o
 obj-$(CONFIG_NO_KVM) += kvm-stub.o
-obj-$(CONFIG_VGA) += vga.o
 obj-y += memory.o savevm.o cputlb.o
 obj-$(CONFIG_HAVE_GET_MEMORY_MAPPING) += memory_mapping.o
 obj-$(CONFIG_HAVE_CORE_DUMP) += dump.o
@@ -148,21 +139,9 @@ QEMU_CFLAGS += $(VNC_JPEG_CFLAGS)
 QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
 
 # xen support
-obj-$(CONFIG_XEN) += xen-all.o xen_machine_pv.o xen_domainbuild.o xen-mapcache.o
+obj-$(CONFIG_XEN) += xen-all.o xen-mapcache.o
 obj-$(CONFIG_NO_XEN) += xen-stub.o
 
-# Inter-VM PCI shared memory
-CONFIG_IVSHMEM =
-ifeq ($(CONFIG_KVM), y)
-  ifeq ($(CONFIG_PCI), y)
-    CONFIG_IVSHMEM = y
-  endif
-endif
-obj-$(CONFIG_IVSHMEM) += ivshmem.o
-
-# Generic hotplugging
-obj-y += device-hotplug.o
-
 # Hardware support
 ifeq ($(TARGET_ARCH), sparc64)
 obj-y += hw/sparc64/
diff --git a/configure b/configure
index 785e3f8..e50ad0b 100755
--- a/configure
+++ b/configure
@@ -3675,6 +3675,7 @@ mkdir -p $target_dir/9pfs
 mkdir -p $target_dir/hw
 mkdir -p $target_dir/hw/ide
 mkdir -p $target_dir/hw/usb
+mkdir -p $target_dir/hw/9pfs
 mkdir -p $target_dir/hw/kvm
 mkdir -p $target_dir/hw/$TARGET_ARCH
 mkdir -p $target_dir/hw/$TARGET_BASE_ARCH
diff --git a/hw/9pfs/Makefile.objs b/hw/9pfs/Makefile.objs
index 2700772..972df24 100644
--- a/hw/9pfs/Makefile.objs
+++ b/hw/9pfs/Makefile.objs
@@ -5,3 +5,5 @@ hw-obj-y += virtio-9p-coth.o cofs.o codir.o cofile.o
 hw-obj-y += coxattr.o virtio-9p-synth.o
 hw-obj-$(CONFIG_OPEN_BY_HANDLE) +=  virtio-9p-handle.o
 hw-obj-y += virtio-9p-proxy.o
+
+obj-y += virtio-9p-device.o
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 08dde63..7e17504 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -145,3 +145,21 @@ common-obj-$(CONFIG_BRLAPI) += baum.o
 # xen backend driver support
 common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o
 common-obj-$(CONFIG_XEN_BACKEND) += xen_console.o xenfb.o xen_disk.o xen_nic.o
+
+# Per-target files
+# virtio has to be here due to weird dependency between PCI and virtio-net.
+# need to fix this properly
+obj-$(CONFIG_VIRTIO) += virtio.o virtio-blk.o virtio-balloon.o virtio-net.o
+obj-$(CONFIG_VIRTIO) += virtio-serial-bus.o virtio-scsi.o
+obj-$(CONFIG_SOFTMMU) += vhost_net.o
+obj-$(CONFIG_VHOST_NET) += vhost.o
+obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/
+obj-$(CONFIG_NO_PCI) += pci-stub.o
+obj-$(CONFIG_VGA) += vga.o
+obj-$(CONFIG_SOFTMMU) += device-hotplug.o
+obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o
+
+# Inter-VM PCI shared memory
+ifeq ($(CONFIG_PCI), y)
+obj-$(CONFIG_KVM) += ivshmem.o
+endif
commit be1029ec30d2eee9e0eb56190d1ed2ed9a400bdf
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue May 29 11:10:55 2012 +0200

    build: convert libhw to nested Makefile.objs
    
    After this patch, the libhw* directories will have a hierarchy
    that mimics the source tree.  This is useful because we do have
    a couple of files there that are in the top source directory.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.hw b/Makefile.hw
index 33f1ab0..155a0c3 100644
--- a/Makefile.hw
+++ b/Makefile.hw
@@ -7,7 +7,7 @@ include $(SRC_PATH)/rules.mak
 
 .PHONY: all
 
-$(call set-vpath, $(SRC_PATH):$(SRC_PATH)/hw)
+$(call set-vpath, $(SRC_PATH))
 
 QEMU_CFLAGS+=-I..
 QEMU_CFLAGS += -I$(SRC_PATH)/include
@@ -19,7 +19,7 @@ all: $(hw-obj-y)
 	@true
 
 clean:
-	rm -f *.o */*.o *.d */*.d *.a */*.a *~ */*~
+	rm -f *.o */*.o *.d */*.d *.a */*.a *~ */*~ */*/*.d
 
 # Include automatically generated dependency files
--include $(wildcard *.d */*.d)
+-include $(wildcard *.d */*.d */*/*.d)
diff --git a/Makefile.objs b/Makefile.objs
index 4aa5f0f..ae3770a 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -109,147 +109,7 @@ user-obj-y += qom/
 ######################################################################
 # libhw
 
-hw-obj-y =
-hw-obj-y += vl.o loader.o
-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 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
-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
-hw-obj-$(CONFIG_ISA_MMIO) += isa_mmio.o
-hw-obj-$(CONFIG_ECC) += ecc.o
-hw-obj-$(CONFIG_NAND) += nand.o
-hw-obj-$(CONFIG_PFLASH_CFI01) += pflash_cfi01.o
-hw-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o
-
-hw-obj-$(CONFIG_M48T59) += m48t59.o
-hw-obj-$(CONFIG_ESCC) += escc.o
-hw-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o
-
-hw-obj-$(CONFIG_SERIAL) += serial.o
-hw-obj-$(CONFIG_PARALLEL) += parallel.o
-hw-obj-$(CONFIG_I8254) += i8254_common.o i8254.o
-hw-obj-$(CONFIG_PCSPK) += pcspk.o
-hw-obj-$(CONFIG_PCKBD) += pckbd.o
-hw-obj-$(CONFIG_USB_UHCI) += usb/hcd-uhci.o
-hw-obj-$(CONFIG_USB_OHCI) += usb/hcd-ohci.o
-hw-obj-$(CONFIG_USB_EHCI) += usb/hcd-ehci.o
-hw-obj-$(CONFIG_USB_XHCI) += usb/hcd-xhci.o
-hw-obj-$(CONFIG_FDC) += fdc.o
-hw-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o
-hw-obj-$(CONFIG_APM) += pm_smbus.o apm.o
-hw-obj-$(CONFIG_DMA) += dma.o
-hw-obj-$(CONFIG_I82374) += i82374.o
-hw-obj-$(CONFIG_HPET) += hpet.o
-hw-obj-$(CONFIG_APPLESMC) += applesmc.o
-hw-obj-$(CONFIG_SMARTCARD) += usb/dev-smartcard-reader.o ccid-card-passthru.o
-hw-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
-hw-obj-$(CONFIG_USB_REDIR) += usb/redirect.o
-hw-obj-$(CONFIG_I8259) += i8259_common.o i8259.o
-
-# PPC devices
-hw-obj-$(CONFIG_PREP_PCI) += prep_pci.o
-hw-obj-$(CONFIG_I82378) += i82378.o
-# Mac shared devices
-hw-obj-$(CONFIG_MACIO) += macio.o
-hw-obj-$(CONFIG_CUDA) += cuda.o
-hw-obj-$(CONFIG_ADB) += adb.o
-hw-obj-$(CONFIG_MAC_NVRAM) += mac_nvram.o
-hw-obj-$(CONFIG_MAC_DBDMA) += mac_dbdma.o
-# OldWorld PowerMac
-hw-obj-$(CONFIG_HEATHROW_PIC) += heathrow_pic.o
-hw-obj-$(CONFIG_GRACKLE_PCI) += grackle_pci.o
-# NewWorld PowerMac
-hw-obj-$(CONFIG_UNIN_PCI) += unin_pci.o
-hw-obj-$(CONFIG_DEC_PCI) += dec_pci.o
-# PowerPC E500 boards
-hw-obj-$(CONFIG_PPCE500_PCI) += ppce500_pci.o
-
-# MIPS devices
-hw-obj-$(CONFIG_PIIX4) += piix4.o
-hw-obj-$(CONFIG_G364FB) += g364fb.o
-hw-obj-$(CONFIG_JAZZ_LED) += jazz_led.o
-
-# PCI watchdog devices
-hw-obj-$(CONFIG_PCI) += wdt_i6300esb.o
-
-hw-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o pcie_port.o
-
-# PCI network cards
-hw-obj-$(CONFIG_NE2000_PCI) += ne2000.o
-hw-obj-$(CONFIG_EEPRO100_PCI) += eepro100.o
-hw-obj-$(CONFIG_PCNET_PCI) += pcnet-pci.o
-hw-obj-$(CONFIG_PCNET_COMMON) += pcnet.o
-hw-obj-$(CONFIG_E1000_PCI) += e1000.o
-hw-obj-$(CONFIG_RTL8139_PCI) += rtl8139.o
-
-hw-obj-$(CONFIG_SMC91C111) += smc91c111.o
-hw-obj-$(CONFIG_LAN9118) += lan9118.o
-hw-obj-$(CONFIG_NE2000_ISA) += ne2000-isa.o
-hw-obj-$(CONFIG_OPENCORES_ETH) += opencores_eth.o
-
-# IDE
-hw-obj-$(CONFIG_IDE_CORE) += ide/core.o ide/atapi.o
-hw-obj-$(CONFIG_IDE_QDEV) += ide/qdev.o
-hw-obj-$(CONFIG_IDE_PCI) += ide/pci.o
-hw-obj-$(CONFIG_IDE_ISA) += ide/isa.o
-hw-obj-$(CONFIG_IDE_PIIX) += ide/piix.o
-hw-obj-$(CONFIG_IDE_CMD646) += ide/cmd646.o
-hw-obj-$(CONFIG_IDE_MACIO) += ide/macio.o
-hw-obj-$(CONFIG_IDE_VIA) += ide/via.o
-hw-obj-$(CONFIG_AHCI) += ide/ahci.o
-hw-obj-$(CONFIG_AHCI) += ide/ich.o
-
-# SCSI layer
-hw-obj-$(CONFIG_LSI_SCSI_PCI) += lsi53c895a.o
-hw-obj-$(CONFIG_ESP) += esp.o
-
-hw-obj-y += dma-helpers.o sysbus.o isa-bus.o
-hw-obj-y += qdev-addr.o
-
-# VGA
-hw-obj-$(CONFIG_VGA_PCI) += vga-pci.o
-hw-obj-$(CONFIG_VGA_ISA) += vga-isa.o
-hw-obj-$(CONFIG_VGA_ISA_MM) += vga-isa-mm.o
-hw-obj-$(CONFIG_VMWARE_VGA) += vmware_vga.o
-hw-obj-$(CONFIG_VMMOUSE) += vmmouse.o
-hw-obj-$(CONFIG_VGA_CIRRUS) += cirrus_vga.o
-
-hw-obj-$(CONFIG_RC4030) += rc4030.o
-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
-sound-obj-$(CONFIG_ES1370) += es1370.o
-sound-obj-$(CONFIG_AC97) += ac97.o
-sound-obj-$(CONFIG_ADLIB) += fmopl.o adlib.o
-sound-obj-$(CONFIG_GUS) += gus.o gusemu_hal.o gusemu_mixer.o
-sound-obj-$(CONFIG_CS4231A) += cs4231a.o
-sound-obj-$(CONFIG_HDA) += intel-hda.o hda-audio.o
-
-adlib.o fmopl.o: QEMU_CFLAGS += -DBUILD_Y8950=0
-hw-obj-$(CONFIG_SOUND) += $(sound-obj-y)
-
-9pfs-nested-$(CONFIG_VIRTFS)  = virtio-9p.o
-9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-local.o virtio-9p-xattr.o
-9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o
-9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-coth.o cofs.o codir.o cofile.o
-9pfs-nested-$(CONFIG_VIRTFS) += coxattr.o virtio-9p-synth.o
-9pfs-nested-$(CONFIG_OPEN_BY_HANDLE) +=  virtio-9p-handle.o
-9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-proxy.o
-
-hw-obj-$(CONFIG_REALLY_VIRTFS) += $(addprefix 9pfs/, $(9pfs-nested-y))
+hw-obj-y = vl.o dma-helpers.o qtest.o hw/
 
 ######################################################################
 # libdis
@@ -364,6 +224,7 @@ vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
 QEMU_CFLAGS+=$(GLIB_CFLAGS)
 
 nested-vars += \
+	hw-obj-y \
 	qga-obj-y \
 	block-obj-y \
 	qom-obj-y \
diff --git a/configure b/configure
index b22ff10..785e3f8 100755
--- a/configure
+++ b/configure
@@ -3996,10 +3996,11 @@ done
 for hwlib in 32 64; do
   d=libhw$hwlib
   mkdir -p $d
-  mkdir -p $d/ide
-  mkdir -p $d/usb
+  mkdir -p $d/hw
+  mkdir -p $d/hw/ide
+  mkdir -p $d/hw/usb
   symlink "$source_path/Makefile.hw" "$d/Makefile"
-  mkdir -p $d/9pfs
+  mkdir -p $d/hw/9pfs
   echo "QEMU_CFLAGS+=-DTARGET_PHYS_ADDR_BITS=$hwlib" > $d/config.mak
 done
 
diff --git a/hw/9pfs/Makefile.objs b/hw/9pfs/Makefile.objs
new file mode 100644
index 0000000..2700772
--- /dev/null
+++ b/hw/9pfs/Makefile.objs
@@ -0,0 +1,7 @@
+hw-obj-y  = virtio-9p.o
+hw-obj-y += virtio-9p-local.o virtio-9p-xattr.o
+hw-obj-y += virtio-9p-xattr-user.o virtio-9p-posix-acl.o
+hw-obj-y += virtio-9p-coth.o cofs.o codir.o cofile.o
+hw-obj-y += coxattr.o virtio-9p-synth.o
+hw-obj-$(CONFIG_OPEN_BY_HANDLE) +=  virtio-9p-handle.o
+hw-obj-y += virtio-9p-proxy.o
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 00642f3..08dde63 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -1,3 +1,118 @@
+hw-obj-y = usb/ ide/
+hw-obj-y += loader.o
+hw-obj-$(CONFIG_VIRTIO) += virtio-console.o
+hw-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
+hw-obj-y += fw_cfg.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
+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
+hw-obj-$(CONFIG_ISA_MMIO) += isa_mmio.o
+hw-obj-$(CONFIG_ECC) += ecc.o
+hw-obj-$(CONFIG_NAND) += nand.o
+hw-obj-$(CONFIG_PFLASH_CFI01) += pflash_cfi01.o
+hw-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o
+
+hw-obj-$(CONFIG_M48T59) += m48t59.o
+hw-obj-$(CONFIG_ESCC) += escc.o
+hw-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o
+
+hw-obj-$(CONFIG_SERIAL) += serial.o
+hw-obj-$(CONFIG_PARALLEL) += parallel.o
+hw-obj-$(CONFIG_I8254) += i8254_common.o i8254.o
+hw-obj-$(CONFIG_PCSPK) += pcspk.o
+hw-obj-$(CONFIG_PCKBD) += pckbd.o
+hw-obj-$(CONFIG_FDC) += fdc.o
+hw-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o
+hw-obj-$(CONFIG_APM) += pm_smbus.o apm.o
+hw-obj-$(CONFIG_DMA) += dma.o
+hw-obj-$(CONFIG_I82374) += i82374.o
+hw-obj-$(CONFIG_HPET) += hpet.o
+hw-obj-$(CONFIG_APPLESMC) += applesmc.o
+hw-obj-$(CONFIG_SMARTCARD) += ccid-card-passthru.o
+hw-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
+hw-obj-$(CONFIG_I8259) += i8259_common.o i8259.o
+
+# PPC devices
+hw-obj-$(CONFIG_PREP_PCI) += prep_pci.o
+hw-obj-$(CONFIG_I82378) += i82378.o
+# Mac shared devices
+hw-obj-$(CONFIG_MACIO) += macio.o
+hw-obj-$(CONFIG_CUDA) += cuda.o
+hw-obj-$(CONFIG_ADB) += adb.o
+hw-obj-$(CONFIG_MAC_NVRAM) += mac_nvram.o
+hw-obj-$(CONFIG_MAC_DBDMA) += mac_dbdma.o
+# OldWorld PowerMac
+hw-obj-$(CONFIG_HEATHROW_PIC) += heathrow_pic.o
+hw-obj-$(CONFIG_GRACKLE_PCI) += grackle_pci.o
+# NewWorld PowerMac
+hw-obj-$(CONFIG_UNIN_PCI) += unin_pci.o
+hw-obj-$(CONFIG_DEC_PCI) += dec_pci.o
+# PowerPC E500 boards
+hw-obj-$(CONFIG_PPCE500_PCI) += ppce500_pci.o
+
+# MIPS devices
+hw-obj-$(CONFIG_PIIX4) += piix4.o
+hw-obj-$(CONFIG_G364FB) += g364fb.o
+hw-obj-$(CONFIG_JAZZ_LED) += jazz_led.o
+
+# PCI watchdog devices
+hw-obj-$(CONFIG_PCI) += wdt_i6300esb.o
+
+hw-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o pcie_port.o
+
+# PCI network cards
+hw-obj-$(CONFIG_NE2000_PCI) += ne2000.o
+hw-obj-$(CONFIG_EEPRO100_PCI) += eepro100.o
+hw-obj-$(CONFIG_PCNET_PCI) += pcnet-pci.o
+hw-obj-$(CONFIG_PCNET_COMMON) += pcnet.o
+hw-obj-$(CONFIG_E1000_PCI) += e1000.o
+hw-obj-$(CONFIG_RTL8139_PCI) += rtl8139.o
+
+hw-obj-$(CONFIG_SMC91C111) += smc91c111.o
+hw-obj-$(CONFIG_LAN9118) += lan9118.o
+hw-obj-$(CONFIG_NE2000_ISA) += ne2000-isa.o
+hw-obj-$(CONFIG_OPENCORES_ETH) += opencores_eth.o
+
+# SCSI layer
+hw-obj-$(CONFIG_LSI_SCSI_PCI) += lsi53c895a.o
+hw-obj-$(CONFIG_ESP) += esp.o
+
+hw-obj-y += sysbus.o isa-bus.o
+hw-obj-y += qdev-addr.o
+
+# VGA
+hw-obj-$(CONFIG_VGA_PCI) += vga-pci.o
+hw-obj-$(CONFIG_VGA_ISA) += vga-isa.o
+hw-obj-$(CONFIG_VGA_ISA_MM) += vga-isa-mm.o
+hw-obj-$(CONFIG_VMWARE_VGA) += vmware_vga.o
+hw-obj-$(CONFIG_VMMOUSE) += vmmouse.o
+hw-obj-$(CONFIG_VGA_CIRRUS) += cirrus_vga.o
+
+hw-obj-$(CONFIG_RC4030) += rc4030.o
+hw-obj-$(CONFIG_DP8393X) += dp8393x.o
+hw-obj-$(CONFIG_DS1225Y) += ds1225y.o
+hw-obj-$(CONFIG_MIPSNET) += mipsnet.o
+
+# Sound
+sound-obj-y =
+sound-obj-$(CONFIG_SB16) += sb16.o
+sound-obj-$(CONFIG_ES1370) += es1370.o
+sound-obj-$(CONFIG_AC97) += ac97.o
+sound-obj-$(CONFIG_ADLIB) += fmopl.o adlib.o
+sound-obj-$(CONFIG_GUS) += gus.o gusemu_hal.o gusemu_mixer.o
+sound-obj-$(CONFIG_CS4231A) += cs4231a.o
+sound-obj-$(CONFIG_HDA) += intel-hda.o hda-audio.o
+
+$(obj)/adlib.o $(obj)/fmopl.o: QEMU_CFLAGS += -DBUILD_Y8950=0
+
+hw-obj-$(CONFIG_SOUND) += $(sound-obj-y)
+
+hw-obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/
+
 common-obj-y += usb/
 common-obj-y += irq.o
 common-obj-$(CONFIG_PTIMER) += ptimer.o
diff --git a/hw/ide/Makefile.objs b/hw/ide/Makefile.objs
new file mode 100644
index 0000000..cf718dd
--- /dev/null
+++ b/hw/ide/Makefile.objs
@@ -0,0 +1,10 @@
+hw-obj-$(CONFIG_IDE_CORE) += core.o atapi.o
+hw-obj-$(CONFIG_IDE_QDEV) += qdev.o
+hw-obj-$(CONFIG_IDE_PCI) += pci.o
+hw-obj-$(CONFIG_IDE_ISA) += isa.o
+hw-obj-$(CONFIG_IDE_PIIX) += piix.o
+hw-obj-$(CONFIG_IDE_CMD646) += cmd646.o
+hw-obj-$(CONFIG_IDE_MACIO) += macio.o
+hw-obj-$(CONFIG_IDE_VIA) += via.o
+hw-obj-$(CONFIG_AHCI) += ahci.o
+hw-obj-$(CONFIG_AHCI) += ich.o
diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs
index 7dbc33b..9c7ddf5 100644
--- a/hw/usb/Makefile.objs
+++ b/hw/usb/Makefile.objs
@@ -1,3 +1,12 @@
+hw-obj-$(CONFIG_USB_UHCI) += hcd-uhci.o
+hw-obj-$(CONFIG_USB_OHCI) += hcd-ohci.o
+hw-obj-$(CONFIG_USB_EHCI) += hcd-ehci.o
+hw-obj-$(CONFIG_USB_XHCI) += hcd-xhci.o
+hw-obj-y += libhw.o
+
+hw-obj-$(CONFIG_SMARTCARD) += dev-smartcard-reader.o
+hw-obj-$(CONFIG_USB_REDIR) += redirect.o
+
 common-obj-y += core.o bus.o desc.o dev-hub.o
 common-obj-y += host-$(HOST_USB).o dev-bluetooth.o
 common-obj-y += dev-hid.o dev-storage.o dev-wacom.o
commit 3d5a3f9a7fded758e37da15471d50de4b0f7e4a5
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue May 29 11:08:47 2012 +0200

    build: move target-independent hw/ objects to nested Makefile.objs
    
    This patch starts converting the hw/ directory.  Some files in hw/
    are compiled once, some twice (32-/64-bit), some once per target.
    Each category is moved in a separate patch.
    
    After this patch, the files that are compiled once will show the
    same hierarchy in the build tree as they do in the source tree,
    for example hw/qdev.o instead of just qdev.o.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile b/Makefile
index 0c0540d..a10005a 100644
--- a/Makefile
+++ b/Makefile
@@ -120,7 +120,7 @@ QEMU_CFLAGS += -I$(SRC_PATH)/include
 
 ui/cocoa.o: ui/cocoa.m
 
-ui/sdl.o audio/sdlaudio.o ui/sdl_zoom.o baum.o: QEMU_CFLAGS += $(SDL_CFLAGS)
+ui/sdl.o audio/sdlaudio.o ui/sdl_zoom.o hw/baum.o: QEMU_CFLAGS += $(SDL_CFLAGS)
 
 ui/vnc.o: QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
 
@@ -214,6 +214,7 @@ clean:
 	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 usb/*.o usb/*.d hw/*.o hw/*.d
 	rm -f qemu-img-cmds.h
 	rm -f trace/*.o trace/*.d
 	rm -f trace-dtrace.dtrace trace-dtrace.dtrace-timestamp
@@ -400,4 +401,5 @@ tar:
 Makefile: $(GENERATED_HEADERS)
 
 # Include automatically generated dependency files
--include $(wildcard *.d audio/*.d slirp/*.d block/*.d net/*.d ui/*.d qapi/*.d qga/*.d)
+-include $(wildcard *.d audio/*.d slirp/*.d block/*.d net/*.d ui/*.d qapi/*.d)
+-include $(wildcard qga/*.d hw/*.d hw/usb/*.d)
diff --git a/Makefile.objs b/Makefile.objs
index fec21a4..4aa5f0f 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -70,50 +70,22 @@ common-obj-$(CONFIG_LINUX) += fsdev/
 extra-obj-$(CONFIG_LINUX) += fsdev/
 
 common-obj-y += tcg-runtime.o host-utils.o main-loop.o
-common-obj-y += irq.o input.o
-common-obj-$(CONFIG_PTIMER) += ptimer.o
-common-obj-$(CONFIG_MAX7310) += max7310.o
-common-obj-$(CONFIG_WM8750) += wm8750.o
-common-obj-$(CONFIG_TWL92230) += twl92230.o
-common-obj-$(CONFIG_TSC2005) += tsc2005.o
-common-obj-$(CONFIG_LM832X) += lm832x.o
-common-obj-$(CONFIG_TMP105) += tmp105.o
-common-obj-$(CONFIG_STELLARIS_INPUT) += stellaris_input.o
-common-obj-$(CONFIG_SSD0303) += ssd0303.o
-common-obj-$(CONFIG_SSD0323) += ssd0323.o
-common-obj-$(CONFIG_ADS7846) += ads7846.o
-common-obj-$(CONFIG_MAX111X) += max111x.o
-common-obj-$(CONFIG_DS1338) += ds1338.o
-common-obj-y += i2c.o smbus.o smbus_eeprom.o
-common-obj-y += eeprom93xx.o
-common-obj-y += scsi-disk.o cdrom.o
-common-obj-y += scsi-generic.o scsi-bus.o
-common-obj-y += hid.o
-common-obj-y += usb/core.o usb/bus.o usb/desc.o usb/dev-hub.o
-common-obj-y += usb/host-$(HOST_USB).o
-common-obj-y += usb/dev-hid.o usb/dev-storage.o usb/dev-wacom.o
-common-obj-y += usb/dev-serial.o usb/dev-network.o usb/dev-audio.o
-common-obj-$(CONFIG_SSI) += ssi.o
-common-obj-$(CONFIG_SSI_SD) += ssi-sd.o
-common-obj-$(CONFIG_SD) += sd.o
-common-obj-y += bt.o bt-host.o bt-vhci.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o
-common-obj-y += bt-hci-csr.o usb/dev-bluetooth.o
+common-obj-y += input.o
 common-obj-y += buffered_file.o migration.o migration-tcp.o
 common-obj-y += qemu-char.o #aio.o
-common-obj-y += msmouse.o ps2.o
-common-obj-y += qdev.o qdev-properties.o qdev-monitor.o
 common-obj-y += block-migration.o iohandler.o
 common-obj-y += pflib.o
 common-obj-y += bitmap.o bitops.o
 
-common-obj-$(CONFIG_BRLAPI) += baum.o
 common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
 common-obj-$(CONFIG_WIN32) += version.o
 
 common-obj-$(CONFIG_SPICE) += spice-qemu-char.o
 
 common-obj-y += audio/
+common-obj-y += hw/
 common-obj-y += ui/
+common-obj-y += bt-host.o bt-vhci.o
 
 common-obj-y += iov.o acl.o
 common-obj-$(CONFIG_POSIX) += compatfd.o
@@ -122,10 +94,6 @@ common-obj-y += qemu-timer.o qemu-timer-common.o
 
 common-obj-$(CONFIG_SLIRP) += slirp/
 
-# xen backend driver support
-common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o
-common-obj-$(CONFIG_XEN_BACKEND) += xen_console.o xenfb.o xen_disk.o xen_nic.o
-
 ######################################################################
 # libuser
 
diff --git a/configure b/configure
index cc77700..b22ff10 100755
--- a/configure
+++ b/configure
@@ -3955,7 +3955,7 @@ 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"
+DIRS="$DIRS fsdev ui hw hw/usb"
 DIRS="$DIRS qapi qapi-generated"
 DIRS="$DIRS qga trace qom"
 FILES="Makefile tests/tcg/Makefile qdict-test-data.txt"
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
new file mode 100644
index 0000000..00642f3
--- /dev/null
+++ b/hw/Makefile.objs
@@ -0,0 +1,32 @@
+common-obj-y += usb/
+common-obj-y += irq.o
+common-obj-$(CONFIG_PTIMER) += ptimer.o
+common-obj-$(CONFIG_MAX7310) += max7310.o
+common-obj-$(CONFIG_WM8750) += wm8750.o
+common-obj-$(CONFIG_TWL92230) += twl92230.o
+common-obj-$(CONFIG_TSC2005) += tsc2005.o
+common-obj-$(CONFIG_LM832X) += lm832x.o
+common-obj-$(CONFIG_TMP105) += tmp105.o
+common-obj-$(CONFIG_STELLARIS_INPUT) += stellaris_input.o
+common-obj-$(CONFIG_SSD0303) += ssd0303.o
+common-obj-$(CONFIG_SSD0323) += ssd0323.o
+common-obj-$(CONFIG_ADS7846) += ads7846.o
+common-obj-$(CONFIG_MAX111X) += max111x.o
+common-obj-$(CONFIG_DS1338) += ds1338.o
+common-obj-y += i2c.o smbus.o smbus_eeprom.o
+common-obj-y += eeprom93xx.o
+common-obj-y += scsi-disk.o cdrom.o
+common-obj-y += scsi-generic.o scsi-bus.o
+common-obj-y += hid.o
+common-obj-$(CONFIG_SSI) += ssi.o
+common-obj-$(CONFIG_SSI_SD) += ssi-sd.o
+common-obj-$(CONFIG_SD) += sd.o
+common-obj-y += bt.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o
+common-obj-y += bt-hci-csr.o
+common-obj-y += msmouse.o ps2.o
+common-obj-y += qdev.o qdev-properties.o qdev-monitor.o
+common-obj-$(CONFIG_BRLAPI) += baum.o
+
+# xen backend driver support
+common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o
+common-obj-$(CONFIG_XEN_BACKEND) += xen_console.o xenfb.o xen_disk.o xen_nic.o
diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs
new file mode 100644
index 0000000..7dbc33b
--- /dev/null
+++ b/hw/usb/Makefile.objs
@@ -0,0 +1,4 @@
+common-obj-y += core.o bus.o desc.o dev-hub.o
+common-obj-y += host-$(HOST_USB).o dev-bluetooth.o
+common-obj-y += dev-hid.o dev-storage.o dev-wacom.o
+common-obj-y += dev-serial.o dev-network.o dev-audio.o
commit 4eb7ba8aff38291296bce7e5efa4ac6f42c989c4
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue May 22 13:50:58 2012 +0200

    build: move qga/ objects to nested Makefile.objs
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index e7f7a85..fec21a4 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -385,11 +385,7 @@ universal-obj-y += $(qapi-obj-y)
 ######################################################################
 # guest agent
 
-qga-nested-y = commands.o guest-agent-command-state.o
-qga-nested-$(CONFIG_POSIX) += commands-posix.o channel-posix.o
-qga-nested-$(CONFIG_WIN32) += commands-win32.o channel-win32.o service-win32.o
-qga-obj-y = $(addprefix qga/, $(qga-nested-y))
-qga-obj-y += qemu-ga.o module.o
+qga-obj-y = qga/ qemu-ga.o module.o
 qga-obj-$(CONFIG_WIN32) += oslib-win32.o
 qga-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-sockets.o qemu-option.o
 
@@ -400,6 +396,7 @@ vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
 QEMU_CFLAGS+=$(GLIB_CFLAGS)
 
 nested-vars += \
+	qga-obj-y \
 	block-obj-y \
 	qom-obj-y \
 	qapi-obj-y \
diff --git a/qga/Makefile.objs b/qga/Makefile.objs
new file mode 100644
index 0000000..6a4d843
--- /dev/null
+++ b/qga/Makefile.objs
@@ -0,0 +1,3 @@
+qga-obj-y = commands.o guest-agent-command-state.o
+qga-obj-$(CONFIG_POSIX) += commands-posix.o channel-posix.o
+qga-obj-$(CONFIG_WIN32) += commands-win32.o channel-win32.o service-win32.o
commit dd5614d6f1d22c4e940368e1433325a3669cbbc2
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue May 22 13:50:34 2012 +0200

    build: move qapi/ objects to nested Makefile.objs
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index 668c148..e7f7a85 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -375,10 +375,7 @@ libcacard-y = cac.o event.o vcard.o vreader.o vcard_emul_nss.o vcard_emul_type.o
 ######################################################################
 # qapi
 
-qapi-nested-y = qapi-visit-core.o qapi-dealloc-visitor.o qmp-input-visitor.o
-qapi-nested-y += qmp-output-visitor.o qmp-registry.o qmp-dispatch.o
-qapi-nested-y += string-input-visitor.o string-output-visitor.o
-qapi-obj-y = $(addprefix qapi/, $(qapi-nested-y))
+qapi-obj-y = qapi/
 
 common-obj-y += qmp-marshal.o qapi-visit.o qapi-types.o
 common-obj-y += qmp.o hmp.o
@@ -405,6 +402,7 @@ QEMU_CFLAGS+=$(GLIB_CFLAGS)
 nested-vars += \
 	block-obj-y \
 	qom-obj-y \
+	qapi-obj-y \
 	user-obj-y \
 	common-obj-y \
 	extra-obj-y
diff --git a/qapi/Makefile.objs b/qapi/Makefile.objs
new file mode 100644
index 0000000..d0b0c16
--- /dev/null
+++ b/qapi/Makefile.objs
@@ -0,0 +1,3 @@
+qapi-obj-y = qapi-visit-core.o qapi-dealloc-visitor.o qmp-input-visitor.o
+qapi-obj-y += qmp-output-visitor.o qmp-registry.o qmp-dispatch.o
+qapi-obj-y += string-input-visitor.o string-output-visitor.o
commit 4c696054727edbc274dd174558e0a796c98d1557
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue May 22 13:49:43 2012 +0200

    build: move slirp/ objects to nested Makefile.objs
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index 7ee2bb6..668c148 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -120,10 +120,7 @@ common-obj-$(CONFIG_POSIX) += compatfd.o
 common-obj-y += notify.o event_notifier.o
 common-obj-y += qemu-timer.o qemu-timer-common.o
 
-slirp-obj-y = cksum.o if.o ip_icmp.o ip_input.o ip_output.o
-slirp-obj-y += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o
-slirp-obj-y += tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o arp_table.o
-common-obj-$(CONFIG_SLIRP) += $(addprefix slirp/, $(slirp-obj-y))
+common-obj-$(CONFIG_SLIRP) += slirp/
 
 # xen backend driver support
 common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o
diff --git a/slirp/Makefile.objs b/slirp/Makefile.objs
new file mode 100644
index 0000000..bb43d3c
--- /dev/null
+++ b/slirp/Makefile.objs
@@ -0,0 +1,3 @@
+common-obj-y = cksum.o if.o ip_icmp.o ip_input.o ip_output.o
+common-obj-y += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o
+common-obj-y += tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o arp_table.o
commit b0b68fc671a55f73a2a886fe75fbe95df4d9105c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue May 22 13:49:02 2012 +0200

    build: move audio/ objects to nested Makefile.objs
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index a6310e3..7ee2bb6 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -110,23 +110,9 @@ common-obj-$(CONFIG_BRLAPI) += baum.o
 common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
 common-obj-$(CONFIG_WIN32) += version.o
 
-
-audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o
-audio-obj-$(CONFIG_SDL) += sdlaudio.o
-audio-obj-$(CONFIG_OSS) += ossaudio.o
-audio-obj-$(CONFIG_SPICE) += spiceaudio.o
-audio-obj-$(CONFIG_COREAUDIO) += coreaudio.o
-audio-obj-$(CONFIG_ALSA) += alsaaudio.o
-audio-obj-$(CONFIG_DSOUND) += dsoundaudio.o
-audio-obj-$(CONFIG_FMOD) += fmodaudio.o
-audio-obj-$(CONFIG_ESD) += esdaudio.o
-audio-obj-$(CONFIG_PA) += paaudio.o
-audio-obj-$(CONFIG_WINWAVE) += winwaveaudio.o
-audio-obj-$(CONFIG_AUDIO_PT_INT) += audio_pt_int.o
-audio-obj-$(CONFIG_AUDIO_WIN_INT) += audio_win_int.o
-audio-obj-y += wavcapture.o
-common-obj-y += $(addprefix audio/, $(audio-obj-y))
 common-obj-$(CONFIG_SPICE) += spice-qemu-char.o
+
+common-obj-y += audio/
 common-obj-y += ui/
 
 common-obj-y += iov.o acl.o
diff --git a/audio/Makefile.objs b/audio/Makefile.objs
new file mode 100644
index 0000000..0f2932d
--- /dev/null
+++ b/audio/Makefile.objs
@@ -0,0 +1,14 @@
+common-obj-y = audio.o noaudio.o wavaudio.o mixeng.o
+common-obj-$(CONFIG_SDL) += sdlaudio.o
+common-obj-$(CONFIG_OSS) += ossaudio.o
+common-obj-$(CONFIG_SPICE) += spiceaudio.o
+common-obj-$(CONFIG_COREAUDIO) += coreaudio.o
+common-obj-$(CONFIG_ALSA) += alsaaudio.o
+common-obj-$(CONFIG_DSOUND) += dsoundaudio.o
+common-obj-$(CONFIG_FMOD) += fmodaudio.o
+common-obj-$(CONFIG_ESD) += esdaudio.o
+common-obj-$(CONFIG_PA) += paaudio.o
+common-obj-$(CONFIG_WINWAVE) += winwaveaudio.o
+common-obj-$(CONFIG_AUDIO_PT_INT) += audio_pt_int.o
+common-obj-$(CONFIG_AUDIO_WIN_INT) += audio_win_int.o
+common-obj-y += wavcapture.o
commit 8867aef02e1e5817c72b2e09be4ae952eb0c9d9d
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue May 22 13:48:15 2012 +0200

    build: move ui/ objects to nested Makefile.objs
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index 4acdbaa..a6310e3 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -110,7 +110,6 @@ common-obj-$(CONFIG_BRLAPI) += baum.o
 common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
 common-obj-$(CONFIG_WIN32) += version.o
 
-common-obj-$(CONFIG_SPICE) += ui/spice-core.o ui/spice-input.o ui/spice-display.o spice-qemu-char.o
 
 audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o
 audio-obj-$(CONFIG_SDL) += sdlaudio.o
@@ -127,24 +126,8 @@ audio-obj-$(CONFIG_AUDIO_PT_INT) += audio_pt_int.o
 audio-obj-$(CONFIG_AUDIO_WIN_INT) += audio_win_int.o
 audio-obj-y += wavcapture.o
 common-obj-y += $(addprefix audio/, $(audio-obj-y))
-
-ui-obj-y += keymaps.o
-ui-obj-$(CONFIG_SDL) += sdl.o sdl_zoom.o x_keymap.o
-ui-obj-$(CONFIG_COCOA) += cocoa.o
-ui-obj-$(CONFIG_CURSES) += curses.o
-vnc-obj-y += vnc.o d3des.o
-vnc-obj-y += vnc-enc-zlib.o vnc-enc-hextile.o
-vnc-obj-y += vnc-enc-tight.o vnc-palette.o
-vnc-obj-y += vnc-enc-zrle.o
-vnc-obj-$(CONFIG_VNC_TLS) += vnc-tls.o vnc-auth-vencrypt.o
-vnc-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o
-ifdef CONFIG_VNC_THREAD
-vnc-obj-y += vnc-jobs-async.o
-else
-vnc-obj-y += vnc-jobs-sync.o
-endif
-common-obj-y += $(addprefix ui/, $(ui-obj-y))
-common-obj-$(CONFIG_VNC) += $(addprefix ui/, $(vnc-obj-y))
+common-obj-$(CONFIG_SPICE) += spice-qemu-char.o
+common-obj-y += ui/
 
 common-obj-y += iov.o acl.o
 common-obj-$(CONFIG_POSIX) += compatfd.o
diff --git a/ui/Makefile.objs b/ui/Makefile.objs
new file mode 100644
index 0000000..3687c8a
--- /dev/null
+++ b/ui/Makefile.objs
@@ -0,0 +1,18 @@
+vnc-obj-y += vnc.o d3des.o
+vnc-obj-y += vnc-enc-zlib.o vnc-enc-hextile.o
+vnc-obj-y += vnc-enc-tight.o vnc-palette.o
+vnc-obj-y += vnc-enc-zrle.o
+vnc-obj-$(CONFIG_VNC_TLS) += vnc-tls.o vnc-auth-vencrypt.o
+vnc-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o
+ifdef CONFIG_VNC_THREAD
+vnc-obj-y += vnc-jobs-async.o
+else
+vnc-obj-y += vnc-jobs-sync.o
+endif
+
+common-obj-y += keymaps.o
+common-obj-$(CONFIG_SPICE) += spice-core.o spice-input.o spice-display.o
+common-obj-$(CONFIG_SDL) += sdl.o sdl_zoom.o x_keymap.o
+common-obj-$(CONFIG_COCOA) += cocoa.o
+common-obj-$(CONFIG_CURSES) += curses.o
+common-obj-$(CONFIG_VNC) += $(vnc-obj-y)
commit ee20477d2463dfaf0d88595c8dcbf0f80404f69c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue May 22 13:46:08 2012 +0200

    build: move fsdev/ objects to nested Makefile.objs
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile b/Makefile
index c0ab97a..0c0540d 100644
--- a/Makefile
+++ b/Makefile
@@ -100,7 +100,7 @@ endif
 
 subdir-libcacard: $(oslib-obj-y) $(trace-obj-y) qemu-timer-common.o
 
-$(filter %-softmmu,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) $(common-obj-y) subdir-libdis
+$(filter %-softmmu,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) $(common-obj-y) $(extra-obj-y) subdir-libdis
 
 $(filter %-user,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) subdir-libdis-user subdir-libuser
 
diff --git a/Makefile.objs b/Makefile.objs
index f40be38..4acdbaa 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -51,11 +51,7 @@ ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy)
 # Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add.
 # only pull in the actual virtio-9p device if we also enabled virtio.
 CONFIG_REALLY_VIRTFS=y
-fsdev-nested-y = qemu-fsdev.o virtio-9p-marshal.o
-else
-fsdev-nested-y = qemu-fsdev-dummy.o
 endif
-fsdev-obj-$(CONFIG_VIRTFS) += $(addprefix fsdev/, $(fsdev-nested-y))
 
 ######################################################################
 # Target independent part of system emulation. The long term path is to
@@ -65,12 +61,14 @@ fsdev-obj-$(CONFIG_VIRTFS) += $(addprefix fsdev/, $(fsdev-nested-y))
 common-obj-y = $(block-obj-y) blockdev.o
 common-obj-y += net.o net/
 common-obj-y += qom/
-common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX))
 common-obj-y += readline.o console.o cursor.o
 common-obj-y += $(oslib-obj-y)
 common-obj-$(CONFIG_WIN32) += os-win32.o
 common-obj-$(CONFIG_POSIX) += os-posix.o
 
+common-obj-$(CONFIG_LINUX) += fsdev/
+extra-obj-$(CONFIG_LINUX) += fsdev/
+
 common-obj-y += tcg-runtime.o host-utils.o main-loop.o
 common-obj-y += irq.o input.o
 common-obj-$(CONFIG_PTIMER) += ptimer.o
@@ -442,5 +440,6 @@ nested-vars += \
 	block-obj-y \
 	qom-obj-y \
 	user-obj-y \
-	common-obj-y
+	common-obj-y \
+	extra-obj-y
 dummy := $(call unnest-vars)
diff --git a/fsdev/Makefile.objs b/fsdev/Makefile.objs
new file mode 100644
index 0000000..cb1e250
--- /dev/null
+++ b/fsdev/Makefile.objs
@@ -0,0 +1,9 @@
+ifeq ($(CONFIG_REALLY_VIRTFS),y)
+common-obj-y = qemu-fsdev.o virtio-9p-marshal.o
+
+# Toplevel always builds this; targets without virtio will put it in
+# common-obj-y
+extra-obj-y = qemu-fsdev-dummy.o
+else
+common-obj-y = qemu-fsdev-dummy.o
+endif
commit d8469de6c10533ce32be063e1ce3b586dc91406e
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue May 22 13:45:55 2012 +0200

    build: move net/ objects to nested Makefile.objs
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index 3285949..f40be38 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -47,21 +47,6 @@ block-obj-$(CONFIG_POSIX) += posix-aio-compat.o
 block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
 block-obj-y += block/
 
-net-obj-y = net.o
-net-nested-y = queue.o checksum.o util.o
-net-nested-y += socket.o
-net-nested-y += dump.o
-net-nested-$(CONFIG_POSIX) += tap.o
-net-nested-$(CONFIG_LINUX) += tap-linux.o
-net-nested-$(CONFIG_WIN32) += tap-win32.o
-net-nested-$(CONFIG_BSD) += tap-bsd.o
-net-nested-$(CONFIG_SOLARIS) += tap-solaris.o
-net-nested-$(CONFIG_AIX) += tap-aix.o
-net-nested-$(CONFIG_HAIKU) += tap-haiku.o
-net-nested-$(CONFIG_SLIRP) += slirp.o
-net-nested-$(CONFIG_VDE) += vde.o
-net-obj-y += $(addprefix net/, $(net-nested-y))
-
 ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy)
 # Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add.
 # only pull in the actual virtio-9p device if we also enabled virtio.
@@ -78,7 +63,7 @@ fsdev-obj-$(CONFIG_VIRTFS) += $(addprefix fsdev/, $(fsdev-nested-y))
 # single QEMU executable should support all CPUs and machines.
 
 common-obj-y = $(block-obj-y) blockdev.o
-common-obj-y += $(net-obj-y)
+common-obj-y += net.o net/
 common-obj-y += qom/
 common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX))
 common-obj-y += readline.o console.o cursor.o
diff --git a/net/Makefile.objs b/net/Makefile.objs
new file mode 100644
index 0000000..72f50bc
--- /dev/null
+++ b/net/Makefile.objs
@@ -0,0 +1,12 @@
+common-obj-y = queue.o checksum.o util.o
+common-obj-y += socket.o
+common-obj-y += dump.o
+common-obj-$(CONFIG_POSIX) += tap.o
+common-obj-$(CONFIG_LINUX) += tap-linux.o
+common-obj-$(CONFIG_WIN32) += tap-win32.o
+common-obj-$(CONFIG_BSD) += tap-bsd.o
+common-obj-$(CONFIG_SOLARIS) += tap-solaris.o
+common-obj-$(CONFIG_AIX) += tap-aix.o
+common-obj-$(CONFIG_HAIKU) += tap-haiku.o
+common-obj-$(CONFIG_SLIRP) += slirp.o
+common-obj-$(CONFIG_VDE) += vde.o
commit 7456e4ce8de73c2406046f29a0e899d8806820ce
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue May 22 13:44:39 2012 +0200

    build: move block/ objects to nested Makefile.objs
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index ef49a09..3285949 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -45,20 +45,7 @@ block-obj-y += nbd.o block.o aio.o aes.o qemu-config.o qemu-progress.o qemu-sock
 block-obj-y += $(coroutine-obj-y) $(qobject-obj-y) $(version-obj-y)
 block-obj-$(CONFIG_POSIX) += posix-aio-compat.o
 block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
-
-block-nested-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o
-block-nested-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o
-block-nested-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o
-block-nested-y += qed-check.o
-block-nested-y += parallels.o nbd.o blkdebug.o sheepdog.o blkverify.o
-block-nested-y += stream.o
-block-nested-$(CONFIG_WIN32) += raw-win32.o
-block-nested-$(CONFIG_POSIX) += raw-posix.o
-block-nested-$(CONFIG_LIBISCSI) += iscsi.o
-block-nested-$(CONFIG_CURL) += curl.o
-block-nested-$(CONFIG_RBD) += rbd.o
-
-block-obj-y +=  $(addprefix block/, $(block-nested-y))
+block-obj-y += block/
 
 net-obj-y = net.o
 net-nested-y = queue.o checksum.o util.o
@@ -467,6 +454,7 @@ vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
 QEMU_CFLAGS+=$(GLIB_CFLAGS)
 
 nested-vars += \
+	block-obj-y \
 	qom-obj-y \
 	user-obj-y \
 	common-obj-y
diff --git a/block/Makefile.objs b/block/Makefile.objs
new file mode 100644
index 0000000..b5754d3
--- /dev/null
+++ b/block/Makefile.objs
@@ -0,0 +1,11 @@
+block-obj-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o
+block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o
+block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o
+block-obj-y += qed-check.o
+block-obj-y += parallels.o nbd.o blkdebug.o sheepdog.o blkverify.o
+block-obj-y += stream.o
+block-obj-$(CONFIG_WIN32) += raw-win32.o
+block-obj-$(CONFIG_POSIX) += raw-posix.o
+block-obj-$(CONFIG_LIBISCSI) += iscsi.o
+block-obj-$(CONFIG_CURL) += curl.o
+block-obj-$(CONFIG_RBD) += rbd.o
commit 7f07b9cbc51066ddaa133b29389e225612aaced2
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue May 22 13:42:53 2012 +0200

    build: adapt qom/Makefile and move it to Makefile.objs
    
    qom/ already used a separate makefile.  Convert it to use relative
    paths, and make it declare both common-obj-y and user-obj-y.  This
    way, the upper makefiles do not need to know that some QOM files
    are compiled twice.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index e06db12..ef49a09 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -12,9 +12,7 @@ universal-obj-y += $(qobject-obj-y)
 
 #######################################################################
 # QOM
-include $(SRC_PATH)/qom/Makefile
-qom-obj-y = $(addprefix qom/, $(qom-y))
-qom-obj-twice-y = $(addprefix qom/, $(qom-twice-y))
+qom-obj-y = qom/
 
 universal-obj-y += $(qom-obj-y)
 
@@ -94,7 +92,7 @@ fsdev-obj-$(CONFIG_VIRTFS) += $(addprefix fsdev/, $(fsdev-nested-y))
 
 common-obj-y = $(block-obj-y) blockdev.o
 common-obj-y += $(net-obj-y)
-common-obj-y += $(qom-obj-twice-y)
+common-obj-y += qom/
 common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX))
 common-obj-y += readline.o console.o cursor.o
 common-obj-y += $(oslib-obj-y)
@@ -202,7 +200,7 @@ user-obj-y += cutils.o cache-utils.o
 user-obj-y += module.o
 user-obj-y += qemu-user.o
 user-obj-y += $(trace-obj-y)
-user-obj-y += $(qom-obj-twice-y)
+user-obj-y += qom/
 
 ######################################################################
 # libhw
@@ -468,5 +466,8 @@ vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
 
 QEMU_CFLAGS+=$(GLIB_CFLAGS)
 
-nested-vars += # ...
+nested-vars += \
+	qom-obj-y \
+	user-obj-y \
+	common-obj-y
 dummy := $(call unnest-vars)
diff --git a/qom/Makefile b/qom/Makefile
deleted file mode 100644
index 34c6de5..0000000
--- a/qom/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-qom-y = object.o container.o qom-qobject.o
-qom-twice-y = cpu.o
diff --git a/qom/Makefile.objs b/qom/Makefile.objs
new file mode 100644
index 0000000..5ef060a
--- /dev/null
+++ b/qom/Makefile.objs
@@ -0,0 +1,4 @@
+qom-obj-y = object.o container.o qom-qobject.o
+qom-obj-twice-y = cpu.o
+common-obj-y = $(qom-obj-twice-y)
+user-obj-y = $(qom-obj-twice-y)
commit 99100dc3b55126fc60fbbfb854d5aab25ab5dafd
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue May 22 13:41:27 2012 +0200

    build: move rules for nesting to Makefile.objs
    
    At this point we will start adding nesting behavior to other files
    than Makefile.target.  Because Makefile.objs is included by
    Makefile.target, it is simpler to move the processing of
    subdirectories there.
    
    To enable this, only add per-target files to obj-y.  Use a separate
    variable for the linker dependencies, all-obj-y.  This variable includes
    obj-y and also all objects that are taken from other directories.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index 1daa92c..e06db12 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -468,3 +468,5 @@ vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
 
 QEMU_CFLAGS+=$(GLIB_CFLAGS)
 
+nested-vars += # ...
+dummy := $(call unnest-vars)
diff --git a/Makefile.target b/Makefile.target
index 655908e..f1d5fe2 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -21,8 +21,6 @@ QEMU_CFLAGS += -I../linux-headers
 endif
 QEMU_CFLAGS += -I.. -I$(TARGET_PATH) -DNEED_CPU_H
 
-include $(SRC_PATH)/Makefile.objs
-
 QEMU_CFLAGS+=-I$(SRC_PATH)/include
 
 ifdef CONFIG_USER_ONLY
@@ -107,10 +105,6 @@ QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) -I$(SRC_PATH)/linux-user
 obj-y += linux-user/
 obj-y += gdbstub.o thunk.o user-exec.o $(oslib-obj-y)
 
-obj-y += $(addprefix ../, $(universal-obj-y))
-obj-y += $(addprefix ../libuser/, $(user-obj-y))
-obj-y += $(addprefix ../libdis-user/, $(libdis-y))
-
 endif #CONFIG_LINUX_USER
 
 #########################################################
@@ -123,10 +117,6 @@ QEMU_CFLAGS+=-I$(SRC_PATH)/bsd-user -I$(SRC_PATH)/bsd-user/$(TARGET_ARCH)
 obj-y += bsd-user/
 obj-y += gdbstub.o user-exec.o
 
-obj-y += $(addprefix ../, $(universal-obj-y))
-obj-y += $(addprefix ../libuser/, $(user-obj-y))
-obj-y += $(addprefix ../libdis-user/, $(libdis-y))
-
 endif #CONFIG_BSD_USER
 
 #########################################################
@@ -191,33 +181,40 @@ main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
 
 GENERATED_HEADERS += hmp-commands.h qmp-commands-old.h
 
-obj-y += $(addprefix ../, $(universal-obj-y))
-obj-y += $(addprefix ../, $(common-obj-y))
-obj-y += $(addprefix ../libdis/, $(libdis-y))
-obj-y += $(addprefix $(HWDIR)/, $(hw-obj-y))
-obj-y += $(addprefix ../, $(trace-obj-y))
-
 endif # CONFIG_SOFTMMU
 
-ifndef CONFIG_LINUX_USER
-ifndef CONFIG_BSD_USER
+nested-vars += obj-y
+
+# This resolves all nested paths, so it must come last
+include $(SRC_PATH)/Makefile.objs
+
+all-obj-y = $(obj-y)
+all-obj-y += $(addprefix ../, $(universal-obj-y))
+
+ifdef CONFIG_SOFTMMU
+
+all-obj-y += $(addprefix ../, $(common-obj-y))
+all-obj-y += $(addprefix ../libdis/, $(libdis-y))
+all-obj-y += $(addprefix $(HWDIR)/, $(hw-obj-y))
+all-obj-y += $(addprefix ../, $(trace-obj-y))
+
 # libcacard needs qemu-thread support, and besides is only needed by devices
 # so not requires with linux-user / bsd-user targets
-obj-$(CONFIG_SMARTCARD_NSS) += $(addprefix ../libcacard/, $(libcacard-y))
-endif # CONFIG_BSD_USER
-endif # CONFIG_LINUX_USER
+all-obj-$(CONFIG_SMARTCARD_NSS) += $(addprefix ../libcacard/, $(libcacard-y))
 
-nested-vars = obj-y
-dummy := $(call unnest-vars)
+else
+all-obj-y += $(addprefix ../libuser/, $(user-obj-y))
+all-obj-y += $(addprefix ../libdis-user/, $(libdis-y))
+endif #CONFIG_LINUX_USER
 
 ifdef QEMU_PROGW
 # The linker builds a windows executable. Make also a console executable.
-$(QEMU_PROGW): $(obj-y)
+$(QEMU_PROGW): $(all-obj-y)
 	$(call LINK,$^)
 $(QEMU_PROG): $(QEMU_PROGW)
 	$(call quiet-command,$(OBJCOPY) --subsystem console $(QEMU_PROGW) $(QEMU_PROG),"  GEN   $(TARGET_DIR)$(QEMU_PROG)")
 else
-$(QEMU_PROG): $(obj-y)
+$(QEMU_PROG): $(all-obj-y)
 	$(call LINK,$^)
 endif
 
commit fbe37ef3e18814f2b98f115a1c855fea7fe71d74
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue May 29 11:48:59 2012 +0200

    build: move other target-*/ objects to nested Makefile.objs
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.target b/Makefile.target
index 4c81171..655908e 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -78,7 +78,7 @@ all: $(PROGS) stap
 
 #########################################################
 # cpu emulator library
-obj-y = exec.o translate-all.o cpu-exec.o translate.o
+obj-y = exec.o translate-all.o cpu-exec.o
 obj-y += tcg/tcg.o tcg/optimize.o
 obj-$(CONFIG_TCG_INTERPRETER) += tci.o
 obj-y += fpu/softfloat.o
@@ -133,7 +133,7 @@ endif #CONFIG_BSD_USER
 # System emulator target
 ifdef CONFIG_SOFTMMU
 
-obj-y += arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o ioport.o
+obj-y += arch_init.o cpus.o monitor.o gdbstub.o balloon.o ioport.o
 # virtio has to be here due to weird dependency between PCI and virtio-net.
 # need to fix this properly
 obj-$(CONFIG_NO_PCI) += pci-stub.o
@@ -142,12 +142,12 @@ obj-$(CONFIG_VIRTIO) += virtio-scsi.o
 obj-y += vhost_net.o
 obj-$(CONFIG_VHOST_NET) += vhost.o
 obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o
-obj-$(CONFIG_KVM) += kvm.o kvm-all.o
+obj-$(CONFIG_KVM) += kvm-all.o
 obj-$(CONFIG_NO_KVM) += kvm-stub.o
 obj-$(CONFIG_VGA) += vga.o
 obj-y += memory.o savevm.o cputlb.o
-obj-$(CONFIG_HAVE_GET_MEMORY_MAPPING) += memory_mapping.o arch_memory_mapping.o
-obj-$(CONFIG_HAVE_CORE_DUMP) += dump.o arch_dump.o
+obj-$(CONFIG_HAVE_GET_MEMORY_MAPPING) += memory_mapping.o
+obj-$(CONFIG_HAVE_CORE_DUMP) += dump.o
 obj-$(CONFIG_NO_GET_MEMORY_MAPPING) += memory_mapping-stub.o
 obj-$(CONFIG_NO_CORE_DUMP) += dump-stub.o
 LIBS+=-lz
diff --git a/target-alpha/Makefile.objs b/target-alpha/Makefile.objs
index 9a72870..590304c 100644
--- a/target-alpha/Makefile.objs
+++ b/target-alpha/Makefile.objs
@@ -1,2 +1,3 @@
-obj-y += helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += machine.o
+obj-y += translate.o helper.o cpu.o
 obj-y += int_helper.o fpu_helper.o sys_helper.o mem_helper.o
diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs
index 4dcd3c5..f447c4f 100644
--- a/target-arm/Makefile.objs
+++ b/target-arm/Makefile.objs
@@ -1,5 +1,6 @@
 obj-y += arm-semi.o
-obj-y += op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += machine.o
+obj-y += translate.o op_helper.o helper.o cpu.o
 obj-y += neon_helper.o iwmmxt_helper.o
 
 $(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-cris/Makefile.objs b/target-cris/Makefile.objs
index 9a50c28..4b09e8c 100644
--- a/target-cris/Makefile.objs
+++ b/target-cris/Makefile.objs
@@ -1,4 +1,4 @@
-obj-y += op_helper.o helper.o cpu.o
-obj-$(CONFIG_SOFTMMU) += mmu.o
+obj-y += translate.o op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += mmu.o machine.o
 
 $(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-i386/Makefile.objs b/target-i386/Makefile.objs
index 2538c43..f913755 100644
--- a/target-i386/Makefile.objs
+++ b/target-i386/Makefile.objs
@@ -1,5 +1,6 @@
-obj-y += op_helper.o helper.o cpu.o
-obj-$(CONFIG_KVM) += hyperv.o
+obj-y += translate.o op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += machine.o arch_memory_mapping.o arch_dump.o
+obj-$(CONFIG_KVM) += kvm.o hyperv.o
 obj-$(CONFIG_LINUX_USER) += ioport-user.o
 obj-$(CONFIG_BSD_USER) += ioport-user.o
 
diff --git a/target-lm32/Makefile.objs b/target-lm32/Makefile.objs
index 8e9be60..2e0e093 100644
--- a/target-lm32/Makefile.objs
+++ b/target-lm32/Makefile.objs
@@ -1,3 +1,4 @@
-obj-y += op_helper.o helper.o cpu.o
+obj-y += translate.o op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += machine.o
 
 $(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-m68k/Makefile.objs b/target-m68k/Makefile.objs
index 553691d..cda6015 100644
--- a/target-m68k/Makefile.objs
+++ b/target-m68k/Makefile.objs
@@ -1,4 +1,5 @@
 obj-y += m68k-semi.o
-obj-y += op_helper.o helper.o cpu.o
+obj-y += translate.o op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += machine.o
 
 $(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-microblaze/Makefile.objs b/target-microblaze/Makefile.objs
index 9a50c28..4b09e8c 100644
--- a/target-microblaze/Makefile.objs
+++ b/target-microblaze/Makefile.objs
@@ -1,4 +1,4 @@
-obj-y += op_helper.o helper.o cpu.o
-obj-$(CONFIG_SOFTMMU) += mmu.o
+obj-y += translate.o op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += mmu.o machine.o
 
 $(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-mips/Makefile.objs b/target-mips/Makefile.objs
index 8e9be60..2e0e093 100644
--- a/target-mips/Makefile.objs
+++ b/target-mips/Makefile.objs
@@ -1,3 +1,4 @@
-obj-y += op_helper.o helper.o cpu.o
+obj-y += translate.o op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += machine.o
 
 $(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-ppc/Makefile.objs b/target-ppc/Makefile.objs
index bf46331..95ed340 100644
--- a/target-ppc/Makefile.objs
+++ b/target-ppc/Makefile.objs
@@ -1,3 +1,6 @@
+obj-y += translate.o op_helper.o helper.o
+obj-$(CONFIG_SOFTMMU) += machine.o
+obj-$(CONFIG_KVM) += kvm.o
 obj-y += op_helper.o helper.o
 
 $(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs
index 8e9be60..262747f 100644
--- a/target-s390x/Makefile.objs
+++ b/target-s390x/Makefile.objs
@@ -1,3 +1,5 @@
-obj-y += op_helper.o helper.o cpu.o
+obj-y += translate.o op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += machine.o
+obj-$(CONFIG_KVM) += kvm.o
 
 $(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-sh4/Makefile.objs b/target-sh4/Makefile.objs
index 8e9be60..2e0e093 100644
--- a/target-sh4/Makefile.objs
+++ b/target-sh4/Makefile.objs
@@ -1,3 +1,4 @@
-obj-y += op_helper.o helper.o cpu.o
+obj-y += translate.o op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += machine.o
 
 $(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-sparc/Makefile.objs b/target-sparc/Makefile.objs
index 3556d13..a93e07d 100644
--- a/target-sparc/Makefile.objs
+++ b/target-sparc/Makefile.objs
@@ -1,4 +1,5 @@
-obj-y += helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += machine.o
+obj-y += translate.o helper.o cpu.o
 obj-y += fop_helper.o cc_helper.o win_helper.o mmu_helper.o ldst_helper.o
 obj-$(TARGET_SPARC) += int32_helper.o
 obj-$(TARGET_SPARC64) += int64_helper.o
diff --git a/target-unicore32/Makefile.objs b/target-unicore32/Makefile.objs
index 8e9be60..2e0e093 100644
--- a/target-unicore32/Makefile.objs
+++ b/target-unicore32/Makefile.objs
@@ -1,3 +1,4 @@
-obj-y += op_helper.o helper.o cpu.o
+obj-y += translate.o op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += machine.o
 
 $(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-xtensa/Makefile.objs b/target-xtensa/Makefile.objs
index 3cdf604..f8fbf91 100644
--- a/target-xtensa/Makefile.objs
+++ b/target-xtensa/Makefile.objs
@@ -2,6 +2,7 @@ obj-y += xtensa-semi.o
 obj-y += core-dc232b.o
 obj-y += core-dc233c.o
 obj-y += core-fsf.o
-obj-y += op_helper.o helper.o cpu.o
+obj-y += translate.o op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += machine.o
 
 $(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
commit 5f86146fb3ad18ef25036329f48d9ea2b7f4ab70
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Jun 7 08:22:56 2012 +0200

    dump: remove dumping stuff from cpu-all.h
    
    This simplifies things, because they will only be included for softmmu
    targets and because the stubs are taken out-of-line in separate files,
    which in the future could even be compiled only once.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.target b/Makefile.target
index f1ec554..4c81171 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -3,6 +3,8 @@
 CONFIG_NO_PCI = $(if $(subst n,,$(CONFIG_PCI)),n,y)
 CONFIG_NO_KVM = $(if $(subst n,,$(CONFIG_KVM)),n,y)
 CONFIG_NO_XEN = $(if $(subst n,,$(CONFIG_XEN)),n,y)
+CONFIG_NO_GET_MEMORY_MAPPING = $(if $(subst n,,$(CONFIG_HAVE_GET_MEMORY_MAPPING)),n,y)
+CONFIG_NO_CORE_DUMP = $(if $(subst n,,$(CONFIG_HAVE_CORE_DUMP)),n,y)
 
 include ../config-host.mak
 include config-devices.mak
@@ -144,10 +146,10 @@ obj-$(CONFIG_KVM) += kvm.o kvm-all.o
 obj-$(CONFIG_NO_KVM) += kvm-stub.o
 obj-$(CONFIG_VGA) += vga.o
 obj-y += memory.o savevm.o cputlb.o
-obj-y += memory_mapping.o
-obj-$(CONFIG_HAVE_GET_MEMORY_MAPPING) += arch_memory_mapping.o
-obj-$(CONFIG_HAVE_CORE_DUMP) += arch_dump.o
-obj-y += dump.o
+obj-$(CONFIG_HAVE_GET_MEMORY_MAPPING) += memory_mapping.o arch_memory_mapping.o
+obj-$(CONFIG_HAVE_CORE_DUMP) += dump.o arch_dump.o
+obj-$(CONFIG_NO_GET_MEMORY_MAPPING) += memory_mapping-stub.o
+obj-$(CONFIG_NO_CORE_DUMP) += dump-stub.o
 LIBS+=-lz
 
 QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
diff --git a/cpu-all.h b/cpu-all.h
index 624030d..3a93c0c 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -22,8 +22,6 @@
 #include "qemu-common.h"
 #include "qemu-tls.h"
 #include "cpu-common.h"
-#include "memory_mapping.h"
-#include "dump.h"
 
 /* some important defines:
  *
@@ -525,72 +523,4 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf);
 int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr,
                         uint8_t *buf, int len, int is_write);
 
-#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING)
-int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env);
-bool cpu_paging_enabled(CPUArchState *env);
-#else
-static inline int cpu_get_memory_mapping(MemoryMappingList *list,
-                                         CPUArchState *env)
-{
-    return -1;
-}
-
-static inline bool cpu_paging_enabled(CPUArchState *env)
-{
-    return true;
-}
-#endif
-
-typedef int (*write_core_dump_function)(void *buf, size_t size, void *opaque);
-#if defined(CONFIG_HAVE_CORE_DUMP)
-int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env,
-                         int cpuid, void *opaque);
-int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env,
-                         int cpuid, void *opaque);
-int cpu_write_elf64_qemunote(write_core_dump_function f, CPUArchState *env,
-                             void *opaque);
-int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env,
-                             void *opaque);
-int cpu_get_dump_info(ArchDumpInfo *info);
-ssize_t cpu_get_note_size(int class, int machine, int nr_cpus);
-#else
-static inline int cpu_write_elf64_note(write_core_dump_function f,
-                                       CPUArchState *env, int cpuid,
-                                       void *opaque)
-{
-    return -1;
-}
-
-static inline int cpu_write_elf32_note(write_core_dump_function f,
-                                       CPUArchState *env, int cpuid,
-                                       void *opaque)
-{
-    return -1;
-}
-
-static inline int cpu_write_elf64_qemunote(write_core_dump_function f,
-                                           CPUArchState *env,
-                                           void *opaque)
-{
-    return -1;
-}
-
-static inline int cpu_write_elf32_qemunote(write_core_dump_function f,
-                                           CPUArchState *env,
-                                           void *opaque)
-{
-    return -1;
-}
-
-static inline int cpu_get_dump_info(ArchDumpInfo *info)
-{
-    return -1;
-}
-
-static inline ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
-{
-    return -1;
-}
-#endif
-
 #endif /* CPU_ALL_H */
diff --git a/dump-stub.c b/dump-stub.c
new file mode 100644
index 0000000..4c8bedb
--- /dev/null
+++ b/dump-stub.c
@@ -0,0 +1,77 @@
+/*
+ * QEMU dump
+ *
+ * Copyright Fujitsu, Corp. 2011, 2012
+ *
+ * Authors:
+ *     Wen Congyang <wency at cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include <unistd.h>
+#include "elf.h"
+#include <sys/procfs.h>
+#include <glib.h>
+#include "cpu.h"
+#include "cpu-all.h"
+#include "targphys.h"
+#include "monitor.h"
+#include "kvm.h"
+#include "dump.h"
+#include "sysemu.h"
+#include "bswap.h"
+#include "memory_mapping.h"
+#include "error.h"
+#include "qmp-commands.h"
+#include "gdbstub.h"
+
+/* we need this function in hmp.c */
+void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
+                           int64_t begin, bool has_length, int64_t length,
+                           Error **errp)
+{
+    error_set(errp, QERR_UNSUPPORTED);
+}
+
+int cpu_write_elf64_note(write_core_dump_function f,
+                                       CPUArchState *env, int cpuid,
+                                       void *opaque)
+{
+    return -1;
+}
+
+int cpu_write_elf32_note(write_core_dump_function f,
+                                       CPUArchState *env, int cpuid,
+                                       void *opaque)
+{
+    return -1;
+}
+
+int cpu_write_elf64_qemunote(write_core_dump_function f,
+                                           CPUArchState *env,
+                                           void *opaque)
+{
+    return -1;
+}
+
+int cpu_write_elf32_qemunote(write_core_dump_function f,
+                                           CPUArchState *env,
+                                           void *opaque)
+{
+    return -1;
+}
+
+int cpu_get_dump_info(ArchDumpInfo *info)
+{
+    return -1;
+}
+
+ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
+{
+    return -1;
+}
+
diff --git a/dump.c b/dump.c
index b24d4be..f5c7283 100644
--- a/dump.c
+++ b/dump.c
@@ -29,7 +29,6 @@
 #include "qmp-commands.h"
 #include "gdbstub.h"
 
-#if defined(CONFIG_HAVE_CORE_DUMP)
 static uint16_t cpu_convert_to_target16(uint16_t val, int endian)
 {
     if (endian == ELFDATA2LSB) {
@@ -876,13 +875,3 @@ void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
 
     g_free(s);
 }
-
-#else
-/* we need this function in hmp.c */
-void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
-                           int64_t begin, bool has_length, int64_t length,
-                           Error **errp)
-{
-    error_set(errp, QERR_UNSUPPORTED);
-}
-#endif
diff --git a/dump.h b/dump.h
index 28340cf..4dea3bb 100644
--- a/dump.h
+++ b/dump.h
@@ -20,4 +20,16 @@ typedef struct ArchDumpInfo {
     int d_class;    /* ELFCLASS32 or ELFCLASS64 */
 } ArchDumpInfo;
 
+typedef int (*write_core_dump_function)(void *buf, size_t size, void *opaque);
+int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env,
+                                                  int cpuid, void *opaque);
+int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env,
+                                                  int cpuid, void *opaque);
+int cpu_write_elf64_qemunote(write_core_dump_function f, CPUArchState *env,
+                                                          void *opaque);
+int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env,
+                                                          void *opaque);
+int cpu_get_dump_info(ArchDumpInfo *info);
+ssize_t cpu_get_note_size(int class, int machine, int nr_cpus);
+
 #endif
diff --git a/memory_mapping-stub.c b/memory_mapping-stub.c
new file mode 100644
index 0000000..104281d
--- /dev/null
+++ b/memory_mapping-stub.c
@@ -0,0 +1,33 @@
+/*
+ * QEMU memory mapping
+ *
+ * Copyright Fujitsu, Corp. 2011, 2012
+ *
+ * Authors:
+ *     Wen Congyang <wency at cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "cpu.h"
+#include "cpu-all.h"
+#include "memory_mapping.h"
+
+int qemu_get_guest_memory_mapping(MemoryMappingList *list)
+{
+    return -2;
+}
+
+int cpu_get_memory_mapping(MemoryMappingList *list,
+					                                          CPUArchState *env)
+{
+    return -1;
+}
+
+bool cpu_paging_enabled(CPUArchState *env)
+{
+    return true;
+}
+
diff --git a/memory_mapping.c b/memory_mapping.c
index 8810bb0..1125e3f 100644
--- a/memory_mapping.c
+++ b/memory_mapping.c
@@ -165,8 +165,6 @@ void memory_mapping_list_init(MemoryMappingList *list)
     QTAILQ_INIT(&list->head);
 }
 
-#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING)
-
 static CPUArchState *find_paging_enabled_cpu(CPUArchState *start_cpu)
 {
     CPUArchState *env;
@@ -210,7 +208,6 @@ int qemu_get_guest_memory_mapping(MemoryMappingList *list)
 
     return 0;
 }
-#endif
 
 void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list)
 {
diff --git a/memory_mapping.h b/memory_mapping.h
index a1aa64f..3f00358 100644
--- a/memory_mapping.h
+++ b/memory_mapping.h
@@ -16,7 +16,6 @@
 
 #include "qemu-queue.h"
 
-#ifndef CONFIG_USER_ONLY
 /* The physical and virtual address in the memory mapping are contiguous. */
 typedef struct MemoryMapping {
     target_phys_addr_t phys_addr;
@@ -31,6 +30,9 @@ typedef struct MemoryMappingList {
     QTAILQ_HEAD(, MemoryMapping) head;
 } MemoryMappingList;
 
+int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env);
+bool cpu_paging_enabled(CPUArchState *env);
+
 /*
  * add or merge the memory region [phys_addr, phys_addr + length) into the
  * memory mapping's list. The region's virtual address starts with virt_addr,
@@ -51,14 +53,7 @@ void memory_mapping_list_init(MemoryMappingList *list);
  *   -1: failed
  *   -2: unsupported
  */
-#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING)
 int qemu_get_guest_memory_mapping(MemoryMappingList *list);
-#else
-static inline int qemu_get_guest_memory_mapping(MemoryMappingList *list)
-{
-    return -2;
-}
-#endif
 
 /* get guest's memory mapping without do paging(virtual address is 0). */
 void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list);
@@ -66,9 +61,4 @@ void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list);
 void memory_mapping_filter(MemoryMappingList *list, int64_t begin,
                            int64_t length);
 
-#else
-
-/* We use MemoryMappingList* in cpu-all.h */
-typedef struct MemoryMappingList MemoryMappingList;
-#endif
 #endif
diff --git a/target-i386/arch_memory_mapping.c b/target-i386/arch_memory_mapping.c
index bd50e11..efb0211 100644
--- a/target-i386/arch_memory_mapping.c
+++ b/target-i386/arch_memory_mapping.c
@@ -13,6 +13,7 @@
 
 #include "cpu.h"
 #include "cpu-all.h"
+#include "memory_mapping.h"
 
 /* PAE Paging or IA-32e Paging */
 static void walk_pte(MemoryMappingList *list, target_phys_addr_t pte_start_addr,
commit 4720bd050655a56b4b048d8856a03ae187481a7f
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Jun 7 08:48:09 2012 +0200

    dump: change cpu_get_note_size to return ssize_t
    
    So that it can use the same prototype in both cases.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/cpu-all.h b/cpu-all.h
index e8749de..624030d 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -552,7 +552,7 @@ int cpu_write_elf64_qemunote(write_core_dump_function f, CPUArchState *env,
 int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env,
                              void *opaque);
 int cpu_get_dump_info(ArchDumpInfo *info);
-size_t cpu_get_note_size(int class, int machine, int nr_cpus);
+ssize_t cpu_get_note_size(int class, int machine, int nr_cpus);
 #else
 static inline int cpu_write_elf64_note(write_core_dump_function f,
                                        CPUArchState *env, int cpuid,
@@ -587,7 +587,7 @@ static inline int cpu_get_dump_info(ArchDumpInfo *info)
     return -1;
 }
 
-static inline int cpu_get_note_size(int class, int machine, int nr_cpus)
+static inline ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
 {
     return -1;
 }
diff --git a/dump.c b/dump.c
index 0ca14f8..b24d4be 100644
--- a/dump.c
+++ b/dump.c
@@ -750,6 +750,13 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
         goto cleanup;
     }
 
+    s->note_size = cpu_get_note_size(s->dump_info.d_class,
+                                     s->dump_info.d_machine, nr_cpus);
+    if (ret < 0) {
+        error_set(errp, QERR_UNSUPPORTED);
+        goto cleanup;
+    }
+
     /* get memory mapping */
     memory_mapping_list_init(&s->list);
     if (paging) {
@@ -784,8 +791,6 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
         }
     }
 
-    s->note_size = cpu_get_note_size(s->dump_info.d_class,
-                                     s->dump_info.d_machine, nr_cpus);
     if (s->dump_info.d_class == ELFCLASS64) {
         if (s->have_section) {
             s->memory_offset = sizeof(Elf64_Ehdr) +
diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c
index 135d855..7c2b514 100644
--- a/target-i386/arch_dump.c
+++ b/target-i386/arch_dump.c
@@ -415,7 +415,7 @@ int cpu_get_dump_info(ArchDumpInfo *info)
     return 0;
 }
 
-size_t cpu_get_note_size(int class, int machine, int nr_cpus)
+ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
 {
     int name_size = 5; /* "CORE" or "QEMU" */
     size_t elf_note_size = 0;
commit db2077692ffee1f87a1f4af0cf275c33aba6c867
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Jun 7 07:02:04 2012 +0200

    dump: do not compile dump.o for user-mode emulation
    
    It is not needed, because the monitor is not included.
    
    Cc: Wen Congyang <wency at cn.fujitsu.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.target b/Makefile.target
index 67d5f3e..f1ec554 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -147,6 +147,7 @@ obj-y += memory.o savevm.o cputlb.o
 obj-y += memory_mapping.o
 obj-$(CONFIG_HAVE_GET_MEMORY_MAPPING) += arch_memory_mapping.o
 obj-$(CONFIG_HAVE_CORE_DUMP) += arch_dump.o
+obj-y += dump.o
 LIBS+=-lz
 
 QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
@@ -196,8 +197,6 @@ obj-y += $(addprefix ../, $(trace-obj-y))
 
 endif # CONFIG_SOFTMMU
 
-obj-y += dump.o
-
 ifndef CONFIG_LINUX_USER
 ifndef CONFIG_BSD_USER
 # libcacard needs qemu-thread support, and besides is only needed by devices
commit 9cdc8df314bddc95125e87039b0f2df3fc5fa866
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue May 29 10:55:47 2012 +0200

    build: move libobj-y variable to nested Makefile.objs
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.target b/Makefile.target
index c416ba5..67d5f3e 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -76,41 +76,19 @@ all: $(PROGS) stap
 
 #########################################################
 # cpu emulator library
-libobj-y = exec.o translate-all.o cpu-exec.o translate.o
-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
-ifneq ($(TARGET_BASE_ARCH), ppc)
-libobj-y += cpu.o
-endif
-libobj-$(TARGET_SPARC64) += vis_helper.o
-libobj-$(CONFIG_NEED_MMU) += mmu.o
-libobj-$(TARGET_ARM) += neon_helper.o iwmmxt_helper.o
-ifeq ($(TARGET_BASE_ARCH), sparc)
-libobj-y += fop_helper.o cc_helper.o win_helper.o mmu_helper.o ldst_helper.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 mem_helper.o
-
-libobj-y += disas.o
-libobj-$(CONFIG_TCI_DIS) += tci-dis.o
-
+obj-y = exec.o translate-all.o cpu-exec.o translate.o
+obj-y += tcg/tcg.o tcg/optimize.o
+obj-$(CONFIG_TCG_INTERPRETER) += tci.o
+obj-y += fpu/softfloat.o
+obj-y += disas.o
+obj-$(CONFIG_TCI_DIS) += tci-dis.o
 obj-y += target-$(TARGET_BASE_ARCH)/
+obj-$(CONFIG_GDBSTUB_XML) += gdbstub-xml.o
 
 tci-dis.o: QEMU_CFLAGS += -I$(SRC_PATH)/tcg -I$(SRC_PATH)/tcg/tci
 
 # HELPER_CFLAGS is used for all the legacy code compiled with static register
 # variables
-ifneq ($(TARGET_BASE_ARCH), sparc)
-op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
-endif
 user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 
 # Note: this is a workaround. The real fix is to avoid compiling
@@ -130,7 +108,6 @@ obj-y += gdbstub.o thunk.o user-exec.o $(oslib-obj-y)
 obj-y += $(addprefix ../, $(universal-obj-y))
 obj-y += $(addprefix ../libuser/, $(user-obj-y))
 obj-y += $(addprefix ../libdis-user/, $(libdis-y))
-obj-y += $(libobj-y)
 
 endif #CONFIG_LINUX_USER
 
@@ -147,7 +124,6 @@ obj-y += gdbstub.o user-exec.o
 obj-y += $(addprefix ../, $(universal-obj-y))
 obj-y += $(addprefix ../libuser/, $(user-obj-y))
 obj-y += $(addprefix ../libdis-user/, $(libdis-y))
-obj-y += $(libobj-y)
 
 endif #CONFIG_BSD_USER
 
@@ -215,7 +191,6 @@ GENERATED_HEADERS += hmp-commands.h qmp-commands-old.h
 obj-y += $(addprefix ../, $(universal-obj-y))
 obj-y += $(addprefix ../, $(common-obj-y))
 obj-y += $(addprefix ../libdis/, $(libdis-y))
-obj-y += $(libobj-y)
 obj-y += $(addprefix $(HWDIR)/, $(hw-obj-y))
 obj-y += $(addprefix ../, $(trace-obj-y))
 
@@ -231,8 +206,6 @@ obj-$(CONFIG_SMARTCARD_NSS) += $(addprefix ../libcacard/, $(libcacard-y))
 endif # CONFIG_BSD_USER
 endif # CONFIG_LINUX_USER
 
-obj-$(CONFIG_GDBSTUB_XML) += gdbstub-xml.o
-
 nested-vars = obj-y
 dummy := $(call unnest-vars)
 
diff --git a/configure b/configure
index a2fca50..cc77700 100755
--- a/configure
+++ b/configure
@@ -3911,12 +3911,6 @@ if test "$target_softmmu" = "yes" ; then
   esac
 fi
 
-if test "$target_softmmu" = "yes" -a \( \
-        "$TARGET_ARCH" = "microblaze" -o \
-        "$TARGET_ARCH" = "cris" \) ; then
-  echo "CONFIG_NEED_MMU=y" >> $config_target_mak
-fi
-
 if test "$gprof" = "yes" ; then
   echo "TARGET_GPROF=yes" >> $config_target_mak
   if test "$target_linux_user" = "yes" ; then
diff --git a/target-alpha/Makefile.objs b/target-alpha/Makefile.objs
index c574c9e..9a72870 100644
--- a/target-alpha/Makefile.objs
+++ b/target-alpha/Makefile.objs
@@ -1 +1,2 @@
-# still empty
+obj-y += helper.o cpu.o
+obj-y += int_helper.o fpu_helper.o sys_helper.o mem_helper.o
diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs
index f5bb920..4dcd3c5 100644
--- a/target-arm/Makefile.objs
+++ b/target-arm/Makefile.objs
@@ -1 +1,5 @@
 obj-y += arm-semi.o
+obj-y += op_helper.o helper.o cpu.o
+obj-y += neon_helper.o iwmmxt_helper.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-cris/Makefile.objs b/target-cris/Makefile.objs
index c574c9e..9a50c28 100644
--- a/target-cris/Makefile.objs
+++ b/target-cris/Makefile.objs
@@ -1 +1,4 @@
-# still empty
+obj-y += op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += mmu.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-i386/Makefile.objs b/target-i386/Makefile.objs
index 93c6f3f..2538c43 100644
--- a/target-i386/Makefile.objs
+++ b/target-i386/Makefile.objs
@@ -1,3 +1,6 @@
+obj-y += op_helper.o helper.o cpu.o
 obj-$(CONFIG_KVM) += hyperv.o
 obj-$(CONFIG_LINUX_USER) += ioport-user.o
 obj-$(CONFIG_BSD_USER) += ioport-user.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-lm32/Makefile.objs b/target-lm32/Makefile.objs
index c574c9e..8e9be60 100644
--- a/target-lm32/Makefile.objs
+++ b/target-lm32/Makefile.objs
@@ -1 +1,3 @@
-# still empty
+obj-y += op_helper.o helper.o cpu.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-m68k/Makefile.objs b/target-m68k/Makefile.objs
index e73a5ba..553691d 100644
--- a/target-m68k/Makefile.objs
+++ b/target-m68k/Makefile.objs
@@ -1 +1,4 @@
 obj-y += m68k-semi.o
+obj-y += op_helper.o helper.o cpu.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-microblaze/Makefile.objs b/target-microblaze/Makefile.objs
index c574c9e..9a50c28 100644
--- a/target-microblaze/Makefile.objs
+++ b/target-microblaze/Makefile.objs
@@ -1 +1,4 @@
-# still empty
+obj-y += op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += mmu.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-mips/Makefile.objs b/target-mips/Makefile.objs
index c574c9e..8e9be60 100644
--- a/target-mips/Makefile.objs
+++ b/target-mips/Makefile.objs
@@ -1 +1,3 @@
-# still empty
+obj-y += op_helper.o helper.o cpu.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-ppc/Makefile.objs b/target-ppc/Makefile.objs
index c574c9e..bf46331 100644
--- a/target-ppc/Makefile.objs
+++ b/target-ppc/Makefile.objs
@@ -1 +1,3 @@
-# still empty
+obj-y += op_helper.o helper.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs
index c574c9e..8e9be60 100644
--- a/target-s390x/Makefile.objs
+++ b/target-s390x/Makefile.objs
@@ -1 +1,3 @@
-# still empty
+obj-y += op_helper.o helper.o cpu.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-sh4/Makefile.objs b/target-sh4/Makefile.objs
index c574c9e..8e9be60 100644
--- a/target-sh4/Makefile.objs
+++ b/target-sh4/Makefile.objs
@@ -1 +1,3 @@
-# still empty
+obj-y += op_helper.o helper.o cpu.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-sparc/Makefile.objs b/target-sparc/Makefile.objs
index c574c9e..3556d13 100644
--- a/target-sparc/Makefile.objs
+++ b/target-sparc/Makefile.objs
@@ -1 +1,7 @@
-# still empty
+obj-y += helper.o cpu.o
+obj-y += fop_helper.o cc_helper.o win_helper.o mmu_helper.o ldst_helper.o
+obj-$(TARGET_SPARC) += int32_helper.o
+obj-$(TARGET_SPARC64) += int64_helper.o
+obj-$(TARGET_SPARC64) += vis_helper.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-unicore32/Makefile.objs b/target-unicore32/Makefile.objs
index c574c9e..8e9be60 100644
--- a/target-unicore32/Makefile.objs
+++ b/target-unicore32/Makefile.objs
@@ -1 +1,3 @@
-# still empty
+obj-y += op_helper.o helper.o cpu.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-xtensa/Makefile.objs b/target-xtensa/Makefile.objs
index a49ca8d..3cdf604 100644
--- a/target-xtensa/Makefile.objs
+++ b/target-xtensa/Makefile.objs
@@ -2,3 +2,6 @@ obj-y += xtensa-semi.o
 obj-y += core-dc232b.o
 obj-y += core-dc233c.o
 obj-y += core-fsf.o
+obj-y += op_helper.o helper.o cpu.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
commit 5e8861a0361d8d39ab69fe557294471c28c49c8b
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue May 29 10:23:15 2012 +0200

    build: move obj-TARGET-y variables to nested Makefile.objs
    
    Also drop duplicate occurrence of device-hotplug.o.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.target b/Makefile.target
index 5cc577b..c416ba5 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -102,6 +102,8 @@ 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
 
+obj-y += target-$(TARGET_BASE_ARCH)/
+
 tci-dis.o: QEMU_CFLAGS += -I$(SRC_PATH)/tcg -I$(SRC_PATH)/tcg/tci
 
 # HELPER_CFLAGS is used for all the legacy code compiled with static register
@@ -124,9 +126,6 @@ QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) -I$(SRC_PATH)/linux-user
 
 obj-y += linux-user/
 obj-y += gdbstub.o thunk.o user-exec.o $(oslib-obj-y)
-obj-i386-y += ioport-user.o
-obj-$(TARGET_ARM) += arm-semi.o
-obj-$(TARGET_M68K) += m68k-semi.o
 
 obj-y += $(addprefix ../, $(universal-obj-y))
 obj-y += $(addprefix ../libuser/, $(user-obj-y))
@@ -144,7 +143,6 @@ QEMU_CFLAGS+=-I$(SRC_PATH)/bsd-user -I$(SRC_PATH)/bsd-user/$(TARGET_ARCH)
 
 obj-y += bsd-user/
 obj-y += gdbstub.o user-exec.o
-obj-i386-y += ioport-user.o
 
 obj-y += $(addprefix ../, $(universal-obj-y))
 obj-y += $(addprefix ../libuser/, $(user-obj-y))
@@ -157,7 +155,7 @@ endif #CONFIG_BSD_USER
 # System emulator target
 ifdef CONFIG_SOFTMMU
 
-obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o ioport.o
+obj-y += arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o ioport.o
 # virtio has to be here due to weird dependency between PCI and virtio-net.
 # need to fix this properly
 obj-$(CONFIG_NO_PCI) += pci-stub.o
@@ -175,8 +173,6 @@ obj-$(CONFIG_HAVE_GET_MEMORY_MAPPING) += arch_memory_mapping.o
 obj-$(CONFIG_HAVE_CORE_DUMP) += arch_dump.o
 LIBS+=-lz
 
-obj-i386-$(CONFIG_KVM) += hyperv.o
-
 QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
 QEMU_CFLAGS += $(VNC_SASL_CFLAGS)
 QEMU_CFLAGS += $(VNC_JPEG_CFLAGS)
@@ -186,8 +182,6 @@ 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 xen_apic.o
-
 # Inter-VM PCI shared memory
 CONFIG_IVSHMEM =
 ifeq ($(CONFIG_KVM), y)
@@ -201,172 +195,18 @@ obj-$(CONFIG_IVSHMEM) += ivshmem.o
 obj-y += device-hotplug.o
 
 # Hardware support
-obj-i386-y += mc146818rtc.o pc.o
-obj-i386-y += apic_common.o apic.o kvmvapic.o
-obj-i386-y += sga.o ioapic_common.o ioapic.o piix_pci.o
-obj-i386-y += vmport.o
-obj-i386-y += pci-hotplug.o smbios.o wdt_ib700.o
-obj-i386-y += debugcon.o multiboot.o
-obj-i386-y += pc_piix.o
-obj-i386-y += pc_sysfw.o
-obj-i386-$(CONFIG_KVM) += kvm/clock.o kvm/apic.o kvm/i8259.o kvm/ioapic.o kvm/i8254.o
-obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
-
-# shared objects
-obj-ppc-y = ppc.o ppc_booke.o
-# PREP target
-obj-ppc-y += mc146818rtc.o
-obj-ppc-y += ppc_prep.o
-# OldWorld PowerMac
-obj-ppc-y += ppc_oldworld.o
-# NewWorld PowerMac
-obj-ppc-y += ppc_newworld.o
-# IBM pSeries (sPAPR)
-obj-ppc-$(CONFIG_PSERIES) += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o
-obj-ppc-$(CONFIG_PSERIES) += xics.o spapr_vty.o spapr_llan.o spapr_vscsi.o
-obj-ppc-$(CONFIG_PSERIES) += spapr_pci.o device-hotplug.o pci-hotplug.o
-# PowerPC 4xx boards
-obj-ppc-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
-obj-ppc-y += ppc440_bamboo.o
-# PowerPC E500 boards
-obj-ppc-y += ppce500_mpc8544ds.o mpc8544_guts.o ppce500_spin.o
-# PowerPC 440 Xilinx ML507 reference board.
-obj-ppc-y += virtex_ml507.o
-obj-ppc-$(CONFIG_KVM) += kvm_ppc.o
-obj-ppc-$(CONFIG_FDT) += device_tree.o
-# PowerPC OpenPIC
-obj-ppc-y += openpic.o
-
-# Xilinx PPC peripherals
-obj-ppc-y += xilinx_intc.o
-obj-ppc-y += xilinx_timer.o
-obj-ppc-y += xilinx_uartlite.o
-obj-ppc-y += xilinx_ethlite.o
-
-# LM32 boards
-obj-lm32-y += lm32_boards.o
-obj-lm32-y += milkymist.o
-
-# LM32 peripherals
-obj-lm32-y += lm32_pic.o
-obj-lm32-y += lm32_juart.o
-obj-lm32-y += lm32_timer.o
-obj-lm32-y += lm32_uart.o
-obj-lm32-y += lm32_sys.o
-obj-lm32-y += milkymist-ac97.o
-obj-lm32-y += milkymist-hpdmc.o
-obj-lm32-y += milkymist-memcard.o
-obj-lm32-y += milkymist-minimac2.o
-obj-lm32-y += milkymist-pfpu.o
-obj-lm32-y += milkymist-softusb.o
-obj-lm32-y += milkymist-sysctl.o
-obj-lm32-$(CONFIG_OPENGL) += milkymist-tmu2.o
-obj-lm32-y += milkymist-uart.o
-obj-lm32-y += milkymist-vgafb.o
-obj-lm32-y += framebuffer.o
-
-obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
-obj-mips-y += mips_addr.o mips_timer.o mips_int.o
-obj-mips-y += gt64xxx.o mc146818rtc.o
-obj-mips-$(CONFIG_FULONG) += bonito.o vt82c686.o mips_fulong2e.o
-
-obj-microblaze-y = petalogix_s3adsp1800_mmu.o
-obj-microblaze-y += petalogix_ml605_mmu.o
-obj-microblaze-y += microblaze_boot.o
-
-obj-microblaze-y += microblaze_pic_cpu.o
-obj-microblaze-y += xilinx_intc.o
-obj-microblaze-y += xilinx_timer.o
-obj-microblaze-y += xilinx_uartlite.o
-obj-microblaze-y += xilinx_ethlite.o
-obj-microblaze-y += xilinx_axidma.o
-obj-microblaze-y += xilinx_axienet.o
-
-obj-microblaze-$(CONFIG_FDT) += device_tree.o
-
-# Boards
-obj-cris-y = cris_pic_cpu.o
-obj-cris-y += cris-boot.o
-obj-cris-y += axis_dev88.o
-
-# IO blocks
-obj-cris-y += etraxfs_dma.o
-obj-cris-y += etraxfs_pic.o
-obj-cris-y += etraxfs_eth.o
-obj-cris-y += etraxfs_timer.o
-obj-cris-y += etraxfs_ser.o
-
 ifeq ($(TARGET_ARCH), sparc64)
-obj-sparc-y = sun4u.o apb_pci.o
-obj-sparc-y += mc146818rtc.o
+obj-y += hw/sparc64/
 else
-obj-sparc-y = sun4m.o lance.o tcx.o sun4m_iommu.o slavio_intctl.o
-obj-sparc-y += slavio_timer.o slavio_misc.o sparc32_dma.o
-obj-sparc-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o leon3.o
-
-# GRLIB
-obj-sparc-y += grlib_gptimer.o grlib_irqmp.o grlib_apbuart.o
+obj-y += hw/$(TARGET_BASE_ARCH)/
 endif
 
-obj-arm-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o
-obj-arm-y += arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o
-obj-arm-y += versatile_pci.o
-obj-arm-y += versatile_i2c.o
-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
-obj-arm-y += exynos4210_pmu.o exynos4210_mct.o exynos4210_fimd.o
-obj-arm-y += arm_l2x0.o
-obj-arm-y += arm_mptimer.o a15mpcore.o
-obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
-obj-arm-y += highbank.o
-obj-arm-y += pl061.o
-obj-arm-y += xgmac.o
-obj-arm-y += arm-semi.o
-obj-arm-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
-obj-arm-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
-obj-arm-y += gumstix.o
-obj-arm-y += zaurus.o ide/microdrive.o spitz.o tosa.o tc6393xb.o
-obj-arm-y += omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o \
-		omap_gpio.o omap_intc.o omap_uart.o
-obj-arm-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o \
-		omap_gpmc.o omap_sdrc.o omap_spi.o omap_tap.o omap_l4.o
-obj-arm-y += omap_sx1.o palm.o tsc210x.o
-obj-arm-y += nseries.o blizzard.o onenand.o cbus.o tusb6010.o usb/hcd-musb.o
-obj-arm-y += mst_fpga.o mainstone.o
-obj-arm-y += z2.o
-obj-arm-y += musicpal.o bitbang_i2c.o marvell_88w8618_audio.o
-obj-arm-y += framebuffer.o
-obj-arm-y += vexpress.o
-obj-arm-y += strongarm.o
-obj-arm-y += collie.o
-obj-arm-y += pl041.o lm4549.o
-obj-arm-$(CONFIG_FDT) += device_tree.o
-
-obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
-obj-sh4-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o sm501.o
-obj-sh4-y += ide/mmio.o
-
-obj-m68k-y = an5206.o mcf5206.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o
-obj-m68k-y += m68k-semi.o dummy_m68k.o
-
-obj-s390x-y = s390-virtio-bus.o s390-virtio.o
-
-obj-alpha-y = mc146818rtc.o
-obj-alpha-y += alpha_pci.o alpha_dp264.o alpha_typhoon.o
-
-obj-xtensa-y += xtensa_pic.o
-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
+# Device tree
+ifeq ($(CONFIG_FDT), y)
+obj-$(TARGET_ARM) += device_tree.o
+obj-$(TARGET_MICROBLAZE) += device_tree.o
+obj-$(TARGET_PPC) += device_tree.o
+endif
 
 main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
 
@@ -398,12 +238,12 @@ dummy := $(call unnest-vars)
 
 ifdef QEMU_PROGW
 # The linker builds a windows executable. Make also a console executable.
-$(QEMU_PROGW): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)
+$(QEMU_PROGW): $(obj-y)
 	$(call LINK,$^)
 $(QEMU_PROG): $(QEMU_PROGW)
 	$(call quiet-command,$(OBJCOPY) --subsystem console $(QEMU_PROGW) $(QEMU_PROG),"  GEN   $(TARGET_DIR)$(QEMU_PROG)")
 else
-$(QEMU_PROG): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)
+$(QEMU_PROG): $(obj-y)
 	$(call LINK,$^)
 endif
 
diff --git a/arm-semi.c b/arm-semi.c
deleted file mode 100644
index 88ca9bb..0000000
--- a/arm-semi.c
+++ /dev/null
@@ -1,509 +0,0 @@
-/*
- *  Arm "Angel" semihosting syscalls
- *
- *  Copyright (c) 2005, 2007 CodeSourcery.
- *  Written by Paul Brook.
- *
- *  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 <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-
-#include "cpu.h"
-#ifdef CONFIG_USER_ONLY
-#include "qemu.h"
-
-#define ARM_ANGEL_HEAP_SIZE (128 * 1024 * 1024)
-#else
-#include "qemu-common.h"
-#include "gdbstub.h"
-#include "hw/arm-misc.h"
-#endif
-
-#define TARGET_SYS_OPEN        0x01
-#define TARGET_SYS_CLOSE       0x02
-#define TARGET_SYS_WRITEC      0x03
-#define TARGET_SYS_WRITE0      0x04
-#define TARGET_SYS_WRITE       0x05
-#define TARGET_SYS_READ        0x06
-#define TARGET_SYS_READC       0x07
-#define TARGET_SYS_ISTTY       0x09
-#define TARGET_SYS_SEEK        0x0a
-#define TARGET_SYS_FLEN        0x0c
-#define TARGET_SYS_TMPNAM      0x0d
-#define TARGET_SYS_REMOVE      0x0e
-#define TARGET_SYS_RENAME      0x0f
-#define TARGET_SYS_CLOCK       0x10
-#define TARGET_SYS_TIME        0x11
-#define TARGET_SYS_SYSTEM      0x12
-#define TARGET_SYS_ERRNO       0x13
-#define TARGET_SYS_GET_CMDLINE 0x15
-#define TARGET_SYS_HEAPINFO    0x16
-#define TARGET_SYS_EXIT        0x18
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-#define GDB_O_RDONLY  0x000
-#define GDB_O_WRONLY  0x001
-#define GDB_O_RDWR    0x002
-#define GDB_O_APPEND  0x008
-#define GDB_O_CREAT   0x200
-#define GDB_O_TRUNC   0x400
-#define GDB_O_BINARY  0
-
-static int gdb_open_modeflags[12] = {
-    GDB_O_RDONLY,
-    GDB_O_RDONLY | GDB_O_BINARY,
-    GDB_O_RDWR,
-    GDB_O_RDWR | GDB_O_BINARY,
-    GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC,
-    GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY,
-    GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC,
-    GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY,
-    GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND,
-    GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY,
-    GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND,
-    GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY
-};
-
-static int open_modeflags[12] = {
-    O_RDONLY,
-    O_RDONLY | O_BINARY,
-    O_RDWR,
-    O_RDWR | O_BINARY,
-    O_WRONLY | O_CREAT | O_TRUNC,
-    O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
-    O_RDWR | O_CREAT | O_TRUNC,
-    O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
-    O_WRONLY | O_CREAT | O_APPEND,
-    O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
-    O_RDWR | O_CREAT | O_APPEND,
-    O_RDWR | O_CREAT | O_APPEND | O_BINARY
-};
-
-#ifdef CONFIG_USER_ONLY
-static inline uint32_t set_swi_errno(TaskState *ts, uint32_t code)
-{
-    if (code == (uint32_t)-1)
-        ts->swi_errno = errno;
-    return code;
-}
-#else
-static inline uint32_t set_swi_errno(CPUARMState *env, uint32_t code)
-{
-    return code;
-}
-
-#include "softmmu-semi.h"
-#endif
-
-static target_ulong arm_semi_syscall_len;
-
-#if !defined(CONFIG_USER_ONLY)
-static target_ulong syscall_err;
-#endif
-
-static void arm_semi_cb(CPUARMState *env, target_ulong ret, target_ulong err)
-{
-#ifdef CONFIG_USER_ONLY
-    TaskState *ts = env->opaque;
-#endif
-
-    if (ret == (target_ulong)-1) {
-#ifdef CONFIG_USER_ONLY
-        ts->swi_errno = err;
-#else
-	syscall_err = err;
-#endif
-        env->regs[0] = ret;
-    } else {
-        /* Fixup syscalls that use nonstardard return conventions.  */
-        switch (env->regs[0]) {
-        case TARGET_SYS_WRITE:
-        case TARGET_SYS_READ:
-            env->regs[0] = arm_semi_syscall_len - ret;
-            break;
-        case TARGET_SYS_SEEK:
-            env->regs[0] = 0;
-            break;
-        default:
-            env->regs[0] = ret;
-            break;
-        }
-    }
-}
-
-static void arm_semi_flen_cb(CPUARMState *env, target_ulong ret, target_ulong err)
-{
-    /* The size is always stored in big-endian order, extract
-       the value. We assume the size always fit in 32 bits.  */
-    uint32_t size;
-    cpu_memory_rw_debug(env, env->regs[13]-64+32, (uint8_t *)&size, 4, 0);
-    env->regs[0] = be32_to_cpu(size);
-#ifdef CONFIG_USER_ONLY
-    ((TaskState *)env->opaque)->swi_errno = err;
-#else
-    syscall_err = err;
-#endif
-}
-
-#define ARG(n)					\
-({						\
-    target_ulong __arg;				\
-    /* FIXME - handle get_user() failure */	\
-    get_user_ual(__arg, args + (n) * 4);	\
-    __arg;					\
-})
-#define SET_ARG(n, val) put_user_ual(val, args + (n) * 4)
-uint32_t do_arm_semihosting(CPUARMState *env)
-{
-    target_ulong args;
-    char * s;
-    int nr;
-    uint32_t ret;
-    uint32_t len;
-#ifdef CONFIG_USER_ONLY
-    TaskState *ts = env->opaque;
-#else
-    CPUARMState *ts = env;
-#endif
-
-    nr = env->regs[0];
-    args = env->regs[1];
-    switch (nr) {
-    case TARGET_SYS_OPEN:
-        if (!(s = lock_user_string(ARG(0))))
-            /* FIXME - should this error code be -TARGET_EFAULT ? */
-            return (uint32_t)-1;
-        if (ARG(1) >= 12)
-            return (uint32_t)-1;
-        if (strcmp(s, ":tt") == 0) {
-            if (ARG(1) < 4)
-                return STDIN_FILENO;
-            else
-                return STDOUT_FILENO;
-        }
-        if (use_gdb_syscalls()) {
-            gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", ARG(0),
-			   (int)ARG(2)+1, gdb_open_modeflags[ARG(1)]);
-            return env->regs[0];
-        } else {
-            ret = set_swi_errno(ts, open(s, open_modeflags[ARG(1)], 0644));
-        }
-        unlock_user(s, ARG(0), 0);
-        return ret;
-    case TARGET_SYS_CLOSE:
-        if (use_gdb_syscalls()) {
-            gdb_do_syscall(arm_semi_cb, "close,%x", ARG(0));
-            return env->regs[0];
-        } else {
-            return set_swi_errno(ts, close(ARG(0)));
-        }
-    case TARGET_SYS_WRITEC:
-        {
-          char c;
-
-          if (get_user_u8(c, args))
-              /* FIXME - should this error code be -TARGET_EFAULT ? */
-              return (uint32_t)-1;
-          /* Write to debug console.  stderr is near enough.  */
-          if (use_gdb_syscalls()) {
-                gdb_do_syscall(arm_semi_cb, "write,2,%x,1", args);
-                return env->regs[0];
-          } else {
-                return write(STDERR_FILENO, &c, 1);
-          }
-        }
-    case TARGET_SYS_WRITE0:
-        if (!(s = lock_user_string(args)))
-            /* FIXME - should this error code be -TARGET_EFAULT ? */
-            return (uint32_t)-1;
-        len = strlen(s);
-        if (use_gdb_syscalls()) {
-            gdb_do_syscall(arm_semi_cb, "write,2,%x,%x\n", args, len);
-            ret = env->regs[0];
-        } else {
-            ret = write(STDERR_FILENO, s, len);
-        }
-        unlock_user(s, args, 0);
-        return ret;
-    case TARGET_SYS_WRITE:
-        len = ARG(2);
-        if (use_gdb_syscalls()) {
-            arm_semi_syscall_len = len;
-            gdb_do_syscall(arm_semi_cb, "write,%x,%x,%x", ARG(0), ARG(1), len);
-            return env->regs[0];
-        } else {
-            if (!(s = lock_user(VERIFY_READ, ARG(1), len, 1)))
-                /* FIXME - should this error code be -TARGET_EFAULT ? */
-                return (uint32_t)-1;
-            ret = set_swi_errno(ts, write(ARG(0), s, len));
-            unlock_user(s, ARG(1), 0);
-            if (ret == (uint32_t)-1)
-                return -1;
-            return len - ret;
-        }
-    case TARGET_SYS_READ:
-        len = ARG(2);
-        if (use_gdb_syscalls()) {
-            arm_semi_syscall_len = len;
-            gdb_do_syscall(arm_semi_cb, "read,%x,%x,%x", ARG(0), ARG(1), len);
-            return env->regs[0];
-        } else {
-            if (!(s = lock_user(VERIFY_WRITE, ARG(1), len, 0)))
-                /* FIXME - should this error code be -TARGET_EFAULT ? */
-                return (uint32_t)-1;
-            do
-              ret = set_swi_errno(ts, read(ARG(0), s, len));
-            while (ret == -1 && errno == EINTR);
-            unlock_user(s, ARG(1), len);
-            if (ret == (uint32_t)-1)
-                return -1;
-            return len - ret;
-        }
-    case TARGET_SYS_READC:
-       /* XXX: Read from debug cosole. Not implemented.  */
-        return 0;
-    case TARGET_SYS_ISTTY:
-        if (use_gdb_syscalls()) {
-            gdb_do_syscall(arm_semi_cb, "isatty,%x", ARG(0));
-            return env->regs[0];
-        } else {
-            return isatty(ARG(0));
-        }
-    case TARGET_SYS_SEEK:
-        if (use_gdb_syscalls()) {
-            gdb_do_syscall(arm_semi_cb, "lseek,%x,%x,0", ARG(0), ARG(1));
-            return env->regs[0];
-        } else {
-            ret = set_swi_errno(ts, lseek(ARG(0), ARG(1), SEEK_SET));
-            if (ret == (uint32_t)-1)
-              return -1;
-            return 0;
-        }
-    case TARGET_SYS_FLEN:
-        if (use_gdb_syscalls()) {
-            gdb_do_syscall(arm_semi_flen_cb, "fstat,%x,%x",
-			   ARG(0), env->regs[13]-64);
-            return env->regs[0];
-        } else {
-            struct stat buf;
-            ret = set_swi_errno(ts, fstat(ARG(0), &buf));
-            if (ret == (uint32_t)-1)
-                return -1;
-            return buf.st_size;
-        }
-    case TARGET_SYS_TMPNAM:
-        /* XXX: Not implemented.  */
-        return -1;
-    case TARGET_SYS_REMOVE:
-        if (use_gdb_syscalls()) {
-            gdb_do_syscall(arm_semi_cb, "unlink,%s", ARG(0), (int)ARG(1)+1);
-            ret = env->regs[0];
-        } else {
-            if (!(s = lock_user_string(ARG(0))))
-                /* FIXME - should this error code be -TARGET_EFAULT ? */
-                return (uint32_t)-1;
-            ret =  set_swi_errno(ts, remove(s));
-            unlock_user(s, ARG(0), 0);
-        }
-        return ret;
-    case TARGET_SYS_RENAME:
-        if (use_gdb_syscalls()) {
-            gdb_do_syscall(arm_semi_cb, "rename,%s,%s",
-                           ARG(0), (int)ARG(1)+1, ARG(2), (int)ARG(3)+1);
-            return env->regs[0];
-        } else {
-            char *s2;
-            s = lock_user_string(ARG(0));
-            s2 = lock_user_string(ARG(2));
-            if (!s || !s2)
-                /* FIXME - should this error code be -TARGET_EFAULT ? */
-                ret = (uint32_t)-1;
-            else
-                ret = set_swi_errno(ts, rename(s, s2));
-            if (s2)
-                unlock_user(s2, ARG(2), 0);
-            if (s)
-                unlock_user(s, ARG(0), 0);
-            return ret;
-        }
-    case TARGET_SYS_CLOCK:
-        return clock() / (CLOCKS_PER_SEC / 100);
-    case TARGET_SYS_TIME:
-        return set_swi_errno(ts, time(NULL));
-    case TARGET_SYS_SYSTEM:
-        if (use_gdb_syscalls()) {
-            gdb_do_syscall(arm_semi_cb, "system,%s", ARG(0), (int)ARG(1)+1);
-            return env->regs[0];
-        } else {
-            if (!(s = lock_user_string(ARG(0))))
-                /* FIXME - should this error code be -TARGET_EFAULT ? */
-                return (uint32_t)-1;
-            ret = set_swi_errno(ts, system(s));
-            unlock_user(s, ARG(0), 0);
-            return ret;
-        }
-    case TARGET_SYS_ERRNO:
-#ifdef CONFIG_USER_ONLY
-        return ts->swi_errno;
-#else
-        return syscall_err;
-#endif
-    case TARGET_SYS_GET_CMDLINE:
-        {
-            /* Build a command-line from the original argv.
-             *
-             * The inputs are:
-             *     * ARG(0), pointer to a buffer of at least the size
-             *               specified in ARG(1).
-             *     * ARG(1), size of the buffer pointed to by ARG(0) in
-             *               bytes.
-             *
-             * The outputs are:
-             *     * ARG(0), pointer to null-terminated string of the
-             *               command line.
-             *     * ARG(1), length of the string pointed to by ARG(0).
-             */
-
-            char *output_buffer;
-            size_t input_size = ARG(1);
-            size_t output_size;
-            int status = 0;
-
-            /* Compute the size of the output string.  */
-#if !defined(CONFIG_USER_ONLY)
-            output_size = strlen(ts->boot_info->kernel_filename)
-                        + 1  /* Separating space.  */
-                        + strlen(ts->boot_info->kernel_cmdline)
-                        + 1; /* Terminating null byte.  */
-#else
-            unsigned int i;
-
-            output_size = ts->info->arg_end - ts->info->arg_start;
-            if (!output_size) {
-                /* We special-case the "empty command line" case (argc==0).
-                   Just provide the terminating 0. */
-                output_size = 1;
-            }
-#endif
-
-            if (output_size > input_size) {
-                 /* Not enough space to store command-line arguments.  */
-                return -1;
-            }
-
-            /* Adjust the command-line length.  */
-            SET_ARG(1, output_size - 1);
-
-            /* Lock the buffer on the ARM side.  */
-            output_buffer = lock_user(VERIFY_WRITE, ARG(0), output_size, 0);
-            if (!output_buffer) {
-                return -1;
-            }
-
-            /* Copy the command-line arguments.  */
-#if !defined(CONFIG_USER_ONLY)
-            pstrcpy(output_buffer, output_size, ts->boot_info->kernel_filename);
-            pstrcat(output_buffer, output_size, " ");
-            pstrcat(output_buffer, output_size, ts->boot_info->kernel_cmdline);
-#else
-            if (output_size == 1) {
-                /* Empty command-line.  */
-                output_buffer[0] = '\0';
-                goto out;
-            }
-
-            if (copy_from_user(output_buffer, ts->info->arg_start,
-                               output_size)) {
-                status = -1;
-                goto out;
-            }
-
-            /* Separate arguments by white spaces.  */
-            for (i = 0; i < output_size - 1; i++) {
-                if (output_buffer[i] == 0) {
-                    output_buffer[i] = ' ';
-                }
-            }
-        out:
-#endif
-            /* Unlock the buffer on the ARM side.  */
-            unlock_user(output_buffer, ARG(0), output_size);
-
-            return status;
-        }
-    case TARGET_SYS_HEAPINFO:
-        {
-            uint32_t *ptr;
-            uint32_t limit;
-
-#ifdef CONFIG_USER_ONLY
-            /* Some C libraries assume the heap immediately follows .bss, so
-               allocate it using sbrk.  */
-            if (!ts->heap_limit) {
-                abi_ulong ret;
-
-                ts->heap_base = do_brk(0);
-                limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE;
-                /* Try a big heap, and reduce the size if that fails.  */
-                for (;;) {
-                    ret = do_brk(limit);
-                    if (ret >= limit) {
-                        break;
-                    }
-                    limit = (ts->heap_base >> 1) + (limit >> 1);
-                }
-                ts->heap_limit = limit;
-            }
-
-            if (!(ptr = lock_user(VERIFY_WRITE, ARG(0), 16, 0)))
-                /* FIXME - should this error code be -TARGET_EFAULT ? */
-                return (uint32_t)-1;
-            ptr[0] = tswap32(ts->heap_base);
-            ptr[1] = tswap32(ts->heap_limit);
-            ptr[2] = tswap32(ts->stack_base);
-            ptr[3] = tswap32(0); /* Stack limit.  */
-            unlock_user(ptr, ARG(0), 16);
-#else
-            limit = ram_size;
-            if (!(ptr = lock_user(VERIFY_WRITE, ARG(0), 16, 0)))
-                /* FIXME - should this error code be -TARGET_EFAULT ? */
-                return (uint32_t)-1;
-            /* TODO: Make this use the limit of the loaded application.  */
-            ptr[0] = tswap32(limit / 2);
-            ptr[1] = tswap32(limit);
-            ptr[2] = tswap32(limit); /* Stack base */
-            ptr[3] = tswap32(0); /* Stack limit.  */
-            unlock_user(ptr, ARG(0), 16);
-#endif
-            return 0;
-        }
-    case TARGET_SYS_EXIT:
-        gdb_exit(env, 0);
-        exit(0);
-    default:
-        fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr);
-        cpu_dump_state(env, stderr, fprintf, 0);
-        abort();
-    }
-}
diff --git a/configure b/configure
index 2c44488..a2fca50 100755
--- a/configure
+++ b/configure
@@ -3514,24 +3514,6 @@ case "$target" in
 esac
 
 mkdir -p $target_dir
-mkdir -p $target_dir/fpu
-mkdir -p $target_dir/tcg
-mkdir -p $target_dir/ide
-mkdir -p $target_dir/usb
-mkdir -p $target_dir/9pfs
-mkdir -p $target_dir/kvm
-if test "$target_linux_user" = yes; then
-  mkdir -p $target_dir/linux-user
-fi
-if test "$target_bsd_user" = yes; then
-  mkdir -p $target_dir/bsd-user
-fi
-if test "$target" = "arm-linux-user" -o "$target" = "armeb-linux-user" -o "$target" = "arm-bsd-user" -o "$target" = "armeb-bsd-user" ; then
-  mkdir -p $target_dir/linux-user/arm/nwfpe
-fi
-symlink "$source_path/Makefile.target" "$target_dir/Makefile"
-
-
 echo "# Automatically generated by configure - do not modify" > $config_target_mak
 
 bflt="no"
@@ -3682,6 +3664,32 @@ case "$target_arch2" in
     exit 1
   ;;
 esac
+# TARGET_BASE_ARCH needs to be defined after TARGET_ARCH
+if [ "$TARGET_BASE_ARCH" = "" ]; then
+  TARGET_BASE_ARCH=$TARGET_ARCH
+fi
+
+mkdir -p $target_dir/fpu
+mkdir -p $target_dir/tcg
+mkdir -p $target_dir/9pfs
+mkdir -p $target_dir/hw
+mkdir -p $target_dir/hw/ide
+mkdir -p $target_dir/hw/usb
+mkdir -p $target_dir/hw/kvm
+mkdir -p $target_dir/hw/$TARGET_ARCH
+mkdir -p $target_dir/hw/$TARGET_BASE_ARCH
+mkdir -p $target_dir/target-$TARGET_BASE_ARCH
+if test "$target_linux_user" = yes; then
+  mkdir -p $target_dir/linux-user
+fi
+if test "$target_bsd_user" = yes; then
+  mkdir -p $target_dir/bsd-user
+fi
+if test "$target" = "arm-linux-user" -o "$target" = "armeb-linux-user" -o "$target" = "arm-bsd-user" -o "$target" = "armeb-bsd-user" ; then
+  mkdir -p $target_dir/linux-user/arm/nwfpe
+fi
+symlink "$source_path/Makefile.target" "$target_dir/Makefile"
+
 
 case "$target_arch2" in
   alpha | sparc*)
@@ -3697,10 +3705,6 @@ echo "TARGET_ARCH=$TARGET_ARCH" >> $config_target_mak
 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
-if [ "$TARGET_BASE_ARCH" = "" ]; then
-  TARGET_BASE_ARCH=$TARGET_ARCH
-fi
 echo "TARGET_BASE_ARCH=$TARGET_BASE_ARCH" >> $config_target_mak
 if [ "$TARGET_ABI_DIR" = "" ]; then
   TARGET_ABI_DIR=$TARGET_ARCH
diff --git a/hw/alpha/Makefile.objs b/hw/alpha/Makefile.objs
new file mode 100644
index 0000000..af1c07f
--- /dev/null
+++ b/hw/alpha/Makefile.objs
@@ -0,0 +1,4 @@
+obj-y = mc146818rtc.o
+obj-y += alpha_pci.o alpha_dp264.o alpha_typhoon.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
new file mode 100644
index 0000000..92b4f1e
--- /dev/null
+++ b/hw/arm/Makefile.objs
@@ -0,0 +1,39 @@
+obj-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o
+obj-y += arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o
+obj-y += versatile_pci.o
+obj-y += versatile_i2c.o
+obj-y += cadence_uart.o
+obj-y += cadence_ttc.o
+obj-y += cadence_gem.o
+obj-y += xilinx_zynq.o zynq_slcr.o
+obj-y += arm_gic.o
+obj-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
+obj-y += exynos4210_gic.o exynos4210_combiner.o exynos4210.o
+obj-y += exynos4_boards.o exynos4210_uart.o exynos4210_pwm.o
+obj-y += exynos4210_pmu.o exynos4210_mct.o exynos4210_fimd.o
+obj-y += arm_l2x0.o
+obj-y += arm_mptimer.o a15mpcore.o
+obj-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
+obj-y += highbank.o
+obj-y += pl061.o
+obj-y += xgmac.o
+obj-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
+obj-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
+obj-y += gumstix.o
+obj-y += zaurus.o ide/microdrive.o spitz.o tosa.o tc6393xb.o
+obj-y += omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o \
+                omap_gpio.o omap_intc.o omap_uart.o
+obj-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o \
+                omap_gpmc.o omap_sdrc.o omap_spi.o omap_tap.o omap_l4.o
+obj-y += omap_sx1.o palm.o tsc210x.o
+obj-y += nseries.o blizzard.o onenand.o cbus.o tusb6010.o usb/hcd-musb.o
+obj-y += mst_fpga.o mainstone.o
+obj-y += z2.o
+obj-y += musicpal.o bitbang_i2c.o marvell_88w8618_audio.o
+obj-y += framebuffer.o
+obj-y += vexpress.o
+obj-y += strongarm.o
+obj-y += collie.o
+obj-y += pl041.o lm4549.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/cris/Makefile.objs b/hw/cris/Makefile.objs
new file mode 100644
index 0000000..aa9298a
--- /dev/null
+++ b/hw/cris/Makefile.objs
@@ -0,0 +1,13 @@
+# Boards
+obj-y = cris_pic_cpu.o
+obj-y += cris-boot.o
+obj-y += axis_dev88.o
+
+# IO blocks
+obj-y += etraxfs_dma.o
+obj-y += etraxfs_pic.o
+obj-y += etraxfs_eth.o
+obj-y += etraxfs_timer.o
+obj-y += etraxfs_ser.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
new file mode 100644
index 0000000..d43f1df
--- /dev/null
+++ b/hw/i386/Makefile.objs
@@ -0,0 +1,13 @@
+obj-y += mc146818rtc.o pc.o
+obj-y += apic_common.o apic.o kvmvapic.o
+obj-y += sga.o ioapic_common.o ioapic.o piix_pci.o
+obj-y += vmport.o
+obj-y += pci-hotplug.o smbios.o wdt_ib700.o
+obj-y += debugcon.o multiboot.o
+obj-y += pc_piix.o
+obj-y += pc_sysfw.o
+obj-$(CONFIG_XEN) += xen_platform.o xen_apic.o
+obj-$(CONFIG_KVM) += kvm/clock.o kvm/apic.o kvm/i8259.o kvm/ioapic.o kvm/i8254.o
+obj-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/lm32/Makefile.objs b/hw/lm32/Makefile.objs
new file mode 100644
index 0000000..4e1843c
--- /dev/null
+++ b/hw/lm32/Makefile.objs
@@ -0,0 +1,23 @@
+# LM32 boards
+obj-y += lm32_boards.o
+obj-y += milkymist.o
+
+# LM32 peripherals
+obj-y += lm32_pic.o
+obj-y += lm32_juart.o
+obj-y += lm32_timer.o
+obj-y += lm32_uart.o
+obj-y += lm32_sys.o
+obj-y += milkymist-ac97.o
+obj-y += milkymist-hpdmc.o
+obj-y += milkymist-memcard.o
+obj-y += milkymist-minimac2.o
+obj-y += milkymist-pfpu.o
+obj-y += milkymist-softusb.o
+obj-y += milkymist-sysctl.o
+obj-$(CONFIG_OPENGL) += milkymist-tmu2.o
+obj-y += milkymist-uart.o
+obj-y += milkymist-vgafb.o
+obj-y += framebuffer.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/m68k/Makefile.objs b/hw/m68k/Makefile.objs
new file mode 100644
index 0000000..93b6d25
--- /dev/null
+++ b/hw/m68k/Makefile.objs
@@ -0,0 +1,4 @@
+obj-y = an5206.o mcf5206.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o
+obj-y += dummy_m68k.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/microblaze/Makefile.objs b/hw/microblaze/Makefile.objs
new file mode 100644
index 0000000..4172442
--- /dev/null
+++ b/hw/microblaze/Makefile.objs
@@ -0,0 +1,13 @@
+obj-y = petalogix_s3adsp1800_mmu.o
+obj-y += petalogix_ml605_mmu.o
+obj-y += microblaze_boot.o
+
+obj-y += microblaze_pic_cpu.o
+obj-y += xilinx_intc.o
+obj-y += xilinx_timer.o
+obj-y += xilinx_uartlite.o
+obj-y += xilinx_ethlite.o
+obj-y += xilinx_axidma.o
+obj-y += xilinx_axienet.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/mips/Makefile.objs b/hw/mips/Makefile.objs
new file mode 100644
index 0000000..29a5d0d
--- /dev/null
+++ b/hw/mips/Makefile.objs
@@ -0,0 +1,6 @@
+obj-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
+obj-y += mips_addr.o mips_timer.o mips_int.o
+obj-y += gt64xxx.o mc146818rtc.o
+obj-$(CONFIG_FULONG) += bonito.o vt82c686.o mips_fulong2e.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
new file mode 100644
index 0000000..5b09849
--- /dev/null
+++ b/hw/ppc/Makefile.objs
@@ -0,0 +1,31 @@
+# shared objects
+obj-y = ppc.o ppc_booke.o
+# PREP target
+obj-y += mc146818rtc.o
+obj-y += ppc_prep.o
+# OldWorld PowerMac
+obj-y += ppc_oldworld.o
+# NewWorld PowerMac
+obj-y += ppc_newworld.o
+# IBM pSeries (sPAPR)
+obj-$(CONFIG_PSERIES) += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o
+obj-$(CONFIG_PSERIES) += xics.o spapr_vty.o spapr_llan.o spapr_vscsi.o
+obj-$(CONFIG_PSERIES) += spapr_pci.o pci-hotplug.o
+# PowerPC 4xx boards
+obj-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
+obj-y += ppc440_bamboo.o
+# PowerPC E500 boards
+obj-y += ppce500_mpc8544ds.o mpc8544_guts.o ppce500_spin.o
+# PowerPC 440 Xilinx ML507 reference board.
+obj-y += virtex_ml507.o
+obj-$(CONFIG_KVM) += kvm_ppc.o
+# PowerPC OpenPIC
+obj-y += openpic.o
+
+# Xilinx PPC peripherals
+obj-y += xilinx_intc.o
+obj-y += xilinx_timer.o
+obj-y += xilinx_uartlite.o
+obj-y += xilinx_ethlite.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs
new file mode 100644
index 0000000..dcdcac8
--- /dev/null
+++ b/hw/s390x/Makefile.objs
@@ -0,0 +1,3 @@
+obj-y = s390-virtio-bus.o s390-virtio.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/sh4/Makefile.objs b/hw/sh4/Makefile.objs
new file mode 100644
index 0000000..68c5921
--- /dev/null
+++ b/hw/sh4/Makefile.objs
@@ -0,0 +1,5 @@
+obj-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
+obj-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o sm501.o
+obj-y += ide/mmio.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/sparc/Makefile.objs b/hw/sparc/Makefile.objs
new file mode 100644
index 0000000..a39a511
--- /dev/null
+++ b/hw/sparc/Makefile.objs
@@ -0,0 +1,8 @@
+obj-y = sun4m.o lance.o tcx.o sun4m_iommu.o slavio_intctl.o
+obj-y += slavio_timer.o slavio_misc.o sparc32_dma.o
+obj-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o leon3.o
+
+# GRLIB
+obj-y += grlib_gptimer.o grlib_irqmp.o grlib_apbuart.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/sparc64/Makefile.objs b/hw/sparc64/Makefile.objs
new file mode 100644
index 0000000..8c65fc4
--- /dev/null
+++ b/hw/sparc64/Makefile.objs
@@ -0,0 +1,4 @@
+obj-y = sun4u.o apb_pci.o
+obj-y += mc146818rtc.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/xtensa/Makefile.objs b/hw/xtensa/Makefile.objs
new file mode 100644
index 0000000..79698e9
--- /dev/null
+++ b/hw/xtensa/Makefile.objs
@@ -0,0 +1,5 @@
+obj-y += xtensa_pic.o
+obj-y += xtensa_sim.o
+obj-y += xtensa_lx60.o
+
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/ioport-user.c b/ioport-user.c
deleted file mode 100644
index 03fac22..0000000
--- a/ioport-user.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- *  qemu user ioport functions
- *
- *  Copyright (c) 2003-2008 Fabrice Bellard
- *
- *  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 <stdio.h>
-
-#include "qemu.h"
-#include "qemu-common.h"
-#include "ioport.h"
-
-void cpu_outb(pio_addr_t addr, uint8_t val)
-{
-    fprintf(stderr, "outb: port=0x%04"FMT_pioaddr", data=%02"PRIx8"\n",
-            addr, val);
-}
-
-void cpu_outw(pio_addr_t addr, uint16_t val)
-{
-    fprintf(stderr, "outw: port=0x%04"FMT_pioaddr", data=%04"PRIx16"\n",
-            addr, val);
-}
-
-void cpu_outl(pio_addr_t addr, uint32_t val)
-{
-    fprintf(stderr, "outl: port=0x%04"FMT_pioaddr", data=%08"PRIx32"\n",
-            addr, val);
-}
-
-uint8_t cpu_inb(pio_addr_t addr)
-{
-    fprintf(stderr, "inb: port=0x%04"FMT_pioaddr"\n", addr);
-    return 0;
-}
-
-uint16_t cpu_inw(pio_addr_t addr)
-{
-    fprintf(stderr, "inw: port=0x%04"FMT_pioaddr"\n", addr);
-    return 0;
-}
-
-uint32_t cpu_inl(pio_addr_t addr)
-{
-    fprintf(stderr, "inl: port=0x%04"FMT_pioaddr"\n", addr);
-    return 0;
-}
diff --git a/m68k-semi.c b/m68k-semi.c
deleted file mode 100644
index 3bb30cd..0000000
--- a/m68k-semi.c
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- *  m68k/ColdFire Semihosting syscall interface
- *
- *  Copyright (c) 2005-2007 CodeSourcery.
- *
- *  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 <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/time.h>
-#include <time.h>
-
-#include "cpu.h"
-#if defined(CONFIG_USER_ONLY)
-#include "qemu.h"
-#define SEMIHOSTING_HEAP_SIZE (128 * 1024 * 1024)
-#else
-#include "qemu-common.h"
-#include "gdbstub.h"
-#include "softmmu-semi.h"
-#endif
-#include "sysemu.h"
-
-#define HOSTED_EXIT  0
-#define HOSTED_INIT_SIM 1
-#define HOSTED_OPEN 2
-#define HOSTED_CLOSE 3
-#define HOSTED_READ 4
-#define HOSTED_WRITE 5
-#define HOSTED_LSEEK 6
-#define HOSTED_RENAME 7
-#define HOSTED_UNLINK 8
-#define HOSTED_STAT 9
-#define HOSTED_FSTAT 10
-#define HOSTED_GETTIMEOFDAY 11
-#define HOSTED_ISATTY 12
-#define HOSTED_SYSTEM 13
-
-typedef uint32_t gdb_mode_t;
-typedef uint32_t gdb_time_t;
-
-struct m68k_gdb_stat {
-  uint32_t    gdb_st_dev;     /* device */
-  uint32_t    gdb_st_ino;     /* inode */
-  gdb_mode_t  gdb_st_mode;    /* protection */
-  uint32_t    gdb_st_nlink;   /* number of hard links */
-  uint32_t    gdb_st_uid;     /* user ID of owner */
-  uint32_t    gdb_st_gid;     /* group ID of owner */
-  uint32_t    gdb_st_rdev;    /* device type (if inode device) */
-  uint64_t    gdb_st_size;    /* total size, in bytes */
-  uint64_t    gdb_st_blksize; /* blocksize for filesystem I/O */
-  uint64_t    gdb_st_blocks;  /* number of blocks allocated */
-  gdb_time_t  gdb_st_atime;   /* time of last access */
-  gdb_time_t  gdb_st_mtime;   /* time of last modification */
-  gdb_time_t  gdb_st_ctime;   /* time of last change */
-} QEMU_PACKED;
-
-struct gdb_timeval {
-  gdb_time_t tv_sec;  /* second */
-  uint64_t tv_usec;   /* microsecond */
-} QEMU_PACKED;
-
-#define GDB_O_RDONLY   0x0
-#define GDB_O_WRONLY   0x1
-#define GDB_O_RDWR     0x2
-#define GDB_O_APPEND   0x8
-#define GDB_O_CREAT  0x200
-#define GDB_O_TRUNC  0x400
-#define GDB_O_EXCL   0x800
-
-static int translate_openflags(int flags)
-{
-    int hf;
-
-    if (flags & GDB_O_WRONLY)
-        hf = O_WRONLY;
-    else if (flags & GDB_O_RDWR)
-        hf = O_RDWR;
-    else
-        hf = O_RDONLY;
-
-    if (flags & GDB_O_APPEND) hf |= O_APPEND;
-    if (flags & GDB_O_CREAT) hf |= O_CREAT;
-    if (flags & GDB_O_TRUNC) hf |= O_TRUNC;
-    if (flags & GDB_O_EXCL) hf |= O_EXCL;
-
-    return hf;
-}
-
-static void translate_stat(CPUM68KState *env, target_ulong addr, struct stat *s)
-{
-    struct m68k_gdb_stat *p;
-
-    if (!(p = lock_user(VERIFY_WRITE, addr, sizeof(struct m68k_gdb_stat), 0)))
-        /* FIXME - should this return an error code? */
-        return;
-    p->gdb_st_dev = cpu_to_be32(s->st_dev);
-    p->gdb_st_ino = cpu_to_be32(s->st_ino);
-    p->gdb_st_mode = cpu_to_be32(s->st_mode);
-    p->gdb_st_nlink = cpu_to_be32(s->st_nlink);
-    p->gdb_st_uid = cpu_to_be32(s->st_uid);
-    p->gdb_st_gid = cpu_to_be32(s->st_gid);
-    p->gdb_st_rdev = cpu_to_be32(s->st_rdev);
-    p->gdb_st_size = cpu_to_be64(s->st_size);
-#ifdef _WIN32
-    /* Windows stat is missing some fields.  */
-    p->gdb_st_blksize = 0;
-    p->gdb_st_blocks = 0;
-#else
-    p->gdb_st_blksize = cpu_to_be64(s->st_blksize);
-    p->gdb_st_blocks = cpu_to_be64(s->st_blocks);
-#endif
-    p->gdb_st_atime = cpu_to_be32(s->st_atime);
-    p->gdb_st_mtime = cpu_to_be32(s->st_mtime);
-    p->gdb_st_ctime = cpu_to_be32(s->st_ctime);
-    unlock_user(p, addr, sizeof(struct m68k_gdb_stat));
-}
-
-static int m68k_semi_is_fseek;
-
-static void m68k_semi_cb(CPUM68KState *env, target_ulong ret, target_ulong err)
-{
-    target_ulong args;
-
-    args = env->dregs[1];
-    if (m68k_semi_is_fseek) {
-        /* FIXME: We've already lost the high bits of the fseek
-           return value.  */
-        /* FIXME - handle put_user() failure */
-        put_user_u32(0, args);
-        args += 4;
-        m68k_semi_is_fseek = 0;
-    }
-    /* FIXME - handle put_user() failure */
-    put_user_u32(ret, args);
-    put_user_u32(errno, args + 4);
-}
-
-#define ARG(n)					\
-({						\
-    target_ulong __arg;				\
-    /* FIXME - handle get_user() failure */	\
-    get_user_ual(__arg, args + (n) * 4);	\
-    __arg;					\
-})
-#define PARG(x) ((unsigned long)ARG(x))
-void do_m68k_semihosting(CPUM68KState *env, int nr)
-{
-    uint32_t args;
-    void *p;
-    void *q;
-    uint32_t len;
-    uint32_t result;
-
-    args = env->dregs[1];
-    switch (nr) {
-    case HOSTED_EXIT:
-        gdb_exit(env, env->dregs[0]);
-        exit(env->dregs[0]);
-    case HOSTED_OPEN:
-        if (use_gdb_syscalls()) {
-            gdb_do_syscall(m68k_semi_cb, "open,%s,%x,%x", ARG(0), (int)ARG(1),
-                           ARG(2), ARG(3));
-            return;
-        } else {
-            if (!(p = lock_user_string(ARG(0)))) {
-                /* FIXME - check error code? */
-                result = -1;
-            } else {
-                result = open(p, translate_openflags(ARG(2)), ARG(3));
-                unlock_user(p, ARG(0), 0);
-            }
-        }
-        break;
-    case HOSTED_CLOSE:
-        {
-            /* Ignore attempts to close stdin/out/err.  */
-            int fd = ARG(0);
-            if (fd > 2) {
-                if (use_gdb_syscalls()) {
-                    gdb_do_syscall(m68k_semi_cb, "close,%x", ARG(0));
-                    return;
-                } else {
-                    result = close(fd);
-                }
-            } else {
-                result = 0;
-            }
-            break;
-        }
-    case HOSTED_READ:
-        len = ARG(2);
-        if (use_gdb_syscalls()) {
-            gdb_do_syscall(m68k_semi_cb, "read,%x,%x,%x",
-                           ARG(0), ARG(1), len);
-            return;
-        } else {
-            if (!(p = lock_user(VERIFY_WRITE, ARG(1), len, 0))) {
-                /* FIXME - check error code? */
-                result = -1;
-            } else {
-                result = read(ARG(0), p, len);
-                unlock_user(p, ARG(1), len);
-            }
-        }
-        break;
-    case HOSTED_WRITE:
-        len = ARG(2);
-        if (use_gdb_syscalls()) {
-            gdb_do_syscall(m68k_semi_cb, "write,%x,%x,%x",
-                           ARG(0), ARG(1), len);
-            return;
-        } else {
-            if (!(p = lock_user(VERIFY_READ, ARG(1), len, 1))) {
-                /* FIXME - check error code? */
-                result = -1;
-            } else {
-                result = write(ARG(0), p, len);
-                unlock_user(p, ARG(0), 0);
-            }
-        }
-        break;
-    case HOSTED_LSEEK:
-        {
-            uint64_t off;
-            off = (uint32_t)ARG(2) | ((uint64_t)ARG(1) << 32);
-            if (use_gdb_syscalls()) {
-                m68k_semi_is_fseek = 1;
-                gdb_do_syscall(m68k_semi_cb, "fseek,%x,%lx,%x",
-                               ARG(0), off, ARG(3));
-            } else {
-                off = lseek(ARG(0), off, ARG(3));
-                /* FIXME - handle put_user() failure */
-                put_user_u32(off >> 32, args);
-                put_user_u32(off, args + 4);
-                put_user_u32(errno, args + 8);
-            }
-            return;
-        }
-    case HOSTED_RENAME:
-        if (use_gdb_syscalls()) {
-            gdb_do_syscall(m68k_semi_cb, "rename,%s,%s",
-                           ARG(0), (int)ARG(1), ARG(2), (int)ARG(3));
-            return;
-        } else {
-            p = lock_user_string(ARG(0));
-            q = lock_user_string(ARG(2));
-            if (!p || !q) {
-                /* FIXME - check error code? */
-                result = -1;
-            } else {
-                result = rename(p, q);
-            }
-            unlock_user(p, ARG(0), 0);
-            unlock_user(q, ARG(2), 0);
-        }
-        break;
-    case HOSTED_UNLINK:
-        if (use_gdb_syscalls()) {
-            gdb_do_syscall(m68k_semi_cb, "unlink,%s",
-                           ARG(0), (int)ARG(1));
-            return;
-        } else {
-            if (!(p = lock_user_string(ARG(0)))) {
-                /* FIXME - check error code? */
-                result = -1;
-            } else {
-                result = unlink(p);
-                unlock_user(p, ARG(0), 0);
-            }
-        }
-        break;
-    case HOSTED_STAT:
-        if (use_gdb_syscalls()) {
-            gdb_do_syscall(m68k_semi_cb, "stat,%s,%x",
-                           ARG(0), (int)ARG(1), ARG(2));
-            return;
-        } else {
-            struct stat s;
-            if (!(p = lock_user_string(ARG(0)))) {
-                /* FIXME - check error code? */
-                result = -1;
-            } else {
-                result = stat(p, &s);
-                unlock_user(p, ARG(0), 0);
-            }
-            if (result == 0) {
-                translate_stat(env, ARG(2), &s);
-            }
-        }
-        break;
-    case HOSTED_FSTAT:
-        if (use_gdb_syscalls()) {
-            gdb_do_syscall(m68k_semi_cb, "fstat,%x,%x",
-                           ARG(0), ARG(1));
-            return;
-        } else {
-            struct stat s;
-            result = fstat(ARG(0), &s);
-            if (result == 0) {
-                translate_stat(env, ARG(1), &s);
-            }
-        }
-        break;
-    case HOSTED_GETTIMEOFDAY:
-        if (use_gdb_syscalls()) {
-            gdb_do_syscall(m68k_semi_cb, "gettimeofday,%x,%x",
-                           ARG(0), ARG(1));
-            return;
-        } else {
-            qemu_timeval tv;
-            struct gdb_timeval *p;
-            result = qemu_gettimeofday(&tv);
-            if (result != 0) {
-                if (!(p = lock_user(VERIFY_WRITE,
-                                    ARG(0), sizeof(struct gdb_timeval), 0))) {
-                    /* FIXME - check error code? */
-                    result = -1;
-                } else {
-                    p->tv_sec = cpu_to_be32(tv.tv_sec);
-                    p->tv_usec = cpu_to_be64(tv.tv_usec);
-                    unlock_user(p, ARG(0), sizeof(struct gdb_timeval));
-                }
-            }
-        }
-        break;
-    case HOSTED_ISATTY:
-        if (use_gdb_syscalls()) {
-            gdb_do_syscall(m68k_semi_cb, "isatty,%x", ARG(0));
-            return;
-        } else {
-            result = isatty(ARG(0));
-        }
-        break;
-    case HOSTED_SYSTEM:
-        if (use_gdb_syscalls()) {
-            gdb_do_syscall(m68k_semi_cb, "system,%s",
-                           ARG(0), (int)ARG(1));
-            return;
-        } else {
-            if (!(p = lock_user_string(ARG(0)))) {
-                /* FIXME - check error code? */
-                result = -1;
-            } else {
-                result = system(p);
-                unlock_user(p, ARG(0), 0);
-            }
-        }
-        break;
-    case HOSTED_INIT_SIM:
-#if defined(CONFIG_USER_ONLY)
-        {
-        TaskState *ts = env->opaque;
-        /* Allocate the heap using sbrk.  */
-        if (!ts->heap_limit) {
-            abi_ulong ret;
-            uint32_t size;
-            uint32_t base;
-
-            base = do_brk(0);
-            size = SEMIHOSTING_HEAP_SIZE;
-            /* Try a big heap, and reduce the size if that fails.  */
-            for (;;) {
-                ret = do_brk(base + size);
-                if (ret >= (base + size)) {
-                    break;
-                }
-                size >>= 1;
-            }
-            ts->heap_limit = base + size;
-        }
-        /* This call may happen before we have writable memory, so return
-           values directly in registers.  */
-        env->dregs[1] = ts->heap_limit;
-        env->aregs[7] = ts->stack_base;
-        }
-#else
-        /* FIXME: This is wrong for boards where RAM does not start at
-           address zero.  */
-        env->dregs[1] = ram_size;
-        env->aregs[7] = ram_size;
-#endif
-        return;
-    default:
-        cpu_abort(env, "Unsupported semihosting syscall %d\n", nr);
-        result = 0;
-    }
-    /* FIXME - handle put_user() failure */
-    put_user_u32(result, args);
-    put_user_u32(errno, args + 4);
-}
diff --git a/target-alpha/Makefile.objs b/target-alpha/Makefile.objs
new file mode 100644
index 0000000..c574c9e
--- /dev/null
+++ b/target-alpha/Makefile.objs
@@ -0,0 +1 @@
+# still empty
diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs
new file mode 100644
index 0000000..f5bb920
--- /dev/null
+++ b/target-arm/Makefile.objs
@@ -0,0 +1 @@
+obj-y += arm-semi.o
diff --git a/target-arm/arm-semi.c b/target-arm/arm-semi.c
new file mode 100644
index 0000000..88ca9bb
--- /dev/null
+++ b/target-arm/arm-semi.c
@@ -0,0 +1,509 @@
+/*
+ *  Arm "Angel" semihosting syscalls
+ *
+ *  Copyright (c) 2005, 2007 CodeSourcery.
+ *  Written by Paul Brook.
+ *
+ *  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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "cpu.h"
+#ifdef CONFIG_USER_ONLY
+#include "qemu.h"
+
+#define ARM_ANGEL_HEAP_SIZE (128 * 1024 * 1024)
+#else
+#include "qemu-common.h"
+#include "gdbstub.h"
+#include "hw/arm-misc.h"
+#endif
+
+#define TARGET_SYS_OPEN        0x01
+#define TARGET_SYS_CLOSE       0x02
+#define TARGET_SYS_WRITEC      0x03
+#define TARGET_SYS_WRITE0      0x04
+#define TARGET_SYS_WRITE       0x05
+#define TARGET_SYS_READ        0x06
+#define TARGET_SYS_READC       0x07
+#define TARGET_SYS_ISTTY       0x09
+#define TARGET_SYS_SEEK        0x0a
+#define TARGET_SYS_FLEN        0x0c
+#define TARGET_SYS_TMPNAM      0x0d
+#define TARGET_SYS_REMOVE      0x0e
+#define TARGET_SYS_RENAME      0x0f
+#define TARGET_SYS_CLOCK       0x10
+#define TARGET_SYS_TIME        0x11
+#define TARGET_SYS_SYSTEM      0x12
+#define TARGET_SYS_ERRNO       0x13
+#define TARGET_SYS_GET_CMDLINE 0x15
+#define TARGET_SYS_HEAPINFO    0x16
+#define TARGET_SYS_EXIT        0x18
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#define GDB_O_RDONLY  0x000
+#define GDB_O_WRONLY  0x001
+#define GDB_O_RDWR    0x002
+#define GDB_O_APPEND  0x008
+#define GDB_O_CREAT   0x200
+#define GDB_O_TRUNC   0x400
+#define GDB_O_BINARY  0
+
+static int gdb_open_modeflags[12] = {
+    GDB_O_RDONLY,
+    GDB_O_RDONLY | GDB_O_BINARY,
+    GDB_O_RDWR,
+    GDB_O_RDWR | GDB_O_BINARY,
+    GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC,
+    GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY,
+    GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC,
+    GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY,
+    GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND,
+    GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY,
+    GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND,
+    GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY
+};
+
+static int open_modeflags[12] = {
+    O_RDONLY,
+    O_RDONLY | O_BINARY,
+    O_RDWR,
+    O_RDWR | O_BINARY,
+    O_WRONLY | O_CREAT | O_TRUNC,
+    O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
+    O_RDWR | O_CREAT | O_TRUNC,
+    O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
+    O_WRONLY | O_CREAT | O_APPEND,
+    O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
+    O_RDWR | O_CREAT | O_APPEND,
+    O_RDWR | O_CREAT | O_APPEND | O_BINARY
+};
+
+#ifdef CONFIG_USER_ONLY
+static inline uint32_t set_swi_errno(TaskState *ts, uint32_t code)
+{
+    if (code == (uint32_t)-1)
+        ts->swi_errno = errno;
+    return code;
+}
+#else
+static inline uint32_t set_swi_errno(CPUARMState *env, uint32_t code)
+{
+    return code;
+}
+
+#include "softmmu-semi.h"
+#endif
+
+static target_ulong arm_semi_syscall_len;
+
+#if !defined(CONFIG_USER_ONLY)
+static target_ulong syscall_err;
+#endif
+
+static void arm_semi_cb(CPUARMState *env, target_ulong ret, target_ulong err)
+{
+#ifdef CONFIG_USER_ONLY
+    TaskState *ts = env->opaque;
+#endif
+
+    if (ret == (target_ulong)-1) {
+#ifdef CONFIG_USER_ONLY
+        ts->swi_errno = err;
+#else
+	syscall_err = err;
+#endif
+        env->regs[0] = ret;
+    } else {
+        /* Fixup syscalls that use nonstardard return conventions.  */
+        switch (env->regs[0]) {
+        case TARGET_SYS_WRITE:
+        case TARGET_SYS_READ:
+            env->regs[0] = arm_semi_syscall_len - ret;
+            break;
+        case TARGET_SYS_SEEK:
+            env->regs[0] = 0;
+            break;
+        default:
+            env->regs[0] = ret;
+            break;
+        }
+    }
+}
+
+static void arm_semi_flen_cb(CPUARMState *env, target_ulong ret, target_ulong err)
+{
+    /* The size is always stored in big-endian order, extract
+       the value. We assume the size always fit in 32 bits.  */
+    uint32_t size;
+    cpu_memory_rw_debug(env, env->regs[13]-64+32, (uint8_t *)&size, 4, 0);
+    env->regs[0] = be32_to_cpu(size);
+#ifdef CONFIG_USER_ONLY
+    ((TaskState *)env->opaque)->swi_errno = err;
+#else
+    syscall_err = err;
+#endif
+}
+
+#define ARG(n)					\
+({						\
+    target_ulong __arg;				\
+    /* FIXME - handle get_user() failure */	\
+    get_user_ual(__arg, args + (n) * 4);	\
+    __arg;					\
+})
+#define SET_ARG(n, val) put_user_ual(val, args + (n) * 4)
+uint32_t do_arm_semihosting(CPUARMState *env)
+{
+    target_ulong args;
+    char * s;
+    int nr;
+    uint32_t ret;
+    uint32_t len;
+#ifdef CONFIG_USER_ONLY
+    TaskState *ts = env->opaque;
+#else
+    CPUARMState *ts = env;
+#endif
+
+    nr = env->regs[0];
+    args = env->regs[1];
+    switch (nr) {
+    case TARGET_SYS_OPEN:
+        if (!(s = lock_user_string(ARG(0))))
+            /* FIXME - should this error code be -TARGET_EFAULT ? */
+            return (uint32_t)-1;
+        if (ARG(1) >= 12)
+            return (uint32_t)-1;
+        if (strcmp(s, ":tt") == 0) {
+            if (ARG(1) < 4)
+                return STDIN_FILENO;
+            else
+                return STDOUT_FILENO;
+        }
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", ARG(0),
+			   (int)ARG(2)+1, gdb_open_modeflags[ARG(1)]);
+            return env->regs[0];
+        } else {
+            ret = set_swi_errno(ts, open(s, open_modeflags[ARG(1)], 0644));
+        }
+        unlock_user(s, ARG(0), 0);
+        return ret;
+    case TARGET_SYS_CLOSE:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_cb, "close,%x", ARG(0));
+            return env->regs[0];
+        } else {
+            return set_swi_errno(ts, close(ARG(0)));
+        }
+    case TARGET_SYS_WRITEC:
+        {
+          char c;
+
+          if (get_user_u8(c, args))
+              /* FIXME - should this error code be -TARGET_EFAULT ? */
+              return (uint32_t)-1;
+          /* Write to debug console.  stderr is near enough.  */
+          if (use_gdb_syscalls()) {
+                gdb_do_syscall(arm_semi_cb, "write,2,%x,1", args);
+                return env->regs[0];
+          } else {
+                return write(STDERR_FILENO, &c, 1);
+          }
+        }
+    case TARGET_SYS_WRITE0:
+        if (!(s = lock_user_string(args)))
+            /* FIXME - should this error code be -TARGET_EFAULT ? */
+            return (uint32_t)-1;
+        len = strlen(s);
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_cb, "write,2,%x,%x\n", args, len);
+            ret = env->regs[0];
+        } else {
+            ret = write(STDERR_FILENO, s, len);
+        }
+        unlock_user(s, args, 0);
+        return ret;
+    case TARGET_SYS_WRITE:
+        len = ARG(2);
+        if (use_gdb_syscalls()) {
+            arm_semi_syscall_len = len;
+            gdb_do_syscall(arm_semi_cb, "write,%x,%x,%x", ARG(0), ARG(1), len);
+            return env->regs[0];
+        } else {
+            if (!(s = lock_user(VERIFY_READ, ARG(1), len, 1)))
+                /* FIXME - should this error code be -TARGET_EFAULT ? */
+                return (uint32_t)-1;
+            ret = set_swi_errno(ts, write(ARG(0), s, len));
+            unlock_user(s, ARG(1), 0);
+            if (ret == (uint32_t)-1)
+                return -1;
+            return len - ret;
+        }
+    case TARGET_SYS_READ:
+        len = ARG(2);
+        if (use_gdb_syscalls()) {
+            arm_semi_syscall_len = len;
+            gdb_do_syscall(arm_semi_cb, "read,%x,%x,%x", ARG(0), ARG(1), len);
+            return env->regs[0];
+        } else {
+            if (!(s = lock_user(VERIFY_WRITE, ARG(1), len, 0)))
+                /* FIXME - should this error code be -TARGET_EFAULT ? */
+                return (uint32_t)-1;
+            do
+              ret = set_swi_errno(ts, read(ARG(0), s, len));
+            while (ret == -1 && errno == EINTR);
+            unlock_user(s, ARG(1), len);
+            if (ret == (uint32_t)-1)
+                return -1;
+            return len - ret;
+        }
+    case TARGET_SYS_READC:
+       /* XXX: Read from debug cosole. Not implemented.  */
+        return 0;
+    case TARGET_SYS_ISTTY:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_cb, "isatty,%x", ARG(0));
+            return env->regs[0];
+        } else {
+            return isatty(ARG(0));
+        }
+    case TARGET_SYS_SEEK:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_cb, "lseek,%x,%x,0", ARG(0), ARG(1));
+            return env->regs[0];
+        } else {
+            ret = set_swi_errno(ts, lseek(ARG(0), ARG(1), SEEK_SET));
+            if (ret == (uint32_t)-1)
+              return -1;
+            return 0;
+        }
+    case TARGET_SYS_FLEN:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_flen_cb, "fstat,%x,%x",
+			   ARG(0), env->regs[13]-64);
+            return env->regs[0];
+        } else {
+            struct stat buf;
+            ret = set_swi_errno(ts, fstat(ARG(0), &buf));
+            if (ret == (uint32_t)-1)
+                return -1;
+            return buf.st_size;
+        }
+    case TARGET_SYS_TMPNAM:
+        /* XXX: Not implemented.  */
+        return -1;
+    case TARGET_SYS_REMOVE:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_cb, "unlink,%s", ARG(0), (int)ARG(1)+1);
+            ret = env->regs[0];
+        } else {
+            if (!(s = lock_user_string(ARG(0))))
+                /* FIXME - should this error code be -TARGET_EFAULT ? */
+                return (uint32_t)-1;
+            ret =  set_swi_errno(ts, remove(s));
+            unlock_user(s, ARG(0), 0);
+        }
+        return ret;
+    case TARGET_SYS_RENAME:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_cb, "rename,%s,%s",
+                           ARG(0), (int)ARG(1)+1, ARG(2), (int)ARG(3)+1);
+            return env->regs[0];
+        } else {
+            char *s2;
+            s = lock_user_string(ARG(0));
+            s2 = lock_user_string(ARG(2));
+            if (!s || !s2)
+                /* FIXME - should this error code be -TARGET_EFAULT ? */
+                ret = (uint32_t)-1;
+            else
+                ret = set_swi_errno(ts, rename(s, s2));
+            if (s2)
+                unlock_user(s2, ARG(2), 0);
+            if (s)
+                unlock_user(s, ARG(0), 0);
+            return ret;
+        }
+    case TARGET_SYS_CLOCK:
+        return clock() / (CLOCKS_PER_SEC / 100);
+    case TARGET_SYS_TIME:
+        return set_swi_errno(ts, time(NULL));
+    case TARGET_SYS_SYSTEM:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_cb, "system,%s", ARG(0), (int)ARG(1)+1);
+            return env->regs[0];
+        } else {
+            if (!(s = lock_user_string(ARG(0))))
+                /* FIXME - should this error code be -TARGET_EFAULT ? */
+                return (uint32_t)-1;
+            ret = set_swi_errno(ts, system(s));
+            unlock_user(s, ARG(0), 0);
+            return ret;
+        }
+    case TARGET_SYS_ERRNO:
+#ifdef CONFIG_USER_ONLY
+        return ts->swi_errno;
+#else
+        return syscall_err;
+#endif
+    case TARGET_SYS_GET_CMDLINE:
+        {
+            /* Build a command-line from the original argv.
+             *
+             * The inputs are:
+             *     * ARG(0), pointer to a buffer of at least the size
+             *               specified in ARG(1).
+             *     * ARG(1), size of the buffer pointed to by ARG(0) in
+             *               bytes.
+             *
+             * The outputs are:
+             *     * ARG(0), pointer to null-terminated string of the
+             *               command line.
+             *     * ARG(1), length of the string pointed to by ARG(0).
+             */
+
+            char *output_buffer;
+            size_t input_size = ARG(1);
+            size_t output_size;
+            int status = 0;
+
+            /* Compute the size of the output string.  */
+#if !defined(CONFIG_USER_ONLY)
+            output_size = strlen(ts->boot_info->kernel_filename)
+                        + 1  /* Separating space.  */
+                        + strlen(ts->boot_info->kernel_cmdline)
+                        + 1; /* Terminating null byte.  */
+#else
+            unsigned int i;
+
+            output_size = ts->info->arg_end - ts->info->arg_start;
+            if (!output_size) {
+                /* We special-case the "empty command line" case (argc==0).
+                   Just provide the terminating 0. */
+                output_size = 1;
+            }
+#endif
+
+            if (output_size > input_size) {
+                 /* Not enough space to store command-line arguments.  */
+                return -1;
+            }
+
+            /* Adjust the command-line length.  */
+            SET_ARG(1, output_size - 1);
+
+            /* Lock the buffer on the ARM side.  */
+            output_buffer = lock_user(VERIFY_WRITE, ARG(0), output_size, 0);
+            if (!output_buffer) {
+                return -1;
+            }
+
+            /* Copy the command-line arguments.  */
+#if !defined(CONFIG_USER_ONLY)
+            pstrcpy(output_buffer, output_size, ts->boot_info->kernel_filename);
+            pstrcat(output_buffer, output_size, " ");
+            pstrcat(output_buffer, output_size, ts->boot_info->kernel_cmdline);
+#else
+            if (output_size == 1) {
+                /* Empty command-line.  */
+                output_buffer[0] = '\0';
+                goto out;
+            }
+
+            if (copy_from_user(output_buffer, ts->info->arg_start,
+                               output_size)) {
+                status = -1;
+                goto out;
+            }
+
+            /* Separate arguments by white spaces.  */
+            for (i = 0; i < output_size - 1; i++) {
+                if (output_buffer[i] == 0) {
+                    output_buffer[i] = ' ';
+                }
+            }
+        out:
+#endif
+            /* Unlock the buffer on the ARM side.  */
+            unlock_user(output_buffer, ARG(0), output_size);
+
+            return status;
+        }
+    case TARGET_SYS_HEAPINFO:
+        {
+            uint32_t *ptr;
+            uint32_t limit;
+
+#ifdef CONFIG_USER_ONLY
+            /* Some C libraries assume the heap immediately follows .bss, so
+               allocate it using sbrk.  */
+            if (!ts->heap_limit) {
+                abi_ulong ret;
+
+                ts->heap_base = do_brk(0);
+                limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE;
+                /* Try a big heap, and reduce the size if that fails.  */
+                for (;;) {
+                    ret = do_brk(limit);
+                    if (ret >= limit) {
+                        break;
+                    }
+                    limit = (ts->heap_base >> 1) + (limit >> 1);
+                }
+                ts->heap_limit = limit;
+            }
+
+            if (!(ptr = lock_user(VERIFY_WRITE, ARG(0), 16, 0)))
+                /* FIXME - should this error code be -TARGET_EFAULT ? */
+                return (uint32_t)-1;
+            ptr[0] = tswap32(ts->heap_base);
+            ptr[1] = tswap32(ts->heap_limit);
+            ptr[2] = tswap32(ts->stack_base);
+            ptr[3] = tswap32(0); /* Stack limit.  */
+            unlock_user(ptr, ARG(0), 16);
+#else
+            limit = ram_size;
+            if (!(ptr = lock_user(VERIFY_WRITE, ARG(0), 16, 0)))
+                /* FIXME - should this error code be -TARGET_EFAULT ? */
+                return (uint32_t)-1;
+            /* TODO: Make this use the limit of the loaded application.  */
+            ptr[0] = tswap32(limit / 2);
+            ptr[1] = tswap32(limit);
+            ptr[2] = tswap32(limit); /* Stack base */
+            ptr[3] = tswap32(0); /* Stack limit.  */
+            unlock_user(ptr, ARG(0), 16);
+#endif
+            return 0;
+        }
+    case TARGET_SYS_EXIT:
+        gdb_exit(env, 0);
+        exit(0);
+    default:
+        fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr);
+        cpu_dump_state(env, stderr, fprintf, 0);
+        abort();
+    }
+}
diff --git a/target-cris/Makefile.objs b/target-cris/Makefile.objs
new file mode 100644
index 0000000..c574c9e
--- /dev/null
+++ b/target-cris/Makefile.objs
@@ -0,0 +1 @@
+# still empty
diff --git a/target-i386/Makefile.objs b/target-i386/Makefile.objs
new file mode 100644
index 0000000..93c6f3f
--- /dev/null
+++ b/target-i386/Makefile.objs
@@ -0,0 +1,3 @@
+obj-$(CONFIG_KVM) += hyperv.o
+obj-$(CONFIG_LINUX_USER) += ioport-user.o
+obj-$(CONFIG_BSD_USER) += ioport-user.o
diff --git a/target-i386/ioport-user.c b/target-i386/ioport-user.c
new file mode 100644
index 0000000..03fac22
--- /dev/null
+++ b/target-i386/ioport-user.c
@@ -0,0 +1,60 @@
+/*
+ *  qemu user ioport functions
+ *
+ *  Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ *  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 <stdio.h>
+
+#include "qemu.h"
+#include "qemu-common.h"
+#include "ioport.h"
+
+void cpu_outb(pio_addr_t addr, uint8_t val)
+{
+    fprintf(stderr, "outb: port=0x%04"FMT_pioaddr", data=%02"PRIx8"\n",
+            addr, val);
+}
+
+void cpu_outw(pio_addr_t addr, uint16_t val)
+{
+    fprintf(stderr, "outw: port=0x%04"FMT_pioaddr", data=%04"PRIx16"\n",
+            addr, val);
+}
+
+void cpu_outl(pio_addr_t addr, uint32_t val)
+{
+    fprintf(stderr, "outl: port=0x%04"FMT_pioaddr", data=%08"PRIx32"\n",
+            addr, val);
+}
+
+uint8_t cpu_inb(pio_addr_t addr)
+{
+    fprintf(stderr, "inb: port=0x%04"FMT_pioaddr"\n", addr);
+    return 0;
+}
+
+uint16_t cpu_inw(pio_addr_t addr)
+{
+    fprintf(stderr, "inw: port=0x%04"FMT_pioaddr"\n", addr);
+    return 0;
+}
+
+uint32_t cpu_inl(pio_addr_t addr)
+{
+    fprintf(stderr, "inl: port=0x%04"FMT_pioaddr"\n", addr);
+    return 0;
+}
diff --git a/target-lm32/Makefile.objs b/target-lm32/Makefile.objs
new file mode 100644
index 0000000..c574c9e
--- /dev/null
+++ b/target-lm32/Makefile.objs
@@ -0,0 +1 @@
+# still empty
diff --git a/target-m68k/Makefile.objs b/target-m68k/Makefile.objs
new file mode 100644
index 0000000..e73a5ba
--- /dev/null
+++ b/target-m68k/Makefile.objs
@@ -0,0 +1 @@
+obj-y += m68k-semi.o
diff --git a/target-m68k/m68k-semi.c b/target-m68k/m68k-semi.c
new file mode 100644
index 0000000..3bb30cd
--- /dev/null
+++ b/target-m68k/m68k-semi.c
@@ -0,0 +1,408 @@
+/*
+ *  m68k/ColdFire Semihosting syscall interface
+ *
+ *  Copyright (c) 2005-2007 CodeSourcery.
+ *
+ *  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 <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <time.h>
+
+#include "cpu.h"
+#if defined(CONFIG_USER_ONLY)
+#include "qemu.h"
+#define SEMIHOSTING_HEAP_SIZE (128 * 1024 * 1024)
+#else
+#include "qemu-common.h"
+#include "gdbstub.h"
+#include "softmmu-semi.h"
+#endif
+#include "sysemu.h"
+
+#define HOSTED_EXIT  0
+#define HOSTED_INIT_SIM 1
+#define HOSTED_OPEN 2
+#define HOSTED_CLOSE 3
+#define HOSTED_READ 4
+#define HOSTED_WRITE 5
+#define HOSTED_LSEEK 6
+#define HOSTED_RENAME 7
+#define HOSTED_UNLINK 8
+#define HOSTED_STAT 9
+#define HOSTED_FSTAT 10
+#define HOSTED_GETTIMEOFDAY 11
+#define HOSTED_ISATTY 12
+#define HOSTED_SYSTEM 13
+
+typedef uint32_t gdb_mode_t;
+typedef uint32_t gdb_time_t;
+
+struct m68k_gdb_stat {
+  uint32_t    gdb_st_dev;     /* device */
+  uint32_t    gdb_st_ino;     /* inode */
+  gdb_mode_t  gdb_st_mode;    /* protection */
+  uint32_t    gdb_st_nlink;   /* number of hard links */
+  uint32_t    gdb_st_uid;     /* user ID of owner */
+  uint32_t    gdb_st_gid;     /* group ID of owner */
+  uint32_t    gdb_st_rdev;    /* device type (if inode device) */
+  uint64_t    gdb_st_size;    /* total size, in bytes */
+  uint64_t    gdb_st_blksize; /* blocksize for filesystem I/O */
+  uint64_t    gdb_st_blocks;  /* number of blocks allocated */
+  gdb_time_t  gdb_st_atime;   /* time of last access */
+  gdb_time_t  gdb_st_mtime;   /* time of last modification */
+  gdb_time_t  gdb_st_ctime;   /* time of last change */
+} QEMU_PACKED;
+
+struct gdb_timeval {
+  gdb_time_t tv_sec;  /* second */
+  uint64_t tv_usec;   /* microsecond */
+} QEMU_PACKED;
+
+#define GDB_O_RDONLY   0x0
+#define GDB_O_WRONLY   0x1
+#define GDB_O_RDWR     0x2
+#define GDB_O_APPEND   0x8
+#define GDB_O_CREAT  0x200
+#define GDB_O_TRUNC  0x400
+#define GDB_O_EXCL   0x800
+
+static int translate_openflags(int flags)
+{
+    int hf;
+
+    if (flags & GDB_O_WRONLY)
+        hf = O_WRONLY;
+    else if (flags & GDB_O_RDWR)
+        hf = O_RDWR;
+    else
+        hf = O_RDONLY;
+
+    if (flags & GDB_O_APPEND) hf |= O_APPEND;
+    if (flags & GDB_O_CREAT) hf |= O_CREAT;
+    if (flags & GDB_O_TRUNC) hf |= O_TRUNC;
+    if (flags & GDB_O_EXCL) hf |= O_EXCL;
+
+    return hf;
+}
+
+static void translate_stat(CPUM68KState *env, target_ulong addr, struct stat *s)
+{
+    struct m68k_gdb_stat *p;
+
+    if (!(p = lock_user(VERIFY_WRITE, addr, sizeof(struct m68k_gdb_stat), 0)))
+        /* FIXME - should this return an error code? */
+        return;
+    p->gdb_st_dev = cpu_to_be32(s->st_dev);
+    p->gdb_st_ino = cpu_to_be32(s->st_ino);
+    p->gdb_st_mode = cpu_to_be32(s->st_mode);
+    p->gdb_st_nlink = cpu_to_be32(s->st_nlink);
+    p->gdb_st_uid = cpu_to_be32(s->st_uid);
+    p->gdb_st_gid = cpu_to_be32(s->st_gid);
+    p->gdb_st_rdev = cpu_to_be32(s->st_rdev);
+    p->gdb_st_size = cpu_to_be64(s->st_size);
+#ifdef _WIN32
+    /* Windows stat is missing some fields.  */
+    p->gdb_st_blksize = 0;
+    p->gdb_st_blocks = 0;
+#else
+    p->gdb_st_blksize = cpu_to_be64(s->st_blksize);
+    p->gdb_st_blocks = cpu_to_be64(s->st_blocks);
+#endif
+    p->gdb_st_atime = cpu_to_be32(s->st_atime);
+    p->gdb_st_mtime = cpu_to_be32(s->st_mtime);
+    p->gdb_st_ctime = cpu_to_be32(s->st_ctime);
+    unlock_user(p, addr, sizeof(struct m68k_gdb_stat));
+}
+
+static int m68k_semi_is_fseek;
+
+static void m68k_semi_cb(CPUM68KState *env, target_ulong ret, target_ulong err)
+{
+    target_ulong args;
+
+    args = env->dregs[1];
+    if (m68k_semi_is_fseek) {
+        /* FIXME: We've already lost the high bits of the fseek
+           return value.  */
+        /* FIXME - handle put_user() failure */
+        put_user_u32(0, args);
+        args += 4;
+        m68k_semi_is_fseek = 0;
+    }
+    /* FIXME - handle put_user() failure */
+    put_user_u32(ret, args);
+    put_user_u32(errno, args + 4);
+}
+
+#define ARG(n)					\
+({						\
+    target_ulong __arg;				\
+    /* FIXME - handle get_user() failure */	\
+    get_user_ual(__arg, args + (n) * 4);	\
+    __arg;					\
+})
+#define PARG(x) ((unsigned long)ARG(x))
+void do_m68k_semihosting(CPUM68KState *env, int nr)
+{
+    uint32_t args;
+    void *p;
+    void *q;
+    uint32_t len;
+    uint32_t result;
+
+    args = env->dregs[1];
+    switch (nr) {
+    case HOSTED_EXIT:
+        gdb_exit(env, env->dregs[0]);
+        exit(env->dregs[0]);
+    case HOSTED_OPEN:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(m68k_semi_cb, "open,%s,%x,%x", ARG(0), (int)ARG(1),
+                           ARG(2), ARG(3));
+            return;
+        } else {
+            if (!(p = lock_user_string(ARG(0)))) {
+                /* FIXME - check error code? */
+                result = -1;
+            } else {
+                result = open(p, translate_openflags(ARG(2)), ARG(3));
+                unlock_user(p, ARG(0), 0);
+            }
+        }
+        break;
+    case HOSTED_CLOSE:
+        {
+            /* Ignore attempts to close stdin/out/err.  */
+            int fd = ARG(0);
+            if (fd > 2) {
+                if (use_gdb_syscalls()) {
+                    gdb_do_syscall(m68k_semi_cb, "close,%x", ARG(0));
+                    return;
+                } else {
+                    result = close(fd);
+                }
+            } else {
+                result = 0;
+            }
+            break;
+        }
+    case HOSTED_READ:
+        len = ARG(2);
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(m68k_semi_cb, "read,%x,%x,%x",
+                           ARG(0), ARG(1), len);
+            return;
+        } else {
+            if (!(p = lock_user(VERIFY_WRITE, ARG(1), len, 0))) {
+                /* FIXME - check error code? */
+                result = -1;
+            } else {
+                result = read(ARG(0), p, len);
+                unlock_user(p, ARG(1), len);
+            }
+        }
+        break;
+    case HOSTED_WRITE:
+        len = ARG(2);
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(m68k_semi_cb, "write,%x,%x,%x",
+                           ARG(0), ARG(1), len);
+            return;
+        } else {
+            if (!(p = lock_user(VERIFY_READ, ARG(1), len, 1))) {
+                /* FIXME - check error code? */
+                result = -1;
+            } else {
+                result = write(ARG(0), p, len);
+                unlock_user(p, ARG(0), 0);
+            }
+        }
+        break;
+    case HOSTED_LSEEK:
+        {
+            uint64_t off;
+            off = (uint32_t)ARG(2) | ((uint64_t)ARG(1) << 32);
+            if (use_gdb_syscalls()) {
+                m68k_semi_is_fseek = 1;
+                gdb_do_syscall(m68k_semi_cb, "fseek,%x,%lx,%x",
+                               ARG(0), off, ARG(3));
+            } else {
+                off = lseek(ARG(0), off, ARG(3));
+                /* FIXME - handle put_user() failure */
+                put_user_u32(off >> 32, args);
+                put_user_u32(off, args + 4);
+                put_user_u32(errno, args + 8);
+            }
+            return;
+        }
+    case HOSTED_RENAME:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(m68k_semi_cb, "rename,%s,%s",
+                           ARG(0), (int)ARG(1), ARG(2), (int)ARG(3));
+            return;
+        } else {
+            p = lock_user_string(ARG(0));
+            q = lock_user_string(ARG(2));
+            if (!p || !q) {
+                /* FIXME - check error code? */
+                result = -1;
+            } else {
+                result = rename(p, q);
+            }
+            unlock_user(p, ARG(0), 0);
+            unlock_user(q, ARG(2), 0);
+        }
+        break;
+    case HOSTED_UNLINK:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(m68k_semi_cb, "unlink,%s",
+                           ARG(0), (int)ARG(1));
+            return;
+        } else {
+            if (!(p = lock_user_string(ARG(0)))) {
+                /* FIXME - check error code? */
+                result = -1;
+            } else {
+                result = unlink(p);
+                unlock_user(p, ARG(0), 0);
+            }
+        }
+        break;
+    case HOSTED_STAT:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(m68k_semi_cb, "stat,%s,%x",
+                           ARG(0), (int)ARG(1), ARG(2));
+            return;
+        } else {
+            struct stat s;
+            if (!(p = lock_user_string(ARG(0)))) {
+                /* FIXME - check error code? */
+                result = -1;
+            } else {
+                result = stat(p, &s);
+                unlock_user(p, ARG(0), 0);
+            }
+            if (result == 0) {
+                translate_stat(env, ARG(2), &s);
+            }
+        }
+        break;
+    case HOSTED_FSTAT:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(m68k_semi_cb, "fstat,%x,%x",
+                           ARG(0), ARG(1));
+            return;
+        } else {
+            struct stat s;
+            result = fstat(ARG(0), &s);
+            if (result == 0) {
+                translate_stat(env, ARG(1), &s);
+            }
+        }
+        break;
+    case HOSTED_GETTIMEOFDAY:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(m68k_semi_cb, "gettimeofday,%x,%x",
+                           ARG(0), ARG(1));
+            return;
+        } else {
+            qemu_timeval tv;
+            struct gdb_timeval *p;
+            result = qemu_gettimeofday(&tv);
+            if (result != 0) {
+                if (!(p = lock_user(VERIFY_WRITE,
+                                    ARG(0), sizeof(struct gdb_timeval), 0))) {
+                    /* FIXME - check error code? */
+                    result = -1;
+                } else {
+                    p->tv_sec = cpu_to_be32(tv.tv_sec);
+                    p->tv_usec = cpu_to_be64(tv.tv_usec);
+                    unlock_user(p, ARG(0), sizeof(struct gdb_timeval));
+                }
+            }
+        }
+        break;
+    case HOSTED_ISATTY:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(m68k_semi_cb, "isatty,%x", ARG(0));
+            return;
+        } else {
+            result = isatty(ARG(0));
+        }
+        break;
+    case HOSTED_SYSTEM:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(m68k_semi_cb, "system,%s",
+                           ARG(0), (int)ARG(1));
+            return;
+        } else {
+            if (!(p = lock_user_string(ARG(0)))) {
+                /* FIXME - check error code? */
+                result = -1;
+            } else {
+                result = system(p);
+                unlock_user(p, ARG(0), 0);
+            }
+        }
+        break;
+    case HOSTED_INIT_SIM:
+#if defined(CONFIG_USER_ONLY)
+        {
+        TaskState *ts = env->opaque;
+        /* Allocate the heap using sbrk.  */
+        if (!ts->heap_limit) {
+            abi_ulong ret;
+            uint32_t size;
+            uint32_t base;
+
+            base = do_brk(0);
+            size = SEMIHOSTING_HEAP_SIZE;
+            /* Try a big heap, and reduce the size if that fails.  */
+            for (;;) {
+                ret = do_brk(base + size);
+                if (ret >= (base + size)) {
+                    break;
+                }
+                size >>= 1;
+            }
+            ts->heap_limit = base + size;
+        }
+        /* This call may happen before we have writable memory, so return
+           values directly in registers.  */
+        env->dregs[1] = ts->heap_limit;
+        env->aregs[7] = ts->stack_base;
+        }
+#else
+        /* FIXME: This is wrong for boards where RAM does not start at
+           address zero.  */
+        env->dregs[1] = ram_size;
+        env->aregs[7] = ram_size;
+#endif
+        return;
+    default:
+        cpu_abort(env, "Unsupported semihosting syscall %d\n", nr);
+        result = 0;
+    }
+    /* FIXME - handle put_user() failure */
+    put_user_u32(result, args);
+    put_user_u32(errno, args + 4);
+}
diff --git a/target-microblaze/Makefile.objs b/target-microblaze/Makefile.objs
new file mode 100644
index 0000000..c574c9e
--- /dev/null
+++ b/target-microblaze/Makefile.objs
@@ -0,0 +1 @@
+# still empty
diff --git a/target-mips/Makefile.objs b/target-mips/Makefile.objs
new file mode 100644
index 0000000..c574c9e
--- /dev/null
+++ b/target-mips/Makefile.objs
@@ -0,0 +1 @@
+# still empty
diff --git a/target-ppc/Makefile.objs b/target-ppc/Makefile.objs
new file mode 100644
index 0000000..c574c9e
--- /dev/null
+++ b/target-ppc/Makefile.objs
@@ -0,0 +1 @@
+# still empty
diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs
new file mode 100644
index 0000000..c574c9e
--- /dev/null
+++ b/target-s390x/Makefile.objs
@@ -0,0 +1 @@
+# still empty
diff --git a/target-sh4/Makefile.objs b/target-sh4/Makefile.objs
new file mode 100644
index 0000000..c574c9e
--- /dev/null
+++ b/target-sh4/Makefile.objs
@@ -0,0 +1 @@
+# still empty
diff --git a/target-sparc/Makefile.objs b/target-sparc/Makefile.objs
new file mode 100644
index 0000000..c574c9e
--- /dev/null
+++ b/target-sparc/Makefile.objs
@@ -0,0 +1 @@
+# still empty
diff --git a/target-unicore32/Makefile.objs b/target-unicore32/Makefile.objs
new file mode 100644
index 0000000..c574c9e
--- /dev/null
+++ b/target-unicore32/Makefile.objs
@@ -0,0 +1 @@
+# still empty
diff --git a/target-xtensa/Makefile.objs b/target-xtensa/Makefile.objs
new file mode 100644
index 0000000..a49ca8d
--- /dev/null
+++ b/target-xtensa/Makefile.objs
@@ -0,0 +1,4 @@
+obj-y += xtensa-semi.o
+obj-y += core-dc232b.o
+obj-y += core-dc233c.o
+obj-y += core-fsf.o
diff --git a/target-xtensa/xtensa-semi.c b/target-xtensa/xtensa-semi.c
new file mode 100644
index 0000000..b7c8c34
--- /dev/null
+++ b/target-xtensa/xtensa-semi.c
@@ -0,0 +1,224 @@
+/*
+ * 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 <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stddef.h>
+#include "cpu.h"
+#include "dyngen-exec.h"
+#include "helper.h"
+#include "qemu-log.h"
+
+enum {
+    TARGET_SYS_exit = 1,
+    TARGET_SYS_read = 3,
+    TARGET_SYS_write = 4,
+    TARGET_SYS_open = 5,
+    TARGET_SYS_close = 6,
+    TARGET_SYS_lseek = 19,
+    TARGET_SYS_select_one = 29,
+
+    TARGET_SYS_argc = 1000,
+    TARGET_SYS_argv_sz = 1001,
+    TARGET_SYS_argv = 1002,
+    TARGET_SYS_memset = 1004,
+};
+
+enum {
+    SELECT_ONE_READ   = 1,
+    SELECT_ONE_WRITE  = 2,
+    SELECT_ONE_EXCEPT = 3,
+};
+
+void HELPER(simcall)(CPUXtensaState *env)
+{
+    uint32_t *regs = env->regs;
+
+    switch (regs[2]) {
+    case TARGET_SYS_exit:
+        qemu_log("exit(%d) simcall\n", regs[3]);
+        exit(regs[3]);
+        break;
+
+    case TARGET_SYS_read:
+    case TARGET_SYS_write:
+        {
+            bool is_write = regs[2] == TARGET_SYS_write;
+            uint32_t fd = regs[3];
+            uint32_t vaddr = regs[4];
+            uint32_t len = regs[5];
+
+            while (len > 0) {
+                target_phys_addr_t paddr =
+                    cpu_get_phys_page_debug(env, vaddr);
+                uint32_t page_left =
+                    TARGET_PAGE_SIZE - (vaddr & (TARGET_PAGE_SIZE - 1));
+                uint32_t io_sz = page_left < len ? page_left : len;
+                target_phys_addr_t sz = io_sz;
+                void *buf = cpu_physical_memory_map(paddr, &sz, is_write);
+
+                if (buf) {
+                    vaddr += io_sz;
+                    len -= io_sz;
+                    regs[2] = is_write ?
+                        write(fd, buf, io_sz) :
+                        read(fd, buf, io_sz);
+                    regs[3] = errno;
+                    cpu_physical_memory_unmap(buf, sz, is_write, sz);
+                    if (regs[2] == -1) {
+                        break;
+                    }
+                } else {
+                    regs[2] = -1;
+                    regs[3] = EINVAL;
+                    break;
+                }
+            }
+        }
+        break;
+
+    case TARGET_SYS_open:
+        {
+            char name[1024];
+            int rc;
+            int i;
+
+            for (i = 0; i < ARRAY_SIZE(name); ++i) {
+                rc = cpu_memory_rw_debug(
+                        env, regs[3] + i, (uint8_t *)name + i, 1, 0);
+                if (rc != 0 || name[i] == 0) {
+                    break;
+                }
+            }
+
+            if (rc == 0 && i < ARRAY_SIZE(name)) {
+                regs[2] = open(name, regs[4], regs[5]);
+                regs[3] = errno;
+            } else {
+                regs[2] = -1;
+                regs[3] = EINVAL;
+            }
+        }
+        break;
+
+    case TARGET_SYS_close:
+        if (regs[3] < 3) {
+            regs[2] = regs[3] = 0;
+        } else {
+            regs[2] = close(regs[3]);
+            regs[3] = errno;
+        }
+        break;
+
+    case TARGET_SYS_lseek:
+        regs[2] = lseek(regs[3], (off_t)(int32_t)regs[4], regs[5]);
+        regs[3] = errno;
+        break;
+
+    case TARGET_SYS_select_one:
+        {
+            uint32_t fd = regs[3];
+            uint32_t rq = regs[4];
+            uint32_t target_tv = regs[5];
+            uint32_t target_tvv[2];
+
+            struct timeval tv = {0};
+            fd_set fdset;
+
+            FD_ZERO(&fdset);
+            FD_SET(fd, &fdset);
+
+            if (target_tv) {
+                cpu_memory_rw_debug(env, target_tv,
+                        (uint8_t *)target_tvv, sizeof(target_tvv), 0);
+                tv.tv_sec = (int32_t)tswap32(target_tvv[0]);
+                tv.tv_usec = (int32_t)tswap32(target_tvv[1]);
+            }
+            regs[2] = select(fd + 1,
+                    rq == SELECT_ONE_READ   ? &fdset : NULL,
+                    rq == SELECT_ONE_WRITE  ? &fdset : NULL,
+                    rq == SELECT_ONE_EXCEPT ? &fdset : NULL,
+                    target_tv ? &tv : NULL);
+            regs[3] = errno;
+        }
+        break;
+
+    case TARGET_SYS_argc:
+        regs[2] = 1;
+        regs[3] = 0;
+        break;
+
+    case TARGET_SYS_argv_sz:
+        regs[2] = 128;
+        regs[3] = 0;
+        break;
+
+    case TARGET_SYS_argv:
+        {
+            struct Argv {
+                uint32_t argptr[2];
+                char text[120];
+            } argv = {
+                {0, 0},
+                "test"
+            };
+
+            argv.argptr[0] = tswap32(regs[3] + offsetof(struct Argv, text));
+            cpu_memory_rw_debug(
+                    env, regs[3], (uint8_t *)&argv, sizeof(argv), 1);
+        }
+        break;
+
+    case TARGET_SYS_memset:
+        {
+            uint32_t base = regs[3];
+            uint32_t sz = regs[5];
+
+            while (sz) {
+                target_phys_addr_t len = sz;
+                void *buf = cpu_physical_memory_map(base, &len, 1);
+
+                if (buf && len) {
+                    memset(buf, regs[4], len);
+                    cpu_physical_memory_unmap(buf, len, 1, len);
+                } else {
+                    len = 1;
+                }
+                base += len;
+                sz -= len;
+            }
+            regs[2] = regs[3];
+            regs[3] = 0;
+        }
+        break;
+
+    default:
+        qemu_log("%s(%d): not implemented\n", __func__, regs[2]);
+        break;
+    }
+}
diff --git a/xtensa-semi.c b/xtensa-semi.c
deleted file mode 100644
index b7c8c34..0000000
--- a/xtensa-semi.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * 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 <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <stddef.h>
-#include "cpu.h"
-#include "dyngen-exec.h"
-#include "helper.h"
-#include "qemu-log.h"
-
-enum {
-    TARGET_SYS_exit = 1,
-    TARGET_SYS_read = 3,
-    TARGET_SYS_write = 4,
-    TARGET_SYS_open = 5,
-    TARGET_SYS_close = 6,
-    TARGET_SYS_lseek = 19,
-    TARGET_SYS_select_one = 29,
-
-    TARGET_SYS_argc = 1000,
-    TARGET_SYS_argv_sz = 1001,
-    TARGET_SYS_argv = 1002,
-    TARGET_SYS_memset = 1004,
-};
-
-enum {
-    SELECT_ONE_READ   = 1,
-    SELECT_ONE_WRITE  = 2,
-    SELECT_ONE_EXCEPT = 3,
-};
-
-void HELPER(simcall)(CPUXtensaState *env)
-{
-    uint32_t *regs = env->regs;
-
-    switch (regs[2]) {
-    case TARGET_SYS_exit:
-        qemu_log("exit(%d) simcall\n", regs[3]);
-        exit(regs[3]);
-        break;
-
-    case TARGET_SYS_read:
-    case TARGET_SYS_write:
-        {
-            bool is_write = regs[2] == TARGET_SYS_write;
-            uint32_t fd = regs[3];
-            uint32_t vaddr = regs[4];
-            uint32_t len = regs[5];
-
-            while (len > 0) {
-                target_phys_addr_t paddr =
-                    cpu_get_phys_page_debug(env, vaddr);
-                uint32_t page_left =
-                    TARGET_PAGE_SIZE - (vaddr & (TARGET_PAGE_SIZE - 1));
-                uint32_t io_sz = page_left < len ? page_left : len;
-                target_phys_addr_t sz = io_sz;
-                void *buf = cpu_physical_memory_map(paddr, &sz, is_write);
-
-                if (buf) {
-                    vaddr += io_sz;
-                    len -= io_sz;
-                    regs[2] = is_write ?
-                        write(fd, buf, io_sz) :
-                        read(fd, buf, io_sz);
-                    regs[3] = errno;
-                    cpu_physical_memory_unmap(buf, sz, is_write, sz);
-                    if (regs[2] == -1) {
-                        break;
-                    }
-                } else {
-                    regs[2] = -1;
-                    regs[3] = EINVAL;
-                    break;
-                }
-            }
-        }
-        break;
-
-    case TARGET_SYS_open:
-        {
-            char name[1024];
-            int rc;
-            int i;
-
-            for (i = 0; i < ARRAY_SIZE(name); ++i) {
-                rc = cpu_memory_rw_debug(
-                        env, regs[3] + i, (uint8_t *)name + i, 1, 0);
-                if (rc != 0 || name[i] == 0) {
-                    break;
-                }
-            }
-
-            if (rc == 0 && i < ARRAY_SIZE(name)) {
-                regs[2] = open(name, regs[4], regs[5]);
-                regs[3] = errno;
-            } else {
-                regs[2] = -1;
-                regs[3] = EINVAL;
-            }
-        }
-        break;
-
-    case TARGET_SYS_close:
-        if (regs[3] < 3) {
-            regs[2] = regs[3] = 0;
-        } else {
-            regs[2] = close(regs[3]);
-            regs[3] = errno;
-        }
-        break;
-
-    case TARGET_SYS_lseek:
-        regs[2] = lseek(regs[3], (off_t)(int32_t)regs[4], regs[5]);
-        regs[3] = errno;
-        break;
-
-    case TARGET_SYS_select_one:
-        {
-            uint32_t fd = regs[3];
-            uint32_t rq = regs[4];
-            uint32_t target_tv = regs[5];
-            uint32_t target_tvv[2];
-
-            struct timeval tv = {0};
-            fd_set fdset;
-
-            FD_ZERO(&fdset);
-            FD_SET(fd, &fdset);
-
-            if (target_tv) {
-                cpu_memory_rw_debug(env, target_tv,
-                        (uint8_t *)target_tvv, sizeof(target_tvv), 0);
-                tv.tv_sec = (int32_t)tswap32(target_tvv[0]);
-                tv.tv_usec = (int32_t)tswap32(target_tvv[1]);
-            }
-            regs[2] = select(fd + 1,
-                    rq == SELECT_ONE_READ   ? &fdset : NULL,
-                    rq == SELECT_ONE_WRITE  ? &fdset : NULL,
-                    rq == SELECT_ONE_EXCEPT ? &fdset : NULL,
-                    target_tv ? &tv : NULL);
-            regs[3] = errno;
-        }
-        break;
-
-    case TARGET_SYS_argc:
-        regs[2] = 1;
-        regs[3] = 0;
-        break;
-
-    case TARGET_SYS_argv_sz:
-        regs[2] = 128;
-        regs[3] = 0;
-        break;
-
-    case TARGET_SYS_argv:
-        {
-            struct Argv {
-                uint32_t argptr[2];
-                char text[120];
-            } argv = {
-                {0, 0},
-                "test"
-            };
-
-            argv.argptr[0] = tswap32(regs[3] + offsetof(struct Argv, text));
-            cpu_memory_rw_debug(
-                    env, regs[3], (uint8_t *)&argv, sizeof(argv), 1);
-        }
-        break;
-
-    case TARGET_SYS_memset:
-        {
-            uint32_t base = regs[3];
-            uint32_t sz = regs[5];
-
-            while (sz) {
-                target_phys_addr_t len = sz;
-                void *buf = cpu_physical_memory_map(base, &len, 1);
-
-                if (buf && len) {
-                    memset(buf, regs[4], len);
-                    cpu_physical_memory_unmap(buf, len, 1, len);
-                } else {
-                    len = 1;
-                }
-                base += len;
-                sz -= len;
-            }
-            regs[2] = regs[3];
-            regs[3] = 0;
-        }
-        break;
-
-    default:
-        qemu_log("%s(%d): not implemented\n", __func__, regs[2]);
-        break;
-    }
-}
commit 7fc5152c6dca17d6061cc399c46716d9e586ad85
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue May 29 09:33:59 2012 +0200

    build: move *-user/ objects to nested Makefile.objs
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.target b/Makefile.target
index 40b774a..5cc577b 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -113,32 +113,20 @@ user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 
 # Note: this is a workaround. The real fix is to avoid compiling
 # cpu_signal_handler() in user-exec.c.
-signal.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
+%/signal.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 
 #########################################################
 # Linux user emulator target
 
 ifdef CONFIG_LINUX_USER
 
-$(call set-vpath, $(SRC_PATH)/linux-user:$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR))
-
 QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) -I$(SRC_PATH)/linux-user
-obj-y = main.o syscall.o strace.o mmap.o signal.o thunk.o \
-      elfload.o linuxload.o uaccess.o gdbstub.o cpu-uname.o \
-      user-exec.o $(oslib-obj-y)
-
-obj-$(TARGET_HAS_BFLT) += flatload.o
-
-obj-$(TARGET_I386) += vm86.o
 
+obj-y += linux-user/
+obj-y += gdbstub.o thunk.o user-exec.o $(oslib-obj-y)
 obj-i386-y += ioport-user.o
-
-nwfpe-obj-y = fpa11.o fpa11_cpdo.o fpa11_cpdt.o fpa11_cprt.o fpopcode.o
-nwfpe-obj-y += single_cpdo.o double_cpdo.o extended_cpdo.o
-obj-arm-y +=  $(addprefix nwfpe/, $(nwfpe-obj-y))
-obj-arm-y += arm-semi.o
-
-obj-m68k-y += m68k-sim.o m68k-semi.o
+obj-$(TARGET_ARM) += arm-semi.o
+obj-$(TARGET_M68K) += m68k-semi.o
 
 obj-y += $(addprefix ../, $(universal-obj-y))
 obj-y += $(addprefix ../libuser/, $(user-obj-y))
@@ -152,13 +140,10 @@ endif #CONFIG_LINUX_USER
 
 ifdef CONFIG_BSD_USER
 
-$(call set-vpath, $(SRC_PATH)/bsd-user)
-
 QEMU_CFLAGS+=-I$(SRC_PATH)/bsd-user -I$(SRC_PATH)/bsd-user/$(TARGET_ARCH)
 
-obj-y = main.o bsdload.o elfload.o mmap.o signal.o strace.o syscall.o \
-        gdbstub.o uaccess.o user-exec.o
-
+obj-y += bsd-user/
+obj-y += gdbstub.o user-exec.o
 obj-i386-y += ioport-user.o
 
 obj-y += $(addprefix ../, $(universal-obj-y))
@@ -408,6 +393,9 @@ endif # CONFIG_LINUX_USER
 
 obj-$(CONFIG_GDBSTUB_XML) += gdbstub-xml.o
 
+nested-vars = obj-y
+dummy := $(call unnest-vars)
+
 ifdef QEMU_PROGW
 # The linker builds a windows executable. Make also a console executable.
 $(QEMU_PROGW): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)
diff --git a/bsd-user/Makefile.objs b/bsd-user/Makefile.objs
new file mode 100644
index 0000000..5e77f57
--- /dev/null
+++ b/bsd-user/Makefile.objs
@@ -0,0 +1,2 @@
+obj-y = main.o bsdload.o elfload.o mmap.o signal.o strace.o syscall.o \
+	        uaccess.o
diff --git a/configure b/configure
index 76dd57f..2c44488 100755
--- a/configure
+++ b/configure
@@ -3520,8 +3520,14 @@ mkdir -p $target_dir/ide
 mkdir -p $target_dir/usb
 mkdir -p $target_dir/9pfs
 mkdir -p $target_dir/kvm
+if test "$target_linux_user" = yes; then
+  mkdir -p $target_dir/linux-user
+fi
+if test "$target_bsd_user" = yes; then
+  mkdir -p $target_dir/bsd-user
+fi
 if test "$target" = "arm-linux-user" -o "$target" = "armeb-linux-user" -o "$target" = "arm-bsd-user" -o "$target" = "armeb-bsd-user" ; then
-  mkdir -p $target_dir/nwfpe
+  mkdir -p $target_dir/linux-user/arm/nwfpe
 fi
 symlink "$source_path/Makefile.target" "$target_dir/Makefile"
 
diff --git a/linux-user/Makefile.objs b/linux-user/Makefile.objs
new file mode 100644
index 0000000..5899d72
--- /dev/null
+++ b/linux-user/Makefile.objs
@@ -0,0 +1,7 @@
+obj-y = main.o syscall.o strace.o mmap.o signal.o \
+	elfload.o linuxload.o uaccess.o cpu-uname.o
+
+obj-$(TARGET_HAS_BFLT) += flatload.o
+obj-$(TARGET_I386) += vm86.o
+obj-$(TARGET_ARM) += arm/nwfpe/
+obj-$(TARGET_M68K) += m68k-sim.o
diff --git a/linux-user/arm/nwfpe/Makefile.objs b/linux-user/arm/nwfpe/Makefile.objs
new file mode 100644
index 0000000..51b0c32
--- /dev/null
+++ b/linux-user/arm/nwfpe/Makefile.objs
@@ -0,0 +1,2 @@
+obj-y = fpa11.o fpa11_cpdo.o fpa11_cpdt.o fpa11_cprt.o fpopcode.o
+obj-y += single_cpdo.o double_cpdo.o extended_cpdo.o
commit e05804eebc6444bc5660ab2770fd9452fd66ec56
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue May 22 13:41:27 2012 +0200

    build: add rules for nesting
    
    This adds the 'magic' rules that take care of subdirectories.
    The subdirectory makefiles in the source tree are not complete; they
    only define some variables (listed in nested-vars) according to the
    configuration.
    
    The magic rules descend into subdirectory makefiles and gather the
    evaluated values of those variables.  The values from all subdirectories
    are joined together, each prefixed with the subdirectory name, and used
    by the "real" makefiles.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/rules.mak b/rules.mak
index efef6f2..f65283c 100644
--- a/rules.mak
+++ b/rules.mak
@@ -73,3 +73,42 @@ TRACETOOL=$(PYTHON) $(SRC_PATH)/scripts/tracetool.py
 
 # will delete the target of a rule if commands exit with a nonzero exit status
 .DELETE_ON_ERROR:
+
+# magic to descend into other directories
+
+obj := .
+old-nested-dirs :=
+
+define push-var
+$(eval save-$2-$1 = $(value $1))
+$(eval $1 :=)
+endef
+
+define pop-var
+$(eval subdir-$2-$1 := $(if $(filter $2,$(save-$2-$1)),$(addprefix $2,$($1))))
+$(eval $1 = $(value save-$2-$1) $$(subdir-$2-$1))
+$(eval save-$2-$1 :=)
+endef
+
+define unnest-dir
+$(foreach var,$(nested-vars),$(call push-var,$(var),$1/))
+$(eval obj := $(obj)/$1)
+$(eval include $(SRC_PATH)/$1/Makefile.objs)
+$(eval obj := $(patsubst %/$1,%,$(obj)))
+$(foreach var,$(nested-vars),$(call pop-var,$(var),$1/))
+endef
+
+define unnest-vars-1
+$(eval nested-dirs := $(filter-out \
+    $(old-nested-dirs), \
+    $(sort $(foreach var,$(nested-vars), $(filter %/, $($(var)))))))
+$(if $(nested-dirs),
+  $(foreach dir,$(nested-dirs),$(call unnest-dir,$(patsubst %/,%,$(dir))))
+  $(eval old-nested-dirs := $(old-nested-dirs) $(nested-dirs))
+  $(call unnest-vars-1))
+endef
+
+define unnest-vars
+$(call unnest-vars-1)
+$(foreach var,$(nested-vars),$(eval $(var) := $(filter-out %/, $($(var)))))
+endef
commit 4115852bb0670841ff0e780692bcfcf1ede120b0
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue May 29 12:41:34 2012 +0200

    build: do not sprinkle around GENERATED_HEADERS dependencies
    
    Keeping GENERATED_HEADERS dependencies up-to-date everywhere is complex.
    We can simply make the Makefile depend on them, and they will be built
    before all other targets.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile b/Makefile
index 9b7a85e..c0ab97a 100644
--- a/Makefile
+++ b/Makefile
@@ -91,19 +91,18 @@ qemu-options.def: $(SRC_PATH)/qemu-options.hx
 
 SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGET_DIRS))
 
-subdir-%: $(GENERATED_HEADERS)
+subdir-%:
 	$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C $* V="$(V)" TARGET_DIR="$*/" all,)
 
 ifneq ($(wildcard config-host.mak),)
 include $(SRC_PATH)/Makefile.objs
 endif
 
-$(universal-obj-y) $(common-obj-y): $(GENERATED_HEADERS)
 subdir-libcacard: $(oslib-obj-y) $(trace-obj-y) qemu-timer-common.o
 
 $(filter %-softmmu,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) $(common-obj-y) subdir-libdis
 
-$(filter %-user,$(SUBDIR_RULES)): $(GENERATED_HEADERS) $(universal-obj-y) $(trace-obj-y) subdir-libdis-user subdir-libuser
+$(filter %-user,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) subdir-libdis-user subdir-libuser
 
 ROMSUBDIR_RULES=$(patsubst %,romsubdir-%, $(ROMS))
 romsubdir-%:
@@ -142,7 +141,7 @@ libcacard.la:
 install-libcacard:
 	@echo "libtool is missing, please install and rerun configure"; exit 1
 else
-libcacard.la: $(GENERATED_HEADERS) $(oslib-obj-y) qemu-timer-common.o $(addsuffix .lo, $(basename $(trace-obj-y)))
+libcacard.la: $(oslib-obj-y) qemu-timer-common.o $(addsuffix .lo, $(basename $(trace-obj-y)))
 	$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C libcacard V="$(V)" TARGET_DIR="$*/" libcacard.la,)
 
 install-libcacard: libcacard.la
@@ -151,7 +150,6 @@ endif
 ######################################################################
 
 qemu-img.o: qemu-img-cmds.h
-qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o cmd.o qemu-ga.o: $(GENERATED_HEADERS)
 
 tools-obj-y = $(oslib-obj-y) $(trace-obj-y) qemu-tool.o qemu-timer.o \
 	qemu-timer-common.o main-loop.o notify.o iohandler.o cutils.o async.o
@@ -162,7 +160,6 @@ qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y)
 qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y)
 
 qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
-qemu-bridge-helper.o: $(GENERATED_HEADERS)
 
 fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/virtio-9p-marshal.o oslib-posix.o $(trace-obj-y)
 fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
@@ -170,7 +167,6 @@ fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
 qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
 	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"  GEN   $@")
 
-$(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)
@@ -203,8 +199,8 @@ $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py
 
 QGALIB_OBJ=$(addprefix $(qapi-dir)/, qga-qapi-types.o qga-qapi-visit.o qga-qmp-marshal.o)
 QGALIB_GEN=$(addprefix $(qapi-dir)/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h)
-$(QGALIB_OBJ): $(QGALIB_GEN) $(GENERATED_HEADERS)
-$(qga-obj-y) qemu-ga.o: $(QGALIB_GEN) $(GENERATED_HEADERS)
+$(QGALIB_OBJ): $(QGALIB_GEN)
+$(qga-obj-y) qemu-ga.o: $(QGALIB_GEN)
 
 qemu-ga$(EXESUF): qemu-ga.o $(qga-obj-y) $(tools-obj-y) $(qapi-obj-y) $(qobject-obj-y) $(version-obj-y) $(QGALIB_OBJ)
 
@@ -399,5 +395,9 @@ tar:
 	cd /tmp && tar zcvf ~/$(FILE).tar.gz $(FILE) --exclude CVS --exclude .git --exclude .svn
 	rm -rf /tmp/$(FILE)
 
+# Add a dependency on the generated files, so that they are always
+# rebuilt before other object files
+Makefile: $(GENERATED_HEADERS)
+
 # Include automatically generated dependency files
 -include $(wildcard *.d audio/*.d slirp/*.d block/*.d net/*.d ui/*.d qapi/*.d qga/*.d)
diff --git a/Makefile.target b/Makefile.target
index c94abfd..40b774a 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -1,6 +1,5 @@
 # -*- Mode: makefile -*-
 
-GENERATED_HEADERS = config-target.h
 CONFIG_NO_PCI = $(if $(subst n,,$(CONFIG_PCI)),n,y)
 CONFIG_NO_KVM = $(if $(subst n,,$(CONFIG_KVM)),n,y)
 CONFIG_NO_XEN = $(if $(subst n,,$(CONFIG_XEN)),n,y)
@@ -105,8 +104,6 @@ libobj-$(CONFIG_TCI_DIS) += tci-dis.o
 
 tci-dis.o: QEMU_CFLAGS += -I$(SRC_PATH)/tcg -I$(SRC_PATH)/tcg/tci
 
-$(libobj-y): $(GENERATED_HEADERS)
-
 # HELPER_CFLAGS is used for all the legacy code compiled with static register
 # variables
 ifneq ($(TARGET_BASE_ARCH), sparc)
@@ -143,8 +140,6 @@ obj-arm-y += arm-semi.o
 
 obj-m68k-y += m68k-sim.o m68k-semi.o
 
-$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y): $(GENERATED_HEADERS)
-
 obj-y += $(addprefix ../, $(universal-obj-y))
 obj-y += $(addprefix ../libuser/, $(user-obj-y))
 obj-y += $(addprefix ../libdis-user/, $(libdis-y))
@@ -166,8 +161,6 @@ obj-y = main.o bsdload.o elfload.o mmap.o signal.o strace.o syscall.o \
 
 obj-i386-y += ioport-user.o
 
-$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y): $(GENERATED_HEADERS)
-
 obj-y += $(addprefix ../, $(universal-obj-y))
 obj-y += $(addprefix ../libuser/, $(user-obj-y))
 obj-y += $(addprefix ../libdis-user/, $(libdis-y))
@@ -392,9 +385,7 @@ obj-xtensa-y += core-fsf.o
 
 main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
 
-monitor.o: hmp-commands.h qmp-commands-old.h
-
-$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y): $(GENERATED_HEADERS)
+GENERATED_HEADERS += hmp-commands.h qmp-commands-old.h
 
 obj-y += $(addprefix ../, $(universal-obj-y))
 obj-y += $(addprefix ../, $(common-obj-y))
@@ -457,5 +448,8 @@ ifdef CONFIG_TRACE_SYSTEMTAP
 	$(INSTALL_DATA) $(QEMU_PROG).stp "$(DESTDIR)$(qemu_datadir)/../systemtap/tapset"
 endif
 
+GENERATED_HEADERS += config-target.h
+Makefile: $(GENERATED_HEADERS)
+
 # Include automatically generated dependency files
 -include $(wildcard *.d */*.d)
diff --git a/tests/Makefile b/tests/Makefile
index ab7f667..2e754c3 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -37,7 +37,6 @@ 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)
commit 046e7c5f934a7a5680a6822eae4dfa80899a1d40
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue May 22 13:50:03 2012 +0200

    build: remove trace-nested-y
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index 70c5c79..1daa92c 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -425,16 +425,11 @@ ifneq ($(TRACE_BACKEND),dtrace)
 trace-obj-y = trace.o
 endif
 
-trace-nested-$(CONFIG_TRACE_DEFAULT) += default.o
-
-trace-nested-$(CONFIG_TRACE_SIMPLE) += simple.o
+trace-obj-$(CONFIG_TRACE_DEFAULT) += trace/default.o
+trace-obj-$(CONFIG_TRACE_SIMPLE) += trace/simple.o
 trace-obj-$(CONFIG_TRACE_SIMPLE) += qemu-timer-common.o
-
-trace-nested-$(CONFIG_TRACE_STDERR) += stderr.o
-
-trace-nested-y += control.o
-
-trace-obj-y += $(addprefix trace/, $(trace-nested-y))
+trace-obj-$(CONFIG_TRACE_STDERR) += trace/stderr.o
+trace-obj-y += trace/control.o
 
 $(trace-obj-y): $(GENERATED_HEADERS)
 
commit 349417004a0f7cf5518a998dca755cd06f6c212b
Merge: e1ae9a7... 4860853...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Jun 6 20:57:56 2012 +0800

    Merge remote-tracking branch 'qmp/queue/qmp' into staging
    
    * qmp/queue/qmp: (29 commits)
      Add 'query-events' command to QMP to query async events
      qapi: convert netdev_del
      qapi: convert netdev_add
      net: net_client_init(): use error_set()
      net: purge the monitor object from all init functions
      qemu-config: introduce qemu_find_opts_err()
      qemu-config: find_list(): use error_set()
      qerror: introduce QERR_INVALID_OPTION_GROUP
      qemu-option: qemu_opts_from_qdict(): use error_set()
      qemu-option: introduce qemu_opt_set_err()
      qemu-option: opt_set(): use error_set()
      qemu-option: qemu_opts_validate(): use error_set()
      qemu-option: qemu_opt_parse(): use error_set()
      qemu-option: parse_option_size(): use error_set()
      qemu-option: parse_option_bool(): use error_set()
      qemu-option: parse_option_number(): use error_set()
      qemu-option: qemu_opts_create(): use error_set()
      introduce a new monitor command 'dump-guest-memory' to dump guest's memory
      make gdb_id() generally avialable and rename it to cpu_index()
      target-i386: Add API to get note's size
      ...

commit e1ae9a7a78be8d894c111059955fe0e25ec4c203
Merge: 6e72ae4... b7e516c...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Jun 6 17:55:07 2012 +0800

    Merge remote-tracking branch 'afaerber-or/qom-cpu-3' into staging
    
    * afaerber-or/qom-cpu-3: (74 commits)
      Kill off cpu_state_reset()
      linux-user: Use cpu_reset() after cpu_init() / cpu_copy()
      bsd-user: Use cpu_reset() in after cpu_init()
      leon3: Store SPARCCPU in ResetData
      leon3: Use cpu_sparc_init() to obtain SPARCCPU
      sun4u: Store SPARCCPU in ResetData
      sun4u: Let cpu_devinit() return SPARCCPU
      sun4u: Use cpu_sparc_init() to obtain SPARCCPU
      sun4m: Pass SPARCCPU to {main,secondary}_cpu_reset()
      sun4m: Use cpu_sparc_init() to obtain SPARCCPU
      target-sparc: Let cpu_sparc_init() return SPARCCPU
      cpu-exec: Use cpu_reset() in cpu_exec() for TARGET_PPC
      virtex_ml507: Pass PowerPCCPU to main_cpu_reset()
      virtex_ml507: Let ppc440_init_xilinx() return PowerPCCPU
      virtex_ml507: Use cpu_ppc_init() to obtain PowerPCCPU
      ppc_prep: Pass PowerPCCPU to ppc_prep_reset()
      ppc_prep: Use cpu_ppc_init() to obtain PowerPCCPU
      ppc_oldworld: Pass PowerPCCPU to ppc_heathrow_reset()
      ppc_oldworld: Use cpu_ppc_init() to obtain PowerPCCPU
      ppc_newworld: Pass PowerPCCPU to ppc_core99_reset()
      ...

commit 6e72ae4690abde06c7e40603b0f03ab7bcf92b0c
Merge: 721589d... d3d3bef...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Jun 6 17:23:59 2012 +0800

    Merge remote-tracking branch 'qemu-kvm/uq/master' into staging
    
    * qemu-kvm/uq/master:
      kvm: Fix build for non-CAP_IRQ_ROUTING targets

commit d3d3bef0a03adfe73216d741d355bb12f6e52b33
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Jun 5 21:03:57 2012 +0200

    kvm: Fix build for non-CAP_IRQ_ROUTING targets
    
    A type definition and a KVMState field initialization escaped the
    required wrapping with KVM_CAP_IRQ_ROUTING. Also, we need to provide a
    dummy kvm_irqchip_release_virq as virtio-pci references (but does not
    use) it.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Acked-by: Ben Collins <bcollins at ubuntu.com>
    Tested-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index 489ee53..4ea7d85 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -62,11 +62,6 @@ typedef struct KVMSlot
 
 typedef struct kvm_dirty_log KVMDirtyLog;
 
-typedef struct KVMMSIRoute {
-    struct kvm_irq_routing_entry kroute;
-    QTAILQ_ENTRY(KVMMSIRoute) entry;
-} KVMMSIRoute;
-
 struct KVMState
 {
     KVMSlot slots[32];
@@ -867,6 +862,11 @@ int kvm_irqchip_set_irq(KVMState *s, int irq, int level)
 }
 
 #ifdef KVM_CAP_IRQ_ROUTING
+typedef struct KVMMSIRoute {
+    struct kvm_irq_routing_entry kroute;
+    QTAILQ_ENTRY(KVMMSIRoute) entry;
+} KVMMSIRoute;
+
 static void set_gsi(KVMState *s, unsigned int gsi)
 {
     s->used_gsi_bitmap[gsi / 32] |= 1U << (gsi % 32);
@@ -1129,6 +1129,10 @@ static void kvm_init_irq_routing(KVMState *s)
 {
 }
 
+void kvm_irqchip_release_virq(KVMState *s, int virq)
+{
+}
+
 int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg)
 {
     abort();
@@ -1286,7 +1290,9 @@ int kvm_init(void)
     s->pit_state2 = kvm_check_extension(s, KVM_CAP_PIT_STATE2);
 #endif
 
+#ifdef KVM_CAP_IRQ_ROUTING
     s->direct_msi = (kvm_check_extension(s, KVM_CAP_SIGNAL_MSI) > 0);
+#endif
 
     ret = kvm_arch_init(s);
     if (ret < 0) {
commit 721589dd74e7d4771a5b996cfd8e1f79fc10f3a3
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Jun 5 09:05:51 2012 +0800

    Revert "Revert "rtl8139: do the network/host communication only in normal operating mode""
    
    This reverts commit 9c92bf7f6c3f675e60b8ba8a5287bb88ea1eac36.
    
    Per Jason's request.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 2413bc3..eb22d04 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 b7e516ce04fecf260e7c0893b0afb3ff24a40358
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 15:43:31 2012 +0200

    Kill off cpu_state_reset()
    
    In commit 1bba0dc932e8826a7d030df3767daf0bc339f9a2 cpu_reset()
    was renamed to cpu_state_reset(), to allow introducing a new cpu_reset()
    that would operate on QOM objects.
    
    All callers have been updated except for one in target-mips, so drop all
    implementations except for the one in target-mips and move the
    declaration there until MIPSCPU reset can be fully QOM'ified.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Michael Walle <michael at walle.cc> (for lm32)
    Acked-by: Max Filippov <jcmvbkbc at gmail.com> (for xtensa)
    Acked-by: Edgar E. Iglesias <edgar.iglesias at gmail.com> (for mb + cris)
    Acked-by: Alexander Graf <agraf at suse.de> (for ppc)
    Acked-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpu-all.h b/cpu-all.h
index 028528f..3a93c0c 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -443,7 +443,6 @@ void cpu_watchpoint_remove_all(CPUArchState *env, int mask);
 #define SSTEP_NOTIMER 0x4  /* Do not Timers while single stepping */
 
 void cpu_single_step(CPUArchState *env, int enabled);
-void cpu_state_reset(CPUArchState *s);
 int cpu_is_stopped(CPUArchState *env);
 void run_on_cpu(CPUArchState *env, void (*func)(void *data), void *data);
 
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 06ebffc..bbb1d05 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -4,11 +4,6 @@
 #include "host-utils.h"
 #include "sysemu.h"
 
-void cpu_state_reset(CPUARMState *env)
-{
-    cpu_reset(ENV_GET_CPU(env));
-}
-
 static int vfp_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
 {
     int nregs;
diff --git a/target-cris/translate.c b/target-cris/translate.c
index eed03d3..1ad9ec7 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3576,11 +3576,6 @@ CRISCPU *cpu_cris_init(const char *cpu_model)
     return cpu;
 }
 
-void cpu_state_reset(CPUCRISState *env)
-{
-    cpu_reset(ENV_GET_CPU(env));
-}
-
 void restore_state_to_opc(CPUCRISState *env, TranslationBlock *tb, int pc_pos)
 {
 	env->pc = gen_opc_pc[pc_pos];
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 8df109f..2cc8097 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -26,12 +26,6 @@
 
 //#define DEBUG_MMU
 
-/* NOTE: must be called outside the CPU execute loop */
-void cpu_state_reset(CPUX86State *env)
-{
-    cpu_reset(ENV_GET_CPU(env));
-}
-
 static void cpu_x86_version(CPUX86State *env, int *family, int *model)
 {
     int cpuver = env->cpuid_version;
diff --git a/target-lm32/helper.c b/target-lm32/helper.c
index 3b1cee7..1ea477f 100644
--- a/target-lm32/helper.c
+++ b/target-lm32/helper.c
@@ -233,9 +233,3 @@ void cpu_lm32_set_phys_msb_ignore(CPULM32State *env, int value)
         env->flags &= ~LM32_FLAG_IGNORE_MSB;
     }
 }
-
-void cpu_state_reset(CPULM32State *env)
-{
-    cpu_reset(ENV_GET_CPU(env));
-}
-
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index f428375..eac0053 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -98,11 +98,6 @@ static int fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-void cpu_state_reset(CPUM68KState *env)
-{
-    cpu_reset(ENV_GET_CPU(env));
-}
-
 CPUM68KState *cpu_m68k_init(const char *cpu_model)
 {
     M68kCPU *cpu;
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 3c2936f..02b2dc6 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -2001,11 +2001,6 @@ MicroBlazeCPU *cpu_mb_init(const char *cpu_model)
     return cpu;
 }
 
-void cpu_state_reset(CPUMBState *env)
-{
-    cpu_reset(ENV_GET_CPU(env));
-}
-
 void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb, int pc_pos)
 {
     env->sregs[SR_PC] = gen_opc_pc[pc_pos];
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index c7c9cb9..ce3467f 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -637,6 +637,9 @@ static inline CPUMIPSState *cpu_init(const char *cpu_model)
     return &cpu->env;
 }
 
+/* TODO QOM'ify CPU reset and remove */
+void cpu_state_reset(CPUMIPSState *s);
+
 /* mips_timer.c */
 uint32_t cpu_mips_get_random (CPUMIPSState *env);
 uint32_t cpu_mips_get_count (CPUMIPSState *env);
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 42f66e8..f556f85 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -3186,11 +3186,6 @@ void cpu_dump_rfi (target_ulong RA, target_ulong msr)
              TARGET_FMT_lx "\n", RA, msr);
 }
 
-void cpu_state_reset(CPUPPCState *env)
-{
-    cpu_reset(ENV_GET_CPU(env));
-}
-
 PowerPCCPU *cpu_ppc_init(const char *cpu_model)
 {
     PowerPCCPU *cpu;
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 209a696..a34a35b 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -106,14 +106,7 @@ int cpu_s390x_handle_mmu_fault (CPUS390XState *env, target_ulong address, int rw
     return 1;
 }
 
-#endif /* CONFIG_USER_ONLY */
-
-void cpu_state_reset(CPUS390XState *env)
-{
-    cpu_reset(ENV_GET_CPU(env));
-}
-
-#ifndef CONFIG_USER_ONLY
+#else /* !CONFIG_USER_ONLY */
 
 /* Ensure to exit the TB after this call! */
 static void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilc)
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 7d35b84..6532ad2 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -178,11 +178,6 @@ void cpu_dump_state(CPUSH4State * env, FILE * f,
     }
 }
 
-void cpu_state_reset(CPUSH4State *env)
-{
-    cpu_reset(ENV_GET_CPU(env));
-}
-
 typedef struct {
     const char *name;
     int id;
diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
index 8ccac23..f7c004c 100644
--- a/target-sparc/cpu.c
+++ b/target-sparc/cpu.c
@@ -23,11 +23,6 @@
 
 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)
 {
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index e6cb3fe..5e7e72e 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -33,11 +33,6 @@
 #include "hw/loader.h"
 #endif
 
-void cpu_state_reset(CPUXtensaState *env)
-{
-    cpu_reset(ENV_GET_CPU(env));
-}
-
 static struct XtensaConfigList *xtensa_cores;
 
 void xtensa_register_core(XtensaConfigList *node)
commit ff18b7625f5f36ac19b69ed5f0f946093a407174
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 14:47:34 2012 +0200

    linux-user: Use cpu_reset() after cpu_init() / cpu_copy()
    
    Eliminates cpu_state_reset() usage.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/linux-user/main.c b/linux-user/main.c
index 191b750..49108b8 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3405,7 +3405,7 @@ int main(int argc, char **argv, char **envp)
         exit(1);
     }
 #if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
-    cpu_state_reset(env);
+    cpu_reset(ENV_GET_CPU(env));
 #endif
 
     thread_env = env;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 20d2a74..539af3f 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4262,7 +4262,7 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
         /* we create a new CPU instance. */
         new_env = cpu_copy(env);
 #if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
-        cpu_state_reset(new_env);
+        cpu_reset(ENV_GET_CPU(new_env));
 #endif
         /* Init regs that differ from the parent.  */
         cpu_clone_regs(new_env, newsp);
commit fdcb4fb6854e958b633dd8806e4ee1b6e7cea36f
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 14:28:09 2012 +0200

    bsd-user: Use cpu_reset() in after cpu_init()
    
    Eliminates cpu_state_reset() usage.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/bsd-user/main.c b/bsd-user/main.c
index 0689e38..cd33d65 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -918,7 +918,7 @@ int main(int argc, char **argv)
         exit(1);
     }
 #if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
-    cpu_state_reset(env);
+    cpu_reset(ENV_GET_CPU(env));
 #endif
     thread_env = env;
 
commit c537d79cc523f6fa29f70a7055a93e2c128beb20
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 02:36:04 2012 +0200

    leon3: Store SPARCCPU in ResetData
    
    Allows us to use cpu_reset() in place of cpu_state_reset() in
    main_cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/leon3.c b/hw/leon3.c
index 8ffef83..878d3aa 100644
--- a/hw/leon3.c
+++ b/hw/leon3.c
@@ -42,16 +42,16 @@
 #define MAX_PILS 16
 
 typedef struct ResetData {
-    CPUSPARCState *env;
+    SPARCCPU *cpu;
     uint32_t  entry;            /* save kernel entry in case of reset */
 } ResetData;
 
 static void main_cpu_reset(void *opaque)
 {
     ResetData *s   = (ResetData *)opaque;
-    CPUSPARCState  *env = s->env;
+    CPUSPARCState  *env = &s->cpu->env;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(s->cpu));
 
     env->halted = 0;
     env->pc     = s->entry;
@@ -129,7 +129,7 @@ static void leon3_generic_hw_init(ram_addr_t  ram_size,
 
     /* Reset data */
     reset_info        = g_malloc0(sizeof(ResetData));
-    reset_info->env   = env;
+    reset_info->cpu   = cpu;
     qemu_register_reset(main_cpu_reset, reset_info);
 
     /* Allocate IRQ manager */
commit 60ad07335697071ae8e183716171f59202c3c466
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 02:33:34 2012 +0200

    leon3: Use cpu_sparc_init() to obtain SPARCCPU
    
    Needed for main_cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/leon3.c b/hw/leon3.c
index 0a5ff16..8ffef83 100644
--- a/hw/leon3.c
+++ b/hw/leon3.c
@@ -101,6 +101,7 @@ static void leon3_generic_hw_init(ram_addr_t  ram_size,
                                   const char *initrd_filename,
                                   const char *cpu_model)
 {
+    SPARCCPU *cpu;
     CPUSPARCState   *env;
     MemoryRegion *address_space_mem = get_system_memory();
     MemoryRegion *ram = g_new(MemoryRegion, 1);
@@ -117,11 +118,12 @@ static void leon3_generic_hw_init(ram_addr_t  ram_size,
         cpu_model = "LEON3";
     }
 
-    env = cpu_init(cpu_model);
-    if (!env) {
+    cpu = cpu_sparc_init(cpu_model);
+    if (cpu == NULL) {
         fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n");
         exit(1);
     }
+    env = &cpu->env;
 
     cpu_sparc_set_id(env, 0);
 
commit 403d7a2d734e1a8237a0d0db11110ece2aad28d8
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu May 3 03:41:16 2012 +0200

    sun4u: Store SPARCCPU in ResetData
    
    We can now use cpu_reset() in place of cpu_state_reset() in
    main_cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/sun4u.c b/hw/sun4u.c
index e63ba39..137a7c6 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -342,7 +342,7 @@ static void cpu_set_ivec_irq(void *opaque, int irq, int level)
 }
 
 typedef struct ResetData {
-    CPUSPARCState *env;
+    SPARCCPU *cpu;
     uint64_t prom_addr;
 } ResetData;
 
@@ -395,10 +395,10 @@ static void cpu_timer_reset(CPUTimer *timer)
 static void main_cpu_reset(void *opaque)
 {
     ResetData *s = (ResetData *)opaque;
-    CPUSPARCState *env = s->env;
+    CPUSPARCState *env = &s->cpu->env;
     static unsigned int nr_resets;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(s->cpu));
 
     cpu_timer_reset(env->tick);
     cpu_timer_reset(env->stick);
@@ -782,7 +782,7 @@ static SPARCCPU *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef)
                                     hstick_frequency, TICK_INT_DIS);
 
     reset_info = g_malloc0(sizeof(ResetData));
-    reset_info->env = env;
+    reset_info->cpu = cpu;
     reset_info->prom_addr = hwdef->prom_addr;
     qemu_register_reset(main_cpu_reset, reset_info);
 
commit f9d1465f5bd11e27099459ab557f646802b11bd1
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu May 3 03:33:52 2012 +0200

    sun4u: Let cpu_devinit() return SPARCCPU
    
    Needed for main_cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/sun4u.c b/hw/sun4u.c
index 92b616f..e63ba39 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -752,7 +752,7 @@ static TypeInfo ram_info = {
     .class_init    = ram_class_init,
 };
 
-static CPUSPARCState *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef)
+static SPARCCPU *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef)
 {
     SPARCCPU *cpu;
     CPUSPARCState *env;
@@ -786,7 +786,7 @@ static CPUSPARCState *cpu_devinit(const char *cpu_model, const struct hwdef *hwd
     reset_info->prom_addr = hwdef->prom_addr;
     qemu_register_reset(main_cpu_reset, reset_info);
 
-    return env;
+    return cpu;
 }
 
 static void sun4uv_init(MemoryRegion *address_space_mem,
@@ -796,6 +796,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
                         const char *initrd_filename, const char *cpu_model,
                         const struct hwdef *hwdef)
 {
+    SPARCCPU *cpu;
     CPUSPARCState *env;
     M48t59State *nvram;
     unsigned int i;
@@ -808,7 +809,8 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
     void *fw_cfg;
 
     /* init CPUs */
-    env = cpu_devinit(cpu_model, hwdef);
+    cpu = cpu_devinit(cpu_model, hwdef);
+    env = &cpu->env;
 
     /* set up devices */
     ram_init(0, RAM_size);
commit 8ebdf9dcc6036171a9f8bac3fe8dc459725a3e83
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu May 3 03:29:49 2012 +0200

    sun4u: Use cpu_sparc_init() to obtain SPARCCPU
    
    This prepares using it in sun4uv_init().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/sun4u.c b/hw/sun4u.c
index 517bdb8..92b616f 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -754,6 +754,7 @@ static TypeInfo ram_info = {
 
 static CPUSPARCState *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef)
 {
+    SPARCCPU *cpu;
     CPUSPARCState *env;
     ResetData *reset_info;
 
@@ -761,13 +762,15 @@ static CPUSPARCState *cpu_devinit(const char *cpu_model, const struct hwdef *hwd
     uint32_t  stick_frequency = 100*1000000;
     uint32_t hstick_frequency = 100*1000000;
 
-    if (!cpu_model)
+    if (cpu_model == NULL) {
         cpu_model = hwdef->default_cpu_model;
-    env = cpu_init(cpu_model);
-    if (!env) {
+    }
+    cpu = cpu_sparc_init(cpu_model);
+    if (cpu == NULL) {
         fprintf(stderr, "Unable to find Sparc CPU definition\n");
         exit(1);
     }
+    env = &cpu->env;
 
     env->tick = cpu_timer_create("tick", env, tick_irq,
                                   tick_frequency, TICK_NPT_MASK);
commit 5414dec6353b24b22480798f08ddc0f110fcbb7f
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu May 3 03:21:31 2012 +0200

    sun4m: Pass SPARCCPU to {main,secondary}_cpu_reset()
    
    We can now use cpu_reset() in place of cpu_state_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/sun4m.c b/hw/sun4m.c
index c5d2e40..a959261 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -281,17 +281,19 @@ static void dummy_cpu_set_irq(void *opaque, int irq, int level)
 
 static void main_cpu_reset(void *opaque)
 {
-    CPUSPARCState *env = opaque;
+    SPARCCPU *cpu = opaque;
+    CPUSPARCState *env = &cpu->env;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(cpu));
     env->halted = 0;
 }
 
 static void secondary_cpu_reset(void *opaque)
 {
-    CPUSPARCState *env = opaque;
+    SPARCCPU *cpu = opaque;
+    CPUSPARCState *env = &cpu->env;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(cpu));
     env->halted = 1;
 }
 
@@ -821,9 +823,9 @@ static void cpu_devinit(const char *cpu_model, unsigned int id,
 
     cpu_sparc_set_id(env, id);
     if (id == 0) {
-        qemu_register_reset(main_cpu_reset, env);
+        qemu_register_reset(main_cpu_reset, cpu);
     } else {
-        qemu_register_reset(secondary_cpu_reset, env);
+        qemu_register_reset(secondary_cpu_reset, cpu);
         env->halted = 1;
     }
     *cpu_irqs = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS);
commit 8968f588e3e42183a49802f1fa18af0f95cf5ba5
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu May 3 03:14:37 2012 +0200

    sun4m: Use cpu_sparc_init() to obtain SPARCCPU
    
    Needed for {main,secondary}_cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/sun4m.c b/hw/sun4m.c
index 34088ad..c5d2e40 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -809,13 +809,15 @@ static TypeInfo ram_info = {
 static void cpu_devinit(const char *cpu_model, unsigned int id,
                         uint64_t prom_addr, qemu_irq **cpu_irqs)
 {
+    SPARCCPU *cpu;
     CPUSPARCState *env;
 
-    env = cpu_init(cpu_model);
-    if (!env) {
+    cpu = cpu_sparc_init(cpu_model);
+    if (cpu == NULL) {
         fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n");
         exit(1);
     }
+    env = &cpu->env;
 
     cpu_sparc_set_id(env, id);
     if (id == 0) {
commit e59be77a5b88510ceca87335ee9f241ded566ae2
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu May 3 03:12:35 2012 +0200

    target-sparc: Let cpu_sparc_init() return SPARCCPU
    
    Make include paths for cpu-qom.h consistent, so that SPARCCPU can be
    used in cpu.h.
    
    Turn cpu_init macro into a static inline function returning
    CPUSPARCState for backwards compatibility.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
index 7ac6bdb..8ccac23 100644
--- a/target-sparc/cpu.c
+++ b/target-sparc/cpu.c
@@ -111,7 +111,7 @@ static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
     return 0;
 }
 
-CPUSPARCState *cpu_sparc_init(const char *cpu_model)
+SPARCCPU *cpu_sparc_init(const char *cpu_model)
 {
     SPARCCPU *cpu;
     CPUSPARCState *env;
@@ -129,7 +129,7 @@ CPUSPARCState *cpu_sparc_init(const char *cpu_model)
     }
     qemu_init_vcpu(env);
 
-    return env;
+    return cpu;
 }
 
 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 29c63c7..e16b7b3 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -511,9 +511,11 @@ struct CPUSPARCState {
     uint32_t cache_control;
 };
 
+#include "cpu-qom.h"
+
 #ifndef NO_CPU_IO_DEFS
 /* cpu_init.c */
-CPUSPARCState *cpu_sparc_init(const char *cpu_model);
+SPARCCPU *cpu_sparc_init(const char *cpu_model);
 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu);
 void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 /* mmu_helper.c */
@@ -590,7 +592,17 @@ target_phys_addr_t cpu_get_phys_page_nofault(CPUSPARCState *env, target_ulong ad
 #endif
 int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
 
-#define cpu_init cpu_sparc_init
+#ifndef NO_CPU_IO_DEFS
+static inline CPUSPARCState *cpu_init(const char *cpu_model)
+{
+    SPARCCPU *cpu = cpu_sparc_init(cpu_model);
+    if (cpu == NULL) {
+        return NULL;
+    }
+    return &cpu->env;
+}
+#endif
+
 #define cpu_exec cpu_sparc_exec
 #define cpu_gen_code cpu_sparc_gen_code
 #define cpu_signal_handler cpu_sparc_signal_handler
@@ -691,7 +703,6 @@ 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 c356a1bcc0b609125cb540dae3796a3618441300
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 19:39:23 2012 +0200

    cpu-exec: Use cpu_reset() in cpu_exec() for TARGET_PPC
    
    CPUState will be needed for all targets in the future, so place it into
    the main variable declaration block.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Alexander Graf <agraf at suse.de>

diff --git a/cpu-exec.c b/cpu-exec.c
index fbb39cb..83cac93 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -184,6 +184,9 @@ volatile sig_atomic_t exit_request;
 
 int cpu_exec(CPUArchState *env)
 {
+#ifdef TARGET_PPC
+    CPUState *cpu = ENV_GET_CPU(env);
+#endif
     int ret, interrupt_request;
     TranslationBlock *tb;
     uint8_t *tc_ptr;
@@ -341,7 +344,7 @@ int cpu_exec(CPUArchState *env)
                     }
 #elif defined(TARGET_PPC)
                     if ((interrupt_request & CPU_INTERRUPT_RESET)) {
-                        cpu_state_reset(env);
+                        cpu_reset(cpu);
                     }
                     if (interrupt_request & CPU_INTERRUPT_HARD) {
                         ppc_hw_interrupt(env);
commit f8031482d72b61b86b3f9165d50303fba18480d2
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 18:20:07 2012 +0200

    virtex_ml507: Pass PowerPCCPU to main_cpu_reset()
    
    Allows us to call cpu_reset() in place of cpu_state_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c
index 0e223bd..cace86b 100644
--- a/hw/virtex_ml507.c
+++ b/hw/virtex_ml507.c
@@ -108,10 +108,11 @@ static PowerPCCPU *ppc440_init_xilinx(ram_addr_t *ram_size,
 
 static void main_cpu_reset(void *opaque)
 {
-    CPUPPCState *env = opaque;
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
     struct boot_info *bi = env->load_info;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(cpu));
     /* Linux Kernel Parameters (passing device tree):
        *   r3: pointer to the fdt
        *   r4: 0
@@ -206,7 +207,7 @@ static void virtex_init(ram_addr_t ram_size,
 
     cpu = ppc440_init_xilinx(&ram_size, 1, cpu_model, 400000000);
     env = &cpu->env;
-    qemu_register_reset(main_cpu_reset, env);
+    qemu_register_reset(main_cpu_reset, cpu);
 
     memory_region_init_ram(phys_ram, "ram", ram_size);
     vmstate_register_ram_global(phys_ram);
commit 68281699ac0218a2446f30ebf2e1191ae65bb162
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 17:59:06 2012 +0200

    virtex_ml507: Let ppc440_init_xilinx() return PowerPCCPU
    
    Needed for main_cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c
index 3013016..0e223bd 100644
--- a/hw/virtex_ml507.c
+++ b/hw/virtex_ml507.c
@@ -78,10 +78,10 @@ static void mmubooke_create_initial_mapping(CPUPPCState *env,
     tlb->PID = 0;
 }
 
-static CPUPPCState *ppc440_init_xilinx(ram_addr_t *ram_size,
-                                    int do_init,
-                                    const char *cpu_model,
-                                    uint32_t sysclk)
+static PowerPCCPU *ppc440_init_xilinx(ram_addr_t *ram_size,
+                                      int do_init,
+                                      const char *cpu_model,
+                                      uint32_t sysclk)
 {
     PowerPCCPU *cpu;
     CPUPPCState *env;
@@ -103,7 +103,7 @@ static CPUPPCState *ppc440_init_xilinx(ram_addr_t *ram_size,
     irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
     irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
     ppcuic_init(env, irqs, 0x0C0, 0, 1);
-    return env;
+    return cpu;
 }
 
 static void main_cpu_reset(void *opaque)
@@ -190,6 +190,7 @@ static void virtex_init(ram_addr_t ram_size,
 {
     MemoryRegion *address_space_mem = get_system_memory();
     DeviceState *dev;
+    PowerPCCPU *cpu;
     CPUPPCState *env;
     target_phys_addr_t ram_base = 0;
     DriveInfo *dinfo;
@@ -203,7 +204,8 @@ static void virtex_init(ram_addr_t ram_size,
         cpu_model = "440-Xilinx";
     }
 
-    env = ppc440_init_xilinx(&ram_size, 1, cpu_model, 400000000);
+    cpu = ppc440_init_xilinx(&ram_size, 1, cpu_model, 400000000);
+    env = &cpu->env;
     qemu_register_reset(main_cpu_reset, env);
 
     memory_region_init_ram(phys_ram, "ram", ram_size);
commit d1d4938ba88e876cb9e46885f10f38d63eb1581c
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 17:57:13 2012 +0200

    virtex_ml507: Use cpu_ppc_init() to obtain PowerPCCPU
    
    Needed to change ppc440_init_xilinx() return type.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c
index 4a133b5..3013016 100644
--- a/hw/virtex_ml507.c
+++ b/hw/virtex_ml507.c
@@ -83,14 +83,16 @@ static CPUPPCState *ppc440_init_xilinx(ram_addr_t *ram_size,
                                     const char *cpu_model,
                                     uint32_t sysclk)
 {
+    PowerPCCPU *cpu;
     CPUPPCState *env;
     qemu_irq *irqs;
 
-    env = cpu_init(cpu_model);
-    if (!env) {
+    cpu = cpu_ppc_init(cpu_model);
+    if (cpu == NULL) {
         fprintf(stderr, "Unable to initialize CPU!\n");
         exit(1);
     }
+    env = &cpu->env;
 
     ppc_booke_timers_init(env, sysclk, 0/* no flags */);
 
commit 5c3e735f9b46582828d5d0606174ab1f487da4d0
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 17:46:13 2012 +0200

    ppc_prep: Pass PowerPCCPU to ppc_prep_reset()
    
    Allows us to use cpu_reset() in place of cpu_state_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 0b880a5..be2b268 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -441,9 +441,9 @@ static void cpu_request_exit(void *opaque, int irq, int level)
 
 static void ppc_prep_reset(void *opaque)
 {
-    CPUPPCState *env = opaque;
+    PowerPCCPU *cpu = opaque;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(cpu));
 }
 
 /* PowerPC PREP hardware initialisation */
@@ -502,7 +502,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
             /* Set time-base frequency to 100 Mhz */
             cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
         }
-        qemu_register_reset(ppc_prep_reset, env);
+        qemu_register_reset(ppc_prep_reset, cpu);
     }
 
     /* allocate RAM */
commit a9bf3df02114563902cd9aa585457f912434e3bc
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 17:45:09 2012 +0200

    ppc_prep: Use cpu_ppc_init() to obtain PowerPCCPU
    
    Needed for ppc_prep_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index b1da114..0b880a5 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -455,6 +455,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
                            const char *cpu_model)
 {
     MemoryRegion *sysmem = get_system_memory();
+    PowerPCCPU *cpu = NULL;
     CPUPPCState *env = NULL;
     char *filename;
     nvram_t nvram;
@@ -487,11 +488,13 @@ static void ppc_prep_init (ram_addr_t ram_size,
     if (cpu_model == NULL)
         cpu_model = "602";
     for (i = 0; i < smp_cpus; i++) {
-        env = cpu_init(cpu_model);
-        if (!env) {
+        cpu = cpu_ppc_init(cpu_model);
+        if (cpu == NULL) {
             fprintf(stderr, "Unable to find PowerPC CPU definition\n");
             exit(1);
         }
+        env = &cpu->env;
+
         if (env->flags & POWERPC_FLAG_RTC_CLK) {
             /* POWER / PowerPC 601 RTC clock frequency is 7.8125 MHz */
             cpu_ppc_tb_init(env, 7812500UL);
commit cd79664f76cd3ddabef92f99eef82db376ab137d
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 17:42:23 2012 +0200

    ppc_oldworld: Pass PowerPCCPU to ppc_heathrow_reset()
    
    Allows us to use cpu_reset() in place of cpu_state_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index ba8f3ad..f2c6908 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -67,9 +67,9 @@ static target_phys_addr_t round_page(target_phys_addr_t addr)
 
 static void ppc_heathrow_reset(void *opaque)
 {
-    CPUPPCState *env = opaque;
+    PowerPCCPU *cpu = opaque;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(cpu));
 }
 
 static void ppc_heathrow_init (ram_addr_t ram_size,
@@ -114,7 +114,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
 
         /* Set time-base frequency to 16.6 Mhz */
         cpu_ppc_tb_init(env,  16600000UL);
-        qemu_register_reset(ppc_heathrow_reset, env);
+        qemu_register_reset(ppc_heathrow_reset, cpu);
     }
 
     /* allocate RAM */
commit 72c33dd7144ed5967db7969683454a5cb230f5f9
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 17:38:41 2012 +0200

    ppc_oldworld: Use cpu_ppc_init() to obtain PowerPCCPU
    
    Needed for ppc_heathrow_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index 7e73d37..ba8f3ad 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -80,6 +80,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
                                const char *cpu_model)
 {
     MemoryRegion *sysmem = get_system_memory();
+    PowerPCCPU *cpu = NULL;
     CPUPPCState *env = NULL;
     char *filename;
     qemu_irq *pic, **heathrow_irqs;
@@ -104,11 +105,13 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
     if (cpu_model == NULL)
         cpu_model = "G3";
     for (i = 0; i < smp_cpus; i++) {
-        env = cpu_init(cpu_model);
-        if (!env) {
+        cpu = cpu_ppc_init(cpu_model);
+        if (cpu == NULL) {
             fprintf(stderr, "Unable to find PowerPC CPU definition\n");
             exit(1);
         }
+        env = &cpu->env;
+
         /* Set time-base frequency to 16.6 Mhz */
         cpu_ppc_tb_init(env,  16600000UL);
         qemu_register_reset(ppc_heathrow_reset, env);
commit 6680988c3037d88763ecbec3fecb4f8c0c4187d2
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 17:30:25 2012 +0200

    ppc_newworld: Pass PowerPCCPU to ppc_core99_reset()
    
    Allows us to use cpu_reset() in place of cpu_state_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index 6f7f1b5..4e2a6e6 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -123,9 +123,9 @@ static target_phys_addr_t round_page(target_phys_addr_t addr)
 
 static void ppc_core99_reset(void *opaque)
 {
-    CPUPPCState *env = opaque;
+    PowerPCCPU *cpu = opaque;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(cpu));
 }
 
 /* PowerPC Mac99 hardware initialisation */
@@ -176,7 +176,7 @@ static void ppc_core99_init (ram_addr_t ram_size,
 
         /* Set time-base frequency to 100 Mhz */
         cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
-        qemu_register_reset(ppc_core99_reset, env);
+        qemu_register_reset(ppc_core99_reset, cpu);
     }
 
     /* allocate RAM */
commit 8f8204ecb7514a384f9e3776b16ef274ddf1e221
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 17:29:07 2012 +0200

    ppc_newworld: Use cpu_ppc_init() to obtain PowerPCCPU
    
    Needed for ppc_core99_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index 8796510..6f7f1b5 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -136,6 +136,7 @@ static void ppc_core99_init (ram_addr_t ram_size,
                              const char *initrd_filename,
                              const char *cpu_model)
 {
+    PowerPCCPU *cpu = NULL;
     CPUPPCState *env = NULL;
     char *filename;
     qemu_irq *pic, **openpic_irqs;
@@ -166,11 +167,13 @@ static void ppc_core99_init (ram_addr_t ram_size,
         cpu_model = "G4";
 #endif
     for (i = 0; i < smp_cpus; i++) {
-        env = cpu_init(cpu_model);
-        if (!env) {
+        cpu = cpu_ppc_init(cpu_model);
+        if (cpu == NULL) {
             fprintf(stderr, "Unable to find PowerPC CPU definition\n");
             exit(1);
         }
+        env = &cpu->env;
+
         /* Set time-base frequency to 100 Mhz */
         cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
         qemu_register_reset(ppc_core99_reset, env);
commit 90cb09d9d3c2fffc5722d091c059702e2cd089f5
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 17:22:20 2012 +0200

    ppc4xx_devs: Pass PowerPCCPU to ppc4xx_reset()
    
    Allows us to use cpu_reset() in place of cpu_state_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
index 4cefd75..41163e6 100644
--- a/hw/ppc4xx_devs.c
+++ b/hw/ppc4xx_devs.c
@@ -40,9 +40,9 @@
 
 static void ppc4xx_reset(void *opaque)
 {
-    CPUPPCState *env = opaque;
+    PowerPCCPU *cpu = opaque;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(cpu));
 }
 
 /*****************************************************************************/
@@ -70,7 +70,7 @@ CPUPPCState *ppc4xx_init (const char *cpu_model,
     tb_clk->opaque = env;
     ppc_dcr_init(env, NULL, NULL);
     /* Register qemu callbacks */
-    qemu_register_reset(ppc4xx_reset, env);
+    qemu_register_reset(ppc4xx_reset, cpu);
 
     return env;
 }
commit 572747136d20bc7e5e2c5a7c54af4aa44b6f42e2
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 17:20:11 2012 +0200

    ppc4xx_devs: Use cpu_ppc_init() to obtain PowerPCCPU
    
    Needed for ppc4xx_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
index 00e36f4..4cefd75 100644
--- a/hw/ppc4xx_devs.c
+++ b/hw/ppc4xx_devs.c
@@ -51,15 +51,18 @@ CPUPPCState *ppc4xx_init (const char *cpu_model,
                        clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
                        uint32_t sysclk)
 {
+    PowerPCCPU *cpu;
     CPUPPCState *env;
 
     /* init CPUs */
-    env = cpu_init(cpu_model);
-    if (!env) {
+    cpu = cpu_ppc_init(cpu_model);
+    if (cpu == NULL) {
         fprintf(stderr, "Unable to find PowerPC %s CPU definition\n",
                 cpu_model);
         exit(1);
     }
+    env = &cpu->env;
+
     cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */
     cpu_clk->opaque = env;
     /* Set time-base frequency to sysclk */
commit 182fbbf218aab161051c3fbe9d27a9fa45d24064
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 16:39:39 2012 +0200

    ppc440_bamboo: Pass PowerPCCPU to main_cpu_reset()
    
    Allows us to use cpu_reset() in place of cpu_state_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
index 1a4e66a..0dd4dab 100644
--- a/hw/ppc440_bamboo.c
+++ b/hw/ppc440_bamboo.c
@@ -145,9 +145,10 @@ static void mmubooke_create_initial_mapping(CPUPPCState *env,
 
 static void main_cpu_reset(void *opaque)
 {
-    CPUPPCState *env = opaque;
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(cpu));
     env->gpr[1] = (16<<20) - 8;
     env->gpr[3] = FDT_ADDR;
     env->nip = entry;
@@ -193,7 +194,7 @@ static void bamboo_init(ram_addr_t ram_size,
     }
     env = &cpu->env;
 
-    qemu_register_reset(main_cpu_reset, env);
+    qemu_register_reset(main_cpu_reset, cpu);
     ppc_booke_timers_init(env, 400000000, 0);
     ppc_dcr_init(env, NULL, NULL);
 
commit 322164e0dba9eeb1264a923c9bfafd7663fba8aa
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 16:35:51 2012 +0200

    ppc440_bamboo: Use cpu_ppc_init() to obtain PowerPCCPU
    
    Needed for main_cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
index f0a3ae4..1a4e66a 100644
--- a/hw/ppc440_bamboo.c
+++ b/hw/ppc440_bamboo.c
@@ -172,6 +172,7 @@ static void bamboo_init(ram_addr_t ram_size,
     qemu_irq *pic;
     qemu_irq *irqs;
     PCIBus *pcibus;
+    PowerPCCPU *cpu;
     CPUPPCState *env;
     uint64_t elf_entry;
     uint64_t elf_lowaddr;
@@ -185,11 +186,12 @@ static void bamboo_init(ram_addr_t ram_size,
     if (cpu_model == NULL) {
         cpu_model = "440EP";
     }
-    env = cpu_init(cpu_model);
-    if (!env) {
+    cpu = cpu_ppc_init(cpu_model);
+    if (cpu == NULL) {
         fprintf(stderr, "Unable to initialize CPU!\n");
         exit(1);
     }
+    env = &cpu->env;
 
     qemu_register_reset(main_cpu_reset, env);
     ppc_booke_timers_init(env, 400000000, 0);
commit 5b2038e04965a4126a31b7b71cc315efe50a9c8e
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 17:49:38 2012 +0200

    spapr: Pass PowerPCCPU to spapr_cpu_reset()
    
    Allows us to use cpu_reset() in place of cpu_state_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/spapr.c b/hw/spapr.c
index 2672330..d0bddbc 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -505,9 +505,9 @@ static void spapr_reset(void *opaque)
 
 static void spapr_cpu_reset(void *opaque)
 {
-    CPUPPCState *env = opaque;
+    PowerPCCPU *cpu = opaque;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(cpu));
 }
 
 /* pSeries LPAR / sPAPR hardware init */
@@ -570,7 +570,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
 
         /* Set time-base frequency to 512 MHz */
         cpu_ppc_tb_init(env, TIMEBASE_FREQ);
-        qemu_register_reset(spapr_cpu_reset, env);
+        qemu_register_reset(spapr_cpu_reset, cpu);
 
         env->hreset_vector = 0x60;
         env->hreset_excp_prefix = 0;
commit 05769733e046e01a08696bcdf0beae8284fc1662
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu May 3 05:45:10 2012 +0200

    spapr: Use cpu_ppc_init() to obtain PowerPCCPU
    
    Needed for spapr_cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/spapr.c b/hw/spapr.c
index cca20f9..2672330 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -518,6 +518,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
                            const char *initrd_filename,
                            const char *cpu_model)
 {
+    PowerPCCPU *cpu;
     CPUPPCState *env;
     int i;
     MemoryRegion *sysmem = get_system_memory();
@@ -560,12 +561,13 @@ static void ppc_spapr_init(ram_addr_t ram_size,
         cpu_model = kvm_enabled() ? "host" : "POWER7";
     }
     for (i = 0; i < smp_cpus; i++) {
-        env = cpu_init(cpu_model);
-
-        if (!env) {
+        cpu = cpu_ppc_init(cpu_model);
+        if (cpu == NULL) {
             fprintf(stderr, "Unable to find PowerPC CPU definition\n");
             exit(1);
         }
+        env = &cpu->env;
+
         /* Set time-base frequency to 512 MHz */
         cpu_ppc_tb_init(env, TIMEBASE_FREQ);
         qemu_register_reset(spapr_cpu_reset, env);
commit 38f92da6e7b07e8ffa0681b60ad314c568f9fd21
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 02:09:06 2012 +0200

    ppce500_mpc8544ds: Pass PowerPCCPU to mpc8544ds_cpu_reset[_sec]
    
    Allows us to use cpu_reset() in place of cpu_state_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index 88a2767..3eb8a23 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -196,9 +196,10 @@ static void mmubooke_create_initial_mapping(CPUPPCState *env,
 
 static void mpc8544ds_cpu_reset_sec(void *opaque)
 {
-    CPUPPCState *env = opaque;
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(cpu));
 
     /* Secondary CPU starts in halted state for now. Needs to change when
        implementing non-kernel boot. */
@@ -208,10 +209,11 @@ static void mpc8544ds_cpu_reset_sec(void *opaque)
 
 static void mpc8544ds_cpu_reset(void *opaque)
 {
-    CPUPPCState *env = opaque;
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
     struct boot_info *bi = env->load_info;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(cpu));
 
     /* Set initial guest state. */
     env->halted = 0;
@@ -281,11 +283,11 @@ static void mpc8544ds_init(ram_addr_t ram_size,
             /* Primary CPU */
             struct boot_info *boot_info;
             boot_info = g_malloc0(sizeof(struct boot_info));
-            qemu_register_reset(mpc8544ds_cpu_reset, env);
+            qemu_register_reset(mpc8544ds_cpu_reset, cpu);
             env->load_info = boot_info;
         } else {
             /* Secondary CPUs */
-            qemu_register_reset(mpc8544ds_cpu_reset_sec, env);
+            qemu_register_reset(mpc8544ds_cpu_reset_sec, cpu);
         }
     }
 
commit 397b457d869fbd5bbe2793c3066bb6bc92845932
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu May 3 05:43:05 2012 +0200

    target-ppc: Let cpu_ppc_init() return PowerPCCPU
    
    Adapt e500 mpc8544ds machine accordingly.
    
    Turn cpu_init() into a static inline function returning CPUPPCState for
    backwards compatibility.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index f1dfbe1..88a2767 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -254,12 +254,15 @@ static void mpc8544ds_init(ram_addr_t ram_size,
     irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
     irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
     for (i = 0; i < smp_cpus; i++) {
+        PowerPCCPU *cpu;
         qemu_irq *input;
-        env = cpu_ppc_init(cpu_model);
-        if (!env) {
+
+        cpu = cpu_ppc_init(cpu_model);
+        if (cpu == NULL) {
             fprintf(stderr, "Unable to initialize CPU!\n");
             exit(1);
         }
+        env = &cpu->env;
 
         if (!firstenv) {
             firstenv = env;
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 84c9674..77a2858 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1099,7 +1099,7 @@ struct mmu_ctx_t {
 #include "cpu-qom.h"
 
 /*****************************************************************************/
-CPUPPCState *cpu_ppc_init (const char *cpu_model);
+PowerPCCPU *cpu_ppc_init(const char *cpu_model);
 void ppc_translate_init(void);
 int cpu_ppc_exec (CPUPPCState *s);
 /* you can call this signal handler from your SIGBUS and SIGSEGV
@@ -1214,7 +1214,15 @@ static inline uint64_t ppc_dump_gpr(CPUPPCState *env, int gprn)
 int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp);
 int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val);
 
-#define cpu_init cpu_ppc_init
+static inline CPUPPCState *cpu_init(const char *cpu_model)
+{
+    PowerPCCPU *cpu = cpu_ppc_init(cpu_model);
+    if (cpu == NULL) {
+        return NULL;
+    }
+    return &cpu->env;
+}
+
 #define cpu_exec cpu_ppc_exec
 #define cpu_gen_code cpu_ppc_gen_code
 #define cpu_signal_handler cpu_ppc_signal_handler
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index e97e496..42f66e8 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -3191,7 +3191,7 @@ void cpu_state_reset(CPUPPCState *env)
     cpu_reset(ENV_GET_CPU(env));
 }
 
-CPUPPCState *cpu_ppc_init (const char *cpu_model)
+PowerPCCPU *cpu_ppc_init(const char *cpu_model)
 {
     PowerPCCPU *cpu;
     CPUPPCState *env;
@@ -3213,5 +3213,5 @@ CPUPPCState *cpu_ppc_init (const char *cpu_model)
 
     qemu_init_vcpu(env);
 
-    return env;
+    return cpu;
 }
commit fa156e5127d367987289e90563cad4c4ca83a2d8
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 14:23:25 2012 +0200

    mips_r4k: Store MIPSCPU in ResetData
    
    Allows us to use cpu_reset() in place of cpu_state_reset() in
    main_cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index f89957c..d685999 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -65,7 +65,7 @@ static const MemoryRegionOps mips_qemu_ops = {
 };
 
 typedef struct ResetData {
-    CPUMIPSState *env;
+    MIPSCPU *cpu;
     uint64_t vector;
 } ResetData;
 
@@ -143,9 +143,9 @@ static int64_t load_kernel(void)
 static void main_cpu_reset(void *opaque)
 {
     ResetData *s = (ResetData *)opaque;
-    CPUMIPSState *env = s->env;
+    CPUMIPSState *env = &s->cpu->env;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(s->cpu));
     env->active_tc.PC = s->vector;
 }
 
@@ -188,7 +188,7 @@ void mips_r4k_init (ram_addr_t ram_size,
     env = &cpu->env;
 
     reset_info = g_malloc0(sizeof(ResetData));
-    reset_info->env = env;
+    reset_info->cpu = cpu;
     reset_info->vector = env->active_tc.PC;
     qemu_register_reset(main_cpu_reset, reset_info);
 
commit 9ac67e2168a6f1d801c6ca1dd856fe83552021d5
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 14:21:43 2012 +0200

    mips_r4k: Use cpu_mips_init() to obtain MIPSCPU
    
    Needed for main_cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index e2da49c..f89957c 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -162,6 +162,7 @@ void mips_r4k_init (ram_addr_t ram_size,
     MemoryRegion *bios;
     MemoryRegion *iomem = g_new(MemoryRegion, 1);
     int bios_size;
+    MIPSCPU *cpu;
     CPUMIPSState *env;
     ResetData *reset_info;
     int i;
@@ -179,11 +180,13 @@ void mips_r4k_init (ram_addr_t ram_size,
         cpu_model = "24Kf";
 #endif
     }
-    env = cpu_init(cpu_model);
-    if (!env) {
+    cpu = cpu_mips_init(cpu_model);
+    if (cpu == NULL) {
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
+    env = &cpu->env;
+
     reset_info = g_malloc0(sizeof(ResetData));
     reset_info->env = env;
     reset_info->vector = env->active_tc.PC;
commit 2d44fc8e2ed1e1efff6ea73de0aea75c44262459
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 14:19:45 2012 +0200

    mips_mipssim: Store MIPSCPU in ResetData
    
    Allows us to use cpu_reset() in place of cpu_state_reset() in
    main_cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
index 7c510da..eb03047 100644
--- a/hw/mips_mipssim.c
+++ b/hw/mips_mipssim.c
@@ -46,7 +46,7 @@ static struct _loaderparams {
 } loaderparams;
 
 typedef struct ResetData {
-    CPUMIPSState *env;
+    MIPSCPU *cpu;
     uint64_t vector;
 } ResetData;
 
@@ -105,9 +105,9 @@ static int64_t load_kernel(void)
 static void main_cpu_reset(void *opaque)
 {
     ResetData *s = (ResetData *)opaque;
-    CPUMIPSState *env = s->env;
+    CPUMIPSState *env = &s->cpu->env;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(s->cpu));
     env->active_tc.PC = s->vector & ~(target_ulong)1;
     if (s->vector & 1) {
         env->hflags |= MIPS_HFLAG_M16;
@@ -161,7 +161,7 @@ mips_mipssim_init (ram_addr_t ram_size,
     env = &cpu->env;
 
     reset_info = g_malloc0(sizeof(ResetData));
-    reset_info->env = env;
+    reset_info->cpu = cpu;
     reset_info->vector = env->active_tc.PC;
     qemu_register_reset(main_cpu_reset, reset_info);
 
commit 7ee274c1937deccfaaa0c98389349eb3e9a6c90d
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 14:17:49 2012 +0200

    mips_mipssim: Use cpu_mips_init() to obtain MIPSCPU
    
    Needed for main_cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
index 1ea7b58..7c510da 100644
--- a/hw/mips_mipssim.c
+++ b/hw/mips_mipssim.c
@@ -140,6 +140,7 @@ mips_mipssim_init (ram_addr_t ram_size,
     MemoryRegion *address_space_mem = get_system_memory();
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     MemoryRegion *bios = g_new(MemoryRegion, 1);
+    MIPSCPU *cpu;
     CPUMIPSState *env;
     ResetData *reset_info;
     int bios_size;
@@ -152,11 +153,13 @@ mips_mipssim_init (ram_addr_t ram_size,
         cpu_model = "24Kf";
 #endif
     }
-    env = cpu_init(cpu_model);
-    if (!env) {
+    cpu = cpu_mips_init(cpu_model);
+    if (cpu == NULL) {
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
+    env = &cpu->env;
+
     reset_info = g_malloc0(sizeof(ResetData));
     reset_info->env = env;
     reset_info->vector = env->active_tc.PC;
commit 1004ee8d26ea8584be26cce0212cec68d5d93117
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 14:14:00 2012 +0200

    mips_malta: Pass MIPSCPU to main_cpu_reset()
    
    Allows us to use cpu_reset() in place of cpu_state_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index d81e8d5..dfd7b6b 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -751,8 +751,10 @@ static void malta_mips_config(CPUMIPSState *env)
 
 static void main_cpu_reset(void *opaque)
 {
-    CPUMIPSState *env = opaque;
-    cpu_state_reset(env);
+    MIPSCPU *cpu = opaque;
+    CPUMIPSState *env = &cpu->env;
+
+    cpu_reset(CPU(cpu));
 
     /* The bootloader does not need to be rewritten as it is located in a
        read only location. The kernel location and the arguments table
@@ -836,7 +838,7 @@ void mips_malta_init (ram_addr_t ram_size,
         /* Init internal devices */
         cpu_mips_irq_init_cpu(env);
         cpu_mips_clock_init(env);
-        qemu_register_reset(main_cpu_reset, env);
+        qemu_register_reset(main_cpu_reset, cpu);
     }
     env = first_cpu;
 
commit 7688b134b8a47a615529b7caaae49da3cf91dcca
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 14:11:48 2012 +0200

    mips_malta: Use cpu_mips_init() to obtain MIPSCPU
    
    Needed for main_cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 4752bb2..d81e8d5 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -788,6 +788,7 @@ void mips_malta_init (ram_addr_t ram_size,
     int64_t kernel_entry;
     PCIBus *pci_bus;
     ISABus *isa_bus;
+    MIPSCPU *cpu;
     CPUMIPSState *env;
     qemu_irq *isa_irq;
     qemu_irq *cpu_exit_irq;
@@ -825,11 +826,13 @@ void mips_malta_init (ram_addr_t ram_size,
     }
 
     for (i = 0; i < smp_cpus; i++) {
-        env = cpu_init(cpu_model);
-        if (!env) {
+        cpu = cpu_mips_init(cpu_model);
+        if (cpu == NULL) {
             fprintf(stderr, "Unable to find CPU definition\n");
             exit(1);
         }
+        env = &cpu->env;
+
         /* Init internal devices */
         cpu_mips_irq_init_cpu(env);
         cpu_mips_clock_init(env);
commit f37f435a3ea16d7d64a0971b40d2269020348d7b
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 14:06:50 2012 +0200

    mips_jazz: Pass MIPSCPU to main_cpu_reset()
    
    Allows us to use cpu_reset() in place of cpu_state_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Hervé Poussineau <hpoussin at reactos.org>

diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index 24959e0..bf1b799 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -50,8 +50,9 @@ enum jazz_model_e
 
 static void main_cpu_reset(void *opaque)
 {
-    CPUMIPSState *env = opaque;
-    cpu_state_reset(env);
+    MIPSCPU *cpu = opaque;
+
+    cpu_reset(CPU(cpu));
 }
 
 static uint64_t rtc_read(void *opaque, target_phys_addr_t addr, unsigned size)
@@ -147,7 +148,7 @@ static void mips_jazz_init(MemoryRegion *address_space,
         exit(1);
     }
     env = &cpu->env;
-    qemu_register_reset(main_cpu_reset, env);
+    qemu_register_reset(main_cpu_reset, cpu);
 
     /* allocate RAM */
     memory_region_init_ram(ram, "mips_jazz.ram", ram_size);
commit 6bd8da655a7a71487e22ea003e652b001fbd96f2
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 14:05:42 2012 +0200

    mips_jazz: Use cpu_mips_init() to obtain MIPSCPU
    
    Needed for main_cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Hervé Poussineau <hpoussin at reactos.org>

diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index a6bc7ba..24959e0 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -112,6 +112,7 @@ static void mips_jazz_init(MemoryRegion *address_space,
 {
     char *filename;
     int bios_size, n;
+    MIPSCPU *cpu;
     CPUMIPSState *env;
     qemu_irq *rc4030, *i8259;
     rc4030_dma *dmas;
@@ -140,11 +141,12 @@ static void mips_jazz_init(MemoryRegion *address_space,
         cpu_model = "24Kf";
 #endif
     }
-    env = cpu_init(cpu_model);
-    if (!env) {
+    cpu = cpu_mips_init(cpu_model);
+    if (cpu == NULL) {
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
+    env = &cpu->env;
     qemu_register_reset(main_cpu_reset, env);
 
     /* allocate RAM */
commit 800cf598f98db86da7b30359ae8b173a1efc1cea
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 13:56:22 2012 +0200

    mips_fulong2e: Pass MIPSCPU to main_cpu_reset()
    
    Allows us to use cpu_reset() in place of cpu_state_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c
index 08d3aa0..38e4b86 100644
--- a/hw/mips_fulong2e.c
+++ b/hw/mips_fulong2e.c
@@ -198,9 +198,10 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base, int64_t kernel_a
 
 static void main_cpu_reset(void *opaque)
 {
-    CPUMIPSState *env = opaque;
+    MIPSCPU *cpu = opaque;
+    CPUMIPSState *env = &cpu->env;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(cpu));
     /* TODO: 2E reset stuff */
     if (loaderparams.kernel_filename) {
         env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
@@ -286,7 +287,7 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device,
     }
     env = &cpu->env;
 
-    qemu_register_reset(main_cpu_reset, env);
+    qemu_register_reset(main_cpu_reset, cpu);
 
     /* fulong 2e has 256M ram. */
     ram_size = 256 * 1024 * 1024;
commit f0f803669701a39e29f0daf62a729f7f3954a2a3
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 13:54:41 2012 +0200

    mips_fulong2e: Use cpu_mips_cpu() to obtain MIPSCPU
    
    Needed for main_cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c
index 1a8df10..08d3aa0 100644
--- a/hw/mips_fulong2e.c
+++ b/hw/mips_fulong2e.c
@@ -272,17 +272,19 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device,
     i2c_bus *smbus;
     int i;
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+    MIPSCPU *cpu;
     CPUMIPSState *env;
 
     /* init CPUs */
     if (cpu_model == NULL) {
         cpu_model = "Loongson-2E";
     }
-    env = cpu_init(cpu_model);
-    if (!env) {
+    cpu = cpu_mips_init(cpu_model);
+    if (cpu == NULL) {
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
+    env = &cpu->env;
 
     qemu_register_reset(main_cpu_reset, env);
 
commit 30bf942d8cd822b22530be602084a0810db45936
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 13:33:04 2012 +0200

    target-mips: Let cpu_mips_init() return MIPSCPU
    
    Turn cpu_init macro into a static inline function returning CPUMIPSState
    for backwards compatibility.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 44c1152..c7c9cb9 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -496,7 +496,6 @@ void cpu_unassigned_access(CPUMIPSState *env, target_phys_addr_t addr,
 
 void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf);
 
-#define cpu_init cpu_mips_init
 #define cpu_exec cpu_mips_exec
 #define cpu_gen_code cpu_mips_gen_code
 #define cpu_signal_handler cpu_mips_signal_handler
@@ -626,9 +625,18 @@ enum {
 #define CPU_INTERRUPT_WAKE CPU_INTERRUPT_TGT_INT_0
 
 int cpu_mips_exec(CPUMIPSState *s);
-CPUMIPSState *cpu_mips_init(const char *cpu_model);
+MIPSCPU *cpu_mips_init(const char *cpu_model);
 int cpu_mips_signal_handler(int host_signum, void *pinfo, void *puc);
 
+static inline CPUMIPSState *cpu_init(const char *cpu_model)
+{
+    MIPSCPU *cpu = cpu_mips_init(cpu_model);
+    if (cpu == NULL) {
+        return NULL;
+    }
+    return &cpu->env;
+}
+
 /* mips_timer.c */
 uint32_t cpu_mips_get_random (CPUMIPSState *env);
 uint32_t cpu_mips_get_count (CPUMIPSState *env);
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 1ab44ed..4e15ee3 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -12689,7 +12689,7 @@ static void mips_tcg_init(void)
 
 #include "translate_init.c"
 
-CPUMIPSState *cpu_mips_init (const char *cpu_model)
+MIPSCPU *cpu_mips_init(const char *cpu_model)
 {
     MIPSCPU *cpu;
     CPUMIPSState *env;
@@ -12711,7 +12711,7 @@ CPUMIPSState *cpu_mips_init (const char *cpu_model)
     mips_tcg_init();
     cpu_reset(CPU(cpu));
     qemu_init_vcpu(env);
-    return env;
+    return cpu;
 }
 
 void cpu_state_reset(CPUMIPSState *env)
commit fca1be7cbcb8535fd9f6de707ac81878f34d5470
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 12:53:17 2012 +0200

    target-mips: Use cpu_reset() in do_interrupt()
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-mips/helper.c b/target-mips/helper.c
index ddf9cb7..4208bb2 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -399,6 +399,7 @@ static void set_hflags_for_handler (CPUMIPSState *env)
 void do_interrupt (CPUMIPSState *env)
 {
 #if !defined(CONFIG_USER_ONLY)
+    MIPSCPU *cpu = mips_env_get_cpu(env);
     target_ulong offset;
     int cause = -1;
     const char *name;
@@ -452,7 +453,7 @@ void do_interrupt (CPUMIPSState *env)
         set_hflags_for_handler(env);
         break;
     case EXCP_RESET:
-        cpu_state_reset(env);
+        cpu_reset(CPU(cpu));
         break;
     case EXCP_SRESET:
         env->CP0_Status |= (1 << CP0St_SR);
commit 3bd4122ef61b3276edc79b700f0e18de2ff673f5
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 13:06:10 2012 +0200

    target-mips: Use cpu_reset() in cpu_mips_init()
    
    Commit 0f71a7095db6bc055bc5bb520d85ea650cca8a33 (target-mips: QOM'ify
    CPU) hooked up cpu_state_reset() to CPUClass::reset(). Dropping the
    introduction of subclasses for 1.1, due to mips_def_t the reset code
    could not be QOM'ified yet, i.e. cpu_state_reset() will not forward to
    CPUClass::reset().
    
    Update cpu_mips_init() with cpu_reset() nontheless, indirectly calling
    cpu_state_reset(), so that generic code can be converted to call
    cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-mips/translate.c b/target-mips/translate.c
index 0c563ee..1ab44ed 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -12709,7 +12709,7 @@ CPUMIPSState *cpu_mips_init (const char *cpu_model)
     fpu_init(env, def);
     mvp_init(env, def);
     mips_tcg_init();
-    cpu_state_reset(env);
+    cpu_reset(CPU(cpu));
     qemu_init_vcpu(env);
     return env;
 }
commit 868bac81d76b6149b246731945de426aee6448be
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 18:40:14 2012 +0200

    r2d: Store SuperHCPU in ResetData
    
    Allows us to use cpu_reset() in place of cpu_state_reset() in
    main_cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/r2d.c b/hw/r2d.c
index 1bd8df6..0f16e81 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -192,16 +192,16 @@ static qemu_irq *r2d_fpga_init(MemoryRegion *sysmem,
 }
 
 typedef struct ResetData {
-    CPUSH4State *env;
+    SuperHCPU *cpu;
     uint32_t vector;
 } ResetData;
 
 static void main_cpu_reset(void *opaque)
 {
     ResetData *s = (ResetData *)opaque;
-    CPUSH4State *env = s->env;
+    CPUSH4State *env = &s->cpu->env;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(s->cpu));
     env->pc = s->vector;
 }
 
@@ -248,7 +248,7 @@ static void r2d_init(ram_addr_t ram_size,
     env = &cpu->env;
 
     reset_info = g_malloc0(sizeof(ResetData));
-    reset_info->env = env;
+    reset_info->cpu = cpu;
     reset_info->vector = env->pc;
     qemu_register_reset(main_cpu_reset, reset_info);
 
commit fd2f410b375a3813b827633c79c2c45ab9e7089a
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 18:38:01 2012 +0200

    r2d: Use cpu_sh4_init() to obtain SuperHCPU
    
    Needed for main_cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/r2d.c b/hw/r2d.c
index c55de01..1bd8df6 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -224,6 +224,7 @@ static void r2d_init(ram_addr_t ram_size,
 	      const char *kernel_filename, const char *kernel_cmdline,
 	      const char *initrd_filename, const char *cpu_model)
 {
+    SuperHCPU *cpu;
     CPUSH4State *env;
     ResetData *reset_info;
     struct SH7750State *s;
@@ -235,14 +236,17 @@ static void r2d_init(ram_addr_t ram_size,
     SysBusDevice *busdev;
     MemoryRegion *address_space_mem = get_system_memory();
 
-    if (!cpu_model)
+    if (cpu_model == NULL) {
         cpu_model = "SH7751R";
+    }
 
-    env = cpu_init(cpu_model);
-    if (!env) {
+    cpu = cpu_sh4_init(cpu_model);
+    if (cpu == NULL) {
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
+    env = &cpu->env;
+
     reset_info = g_malloc0(sizeof(ResetData));
     reset_info->env = env;
     reset_info->vector = env->pc;
commit 445e957194807aa9eb1d02c23430dbb0c6bac34e
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 18:35:09 2012 +0200

    target-sh4: Let cpu_sh4_init() return SuperHCPU
    
    Turn cpu_init macro into a static inline function returning
    CPUSH4State for backwards compatibility.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index b6768f1..bf59222 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -191,7 +191,7 @@ typedef struct CPUSH4State {
 
 #include "cpu-qom.h"
 
-CPUSH4State *cpu_sh4_init(const char *cpu_model);
+SuperHCPU *cpu_sh4_init(const char *cpu_model);
 int cpu_sh4_exec(CPUSH4State * s);
 int cpu_sh4_signal_handler(int host_signum, void *pinfo,
                            void *puc);
@@ -232,7 +232,15 @@ void cpu_load_tlb(CPUSH4State * env);
 
 #include "softfloat.h"
 
-#define cpu_init cpu_sh4_init
+static inline CPUSH4State *cpu_init(const char *cpu_model)
+{
+    SuperHCPU *cpu = cpu_sh4_init(cpu_model);
+    if (cpu == NULL) {
+        return NULL;
+    }
+    return &cpu->env;
+}
+
 #define cpu_exec cpu_sh4_exec
 #define cpu_gen_code cpu_sh4_gen_code
 #define cpu_signal_handler cpu_sh4_signal_handler
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index d25f0c5..7d35b84 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -247,7 +247,7 @@ static void cpu_register(CPUSH4State *env, const sh4_def_t *def)
     env->id = def->id;
 }
 
-CPUSH4State *cpu_sh4_init(const char *cpu_model)
+SuperHCPU *cpu_sh4_init(const char *cpu_model)
 {
     SuperHCPU *cpu;
     CPUSH4State *env;
@@ -264,7 +264,7 @@ CPUSH4State *cpu_sh4_init(const char *cpu_model)
     cpu_reset(CPU(cpu));
     cpu_register(env, def);
     qemu_init_vcpu(env);
-    return env;
+    return cpu;
 }
 
 static void gen_goto_tb(DisasContext * ctx, int n, target_ulong dest)
commit e5fe7a34d421eb97fc3b69f58d8e91f4679ffb41
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed May 2 19:37:34 2012 +0200

    pc: Pass X86CPU to pc_cpu_reset()
    
    Allows us to use cpu_reset() in place of cpu_state_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Igor Mammedov <imammedo at redhat.com>

diff --git a/hw/pc.c b/hw/pc.c
index 1133921..8368701 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -926,9 +926,10 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
 
 static void pc_cpu_reset(void *opaque)
 {
-    CPUX86State *env = opaque;
+    X86CPU *cpu = opaque;
+    CPUX86State *env = &cpu->env;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(cpu));
     env->halted = !cpu_is_bsp(env);
 }
 
@@ -946,8 +947,8 @@ static X86CPU *pc_new_cpu(const char *cpu_model)
     if ((env->cpuid_features & CPUID_APIC) || smp_cpus > 1) {
         env->apic_state = apic_init(env, env->cpuid_apic_id);
     }
-    qemu_register_reset(pc_cpu_reset, env);
-    pc_cpu_reset(env);
+    qemu_register_reset(pc_cpu_reset, cpu);
+    pc_cpu_reset(cpu);
     return cpu;
 }
 
commit 608911acac53f08dfaaf1878f56d4e32ee572ce4
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed May 2 18:49:27 2012 +0200

    pc: Use cpu_x86_init() to obtain X86CPU
    
    Needed for pc_cpu_reset().
    
    Also change return type to X86CPU.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Igor Mammedov <imammedo at redhat.com>

diff --git a/hw/pc.c b/hw/pc.c
index c790bcb..1133921 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -932,21 +932,23 @@ static void pc_cpu_reset(void *opaque)
     env->halted = !cpu_is_bsp(env);
 }
 
-static CPUX86State *pc_new_cpu(const char *cpu_model)
+static X86CPU *pc_new_cpu(const char *cpu_model)
 {
+    X86CPU *cpu;
     CPUX86State *env;
 
-    env = cpu_init(cpu_model);
-    if (!env) {
+    cpu = cpu_x86_init(cpu_model);
+    if (cpu == NULL) {
         fprintf(stderr, "Unable to find x86 CPU definition\n");
         exit(1);
     }
+    env = &cpu->env;
     if ((env->cpuid_features & CPUID_APIC) || smp_cpus > 1) {
         env->apic_state = apic_init(env, env->cpuid_apic_id);
     }
     qemu_register_reset(pc_cpu_reset, env);
     pc_cpu_reset(env);
-    return env;
+    return cpu;
 }
 
 void pc_cpus_init(const char *cpu_model)
commit b47ed9969fb12527c40aa507e165061c20e21836
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed May 2 18:42:46 2012 +0200

    target-i386: Let cpu_x86_init() return X86CPU
    
    Turn cpu_init macro into a static inline function returning CPUX86State
    for backwards compatibility.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Igor Mammedov <imammedo at redhat.com>

diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index aeff20b..bcf663e 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -787,7 +787,7 @@ typedef struct CPUX86State {
 
 #include "cpu-qom.h"
 
-CPUX86State *cpu_x86_init(const char *cpu_model);
+X86CPU *cpu_x86_init(const char *cpu_model);
 int cpu_x86_exec(CPUX86State *s);
 void x86_cpu_list (FILE *f, fprintf_function cpu_fprintf, const char *optarg);
 void x86_cpudef_setup(void);
@@ -960,7 +960,15 @@ uint64_t cpu_get_tsc(CPUX86State *env);
 #define TARGET_VIRT_ADDR_SPACE_BITS 32
 #endif
 
-#define cpu_init cpu_x86_init
+static inline CPUX86State *cpu_init(const char *cpu_model)
+{
+    X86CPU *cpu = cpu_x86_init(cpu_model);
+    if (cpu == NULL) {
+        return NULL;
+    }
+    return &cpu->env;
+}
+
 #define cpu_exec cpu_x86_exec
 #define cpu_gen_code cpu_x86_gen_code
 #define cpu_signal_handler cpu_x86_signal_handler
diff --git a/target-i386/helper.c b/target-i386/helper.c
index e182025..8df109f 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1157,7 +1157,7 @@ int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
     return 1;
 }
 
-CPUX86State *cpu_x86_init(const char *cpu_model)
+X86CPU *cpu_x86_init(const char *cpu_model)
 {
     X86CPU *cpu;
     CPUX86State *env;
@@ -1183,7 +1183,7 @@ CPUX86State *cpu_x86_init(const char *cpu_model)
 
     x86_cpu_realize(OBJECT(cpu), NULL);
 
-    return env;
+    return cpu;
 }
 
 #if !defined(CONFIG_USER_ONLY)
commit 232fc23bed97f92b939d5b2802a481c1dea5991b
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 01:14:41 2012 +0200

    target-i386: Pass X86CPU to do_cpu_{init,sipi}()
    
    Allows to use cpu_reset() in place of cpu_state_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Igor Mammedov <imammedo at redhat.com>

diff --git a/cpu-exec.c b/cpu-exec.c
index 0344cd5..fbb39cb 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -287,11 +287,11 @@ int cpu_exec(CPUArchState *env)
 #if defined(TARGET_I386)
                     if (interrupt_request & CPU_INTERRUPT_INIT) {
                             svm_check_intercept(env, SVM_EXIT_INIT);
-                            do_cpu_init(env);
+                            do_cpu_init(x86_env_get_cpu(env));
                             env->exception_index = EXCP_HALTED;
                             cpu_loop_exit(env);
                     } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
-                            do_cpu_sipi(env);
+                            do_cpu_sipi(x86_env_get_cpu(env));
                     } else if (env->hflags2 & HF2_GIF_MASK) {
                         if ((interrupt_request & CPU_INTERRUPT_SMI) &&
                             !(env->hflags & HF_SMM_MASK)) {
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 2460f63..aeff20b 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -1053,8 +1053,8 @@ static inline void cpu_get_tb_cpu_state(CPUX86State *env, target_ulong *pc,
         (env->eflags & (IOPL_MASK | TF_MASK | RF_MASK | VM_MASK));
 }
 
-void do_cpu_init(CPUX86State *env);
-void do_cpu_sipi(CPUX86State *env);
+void do_cpu_init(X86CPU *cpu);
+void do_cpu_sipi(X86CPU *cpu);
 
 #define MCE_INJECT_BROADCAST    1
 #define MCE_INJECT_UNCOND_AO    2
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 3421be2..e182025 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1187,27 +1187,30 @@ CPUX86State *cpu_x86_init(const char *cpu_model)
 }
 
 #if !defined(CONFIG_USER_ONLY)
-void do_cpu_init(CPUX86State *env)
+void do_cpu_init(X86CPU *cpu)
 {
+    CPUX86State *env = &cpu->env;
     int sipi = env->interrupt_request & CPU_INTERRUPT_SIPI;
     uint64_t pat = env->pat;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(cpu));
     env->interrupt_request = sipi;
     env->pat = pat;
     apic_init_reset(env->apic_state);
     env->halted = !cpu_is_bsp(env);
 }
 
-void do_cpu_sipi(CPUX86State *env)
+void do_cpu_sipi(X86CPU *cpu)
 {
+    CPUX86State *env = &cpu->env;
+
     apic_sipi(env->apic_state);
 }
 #else
-void do_cpu_init(CPUX86State *env)
+void do_cpu_init(X86CPU *cpu)
 {
 }
-void do_cpu_sipi(CPUX86State *env)
+void do_cpu_sipi(X86CPU *cpu)
 {
 }
 #endif
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index e74a9e4..0d0d8f6 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1698,6 +1698,8 @@ void kvm_arch_post_run(CPUX86State *env, struct kvm_run *run)
 
 int kvm_arch_process_async_events(CPUX86State *env)
 {
+    X86CPU *cpu = x86_env_get_cpu(env);
+
     if (env->interrupt_request & CPU_INTERRUPT_MCE) {
         /* We must not raise CPU_INTERRUPT_MCE if it's not supported. */
         assert(env->mcg_cap);
@@ -1732,11 +1734,11 @@ int kvm_arch_process_async_events(CPUX86State *env)
     }
     if (env->interrupt_request & CPU_INTERRUPT_INIT) {
         kvm_cpu_synchronize_state(env);
-        do_cpu_init(env);
+        do_cpu_init(cpu);
     }
     if (env->interrupt_request & CPU_INTERRUPT_SIPI) {
         kvm_cpu_synchronize_state(env);
-        do_cpu_sipi(env);
+        do_cpu_sipi(cpu);
     }
     if (env->interrupt_request & CPU_INTERRUPT_TPR) {
         env->interrupt_request &= ~CPU_INTERRUPT_TPR;
commit bf494367fa77b5ed872d8add50677542a7141836
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 12:30:53 2012 +0200

    microblaze_boot: Pass MicroBlazeCPU to microblaze_load_kernel()
    
    Allows us to use cpu_reset() in place of cpu_state_reset() in
    main_cpu_reset().
    
    Also pass it through to its reset callbacks, while at it.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/hw/microblaze_boot.c b/hw/microblaze_boot.c
index b4fbb10..1030e9c 100644
--- a/hw/microblaze_boot.c
+++ b/hw/microblaze_boot.c
@@ -35,7 +35,7 @@
 
 static struct
 {
-    void (*machine_cpu_reset)(CPUMBState *);
+    void (*machine_cpu_reset)(MicroBlazeCPU *);
     uint32_t bootstrap_pc;
     uint32_t cmdline;
     uint32_t fdt;
@@ -43,14 +43,15 @@ static struct
 
 static void main_cpu_reset(void *opaque)
 {
-    CPUMBState *env = opaque;
+    MicroBlazeCPU *cpu = opaque;
+    CPUMBState *env = &cpu->env;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(cpu));
     env->regs[5] = boot_info.cmdline;
     env->regs[7] = boot_info.fdt;
     env->sregs[SR_PC] = boot_info.bootstrap_pc;
     if (boot_info.machine_cpu_reset) {
-        boot_info.machine_cpu_reset(env);
+        boot_info.machine_cpu_reset(cpu);
     }
 }
 
@@ -99,11 +100,10 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
     return addr - 0x30000000LL;
 }
 
-void microblaze_load_kernel(CPUMBState *env, target_phys_addr_t ddr_base,
+void microblaze_load_kernel(MicroBlazeCPU *cpu, target_phys_addr_t ddr_base,
                             uint32_t ramsize, const char *dtb_filename,
-                                  void (*machine_cpu_reset)(CPUMBState *))
+                            void (*machine_cpu_reset)(MicroBlazeCPU *))
 {
-
     QemuOpts *machine_opts;
     const char *kernel_filename = NULL;
     const char *kernel_cmdline = NULL;
@@ -122,7 +122,7 @@ void microblaze_load_kernel(CPUMBState *env, target_phys_addr_t ddr_base,
     }
 
     boot_info.machine_cpu_reset = machine_cpu_reset;
-    qemu_register_reset(main_cpu_reset, env);
+    qemu_register_reset(main_cpu_reset, cpu);
 
     if (kernel_filename) {
         int kernel_size;
diff --git a/hw/microblaze_boot.h b/hw/microblaze_boot.h
index bf9d136..c9a3064 100644
--- a/hw/microblaze_boot.h
+++ b/hw/microblaze_boot.h
@@ -3,8 +3,8 @@
 
 #include "hw.h"
 
-void microblaze_load_kernel(CPUMBState *env, target_phys_addr_t ddr_base,
+void microblaze_load_kernel(MicroBlazeCPU *cpu, target_phys_addr_t ddr_base,
                             uint32_t ramsize, const char *dtb_filename,
-                                  void (*machine_cpu_reset)(CPUMBState *));
+                            void (*machine_cpu_reset)(MicroBlazeCPU *));
 
 #endif /* __MICROBLAZE_BOOT __ */
diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c
index 6819241..bff63e3 100644
--- a/hw/petalogix_ml605_mmu.c
+++ b/hw/petalogix_ml605_mmu.c
@@ -54,8 +54,10 @@
 #define AXIENET_BASEADDR 0x82780000
 #define AXIDMA_BASEADDR 0x84600000
 
-static void machine_cpu_reset(CPUMBState *env)
+static void machine_cpu_reset(MicroBlazeCPU *cpu)
 {
+    CPUMBState *env = &cpu->env;
+
     env->pvr.regs[10] = 0x0e000000; /* virtex 6 */
     /* setup pvr to match kernel setting */
     env->pvr.regs[5] |= PVR5_DCACHE_WRITEBACK_MASK;
@@ -133,7 +135,7 @@ petalogix_ml605_init(ram_addr_t ram_size,
                                      irq[1], irq[0], 100 * 1000000);
     }
 
-    microblaze_load_kernel(env, ddr_base, ram_size, BINARY_DEVICE_TREE_FILE,
+    microblaze_load_kernel(cpu, ddr_base, ram_size, BINARY_DEVICE_TREE_FILE,
                                                             machine_cpu_reset);
 
 }
diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index 7ff3cd5..f41c559 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -49,8 +49,10 @@
 #define UARTLITE_BASEADDR 0x84000000
 #define ETHLITE_BASEADDR 0x81000000
 
-static void machine_cpu_reset(CPUMBState *env)
+static void machine_cpu_reset(MicroBlazeCPU *cpu)
 {
+    CPUMBState *env = &cpu->env;
+
     env->pvr.regs[10] = 0x0c000000; /* spartan 3a dsp family.  */
 }
 
@@ -107,7 +109,7 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
     xilinx_timer_create(TIMER_BASEADDR, irq[0], 2, 62 * 1000000);
     xilinx_ethlite_create(&nd_table[0], ETHLITE_BASEADDR, irq[1], 0, 0);
 
-    microblaze_load_kernel(env, ddr_base, ram_size,
+    microblaze_load_kernel(cpu, ddr_base, ram_size,
                     BINARY_DEVICE_TREE_FILE, machine_cpu_reset);
 }
 
commit 3ed607333e979a1637cc08af66858b7b37bd37ff
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 12:20:29 2012 +0200

    petalogix_s3adsp1800_mmu: Use cpu_mb_init() to obtain MicroBlazeCPU
    
    Needed for microblaze_load_kernel().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index 8b37336..7ff3cd5 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -62,6 +62,7 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
                           const char *initrd_filename, const char *cpu_model)
 {
     DeviceState *dev;
+    MicroBlazeCPU *cpu;
     CPUMBState *env;
     DriveInfo *dinfo;
     int i;
@@ -75,7 +76,8 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
     if (cpu_model == NULL) {
         cpu_model = "microblaze";
     }
-    env = cpu_init(cpu_model);
+    cpu = cpu_mb_init(cpu_model);
+    env = &cpu->env;
 
     /* Attach emulated BRAM through the LMB.  */
     memory_region_init_ram(phys_lmb_bram,
commit a9480e5d32f8746363c361cd86878cc33b4ab597
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 12:19:03 2012 +0200

    petalogix_ml605: Use cpu_mb_init() to obtain MicroBlazeCPU
    
    Needed for microblaze_load_kernel().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c
index 31a4348..6819241 100644
--- a/hw/petalogix_ml605_mmu.c
+++ b/hw/petalogix_ml605_mmu.c
@@ -75,6 +75,7 @@ petalogix_ml605_init(ram_addr_t ram_size,
 {
     MemoryRegion *address_space_mem = get_system_memory();
     DeviceState *dev;
+    MicroBlazeCPU *cpu;
     CPUMBState *env;
     DriveInfo *dinfo;
     int i;
@@ -87,7 +88,8 @@ petalogix_ml605_init(ram_addr_t ram_size,
     if (cpu_model == NULL) {
         cpu_model = "microblaze";
     }
-    env = cpu_init(cpu_model);
+    cpu = cpu_mb_init(cpu_model);
+    env = &cpu->env;
 
     /* Attach emulated BRAM through the LMB.  */
     memory_region_init_ram(phys_lmb_bram, "petalogix_ml605.lmb_bram",
commit b33ab1f7a965a9765dc9a5b9f061c44eee2e25e2
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 12:14:03 2012 +0200

    target-microblaze: Let cpu_mb_init() return MicroBlazeCPU
    
    Since qemu_init_vcpu() is no-op for CONFIG_USER_ONLY drop the env
    variable that is now unused there.
    
    Turn cpu_init macro into a static inline function returning CPUMBState
    for backwards compatibility.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index b0ba9fe..4968c24 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -272,7 +272,7 @@ struct CPUMBState {
 
 #include "cpu-qom.h"
 
-CPUMBState *cpu_mb_init(const char *cpu_model);
+MicroBlazeCPU *cpu_mb_init(const char *cpu_model);
 int cpu_mb_exec(CPUMBState *s);
 void cpu_mb_close(CPUMBState *s);
 void do_interrupt(CPUMBState *env);
@@ -295,7 +295,15 @@ enum {
 #define TARGET_PHYS_ADDR_SPACE_BITS 32
 #define TARGET_VIRT_ADDR_SPACE_BITS 32
 
-#define cpu_init cpu_mb_init
+static inline CPUMBState *cpu_init(const char *cpu_model)
+{
+    MicroBlazeCPU *cpu = cpu_mb_init(cpu_model);
+    if (cpu == NULL) {
+        return NULL;
+    }
+    return &cpu->env;
+}
+
 #define cpu_exec cpu_mb_exec
 #define cpu_gen_code cpu_mb_gen_code
 #define cpu_signal_handler cpu_mb_signal_handler
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index f0ebd59..3c2936f 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1951,21 +1951,20 @@ void cpu_dump_state (CPUMBState *env, FILE *f, fprintf_function cpu_fprintf,
     cpu_fprintf(f, "\n\n");
 }
 
-CPUMBState *cpu_mb_init (const char *cpu_model)
+MicroBlazeCPU *cpu_mb_init(const char *cpu_model)
 {
     MicroBlazeCPU *cpu;
-    CPUMBState *env;
     static int tcg_initialized = 0;
     int i;
 
     cpu = MICROBLAZE_CPU(object_new(TYPE_MICROBLAZE_CPU));
-    env = &cpu->env;
 
     cpu_reset(CPU(cpu));
-    qemu_init_vcpu(env);
+    qemu_init_vcpu(&cpu->env);
 
-    if (tcg_initialized)
-        return env;
+    if (tcg_initialized) {
+        return cpu;
+    }
 
     tcg_initialized = 1;
 
@@ -1999,7 +1998,7 @@ CPUMBState *cpu_mb_init (const char *cpu_model)
 #define GEN_HELPER 2
 #include "helper.h"
 
-    return env;
+    return cpu;
 }
 
 void cpu_state_reset(CPUMBState *env)
commit 1584aafd02b949d6fa554e93bd70e5940217b66c
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 11:58:29 2012 +0200

    cris-boot: Pass CRISCPU to main_cpu_reset().
    
    Allows us to use cpu_reset() in place of cpu_state_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/hw/cris-boot.c b/hw/cris-boot.c
index 331b2d1..b21326f 100644
--- a/hw/cris-boot.c
+++ b/hw/cris-boot.c
@@ -29,12 +29,13 @@
 
 static void main_cpu_reset(void *opaque)
 {
-    CPUCRISState *env = opaque;
+    CRISCPU *cpu = opaque;
+    CPUCRISState *env = &cpu->env;
     struct cris_load_info *li;
 
     li = env->load_info;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(cpu));
 
     if (!li) {
         /* nothing more to do.  */
@@ -93,5 +94,5 @@ void cris_load_image(CRISCPU *cpu, struct cris_load_info *li)
         }
         pstrcpy_targphys("cmdline", 0x40000000, 256, li->cmdline);
     }
-    qemu_register_reset(main_cpu_reset, env);
+    qemu_register_reset(main_cpu_reset, cpu);
 }
commit 5935664fc06f1b6c0276c11e736608ac7ccebe5f
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 11:57:07 2012 +0200

    cris-boot: Pass CRISCPU to cris_load_image()
    
    Needed for main_cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index 636708c..eab6327 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -346,7 +346,7 @@ void axisdev88_init (ram_addr_t ram_size,
 
     li.image_filename = kernel_filename;
     li.cmdline = kernel_cmdline;
-    cris_load_image(env, &li);
+    cris_load_image(cpu, &li);
 }
 
 static QEMUMachine axisdev88_machine = {
diff --git a/hw/cris-boot.c b/hw/cris-boot.c
index ca6c52f..331b2d1 100644
--- a/hw/cris-boot.c
+++ b/hw/cris-boot.c
@@ -60,8 +60,9 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
     return addr - 0x80000000LL;
 }
 
-void cris_load_image(CPUCRISState *env, struct cris_load_info *li)
+void cris_load_image(CRISCPU *cpu, struct cris_load_info *li)
 {
+    CPUCRISState *env = &cpu->env;
     uint64_t entry, high;
     int kcmdline_len;
     int image_size;
diff --git a/hw/cris-boot.h b/hw/cris-boot.h
index ecb9779..0a2c242 100644
--- a/hw/cris-boot.h
+++ b/hw/cris-boot.h
@@ -8,4 +8,4 @@ struct cris_load_info
     target_phys_addr_t entry;
 };
 
-void cris_load_image(CPUCRISState *env, struct cris_load_info *li);
+void cris_load_image(CRISCPU *cpu, struct cris_load_info *li);
commit ddeb9ae5fa4270356d7cfdde279e7cbfbba8448d
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 11:50:35 2012 +0200

    axis_dev88: Use cpu_cris_init() to obtain CRISCPU
    
    Needed for cris_load_image().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index 2304e35..636708c 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -247,6 +247,7 @@ void axisdev88_init (ram_addr_t ram_size,
                      const char *kernel_filename, const char *kernel_cmdline,
                      const char *initrd_filename, const char *cpu_model)
 {
+    CRISCPU *cpu;
     CPUCRISState *env;
     DeviceState *dev;
     SysBusDevice *s;
@@ -263,7 +264,8 @@ void axisdev88_init (ram_addr_t ram_size,
     if (cpu_model == NULL) {
         cpu_model = "crisv32";
     }
-    env = cpu_init(cpu_model);
+    cpu = cpu_cris_init(cpu_model);
+    env = &cpu->env;
 
     /* allocate RAM */
     memory_region_init_ram(phys_ram, "axisdev88.ram", ram_size);
commit 9fca5636e1883346418d437320f43b0c34cb6cc1
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 11:37:07 2012 +0200

    target-cris: Let cpu_cris_init() return CRISCPU
    
    Turn cpu_init macro into a static inline function returning CPUCRISState
    for backwards compatibility.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index 5449cc4..a760367 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -171,7 +171,7 @@ typedef struct CPUCRISState {
 
 #include "cpu-qom.h"
 
-CPUCRISState *cpu_cris_init(const char *cpu_model);
+CRISCPU *cpu_cris_init(const char *cpu_model);
 int cpu_cris_exec(CPUCRISState *s);
 void cpu_cris_close(CPUCRISState *s);
 void do_interrupt(CPUCRISState *env);
@@ -216,7 +216,15 @@ enum {
 #define TARGET_PHYS_ADDR_SPACE_BITS 32
 #define TARGET_VIRT_ADDR_SPACE_BITS 32
 
-#define cpu_init cpu_cris_init
+static inline CPUCRISState *cpu_init(const char *cpu_model)
+{
+    CRISCPU *cpu = cpu_cris_init(cpu_model);
+    if (cpu == NULL) {
+        return NULL;
+    }
+    return &cpu->env;
+}
+
 #define cpu_exec cpu_cris_exec
 #define cpu_gen_code cpu_cris_gen_code
 #define cpu_signal_handler cpu_cris_signal_handler
diff --git a/target-cris/translate.c b/target-cris/translate.c
index a398057..eed03d3 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3503,7 +3503,7 @@ static uint32_t vr_by_name(const char *name)
     return 32;
 }
 
-CPUCRISState *cpu_cris_init (const char *cpu_model)
+CRISCPU *cpu_cris_init(const char *cpu_model)
 {
     CRISCPU *cpu;
     CPUCRISState *env;
@@ -3519,7 +3519,7 @@ CPUCRISState *cpu_cris_init (const char *cpu_model)
     qemu_init_vcpu(env);
 
     if (tcg_initialized) {
-        return env;
+        return cpu;
     }
 
     tcg_initialized = 1;
@@ -3529,7 +3529,7 @@ CPUCRISState *cpu_cris_init (const char *cpu_model)
 
     if (env->pregs[PR_VR] < 32) {
         cpu_crisv10_init(env);
-        return env;
+        return cpu;
     }
 
 
@@ -3573,7 +3573,7 @@ CPUCRISState *cpu_cris_init (const char *cpu_model)
                                        pregnames[i]);
     }
 
-    return env;
+    return cpu;
 }
 
 void cpu_state_reset(CPUCRISState *env)
commit dd10ce6d8a437b8c5d2ce9c193a3b64080038c43
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 11:45:32 2012 +0200

    target-cris: Reindent cpu_cris_init()
    
    Judging by TCG variable initialization it used 8-char tabs; use 4 spaces
    instead. Also remove trailing whitespace.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-cris/translate.c b/target-cris/translate.c
index e353ea3..a398057 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3506,73 +3506,74 @@ static uint32_t vr_by_name(const char *name)
 CPUCRISState *cpu_cris_init (const char *cpu_model)
 {
     CRISCPU *cpu;
-	CPUCRISState *env;
-	static int tcg_initialized = 0;
-	int i;
+    CPUCRISState *env;
+    static int tcg_initialized = 0;
+    int i;
 
     cpu = CRIS_CPU(object_new(TYPE_CRIS_CPU));
     env = &cpu->env;
 
-	env->pregs[PR_VR] = vr_by_name(cpu_model);
+    env->pregs[PR_VR] = vr_by_name(cpu_model);
 
     cpu_reset(CPU(cpu));
-	qemu_init_vcpu(env);
+    qemu_init_vcpu(env);
 
-	if (tcg_initialized)
-		return env;
+    if (tcg_initialized) {
+        return env;
+    }
 
-	tcg_initialized = 1;
+    tcg_initialized = 1;
 
 #define GEN_HELPER 2
 #include "helper.h"
 
-	if (env->pregs[PR_VR] < 32) {
-		cpu_crisv10_init(env);
-		return env; 
-	}
+    if (env->pregs[PR_VR] < 32) {
+        cpu_crisv10_init(env);
+        return env;
+    }
 
 
-	cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
-	cc_x = tcg_global_mem_new(TCG_AREG0,
-				  offsetof(CPUCRISState, cc_x), "cc_x");
-	cc_src = tcg_global_mem_new(TCG_AREG0,
-				    offsetof(CPUCRISState, cc_src), "cc_src");
-	cc_dest = tcg_global_mem_new(TCG_AREG0,
-				     offsetof(CPUCRISState, cc_dest),
-				     "cc_dest");
-	cc_result = tcg_global_mem_new(TCG_AREG0,
-				       offsetof(CPUCRISState, cc_result),
-				       "cc_result");
-	cc_op = tcg_global_mem_new(TCG_AREG0,
-				   offsetof(CPUCRISState, cc_op), "cc_op");
-	cc_size = tcg_global_mem_new(TCG_AREG0,
-				     offsetof(CPUCRISState, cc_size),
-				     "cc_size");
-	cc_mask = tcg_global_mem_new(TCG_AREG0,
-				     offsetof(CPUCRISState, cc_mask),
-				     "cc_mask");
-
-	env_pc = tcg_global_mem_new(TCG_AREG0, 
-				    offsetof(CPUCRISState, pc),
-				    "pc");
-	env_btarget = tcg_global_mem_new(TCG_AREG0,
-					 offsetof(CPUCRISState, btarget),
-					 "btarget");
-	env_btaken = tcg_global_mem_new(TCG_AREG0,
-					 offsetof(CPUCRISState, btaken),
-					 "btaken");
-	for (i = 0; i < 16; i++) {
-		cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
-					      offsetof(CPUCRISState, regs[i]),
-					      regnames[i]);
-	}
-	for (i = 0; i < 16; i++) {
-		cpu_PR[i] = tcg_global_mem_new(TCG_AREG0,
-					       offsetof(CPUCRISState, pregs[i]),
-					       pregnames[i]);
-	}
+    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    cc_x = tcg_global_mem_new(TCG_AREG0,
+                              offsetof(CPUCRISState, cc_x), "cc_x");
+    cc_src = tcg_global_mem_new(TCG_AREG0,
+                                offsetof(CPUCRISState, cc_src), "cc_src");
+    cc_dest = tcg_global_mem_new(TCG_AREG0,
+                                 offsetof(CPUCRISState, cc_dest),
+                                 "cc_dest");
+    cc_result = tcg_global_mem_new(TCG_AREG0,
+                                   offsetof(CPUCRISState, cc_result),
+                                   "cc_result");
+    cc_op = tcg_global_mem_new(TCG_AREG0,
+                               offsetof(CPUCRISState, cc_op), "cc_op");
+    cc_size = tcg_global_mem_new(TCG_AREG0,
+                                 offsetof(CPUCRISState, cc_size),
+                                 "cc_size");
+    cc_mask = tcg_global_mem_new(TCG_AREG0,
+                                 offsetof(CPUCRISState, cc_mask),
+                                 "cc_mask");
+
+    env_pc = tcg_global_mem_new(TCG_AREG0,
+                                offsetof(CPUCRISState, pc),
+                                "pc");
+    env_btarget = tcg_global_mem_new(TCG_AREG0,
+                                     offsetof(CPUCRISState, btarget),
+                                     "btarget");
+    env_btaken = tcg_global_mem_new(TCG_AREG0,
+                                    offsetof(CPUCRISState, btaken),
+                                    "btaken");
+    for (i = 0; i < 16; i++) {
+        cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
+                                      offsetof(CPUCRISState, regs[i]),
+                                      regnames[i]);
+    }
+    for (i = 0; i < 16; i++) {
+        cpu_PR[i] = tcg_global_mem_new(TCG_AREG0,
+                                       offsetof(CPUCRISState, pregs[i]),
+                                       pregnames[i]);
+    }
 
-	return env;
+    return env;
 }
 
 void cpu_state_reset(CPUCRISState *env)
commit eded12679dcf4c205c00bebfb77fb9883d2a2f68
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 19:33:05 2012 +0200

    xtensa_lx60: Pass XtensaCPU to lx60_reset()
    
    Allows us to use cpu_reset() in place of cpu_state_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c
index 31f8adc..b153bfd 100644
--- a/hw/xtensa_lx60.c
+++ b/hw/xtensa_lx60.c
@@ -148,9 +148,9 @@ static uint64_t translate_phys_addr(void *env, uint64_t addr)
 
 static void lx60_reset(void *opaque)
 {
-    CPUXtensaState *env = opaque;
+    XtensaCPU *cpu = opaque;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(cpu));
 }
 
 static void lx_init(const LxBoardDesc *board,
@@ -184,7 +184,7 @@ static void lx_init(const LxBoardDesc *board,
         env = &cpu->env;
 
         env->sregs[PRID] = n;
-        qemu_register_reset(lx60_reset, env);
+        qemu_register_reset(lx60_reset, cpu);
         /* Need MMU initialized prior to ELF loading,
          * so that ELF gets loaded into virtual addresses
          */
commit adbb0f75f0be1d747503e5b19ce6a7efa37cf562
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 19:31:25 2012 +0200

    xtensa_lx60: Use cpu_xtensa_init() to obtain XtensaCPU
    
    Allows us to use cpu_reset() in place of cpu_state_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c
index afdef49..31f8adc 100644
--- a/hw/xtensa_lx60.c
+++ b/hw/xtensa_lx60.c
@@ -164,6 +164,7 @@ static void lx_init(const LxBoardDesc *board,
     int be = 0;
 #endif
     MemoryRegion *system_memory = get_system_memory();
+    XtensaCPU *cpu = NULL;
     CPUXtensaState *env = NULL;
     MemoryRegion *ram, *rom, *system_io;
     DriveInfo *dinfo;
@@ -175,17 +176,19 @@ static void lx_init(const LxBoardDesc *board,
     }
 
     for (n = 0; n < smp_cpus; n++) {
-        env = cpu_init(cpu_model);
-        if (!env) {
+        cpu = cpu_xtensa_init(cpu_model);
+        if (cpu == NULL) {
             fprintf(stderr, "Unable to find CPU definition\n");
             exit(1);
         }
+        env = &cpu->env;
+
         env->sregs[PRID] = n;
         qemu_register_reset(lx60_reset, env);
         /* Need MMU initialized prior to ELF loading,
          * so that ELF gets loaded into virtual addresses
          */
-        cpu_state_reset(env);
+        cpu_reset(CPU(cpu));
     }
 
     ram = g_malloc(sizeof(*ram));
commit 11e7bfd7e04346f3acd77150ac82784f58bbe89f
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 19:28:19 2012 +0200

    xtensa_sim: Pass XtensaCPU to sim_reset()
    
    Allows us to use cpu_reset() in place of cpu_state_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/hw/xtensa_sim.c b/hw/xtensa_sim.c
index dae08a1..1ce07fb 100644
--- a/hw/xtensa_sim.c
+++ b/hw/xtensa_sim.c
@@ -37,9 +37,11 @@ static uint64_t translate_phys_addr(void *env, uint64_t addr)
     return cpu_get_phys_page_debug(env, addr);
 }
 
-static void sim_reset(void *env)
+static void sim_reset(void *opaque)
 {
-    cpu_state_reset(env);
+    XtensaCPU *cpu = opaque;
+
+    cpu_reset(CPU(cpu));
 }
 
 static void sim_init(ram_addr_t ram_size,
@@ -61,11 +63,11 @@ static void sim_init(ram_addr_t ram_size,
         env = &cpu->env;
 
         env->sregs[PRID] = n;
-        qemu_register_reset(sim_reset, env);
+        qemu_register_reset(sim_reset, cpu);
         /* Need MMU initialized prior to ELF loading,
          * so that ELF gets loaded into virtual addresses
          */
-        sim_reset(env);
+        sim_reset(cpu);
     }
 
     ram = g_malloc(sizeof(*ram));
commit 06d26274cdd2f3ce79ba91dbf2dd0f535cbabd3c
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 19:26:57 2012 +0200

    xtensa_sim: Use cpu_xtensa_init() to obtain XtensaCPU
    
    Needed for sim_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/hw/xtensa_sim.c b/hw/xtensa_sim.c
index c7e05dc..dae08a1 100644
--- a/hw/xtensa_sim.c
+++ b/hw/xtensa_sim.c
@@ -47,16 +47,19 @@ static void sim_init(ram_addr_t ram_size,
         const char *kernel_filename, const char *kernel_cmdline,
         const char *initrd_filename, const char *cpu_model)
 {
+    XtensaCPU *cpu = NULL;
     CPUXtensaState *env = NULL;
     MemoryRegion *ram, *rom;
     int n;
 
     for (n = 0; n < smp_cpus; n++) {
-        env = cpu_init(cpu_model);
-        if (!env) {
+        cpu = cpu_xtensa_init(cpu_model);
+        if (cpu == NULL) {
             fprintf(stderr, "Unable to find CPU definition\n");
             exit(1);
         }
+        env = &cpu->env;
+
         env->sregs[PRID] = n;
         qemu_register_reset(sim_reset, env);
         /* Need MMU initialized prior to ELF loading,
commit 15be3171392a14cb90abd89ac7310681556f736e
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun May 6 12:41:53 2012 +0200

    target-xtensa: Let cpu_xtensa_init() return XtensaCPU
    
    Make the include paths for cpu-qom.h consistent to allow using XtensaCPU
    in cpu.h.
    
    Turn cpu_init macro into a static inline function returning
    CPUXtensaState for backwards compatibility.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/target-xtensa/cpu.c b/target-xtensa/cpu.c
index 97deacb..9d01983 100644
--- a/target-xtensa/cpu.c
+++ b/target-xtensa/cpu.c
@@ -28,7 +28,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "cpu-qom.h"
+#include "cpu.h"
 #include "qemu-common.h"
 
 
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 6d0ea7c..81f7833 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -344,13 +344,24 @@ typedef struct CPUXtensaState {
     CPU_COMMON
 } CPUXtensaState;
 
-#define cpu_init cpu_xtensa_init
+#include "cpu-qom.h"
+
 #define cpu_exec cpu_xtensa_exec
 #define cpu_gen_code cpu_xtensa_gen_code
 #define cpu_signal_handler cpu_xtensa_signal_handler
 #define cpu_list xtensa_cpu_list
 
-CPUXtensaState *cpu_xtensa_init(const char *cpu_model);
+XtensaCPU *cpu_xtensa_init(const char *cpu_model);
+
+static inline CPUXtensaState *cpu_init(const char *cpu_model)
+{
+    XtensaCPU *cpu = cpu_xtensa_init(cpu_model);
+    if (cpu == NULL) {
+        return NULL;
+    }
+    return &cpu->env;
+}
+
 void xtensa_translate_init(void);
 int cpu_xtensa_exec(CPUXtensaState *s);
 void xtensa_register_core(XtensaConfigList *node);
@@ -471,7 +482,6 @@ 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 2094227..e6cb3fe 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -80,7 +80,7 @@ static void breakpoint_handler(CPUXtensaState *env)
     }
 }
 
-CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
+XtensaCPU *cpu_xtensa_init(const char *cpu_model)
 {
     static int tcg_inited;
     static int debug_handler_inited;
@@ -116,7 +116,7 @@ CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
 
     xtensa_irq_init(env);
     qemu_init_vcpu(env);
-    return env;
+    return cpu;
 }
 
 
commit f6932a867d862a5d39506701e9b9d8abcdf1f4ff
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 19:05:02 2012 +0200

    milkymist: Store LM32 in ResetInfo
    
    Allows us to use cpu_reset() in place of cpu_state_reset() in
    main_cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Michael Walle <michael at walle.cc>

diff --git a/hw/milkymist.c b/hw/milkymist.c
index 59f37b4..2e7235b 100644
--- a/hw/milkymist.c
+++ b/hw/milkymist.c
@@ -37,7 +37,7 @@
 #define KERNEL_LOAD_ADDR 0x40000000
 
 typedef struct {
-    CPULM32State *env;
+    LM32CPU *cpu;
     target_phys_addr_t bootstrap_pc;
     target_phys_addr_t flash_base;
     target_phys_addr_t initrd_base;
@@ -59,9 +59,9 @@ static void cpu_irq_handler(void *opaque, int irq, int level)
 static void main_cpu_reset(void *opaque)
 {
     ResetInfo *reset_info = opaque;
-    CPULM32State *env = reset_info->env;
+    CPULM32State *env = &reset_info->cpu->env;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(reset_info->cpu));
 
     /* init defaults */
     env->pc = reset_info->bootstrap_pc;
@@ -108,7 +108,7 @@ milkymist_init(ram_addr_t ram_size_not_used,
     }
     cpu = cpu_lm32_init(cpu_model);
     env = &cpu->env;
-    reset_info->env = env;
+    reset_info->cpu = cpu;
 
     cpu_lm32_set_phys_msb_ignore(env, 1);
 
commit 1328cc01f18b416666cdc65c72efec33a6dce396
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 19:03:24 2012 +0200

    milkymist: Use cpu_lm32_init() to obtain LM32CPU
    
    Needed for main_cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Michael Walle <michael at walle.cc>

diff --git a/hw/milkymist.c b/hw/milkymist.c
index 8bb6a97..59f37b4 100644
--- a/hw/milkymist.c
+++ b/hw/milkymist.c
@@ -79,6 +79,7 @@ milkymist_init(ram_addr_t ram_size_not_used,
                           const char *kernel_cmdline,
                           const char *initrd_filename, const char *cpu_model)
 {
+    LM32CPU *cpu;
     CPULM32State *env;
     int kernel_size;
     DriveInfo *dinfo;
@@ -105,7 +106,8 @@ milkymist_init(ram_addr_t ram_size_not_used,
     if (cpu_model == NULL) {
         cpu_model = "lm32-full";
     }
-    env = cpu_init(cpu_model);
+    cpu = cpu_lm32_init(cpu_model);
+    env = &cpu->env;
     reset_info->env = env;
 
     cpu_lm32_set_phys_msb_ignore(env, 1);
commit b143559655d0b558627cd7b6f71ad350451e3b3b
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 19:00:34 2012 +0200

    lm32_boards: Store LM32CPU in ResetInfo
    
    Allows us to use cpu_reset() in place of cpu_state_reset() in
    main_cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Michael Walle <michael at walle.cc>

diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c
index ffb273c..b76d800 100644
--- a/hw/lm32_boards.c
+++ b/hw/lm32_boards.c
@@ -31,7 +31,7 @@
 #include "exec-memory.h"
 
 typedef struct {
-    CPULM32State *env;
+    LM32CPU *cpu;
     target_phys_addr_t bootstrap_pc;
     target_phys_addr_t flash_base;
     target_phys_addr_t hwsetup_base;
@@ -54,9 +54,9 @@ static void cpu_irq_handler(void *opaque, int irq, int level)
 static void main_cpu_reset(void *opaque)
 {
     ResetInfo *reset_info = opaque;
-    CPULM32State *env = reset_info->env;
+    CPULM32State *env = &reset_info->cpu->env;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(reset_info->cpu));
 
     /* init defaults */
     env->pc = (uint32_t)reset_info->bootstrap_pc;
@@ -104,7 +104,7 @@ static void lm32_evr_init(ram_addr_t ram_size_not_used,
     }
     cpu = cpu_lm32_init(cpu_model);
     env = &cpu->env;
-    reset_info->env = env;
+    reset_info->cpu = cpu;
 
     reset_info->flash_base = flash_base;
 
@@ -201,7 +201,7 @@ static void lm32_uclinux_init(ram_addr_t ram_size_not_used,
     }
     cpu = cpu_lm32_init(cpu_model);
     env = &cpu->env;
-    reset_info->env = env;
+    reset_info->cpu = cpu;
 
     reset_info->flash_base = flash_base;
 
commit 47dc4fa211aa3eaf408c9af521dcb3ad8e98ab65
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 18:55:25 2012 +0200

    lm32_boards: Use cpu_lm32_init() to obtain LM32CPU
    
    Needed for main_cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Michael Walle <michael at walle.cc>

diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c
index 4dd4f0a..ffb273c 100644
--- a/hw/lm32_boards.c
+++ b/hw/lm32_boards.c
@@ -75,6 +75,7 @@ static void lm32_evr_init(ram_addr_t ram_size_not_used,
                           const char *kernel_cmdline,
                           const char *initrd_filename, const char *cpu_model)
 {
+    LM32CPU *cpu;
     CPULM32State *env;
     DriveInfo *dinfo;
     MemoryRegion *address_space_mem =  get_system_memory();
@@ -101,7 +102,8 @@ static void lm32_evr_init(ram_addr_t ram_size_not_used,
     if (cpu_model == NULL) {
         cpu_model = "lm32-full";
     }
-    env = cpu_init(cpu_model);
+    cpu = cpu_lm32_init(cpu_model);
+    env = &cpu->env;
     reset_info->env = env;
 
     reset_info->flash_base = flash_base;
@@ -163,6 +165,7 @@ static void lm32_uclinux_init(ram_addr_t ram_size_not_used,
                           const char *kernel_cmdline,
                           const char *initrd_filename, const char *cpu_model)
 {
+    LM32CPU *cpu;
     CPULM32State *env;
     DriveInfo *dinfo;
     MemoryRegion *address_space_mem =  get_system_memory();
@@ -196,7 +199,8 @@ static void lm32_uclinux_init(ram_addr_t ram_size_not_used,
     if (cpu_model == NULL) {
         cpu_model = "lm32-full";
     }
-    env = cpu_init(cpu_model);
+    cpu = cpu_lm32_init(cpu_model);
+    env = &cpu->env;
     reset_info->env = env;
 
     reset_info->flash_base = flash_base;
commit 0347d689f7339ec925f3a2dcb2c3bcad4d6ef315
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun May 6 12:40:55 2012 +0200

    target-lm32: Let cpu_lm32_init() return LM32CPU
    
    Make the include paths for cpu-qom.h consistent to allow using LM32CPU
    in cpu.h.
    
    Turn cpu_init macro into a static inline function returning CPULM32State
    for backwards compatibility.
    
    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 48a5fe3..caa4834 100644
--- a/target-lm32/cpu.c
+++ b/target-lm32/cpu.c
@@ -18,7 +18,7 @@
  * <http://www.gnu.org/licenses/lgpl-2.1.html>
  */
 
-#include "cpu-qom.h"
+#include "cpu.h"
 #include "qemu-common.h"
 
 
diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index 422a55b..da80469 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -186,7 +186,7 @@ struct CPULM32State {
 
 #include "cpu-qom.h"
 
-CPULM32State *cpu_lm32_init(const char *cpu_model);
+LM32CPU *cpu_lm32_init(const char *cpu_model);
 void cpu_lm32_list(FILE *f, fprintf_function cpu_fprintf);
 int cpu_lm32_exec(CPULM32State *s);
 void cpu_lm32_close(CPULM32State *s);
@@ -199,8 +199,16 @@ int cpu_lm32_signal_handler(int host_signum, void *pinfo,
 void lm32_translate_init(void);
 void cpu_lm32_set_phys_msb_ignore(CPULM32State *env, int value);
 
+static inline CPULM32State *cpu_init(const char *cpu_model)
+{
+    LM32CPU *cpu = cpu_lm32_init(cpu_model);
+    if (cpu == NULL) {
+        return NULL;
+    }
+    return &cpu->env;
+}
+
 #define cpu_list cpu_lm32_list
-#define cpu_init cpu_lm32_init
 #define cpu_exec cpu_lm32_exec
 #define cpu_gen_code cpu_lm32_gen_code
 #define cpu_signal_handler cpu_lm32_signal_handler
diff --git a/target-lm32/helper.c b/target-lm32/helper.c
index d0bc193..3b1cee7 100644
--- a/target-lm32/helper.c
+++ b/target-lm32/helper.c
@@ -192,7 +192,7 @@ static uint32_t cfg_by_def(const LM32Def *def)
     return cfg;
 }
 
-CPULM32State *cpu_lm32_init(const char *cpu_model)
+LM32CPU *cpu_lm32_init(const char *cpu_model)
 {
     LM32CPU *cpu;
     CPULM32State *env;
@@ -219,7 +219,7 @@ CPULM32State *cpu_lm32_init(const char *cpu_model)
         lm32_translate_init();
     }
 
-    return env;
+    return cpu;
 }
 
 /* Some soc ignores the MSB on the address bus. Thus creating a shadow memory
commit 351d56662175bd00473326b0460516c94a427876
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat May 5 12:40:39 2012 +0200

    arm_boot: Pass ARMCPU to do_cpu_reset()
    
    Allows us to use cpu_reset() in place of cpu_state_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index 7447f5c..eb2d176 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -274,10 +274,11 @@ static int load_dtb(target_phys_addr_t addr, const struct arm_boot_info *binfo)
 
 static void do_cpu_reset(void *opaque)
 {
-    CPUARMState *env = opaque;
+    ARMCPU *cpu = opaque;
+    CPUARMState *env = &cpu->env;
     const struct arm_boot_info *info = env->boot_info;
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(cpu));
     if (info) {
         if (!info->is_linux) {
             /* Jump to the entry point.  */
@@ -302,6 +303,7 @@ static void do_cpu_reset(void *opaque)
 
 void arm_load_kernel(CPUARMState *env, struct arm_boot_info *info)
 {
+    ARMCPU *cpu;
     int kernel_size;
     int initrd_size;
     int n;
@@ -406,7 +408,8 @@ void arm_load_kernel(CPUARMState *env, struct arm_boot_info *info)
     info->is_linux = is_linux;
 
     for (; env; env = env->next_cpu) {
+        cpu = arm_env_get_cpu(env);
         env->boot_info = info;
-        qemu_register_reset(do_cpu_reset, env);
+        qemu_register_reset(do_cpu_reset, cpu);
     }
 }
commit 31363f12f56c98015a9e98dc46658f17b6477d24
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 16:11:34 2012 +0200

    armv7m: Pass ARMCPU to armv7m_reset()
    
    Allows us to use cpu_reset() in place of cpu_state_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/armv7m.c b/hw/armv7m.c
index 4e5971c..418139a 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -149,7 +149,9 @@ static void armv7m_bitband_init(void)
 
 static void armv7m_reset(void *opaque)
 {
-    cpu_state_reset((CPUARMState *)opaque);
+    ARMCPU *cpu = opaque;
+
+    cpu_reset(CPU(cpu));
 }
 
 /* Init CPU and memory for a v7-M based board.
@@ -244,7 +246,7 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
     vmstate_register_ram_global(hack);
     memory_region_add_subregion(address_space_mem, 0xfffff000, hack);
 
-    qemu_register_reset(armv7m_reset, env);
+    qemu_register_reset(armv7m_reset, cpu);
     return pic;
 }
 
commit 0f37c99b27b7e89c77d30c82f46485fd2bc61ab8
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 16:09:50 2012 +0200

    armv7m: Use cpu_arm_init() to obtain ARMCPU
    
    Needed for armv7m_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/armv7m.c b/hw/armv7m.c
index 4aac076..4e5971c 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -160,6 +160,7 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
                       int flash_size, int sram_size,
                       const char *kernel_filename, const char *cpu_model)
 {
+    ARMCPU *cpu;
     CPUARMState *env;
     DeviceState *nvic;
     /* FIXME: make this local state.  */
@@ -177,13 +178,15 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
     flash_size *= 1024;
     sram_size *= 1024;
 
-    if (!cpu_model)
+    if (cpu_model == NULL) {
 	cpu_model = "cortex-m3";
-    env = cpu_init(cpu_model);
-    if (!env) {
+    }
+    cpu = cpu_arm_init(cpu_model);
+    if (cpu == NULL) {
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
+    env = &cpu->env;
 
 #if 0
     /* > 32Mb SRAM gets complicated because it overlaps the bitband area.
commit 5f4ef08b20ece1b3711bcfb3751efb13986d17e5
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 00:42:39 2012 +0200

    omap: Use cpu_arm_init() to store ARMCPU in omap_mpu_state_s
    
    Fix tab indentations of comments, add braces, use cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/nseries.c b/hw/nseries.c
index a5cfa8c..b8c6a29 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -1023,7 +1023,7 @@ static void n8x0_boot_init(void *opaque)
     n800_dss_init(&s->blizzard);
 
     /* CPU setup */
-    s->cpu->env->GE = 0x5;
+    s->cpu->cpu->env.GE = 0x5;
 
     /* If the machine has a slided keyboard, open it */
     if (s->kbd)
@@ -1329,7 +1329,7 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
         binfo->kernel_filename = kernel_filename;
         binfo->kernel_cmdline = kernel_cmdline;
         binfo->initrd_filename = initrd_filename;
-        arm_load_kernel(s->cpu->env, binfo);
+        arm_load_kernel(&s->cpu->cpu->env, binfo);
 
         qemu_register_reset(n8x0_boot_init, s);
     }
@@ -1338,7 +1338,7 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
         int rom_size;
         uint8_t nolo_tags[0x10000];
         /* No, wait, better start at the ROM.  */
-        s->cpu->env->regs[15] = OMAP2_Q2_BASE + 0x400000;
+        s->cpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000;
 
         /* This is intended for loading the `secondary.bin' program from
          * Nokia images (the NOLO bootloader).  The entry point seems
diff --git a/hw/omap.h b/hw/omap.h
index 6c3d004..2819e5d 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -804,7 +804,7 @@ struct omap_mpu_state_s {
         omap3630,
     } mpu_model;
 
-    CPUARMState *env;
+    ARMCPU *cpu;
 
     qemu_irq *drq;
 
diff --git a/hw/omap1.c b/hw/omap1.c
index 80d47f0..a997d30 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -1519,8 +1519,9 @@ static inline void omap_clkm_idlect1_update(struct omap_mpu_state_s *s,
 {
     omap_clk clk;
 
-    if (value & (1 << 11))				/* SETARM_IDLE */
-        cpu_interrupt(s->env, CPU_INTERRUPT_HALT);
+    if (value & (1 << 11)) {                            /* SETARM_IDLE */
+        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
+    }
     if (!(value & (1 << 10)))				/* WKUP_MODE */
         qemu_system_shutdown_request();	/* XXX: disable wakeup from IRQ */
 
@@ -1734,7 +1735,7 @@ static uint64_t omap_clkdsp_read(void *opaque, target_phys_addr_t addr,
 
     case 0x18:	/* DSP_SYSST */
         return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start |
-                (s->env->halted << 6);	/* Quite useless... */
+                (s->cpu->env.halted << 6);      /* Quite useless... */
     }
 
     OMAP_BAD_REG(addr);
@@ -3701,7 +3702,7 @@ static void omap1_mpu_reset(void *opaque)
     omap_lpg_reset(mpu->led[0]);
     omap_lpg_reset(mpu->led[1]);
     omap_clkm_reset(mpu);
-    cpu_state_reset(mpu->env);
+    cpu_reset(CPU(mpu->cpu));
 }
 
 static const struct omap_map_s {
@@ -3751,8 +3752,9 @@ void omap_mpu_wakeup(void *opaque, int irq, int req)
 {
     struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
 
-    if (mpu->env->halted)
-        cpu_interrupt(mpu->env, CPU_INTERRUPT_EXITTB);
+    if (mpu->cpu->env.halted) {
+        cpu_interrupt(&mpu->cpu->env, CPU_INTERRUPT_EXITTB);
+    }
 }
 
 static const struct dma_irq_map omap1_dma_irq_map[] = {
@@ -3829,8 +3831,8 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
 
     /* Core */
     s->mpu_model = omap310;
-    s->env = cpu_init(core);
-    if (!s->env) {
+    s->cpu = cpu_arm_init(core);
+    if (s->cpu == NULL) {
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
@@ -3852,7 +3854,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
 
     omap_clkm_init(system_memory, 0xfffece00, 0xe1008000, s);
 
-    cpu_irq = arm_pic_init_cpu(s->env);
+    cpu_irq = arm_pic_init_cpu(&s->cpu->env);
     s->ih[0] = qdev_create(NULL, "omap-intc");
     qdev_prop_set_uint32(s->ih[0], "size", 0x100);
     qdev_prop_set_ptr(s->ih[0], "clk", omap_findclk(s, "arminth_ck"));
diff --git a/hw/omap2.c b/hw/omap2.c
index 42fce5e..196c4b6 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -2222,7 +2222,7 @@ static void omap2_mpu_reset(void *opaque)
     omap_mmc_reset(mpu->mmc);
     omap_mcspi_reset(mpu->mcspi[0]);
     omap_mcspi_reset(mpu->mcspi[1]);
-    cpu_state_reset(mpu->env);
+    cpu_reset(CPU(mpu->cpu));
 }
 
 static int omap2_validate_addr(struct omap_mpu_state_s *s,
@@ -2253,8 +2253,8 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
 
     /* Core */
     s->mpu_model = omap2420;
-    s->env = cpu_init(core ?: "arm1136-r2");
-    if (!s->env) {
+    s->cpu = cpu_arm_init(core ?: "arm1136-r2");
+    if (s->cpu == NULL) {
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
@@ -2277,7 +2277,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
     s->l4 = omap_l4_init(sysmem, OMAP2_L4_BASE, 54);
 
     /* Actually mapped at any 2K boundary in the ARM11 private-peripheral if */
-    cpu_irq = arm_pic_init_cpu(s->env);
+    cpu_irq = arm_pic_init_cpu(&s->cpu->env);
     s->ih[0] = qdev_create(NULL, "omap2-intc");
     qdev_prop_set_uint8(s->ih[0], "revision", 0x21);
     qdev_prop_set_ptr(s->ih[0], "fclk", omap_findclk(s, "mpu_intc_fclk"));
diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c
index 4e8ec4a..c7618c6 100644
--- a/hw/omap_sx1.c
+++ b/hw/omap_sx1.c
@@ -202,7 +202,7 @@ static void sx1_init(ram_addr_t ram_size,
         sx1_binfo.kernel_filename = kernel_filename;
         sx1_binfo.kernel_cmdline = kernel_cmdline;
         sx1_binfo.initrd_filename = initrd_filename;
-        arm_load_kernel(cpu->env, &sx1_binfo);
+        arm_load_kernel(&cpu->cpu->env, &sx1_binfo);
     }
 
     /* TODO: fix next line */
diff --git a/hw/palm.c b/hw/palm.c
index b1252ab..6d81829 100644
--- a/hw/palm.c
+++ b/hw/palm.c
@@ -265,7 +265,7 @@ static void palmte_init(ram_addr_t ram_size,
         palmte_binfo.kernel_filename = kernel_filename;
         palmte_binfo.kernel_cmdline = kernel_cmdline;
         palmte_binfo.initrd_filename = initrd_filename;
-        arm_load_kernel(cpu->env, &palmte_binfo);
+        arm_load_kernel(&cpu->cpu->env, &palmte_binfo);
     }
 
     /* FIXME: We shouldn't really be doing this here.  The LCD controller
commit 43824588af2fa77f9586e16ef2f01d1990c6460e
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu May 3 23:47:04 2012 +0200

    pxa2xx: Use cpu_arm_init() and store ARMCPU
    
    Also use cpu_reset() in place of cpu_state_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/mainstone.c b/hw/mainstone.c
index 27f5900..00a8adc 100644
--- a/hw/mainstone.c
+++ b/hw/mainstone.c
@@ -168,7 +168,7 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
     mainstone_binfo.kernel_cmdline = kernel_cmdline;
     mainstone_binfo.initrd_filename = initrd_filename;
     mainstone_binfo.board_id = arm_id;
-    arm_load_kernel(cpu->env, &mainstone_binfo);
+    arm_load_kernel(&cpu->cpu->env, &mainstone_binfo);
 }
 
 static void mainstone_init(ram_addr_t ram_size,
diff --git a/hw/pxa.h b/hw/pxa.h
index 025be34..2be006d 100644
--- a/hw/pxa.h
+++ b/hw/pxa.h
@@ -122,7 +122,7 @@ typedef struct PXA2xxI2SState PXA2xxI2SState;
 typedef struct PXA2xxFIrState PXA2xxFIrState;
 
 typedef struct {
-    CPUARMState *env;
+    ARMCPU *cpu;
     DeviceState *pic;
     qemu_irq reset;
     MemoryRegion sdram;
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index ddaa846..5f8f226 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -269,24 +269,24 @@ static void pxa2xx_clkpwr_write(void *opaque, int op2, int reg, int crm,
         case 1:
             /* Idle */
             if (!(s->cm_regs[CCCR >> 2] & (1 << 31))) {	/* CPDIS */
-                cpu_interrupt(s->env, CPU_INTERRUPT_HALT);
+                cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
                 break;
             }
             /* Fall through.  */
 
         case 2:
             /* Deep-Idle */
-            cpu_interrupt(s->env, CPU_INTERRUPT_HALT);
+            cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
             s->pm_regs[RCSR >> 2] |= 0x8;	/* Set GPR */
             goto message;
 
         case 3:
-            s->env->uncached_cpsr =
+            s->cpu->env.uncached_cpsr =
                     ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
-            s->env->cp15.c1_sys = 0;
-            s->env->cp15.c1_coproc = 0;
-            s->env->cp15.c2_base0 = 0;
-            s->env->cp15.c3 = 0;
+            s->cpu->env.cp15.c1_sys = 0;
+            s->cpu->env.cp15.c1_coproc = 0;
+            s->cpu->env.cp15.c2_base0 = 0;
+            s->cpu->env.cp15.c3 = 0;
             s->pm_regs[PSSR >> 2] |= 0x8;	/* Set STS */
             s->pm_regs[RCSR >> 2] |= 0x8;	/* Set GPR */
 
@@ -296,8 +296,8 @@ static void pxa2xx_clkpwr_write(void *opaque, int op2, int reg, int crm,
              * lack of a resuming bootloader, perform a jump
              * directly to that address.
              */
-            memset(s->env->regs, 0, 4 * 15);
-            s->env->regs[15] = s->pm_regs[PSPR >> 2];
+            memset(s->cpu->env.regs, 0, 4 * 15);
+            s->cpu->env.regs[15] = s->pm_regs[PSPR >> 2];
 
 #if 0
             buffer = 0xe59ff000;	/* ldr     pc, [pc, #0] */
@@ -2044,7 +2044,7 @@ static void pxa2xx_reset(void *opaque, int line, int level)
     PXA2xxState *s = (PXA2xxState *) opaque;
 
     if (level && (s->pm_regs[PCFR >> 2] & 0x10)) {	/* GPR_EN */
-        cpu_state_reset(s->env);
+        cpu_reset(CPU(s->cpu));
         /* TODO: reset peripherals */
     }
 }
@@ -2065,8 +2065,8 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
     if (!revision)
         revision = "pxa270";
     
-    s->env = cpu_init(revision);
-    if (!s->env) {
+    s->cpu = cpu_arm_init(revision);
+    if (s->cpu == NULL) {
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
@@ -2081,7 +2081,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
     memory_region_add_subregion(address_space, PXA2XX_INTERNAL_BASE,
                                 &s->internal);
 
-    s->pic = pxa2xx_pic_init(0x40d00000, s->env);
+    s->pic = pxa2xx_pic_init(0x40d00000, &s->cpu->env);
 
     s->dma = pxa27x_dma_init(0x40000000,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_DMA));
@@ -2094,7 +2094,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
                     qdev_get_gpio_in(s->pic, PXA27X_PIC_OST_4_11),
                     NULL);
 
-    s->gpio = pxa2xx_gpio_init(0x40e00000, s->env, s->pic, 121);
+    s->gpio = pxa2xx_gpio_init(0x40e00000, &s->cpu->env, s->pic, 121);
 
     dinfo = drive_get(IF_SD, 0, 0);
     if (!dinfo) {
@@ -2133,7 +2133,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
     memory_region_add_subregion(address_space, s->cm_base, &s->cm_iomem);
     vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
 
-    cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
+    cpu_arm_set_cp_io(&s->cpu->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
 
     s->mm_base = 0x48000000;
     s->mm_regs[MDMRS >> 2] = 0x00020002;
@@ -2196,8 +2196,8 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
 
     s = (PXA2xxState *) g_malloc0(sizeof(PXA2xxState));
 
-    s->env = cpu_init("pxa255");
-    if (!s->env) {
+    s->cpu = cpu_arm_init("pxa255");
+    if (s->cpu == NULL) {
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
@@ -2213,7 +2213,7 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
     memory_region_add_subregion(address_space, PXA2XX_INTERNAL_BASE,
                                 &s->internal);
 
-    s->pic = pxa2xx_pic_init(0x40d00000, s->env);
+    s->pic = pxa2xx_pic_init(0x40d00000, &s->cpu->env);
 
     s->dma = pxa255_dma_init(0x40000000,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_DMA));
@@ -2225,7 +2225,7 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 3),
                     NULL);
 
-    s->gpio = pxa2xx_gpio_init(0x40e00000, s->env, s->pic, 85);
+    s->gpio = pxa2xx_gpio_init(0x40e00000, &s->cpu->env, s->pic, 85);
 
     dinfo = drive_get(IF_SD, 0, 0);
     if (!dinfo) {
@@ -2264,7 +2264,7 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
     memory_region_add_subregion(address_space, s->cm_base, &s->cm_iomem);
     vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
 
-    cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
+    cpu_arm_set_cp_io(&s->cpu->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
 
     s->mm_base = 0x48000000;
     s->mm_regs[MDMRS >> 2] = 0x00020002;
diff --git a/hw/spitz.c b/hw/spitz.c
index 1d6d2b0..9042d44 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -932,7 +932,7 @@ static void spitz_common_init(ram_addr_t ram_size,
     spitz_binfo.kernel_cmdline = kernel_cmdline;
     spitz_binfo.initrd_filename = initrd_filename;
     spitz_binfo.board_id = arm_id;
-    arm_load_kernel(cpu->env, &spitz_binfo);
+    arm_load_kernel(&cpu->cpu->env, &spitz_binfo);
     sl_bootparam_write(SL_PXA_PARAM_BASE);
 }
 
diff --git a/hw/tosa.c b/hw/tosa.c
index 6baa17d..d1ede8d 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -242,7 +242,7 @@ static void tosa_init(ram_addr_t ram_size,
     tosa_binfo.kernel_cmdline = kernel_cmdline;
     tosa_binfo.initrd_filename = initrd_filename;
     tosa_binfo.board_id = 0x208;
-    arm_load_kernel(cpu->env, &tosa_binfo);
+    arm_load_kernel(&cpu->cpu->env, &tosa_binfo);
     sl_bootparam_write(SL_PXA_PARAM_BASE);
 }
 
diff --git a/hw/z2.c b/hw/z2.c
index 654ac55..9dd83ff 100644
--- a/hw/z2.c
+++ b/hw/z2.c
@@ -363,7 +363,7 @@ static void z2_init(ram_addr_t ram_size,
         z2_binfo.kernel_cmdline = kernel_cmdline;
         z2_binfo.initrd_filename = initrd_filename;
         z2_binfo.board_id = 0x6dd;
-        arm_load_kernel(cpu->env, &z2_binfo);
+        arm_load_kernel(&cpu->cpu->env, &z2_binfo);
     }
 }
 
commit df90dadb4507afa31fdc85f94d8571e7aa25b80b
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri May 4 19:14:38 2012 +0200

    target-arm: Use cpu_reset() in cpu_arm_init()
    
    Commit 3c30dd5a68e9fee6af67cfd0d14ed7520820f36a (target-arm: Move reset
    handling to arm_cpu_reset) QOM'ified CPU reset. Complete it by replacing
    cpu_state_reset() with cpu_reset().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 7e1c2c0..06ebffc 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -80,7 +80,7 @@ ARMCPU *cpu_arm_init(const char *cpu_model)
         arm_translate_init();
     }
 
-    cpu_state_reset(env);
+    cpu_reset(CPU(cpu));
     if (arm_feature(env, ARM_FEATURE_NEON)) {
         gdb_register_coprocessor(env, vfp_gdb_get_reg, vfp_gdb_set_reg,
                                  51, "arm-neon.xml", 0);
commit 4860853d60ecea44b65e9cdefce980de3a641dce
Author: Daniel P. Berrange <berrange at redhat.com>
Date:   Mon May 21 17:59:51 2012 +0100

    Add 'query-events' command to QMP to query async events
    
    Sometimes it is neccessary for an application to determine
    whether a particular QMP event is available, so they can
    decide whether to use compatibility code instead. This
    introduces a new 'query-events' command to QMP to do just
    that
    
     { "execute": "query-events" }
     {"return": [{"name": "WAKEUP"},
                 {"name": "SUSPEND"},
                 {"name": "DEVICE_TRAY_MOVED"},
                 {"name": "BLOCK_JOB_CANCELLED"},
                 {"name": "BLOCK_JOB_COMPLETED"},
                 ...snip...
                 {"name": "SHUTDOWN"}]}
    
    * monitor.c: Turn MonitorEvent -> string conversion
      into a lookup from a static table of constant strings.
      Add impl of qmp_query_events monitor command handler
    * qapi-schema.json, qmp-commands.hx: Define contract of
      query-events command
    
    Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/monitor.c b/monitor.c
index 12a6fe2..a3bc2c7 100644
--- a/monitor.c
+++ b/monitor.c
@@ -422,6 +422,30 @@ static void timestamp_put(QDict *qdict)
     qdict_put_obj(qdict, "timestamp", obj);
 }
 
+
+static const char *monitor_event_names[] = {
+    [QEVENT_SHUTDOWN] = "SHUTDOWN",
+    [QEVENT_RESET] = "RESET",
+    [QEVENT_POWERDOWN] = "POWERDOWN",
+    [QEVENT_STOP] = "STOP",
+    [QEVENT_RESUME] = "RESUME",
+    [QEVENT_VNC_CONNECTED] = "VNC_CONNECTED",
+    [QEVENT_VNC_INITIALIZED] = "VNC_INITIALIZED",
+    [QEVENT_VNC_DISCONNECTED] = "VNC_DISCONNECTED",
+    [QEVENT_BLOCK_IO_ERROR] = "BLOCK_IO_ERROR",
+    [QEVENT_RTC_CHANGE] = "RTC_CHANGE",
+    [QEVENT_WATCHDOG] = "WATCHDOG",
+    [QEVENT_SPICE_CONNECTED] = "SPICE_CONNECTED",
+    [QEVENT_SPICE_INITIALIZED] = "SPICE_INITIALIZED",
+    [QEVENT_SPICE_DISCONNECTED] = "SPICE_DISCONNECTED",
+    [QEVENT_BLOCK_JOB_COMPLETED] = "BLOCK_JOB_COMPLETED",
+    [QEVENT_BLOCK_JOB_CANCELLED] = "BLOCK_JOB_CANCELLED",
+    [QEVENT_DEVICE_TRAY_MOVED] = "DEVICE_TRAY_MOVED",
+    [QEVENT_SUSPEND] = "SUSPEND",
+    [QEVENT_WAKEUP] = "WAKEUP",
+};
+QEMU_BUILD_BUG_ON(ARRAY_SIZE(monitor_event_names) != QEVENT_MAX)
+
 /**
  * monitor_protocol_event(): Generate a Monitor event
  *
@@ -435,68 +459,8 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
 
     assert(event < QEVENT_MAX);
 
-    switch (event) {
-        case QEVENT_SHUTDOWN:
-            event_name = "SHUTDOWN";
-            break;
-        case QEVENT_RESET:
-            event_name = "RESET";
-            break;
-        case QEVENT_POWERDOWN:
-            event_name = "POWERDOWN";
-            break;
-        case QEVENT_STOP:
-            event_name = "STOP";
-            break;
-        case QEVENT_RESUME:
-            event_name = "RESUME";
-            break;
-        case QEVENT_VNC_CONNECTED:
-            event_name = "VNC_CONNECTED";
-            break;
-        case QEVENT_VNC_INITIALIZED:
-            event_name = "VNC_INITIALIZED";
-            break;
-        case QEVENT_VNC_DISCONNECTED:
-            event_name = "VNC_DISCONNECTED";
-            break;
-        case QEVENT_BLOCK_IO_ERROR:
-            event_name = "BLOCK_IO_ERROR";
-            break;
-        case QEVENT_RTC_CHANGE:
-            event_name = "RTC_CHANGE";
-            break;
-        case QEVENT_WATCHDOG:
-            event_name = "WATCHDOG";
-            break;
-        case QEVENT_SPICE_CONNECTED:
-            event_name = "SPICE_CONNECTED";
-            break;
-        case QEVENT_SPICE_INITIALIZED:
-            event_name = "SPICE_INITIALIZED";
-            break;
-        case QEVENT_SPICE_DISCONNECTED:
-            event_name = "SPICE_DISCONNECTED";
-            break;
-        case QEVENT_BLOCK_JOB_COMPLETED:
-            event_name = "BLOCK_JOB_COMPLETED";
-            break;
-        case QEVENT_BLOCK_JOB_CANCELLED:
-            event_name = "BLOCK_JOB_CANCELLED";
-            break;
-        case QEVENT_DEVICE_TRAY_MOVED:
-             event_name = "DEVICE_TRAY_MOVED";
-            break;
-        case QEVENT_SUSPEND:
-            event_name = "SUSPEND";
-            break;
-        case QEVENT_WAKEUP:
-            event_name = "WAKEUP";
-            break;
-        default:
-            abort();
-            break;
-    }
+    event_name = monitor_event_names[event];
+    assert(event_name != NULL);
 
     qmp = qdict_new();
     timestamp_put(qmp);
@@ -738,6 +702,25 @@ CommandInfoList *qmp_query_commands(Error **errp)
     return cmd_list;
 }
 
+EventInfoList *qmp_query_events(Error **errp)
+{
+    EventInfoList *info, *ev_list = NULL;
+    MonitorEvent e;
+
+    for (e = 0 ; e < QEVENT_MAX ; e++) {
+        const char *event_name = monitor_event_names[e];
+        assert(event_name != NULL);
+        info = g_malloc0(sizeof(*info));
+        info->value = g_malloc0(sizeof(*info->value));
+        info->value->name = g_strdup(event_name);
+
+        info->next = ev_list;
+        ev_list = info;
+    }
+
+    return ev_list;
+}
+
 /* set the current CPU defined by the user */
 int monitor_set_cpu(int cpu_index)
 {
diff --git a/monitor.h b/monitor.h
index 0d49800..cd1d878 100644
--- a/monitor.h
+++ b/monitor.h
@@ -41,6 +41,10 @@ typedef enum MonitorEvent {
     QEVENT_DEVICE_TRAY_MOVED,
     QEVENT_SUSPEND,
     QEVENT_WAKEUP,
+
+    /* Add to 'monitor_event_names' array in monitor.c when
+     * defining new events here */
+
     QEVENT_MAX,
 } MonitorEvent;
 
diff --git a/qapi-schema.json b/qapi-schema.json
index bb1f806..3b6e346 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -228,6 +228,28 @@
 { 'command': 'query-commands', 'returns': ['CommandInfo'] }
 
 ##
+# @EventInfo:
+#
+# Information about a QMP event
+#
+# @name: The event name
+#
+# Since: 1.2.0
+##
+{ 'type': 'EventInfo', 'data': {'name': 'str'} }
+
+##
+# @query-events:
+#
+# Return a list of supported QMP events by this server
+#
+# Returns: A list of @EventInfo for all supported events
+#
+# Since: 1.2.0
+##
+{ 'command': 'query-events', 'returns': ['EventInfo'] }
+
+##
 # @MigrationStats
 #
 # Detailed migration status.
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 57ea803..2e1a38e 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1209,6 +1209,43 @@ EQMP
     },
 
 SQMP
+query-events
+--------------
+
+List QMP available events.
+
+Each event is represented by a json-object, the returned value is a json-array
+of all events.
+
+Each json-object contains:
+
+- "name": event's name (json-string)
+
+Example:
+
+-> { "execute": "query-events" }
+<- {
+      "return":[
+         {
+            "name":"SHUTDOWN"
+         },
+         {
+            "name":"RESET"
+         }
+      ]
+   }
+
+Note: This example has been shortened as the real response is too long.
+
+EQMP
+
+    {
+        .name       = "query-events",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_events,
+    },
+
+SQMP
 query-chardev
 -------------
 
commit 5f96415527e4f25dc83cfc458c46e5bcbfee79ba
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Mon Apr 16 14:36:32 2012 -0300

    qapi: convert netdev_del
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-By: Laszlo Ersek <lersek at redhat.com>

diff --git a/hmp-commands.hx b/hmp-commands.hx
index d0ce6a5..f5d9d91 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1051,8 +1051,7 @@ ETEXI
         .args_type  = "id:s",
         .params     = "id",
         .help       = "remove host network device",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_netdev_del,
+        .mhandler.cmd = hmp_netdev_del,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index 7a4e25f..2ce8cb9 100644
--- a/hmp.c
+++ b/hmp.c
@@ -990,3 +990,12 @@ void hmp_netdev_add(Monitor *mon, const QDict *qdict)
 out:
     hmp_handle_error(mon, &err);
 }
+
+void hmp_netdev_del(Monitor *mon, const QDict *qdict)
+{
+    const char *id = qdict_get_str(qdict, "id");
+    Error *err = NULL;
+
+    qmp_netdev_del(id, &err);
+    hmp_handle_error(mon, &err);
+}
diff --git a/hmp.h b/hmp.h
index 017df87..79d138d 100644
--- a/hmp.h
+++ b/hmp.h
@@ -63,5 +63,6 @@ void hmp_migrate(Monitor *mon, const QDict *qdict);
 void hmp_device_del(Monitor *mon, const QDict *qdict);
 void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict);
 void hmp_netdev_add(Monitor *mon, const QDict *qdict);
+void hmp_netdev_del(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/net.c b/net.c
index 5f0c53c..4aa416c 100644
--- a/net.c
+++ b/net.c
@@ -1269,19 +1269,18 @@ exit_err:
     return -1;
 }
 
-int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void qmp_netdev_del(const char *id, Error **errp)
 {
-    const char *id = qdict_get_str(qdict, "id");
     VLANClientState *vc;
 
     vc = qemu_find_netdev(id);
     if (!vc) {
-        qerror_report(QERR_DEVICE_NOT_FOUND, id);
-        return -1;
+        error_set(errp, QERR_DEVICE_NOT_FOUND, id);
+        return;
     }
+
     qemu_del_vlan_client(vc);
-    qemu_opts_del(qemu_opts_find(qemu_find_opts("netdev"), id));
-    return 0;
+    qemu_opts_del(qemu_opts_find(qemu_find_opts_err("netdev", errp), id));
 }
 
 static void print_net_client(Monitor *mon, VLANClientState *vc)
diff --git a/net.h b/net.h
index 1eb9280..bdc2a06 100644
--- a/net.h
+++ b/net.h
@@ -172,7 +172,6 @@ void net_host_device_add(Monitor *mon, const QDict *qdict);
 void net_host_device_remove(Monitor *mon, const QDict *qdict);
 void netdev_add(QemuOpts *opts, Error **errp);
 int qmp_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret);
-int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
 #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
 #define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown"
diff --git a/qapi-schema.json b/qapi-schema.json
index 69fcd8e..bb1f806 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1826,3 +1826,17 @@
 { 'command': 'netdev_add',
   'data': {'type': 'str', 'id': 'str', '*props': '**'},
   'gen': 'no' }
+
+##
+# @netdev_del:
+#
+# Remove a network backend.
+#
+# @id: the name of the network backend to remove
+#
+# Returns: Nothing on success
+#          If @id is not a valid network backend, DeviceNotFound
+#
+# Since: 0.14.0
+##
+{ 'command': 'netdev_del', 'data': {'id': 'str'} }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index f6550cb..57ea803 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -671,10 +671,7 @@ EQMP
     {
         .name       = "netdev_del",
         .args_type  = "id:s",
-        .params     = "id",
-        .help       = "remove host network device",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_netdev_del,
+        .mhandler.cmd_new = qmp_marshal_input_netdev_del,
     },
 
 SQMP
commit 928059a37b8e1f152962431fb846f39597b63c36
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Apr 18 17:34:15 2012 -0300

    qapi: convert netdev_add
    
    This is not a full QAPI conversion, but an intermediate step.
    
    In essence, do_netdev_add() is split into three functions:
    
     1. netdev_add(): performs the actual work. This function is fully
        converted to Error (thus, it's "qapi-friendly")
    
     2. qmp_netdev_add(): the QMP front-end for netdev_add(). This is
        coded by hand and not auto-generated (gen=no in the schema). The
        reason for this it's a lot easier and simpler to with QemuOpts
        this way
    
     3. hmp_netdev_add(): HMP front-end.
    
    This design was suggested by Paolo Bonzini.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-By: Laszlo Ersek <lersek at redhat.com>

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 81723c8..d0ce6a5 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1037,8 +1037,7 @@ ETEXI
         .args_type  = "netdev:O",
         .params     = "[user|tap|socket],id=str[,prop=value][,...]",
         .help       = "add host network device",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_netdev_add,
+        .mhandler.cmd = hmp_netdev_add,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index 42ced2a..7a4e25f 100644
--- a/hmp.c
+++ b/hmp.c
@@ -14,6 +14,8 @@
  */
 
 #include "hmp.h"
+#include "net.h"
+#include "qemu-option.h"
 #include "qemu-timer.h"
 #include "qmp-commands.h"
 
@@ -969,3 +971,22 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
                           &errp);
     hmp_handle_error(mon, &errp);
 }
+
+void hmp_netdev_add(Monitor *mon, const QDict *qdict)
+{
+    Error *err = NULL;
+    QemuOpts *opts;
+
+    opts = qemu_opts_from_qdict(qemu_find_opts("netdev"), qdict, &err);
+    if (error_is_set(&err)) {
+        goto out;
+    }
+
+    netdev_add(opts, &err);
+    if (error_is_set(&err)) {
+        qemu_opts_del(opts);
+    }
+
+out:
+    hmp_handle_error(mon, &err);
+}
diff --git a/hmp.h b/hmp.h
index 5cf3241..017df87 100644
--- a/hmp.h
+++ b/hmp.h
@@ -62,5 +62,6 @@ 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);
 void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict);
+void hmp_netdev_add(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/net.c b/net.c
index 8f7cb40..5f0c53c 100644
--- a/net.c
+++ b/net.c
@@ -1234,27 +1234,39 @@ void net_host_device_remove(Monitor *mon, const QDict *qdict)
     qemu_del_vlan_client(vc);
 }
 
-int do_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void netdev_add(QemuOpts *opts, Error **errp)
+{
+    net_client_init(opts, 1, errp);
+}
+
+int qmp_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret)
 {
     Error *local_err = NULL;
+    QemuOptsList *opts_list;
     QemuOpts *opts;
-    int res;
 
-    opts = qemu_opts_from_qdict(qemu_find_opts("netdev"), qdict, &local_err);
-    if (!opts) {
-        qerror_report_err(local_err);
-        error_free(local_err);
-        return -1;
+    opts_list = qemu_find_opts_err("netdev", &local_err);
+    if (error_is_set(&local_err)) {
+        goto exit_err;
     }
 
-    res = net_client_init(opts, 1, &local_err);
-    if (res < 0) {
-        qerror_report_err(local_err);
-        error_free(local_err);
+    opts = qemu_opts_from_qdict(opts_list, qdict, &local_err);
+    if (error_is_set(&local_err)) {
+        goto exit_err;
+    }
+
+    netdev_add(opts, &local_err);
+    if (error_is_set(&local_err)) {
         qemu_opts_del(opts);
+        goto exit_err;
     }
 
-    return res;
+    return 0;
+
+exit_err:
+    qerror_report_err(local_err);
+    error_free(local_err);
+    return -1;
 }
 
 int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
diff --git a/net.h b/net.h
index 7ee97e9..1eb9280 100644
--- a/net.h
+++ b/net.h
@@ -170,7 +170,8 @@ void net_check_clients(void);
 void net_cleanup(void);
 void net_host_device_add(Monitor *mon, const QDict *qdict);
 void net_host_device_remove(Monitor *mon, const QDict *qdict);
-int do_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret_data);
+void netdev_add(QemuOpts *opts, Error **errp);
+int qmp_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret);
 int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
 #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
diff --git a/qapi-schema.json b/qapi-schema.json
index dfa0e1f..69fcd8e 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1798,3 +1798,31 @@
 { 'command': 'dump-guest-memory',
   'data': { 'paging': 'bool', 'protocol': 'str', '*begin': 'int',
             '*length': 'int' } }
+##
+# @netdev_add:
+#
+# Add a network backend.
+#
+# @type: the type of network backend.  Current valid values are 'user', 'tap',
+#        'vde', 'socket', 'dump' and 'bridge'
+#
+# @id: the name of the new network backend
+#
+# @props: #optional a list of properties to be passed to the backend in
+#         the format 'name=value', like 'ifname=tap0,script=no'
+#
+# Notes: The semantics of @props is not well defined.  Future commands will be
+#        introduced that provide stronger typing for backend creation.
+#
+# Since: 0.14.0
+#
+# Returns: Nothing on success
+#          If @type is not a valid network backend, DeviceNotFound
+#          If @id is not a valid identifier, InvalidParameterValue
+#          if @id already exists, DuplicateId
+#          If @props contains an invalid parameter for this backend,
+#            InvalidParameter
+##
+{ 'command': 'netdev_add',
+  'data': {'type': 'str', 'id': 'str', '*props': '**'},
+  'gen': 'no' }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 2aa64ad..f6550cb 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -642,10 +642,7 @@ EQMP
     {
         .name       = "netdev_add",
         .args_type  = "netdev:O",
-        .params     = "[user|tap|socket],id=str[,prop=value][,...]",
-        .help       = "add host network device",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_netdev_add,
+        .mhandler.cmd_new = qmp_netdev_add,
     },
 
 SQMP
commit 4559a1dbcc15a10482de822e2839645a1819ef6f
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Fri Apr 20 16:50:25 2012 -0300

    net: net_client_init(): use error_set()
    
    Callers are changed to use qerror_report_err() to keep their QError
    semantics.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-By: Laszlo Ersek <lersek at redhat.com>

diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index 785eb3d..61257f4 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -39,6 +39,7 @@ static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
                                        const char *devaddr,
                                        const char *opts_str)
 {
+    Error *local_err = NULL;
     QemuOpts *opts;
     PCIBus *bus;
     int ret, devfn;
@@ -60,9 +61,12 @@ static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
 
     qemu_opt_set(opts, "type", "nic");
 
-    ret = net_client_init(opts, 0);
-    if (ret < 0)
+    ret = net_client_init(opts, 0, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
         return NULL;
+    }
     if (nd_table[ret].devaddr) {
         monitor_printf(mon, "Parameter addr not supported\n");
         return NULL;
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index 4e26e64..5d2f098 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -1356,6 +1356,7 @@ static int usb_net_initfn(USBDevice *dev)
 
 static USBDevice *usb_net_init(USBBus *bus, const char *cmdline)
 {
+    Error *local_err = NULL;
     USBDevice *dev;
     QemuOpts *opts;
     int idx;
@@ -1367,8 +1368,10 @@ static USBDevice *usb_net_init(USBBus *bus, const char *cmdline)
     qemu_opt_set(opts, "type", "nic");
     qemu_opt_set(opts, "model", "usb");
 
-    idx = net_client_init(opts, 0);
-    if (idx == -1) {
+    idx = net_client_init(opts, 0, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
         return NULL;
     }
 
diff --git a/net.c b/net.c
index adb7e20..8f7cb40 100644
--- a/net.c
+++ b/net.c
@@ -1081,7 +1081,7 @@ static const struct {
 #endif /* CONFIG_NET_BRIDGE */
 };
 
-int net_client_init(QemuOpts *opts, int is_netdev)
+int net_client_init(QemuOpts *opts, int is_netdev, Error **errp)
 {
     const char *name;
     const char *type;
@@ -1089,7 +1089,7 @@ int net_client_init(QemuOpts *opts, int is_netdev)
 
     type = qemu_opt_get(opts, "type");
     if (!type) {
-        qerror_report(QERR_MISSING_PARAMETER, "type");
+        error_set(errp, QERR_MISSING_PARAMETER, "type");
         return -1;
     }
 
@@ -1105,21 +1105,21 @@ int net_client_init(QemuOpts *opts, int is_netdev)
             strcmp(type, "vde") != 0 &&
 #endif
             strcmp(type, "socket") != 0) {
-            qerror_report(QERR_INVALID_PARAMETER_VALUE, "type",
-                          "a netdev backend type");
+            error_set(errp, QERR_INVALID_PARAMETER_VALUE, "type",
+                      "a netdev backend type");
             return -1;
         }
 
         if (qemu_opt_get(opts, "vlan")) {
-            qerror_report(QERR_INVALID_PARAMETER, "vlan");
+            error_set(errp, QERR_INVALID_PARAMETER, "vlan");
             return -1;
         }
         if (qemu_opt_get(opts, "name")) {
-            qerror_report(QERR_INVALID_PARAMETER, "name");
+            error_set(errp, QERR_INVALID_PARAMETER, "name");
             return -1;
         }
         if (!qemu_opts_id(opts)) {
-            qerror_report(QERR_MISSING_PARAMETER, "id");
+            error_set(errp, QERR_MISSING_PARAMETER, "id");
             return -1;
         }
     }
@@ -1138,8 +1138,7 @@ int net_client_init(QemuOpts *opts, int is_netdev)
 
             qemu_opts_validate(opts, &net_client_types[i].desc[0], &local_err);
             if (error_is_set(&local_err)) {
-                qerror_report_err(local_err);
-                error_free(local_err);
+                error_propagate(errp, local_err);
                 return -1;
             }
 
@@ -1155,7 +1154,7 @@ int net_client_init(QemuOpts *opts, int is_netdev)
                 ret = net_client_types[i].init(opts, name, vlan);
                 if (ret < 0) {
                     /* TODO push error reporting into init() methods */
-                    qerror_report(QERR_DEVICE_INIT_FAILED, type);
+                    error_set(errp, QERR_DEVICE_INIT_FAILED, type);
                     return -1;
                 }
             }
@@ -1163,8 +1162,8 @@ int net_client_init(QemuOpts *opts, int is_netdev)
         }
     }
 
-    qerror_report(QERR_INVALID_PARAMETER_VALUE, "type",
-                  "a network client type");
+    error_set(errp, QERR_INVALID_PARAMETER_VALUE, "type",
+              "a network client type");
     return -1;
 }
 
@@ -1195,6 +1194,7 @@ void net_host_device_add(Monitor *mon, const QDict *qdict)
 {
     const char *device = qdict_get_str(qdict, "device");
     const char *opts_str = qdict_get_try_str(qdict, "opts");
+    Error *local_err = NULL;
     QemuOpts *opts;
 
     if (!net_host_check_device(device)) {
@@ -1209,7 +1209,10 @@ void net_host_device_add(Monitor *mon, const QDict *qdict)
 
     qemu_opt_set(opts, "type", device);
 
-    if (net_client_init(opts, 0) < 0) {
+    net_client_init(opts, 0, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
         monitor_printf(mon, "adding host network device %s failed\n", device);
     }
 }
@@ -1244,8 +1247,10 @@ int do_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
         return -1;
     }
 
-    res = net_client_init(opts, 1);
+    res = net_client_init(opts, 1, &local_err);
     if (res < 0) {
+        qerror_report_err(local_err);
+        error_free(local_err);
         qemu_opts_del(opts);
     }
 
@@ -1427,14 +1432,31 @@ void net_check_clients(void)
 
 static int net_init_client(QemuOpts *opts, void *dummy)
 {
-    if (net_client_init(opts, 0) < 0)
+    Error *local_err = NULL;
+
+    net_client_init(opts, 0, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
         return -1;
+    }
+
     return 0;
 }
 
 static int net_init_netdev(QemuOpts *opts, void *dummy)
 {
-    return net_client_init(opts, 1);
+    Error *local_err = NULL;
+    int ret;
+
+    ret = net_client_init(opts, 1, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+        return -1;
+    }
+
+    return ret;
 }
 
 int net_init_clients(void)
diff --git a/net.h b/net.h
index 9d1ed93..7ee97e9 100644
--- a/net.h
+++ b/net.h
@@ -163,7 +163,7 @@ struct HCIInfo *qemu_next_hci(void);
 extern const char *legacy_tftp_prefix;
 extern const char *legacy_bootp_filename;
 
-int net_client_init(QemuOpts *opts, int is_netdev);
+int net_client_init(QemuOpts *opts, int is_netdev, Error **errp);
 int net_client_parse(QemuOptsList *opts_list, const char *str);
 int net_init_clients(void);
 void net_check_clients(void);
commit 42dcc547e1982f31d0f678e02f0aae5be570384a
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Thu Apr 12 13:20:40 2012 -0300

    net: purge the monitor object from all init functions
    
    The only backend that really uses it is the socket one, which calls
    monitor_get_fd(). But it can use 'cur_mon' instead.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-By: Laszlo Ersek <lersek at redhat.com>

diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index c55d8b9..785eb3d 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -60,7 +60,7 @@ static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
 
     qemu_opt_set(opts, "type", "nic");
 
-    ret = net_client_init(mon, opts, 0);
+    ret = net_client_init(opts, 0);
     if (ret < 0)
         return NULL;
     if (nd_table[ret].devaddr) {
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index b238a09..4e26e64 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -1367,7 +1367,7 @@ static USBDevice *usb_net_init(USBBus *bus, const char *cmdline)
     qemu_opt_set(opts, "type", "nic");
     qemu_opt_set(opts, "model", "usb");
 
-    idx = net_client_init(NULL, opts, 0);
+    idx = net_client_init(opts, 0);
     if (idx == -1) {
         return NULL;
     }
diff --git a/net.c b/net.c
index 246209f..adb7e20 100644
--- a/net.c
+++ b/net.c
@@ -745,10 +745,7 @@ int net_handle_fd_param(Monitor *mon, const char *param)
     return fd;
 }
 
-static int net_init_nic(QemuOpts *opts,
-                        Monitor *mon,
-                        const char *name,
-                        VLANState *vlan)
+static int net_init_nic(QemuOpts *opts, const char *name, VLANState *vlan)
 {
     int idx;
     NICInfo *nd;
@@ -821,7 +818,6 @@ static int net_init_nic(QemuOpts *opts,
      }
 
 typedef int (*net_client_init_func)(QemuOpts *opts,
-                                    Monitor *mon,
                                     const char *name,
                                     VLANState *vlan);
 
@@ -1085,7 +1081,7 @@ static const struct {
 #endif /* CONFIG_NET_BRIDGE */
 };
 
-int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
+int net_client_init(QemuOpts *opts, int is_netdev)
 {
     const char *name;
     const char *type;
@@ -1156,7 +1152,7 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
 
             ret = 0;
             if (net_client_types[i].init) {
-                ret = net_client_types[i].init(opts, mon, name, vlan);
+                ret = net_client_types[i].init(opts, name, vlan);
                 if (ret < 0) {
                     /* TODO push error reporting into init() methods */
                     qerror_report(QERR_DEVICE_INIT_FAILED, type);
@@ -1213,7 +1209,7 @@ void net_host_device_add(Monitor *mon, const QDict *qdict)
 
     qemu_opt_set(opts, "type", device);
 
-    if (net_client_init(mon, opts, 0) < 0) {
+    if (net_client_init(opts, 0) < 0) {
         monitor_printf(mon, "adding host network device %s failed\n", device);
     }
 }
@@ -1248,7 +1244,7 @@ int do_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
         return -1;
     }
 
-    res = net_client_init(mon, opts, 1);
+    res = net_client_init(opts, 1);
     if (res < 0) {
         qemu_opts_del(opts);
     }
@@ -1431,14 +1427,14 @@ void net_check_clients(void)
 
 static int net_init_client(QemuOpts *opts, void *dummy)
 {
-    if (net_client_init(NULL, opts, 0) < 0)
+    if (net_client_init(opts, 0) < 0)
         return -1;
     return 0;
 }
 
 static int net_init_netdev(QemuOpts *opts, void *dummy)
 {
-    return net_client_init(NULL, opts, 1);
+    return net_client_init(opts, 1);
 }
 
 int net_init_clients(void)
diff --git a/net.h b/net.h
index 64993b4..9d1ed93 100644
--- a/net.h
+++ b/net.h
@@ -163,7 +163,7 @@ struct HCIInfo *qemu_next_hci(void);
 extern const char *legacy_tftp_prefix;
 extern const char *legacy_bootp_filename;
 
-int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev);
+int net_client_init(QemuOpts *opts, int is_netdev);
 int net_client_parse(QemuOptsList *opts_list, const char *str);
 int net_init_clients(void);
 void net_check_clients(void);
diff --git a/net/dump.c b/net/dump.c
index 4b48d48..f835c51 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -144,7 +144,7 @@ static int net_dump_init(VLANState *vlan, const char *device,
     return 0;
 }
 
-int net_init_dump(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan)
+int net_init_dump(QemuOpts *opts, const char *name, VLANState *vlan)
 {
     int len;
     const char *file;
diff --git a/net/dump.h b/net/dump.h
index fdc91ad..2b5d9ba 100644
--- a/net/dump.h
+++ b/net/dump.h
@@ -27,7 +27,6 @@
 #include "net.h"
 #include "qemu-common.h"
 
-int net_init_dump(QemuOpts *opts, Monitor *mon,
-                  const char *name, VLANState *vlan);
+int net_init_dump(QemuOpts *opts, const char *name, VLANState *vlan);
 
 #endif /* QEMU_NET_DUMP_H */
diff --git a/net/slirp.c b/net/slirp.c
index 96f5032..37b6ccf 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -676,10 +676,7 @@ static int net_init_slirp_configs(const char *name, const char *value, void *opa
     return 0;
 }
 
-int net_init_slirp(QemuOpts *opts,
-                   Monitor *mon,
-                   const char *name,
-                   VLANState *vlan)
+int net_init_slirp(QemuOpts *opts, const char *name, VLANState *vlan)
 {
     struct slirp_config_str *config;
     const char *vhost;
diff --git a/net/slirp.h b/net/slirp.h
index c17de8e..53fe95d 100644
--- a/net/slirp.h
+++ b/net/slirp.h
@@ -30,10 +30,7 @@
 
 #ifdef CONFIG_SLIRP
 
-int net_init_slirp(QemuOpts *opts,
-                   Monitor *mon,
-                   const char *name,
-                   VLANState *vlan);
+int net_init_slirp(QemuOpts *opts, const char *name, VLANState *vlan);
 
 void net_slirp_hostfwd_add(Monitor *mon, const QDict *qdict);
 void net_slirp_hostfwd_remove(Monitor *mon, const QDict *qdict);
diff --git a/net/socket.c b/net/socket.c
index 0bcf229..fcd0a3c 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -26,6 +26,7 @@
 #include "config-host.h"
 
 #include "net.h"
+#include "monitor.h"
 #include "qemu-char.h"
 #include "qemu-common.h"
 #include "qemu-error.h"
@@ -585,10 +586,7 @@ static int net_socket_udp_init(VLANState *vlan,
     return 0;
 }
 
-int net_init_socket(QemuOpts *opts,
-                    Monitor *mon,
-                    const char *name,
-                    VLANState *vlan)
+int net_init_socket(QemuOpts *opts, const char *name, VLANState *vlan)
 {
     if (qemu_opt_get(opts, "fd")) {
         int fd;
@@ -601,7 +599,7 @@ int net_init_socket(QemuOpts *opts,
             return -1;
         }
 
-        fd = net_handle_fd_param(mon, qemu_opt_get(opts, "fd"));
+        fd = net_handle_fd_param(cur_mon, qemu_opt_get(opts, "fd"));
         if (fd == -1) {
             return -1;
         }
diff --git a/net/socket.h b/net/socket.h
index ea46f02..e1fe959 100644
--- a/net/socket.h
+++ b/net/socket.h
@@ -27,7 +27,6 @@
 #include "net.h"
 #include "qemu-common.h"
 
-int net_init_socket(QemuOpts *opts, Monitor *mon,
-                    const char *name, VLANState *vlan);
+int net_init_socket(QemuOpts *opts, const char *name, VLANState *vlan);
 
 #endif /* QEMU_NET_SOCKET_H */
diff --git a/net/tap-win32.c b/net/tap-win32.c
index 596132e..a801a55 100644
--- a/net/tap-win32.c
+++ b/net/tap-win32.c
@@ -699,7 +699,7 @@ static int tap_win32_init(VLANState *vlan, const char *model,
     return 0;
 }
 
-int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan)
+int net_init_tap(QemuOpts *opts, const char *name, VLANState *vlan)
 {
     const char *ifname;
 
diff --git a/net/tap.c b/net/tap.c
index f240028..5ac4ba3 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -512,8 +512,7 @@ static int net_bridge_run_helper(const char *helper, const char *bridge)
     return -1;
 }
 
-int net_init_bridge(QemuOpts *opts, Monitor *mon, const char *name,
-                    VLANState *vlan)
+int net_init_bridge(QemuOpts *opts, const char *name, VLANState *vlan)
 {
     TAPState *s;
     int fd, vnet_hdr;
@@ -583,7 +582,7 @@ static int net_tap_init(QemuOpts *opts, int *vnet_hdr)
     return fd;
 }
 
-int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan)
+int net_init_tap(QemuOpts *opts, const char *name, VLANState *vlan)
 {
     TAPState *s;
     int fd, vnet_hdr = 0;
@@ -600,7 +599,7 @@ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
             return -1;
         }
 
-        fd = net_handle_fd_param(mon, qemu_opt_get(opts, "fd"));
+        fd = net_handle_fd_param(cur_mon, qemu_opt_get(opts, "fd"));
         if (fd == -1) {
             return -1;
         }
@@ -687,7 +686,7 @@ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
         int vhostfd, r;
         bool force = qemu_opt_get_bool(opts, "vhostforce", false);
         if (qemu_opt_get(opts, "vhostfd")) {
-            r = net_handle_fd_param(mon, qemu_opt_get(opts, "vhostfd"));
+            r = net_handle_fd_param(cur_mon, qemu_opt_get(opts, "vhostfd"));
             if (r == -1) {
                 return -1;
             }
diff --git a/net/tap.h b/net/tap.h
index 56c591f..b2a9450 100644
--- a/net/tap.h
+++ b/net/tap.h
@@ -32,7 +32,7 @@
 #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
 #define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown"
 
-int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan);
+int net_init_tap(QemuOpts *opts, const char *name, VLANState *vlan);
 
 int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required);
 
@@ -57,7 +57,6 @@ int tap_get_fd(VLANClientState *vc);
 struct vhost_net;
 struct vhost_net *tap_get_vhost_net(VLANClientState *vc);
 
-int net_init_bridge(QemuOpts *opts, Monitor *mon, const char *name,
-                    VLANState *vlan);
+int net_init_bridge(QemuOpts *opts, const char *name, VLANState *vlan);
 
 #endif /* QEMU_NET_TAP_H */
diff --git a/net/vde.c b/net/vde.c
index ac48ab2..6b9d452 100644
--- a/net/vde.c
+++ b/net/vde.c
@@ -110,7 +110,7 @@ static int net_vde_init(VLANState *vlan, const char *model,
     return 0;
 }
 
-int net_init_vde(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan)
+int net_init_vde(QemuOpts *opts, const char *name, VLANState *vlan)
 {
     const char *sock;
     const char *group;
diff --git a/net/vde.h b/net/vde.h
index 3e6ca3e..732e575 100644
--- a/net/vde.h
+++ b/net/vde.h
@@ -29,7 +29,7 @@
 
 #ifdef CONFIG_VDE
 
-int net_init_vde(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan);
+int net_init_vde(QemuOpts *opts, const char *name, VLANState *vlan);
 
 #endif /* CONFIG_VDE */
 
commit 60d5666f7d4eec6df4a3d066769009f0c1a685bf
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Mar 28 14:16:37 2012 -0300

    qemu-config: introduce qemu_find_opts_err()
    
    This is like qemu_find_opts(), except that it takes an Error argument.
    
    This new function allows for a incremental conversion of code using
    qemu_find_opts().
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-By: Laszlo Ersek <lersek at redhat.com>

diff --git a/qemu-config.c b/qemu-config.c
index bdb381d..bb3bff4 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -661,6 +661,11 @@ QemuOptsList *qemu_find_opts(const char *group)
     return ret;
 }
 
+QemuOptsList *qemu_find_opts_err(const char *group, Error **errp)
+{
+    return find_list(vm_config_groups, group, errp);
+}
+
 void qemu_add_opts(QemuOptsList *list)
 {
     int entries, i;
diff --git a/qemu-config.h b/qemu-config.h
index 6d7365d..e9f2ef4 100644
--- a/qemu-config.h
+++ b/qemu-config.h
@@ -1,11 +1,14 @@
 #ifndef QEMU_CONFIG_H
 #define QEMU_CONFIG_H
 
+#include "error.h"
+
 extern QemuOptsList qemu_fsdev_opts;
 extern QemuOptsList qemu_virtfs_opts;
 extern QemuOptsList qemu_spice_opts;
 
 QemuOptsList *qemu_find_opts(const char *group);
+QemuOptsList *qemu_find_opts_err(const char *group, Error **errp);
 void qemu_add_opts(QemuOptsList *list);
 int qemu_set_option(const char *str);
 int qemu_global_option(const char *str);
commit 2ac20613384c1c66bc27302e1e38698fa238bb2f
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Mar 28 14:14:17 2012 -0300

    qemu-config: find_list(): use error_set()
    
    Note that qemu_find_opts() and qemu_config_parse() need to call
    error_report() to maintain their semantics on error.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-By: Laszlo Ersek <lersek at redhat.com>

diff --git a/qemu-config.c b/qemu-config.c
index f876646..bdb381d 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -3,6 +3,7 @@
 #include "qemu-option.h"
 #include "qemu-config.h"
 #include "hw/qdev.h"
+#include "error.h"
 
 static QemuOptsList qemu_drive_opts = {
     .name = "drive",
@@ -631,7 +632,8 @@ static QemuOptsList *vm_config_groups[32] = {
     NULL,
 };
 
-static QemuOptsList *find_list(QemuOptsList **lists, const char *group)
+static QemuOptsList *find_list(QemuOptsList **lists, const char *group,
+                               Error **errp)
 {
     int i;
 
@@ -640,14 +642,23 @@ static QemuOptsList *find_list(QemuOptsList **lists, const char *group)
             break;
     }
     if (lists[i] == NULL) {
-        error_report("there is no option group \"%s\"", group);
+        error_set(errp, QERR_INVALID_OPTION_GROUP, group);
     }
     return lists[i];
 }
 
 QemuOptsList *qemu_find_opts(const char *group)
 {
-    return find_list(vm_config_groups, group);
+    QemuOptsList *ret;
+    Error *local_err = NULL;
+
+    ret = find_list(vm_config_groups, group, &local_err);
+    if (error_is_set(&local_err)) {
+        error_report("%s\n", error_get_pretty(local_err));
+        error_free(local_err);
+    }
+
+    return ret;
 }
 
 void qemu_add_opts(QemuOptsList *list)
@@ -762,6 +773,7 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
     char line[1024], group[64], id[64], arg[64], value[1024];
     Location loc;
     QemuOptsList *list = NULL;
+    Error *local_err = NULL;
     QemuOpts *opts = NULL;
     int res = -1, lno = 0;
 
@@ -778,17 +790,23 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
         }
         if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) {
             /* group with id */
-            list = find_list(lists, group);
-            if (list == NULL)
+            list = find_list(lists, group, &local_err);
+            if (error_is_set(&local_err)) {
+                error_report("%s\n", error_get_pretty(local_err));
+                error_free(local_err);
                 goto out;
+            }
             opts = qemu_opts_create(list, id, 1, NULL);
             continue;
         }
         if (sscanf(line, "[%63[^]]]", group) == 1) {
             /* group without id */
-            list = find_list(lists, group);
-            if (list == NULL)
+            list = find_list(lists, group, &local_err);
+            if (error_is_set(&local_err)) {
+                error_report("%s\n", error_get_pretty(local_err));
+                error_free(local_err);
                 goto out;
+            }
             opts = qemu_opts_create(list, NULL, 0, NULL);
             continue;
         }
commit 8ff15d4a2dec25167013d222f1c4aaef8595e02e
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Mar 28 14:01:15 2012 -0300

    qerror: introduce QERR_INVALID_OPTION_GROUP
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-By: Laszlo Ersek <lersek at redhat.com>

diff --git a/qerror.c b/qerror.c
index 5092fe7..92c4eff 100644
--- a/qerror.c
+++ b/qerror.c
@@ -156,6 +156,10 @@ static const QErrorStringTable qerror_table[] = {
         .desc      = "Invalid block format '%(name)'",
     },
     {
+        .error_fmt = QERR_INVALID_OPTION_GROUP,
+        .desc      = "There is no option group '%(group)'",
+    },
+    {
         .error_fmt = QERR_INVALID_PARAMETER,
         .desc      = "Invalid parameter '%(name)'",
     },
diff --git a/qerror.h b/qerror.h
index 4cbba48..b4c8758 100644
--- a/qerror.h
+++ b/qerror.h
@@ -139,6 +139,9 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_INVALID_BLOCK_FORMAT \
     "{ 'class': 'InvalidBlockFormat', 'data': { 'name': %s } }"
 
+#define QERR_INVALID_OPTION_GROUP \
+    "{ 'class': 'InvalidOptionGroup', 'data': { 'group': %s } }"
+
 #define QERR_INVALID_PARAMETER \
     "{ 'class': 'InvalidParameter', 'data': { 'name': %s } }"
 
commit 4e89978e2021c0431aad9898823eb9d3526e9018
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Apr 18 17:24:01 2012 -0300

    qemu-option: qemu_opts_from_qdict(): use error_set()
    
    do_device_add() and do_netdev_add() call qerror_report_err() to maintain
    their QError semantics.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-By: Laszlo Ersek <lersek at redhat.com>

diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c
index eed781d..b01ef06 100644
--- a/hw/qdev-monitor.c
+++ b/hw/qdev-monitor.c
@@ -554,10 +554,13 @@ void do_info_qdm(Monitor *mon)
 
 int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
+    Error *local_err = NULL;
     QemuOpts *opts;
 
-    opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
-    if (!opts) {
+    opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
         return -1;
     }
     if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
diff --git a/net.c b/net.c
index f5d9cc7..246209f 100644
--- a/net.c
+++ b/net.c
@@ -1237,11 +1237,14 @@ void net_host_device_remove(Monitor *mon, const QDict *qdict)
 
 int do_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
+    Error *local_err = NULL;
     QemuOpts *opts;
     int res;
 
-    opts = qemu_opts_from_qdict(qemu_find_opts("netdev"), qdict);
+    opts = qemu_opts_from_qdict(qemu_find_opts("netdev"), qdict, &local_err);
     if (!opts) {
+        qerror_report_err(local_err);
+        error_free(local_err);
         return -1;
     }
 
diff --git a/qemu-option.c b/qemu-option.c
index 1cddb9d..bb3886c 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -968,13 +968,19 @@ void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
     assert(opts);
 }
 
+typedef struct OptsFromQDictState {
+    QemuOpts *opts;
+    Error **errp;
+} OptsFromQDictState;
+
 static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
 {
+    OptsFromQDictState *state = opaque;
     char buf[32];
     const char *value;
     int n;
 
-    if (!strcmp(key, "id")) {
+    if (!strcmp(key, "id") || error_is_set(state->errp)) {
         return;
     }
 
@@ -1002,7 +1008,8 @@ static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
     default:
         return;
     }
-    qemu_opt_set(opaque, key, value);
+
+    qemu_opt_set_err(state->opts, key, value, state->errp);
 }
 
 /*
@@ -1011,21 +1018,31 @@ static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
  * Only QStrings, QInts, QFloats and QBools are copied.  Entries with
  * other types are silently ignored.
  */
-QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict)
+QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
+                               Error **errp)
 {
-    QemuOpts *opts;
+    OptsFromQDictState state;
     Error *local_err = NULL;
+    QemuOpts *opts;
 
     opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1,
                             &local_err);
     if (error_is_set(&local_err)) {
-        qerror_report_err(local_err);
-        error_free(local_err);
+        error_propagate(errp, local_err);
         return NULL;
     }
 
     assert(opts != NULL);
-    qdict_iter(qdict, qemu_opts_from_qdict_1, opts);
+
+    state.errp = &local_err;
+    state.opts = opts;
+    qdict_iter(qdict, qemu_opts_from_qdict_1, &state);
+    if (error_is_set(&local_err)) {
+        error_propagate(errp, local_err);
+        qemu_opts_del(opts);
+        return NULL;
+    }
+
     return opts;
 }
 
diff --git a/qemu-option.h b/qemu-option.h
index c0e022b..951dec3 100644
--- a/qemu-option.h
+++ b/qemu-option.h
@@ -132,7 +132,8 @@ int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname
 QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, int permit_abbrev);
 void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
                             int permit_abbrev);
-QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict);
+QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
+                               Error **errp);
 QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict);
 
 typedef int (*qemu_opts_loopfunc)(QemuOpts *opts, void *opaque);
commit 384f2139ff681cd3c26de365417cff46c186b5f0
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Mar 21 16:17:21 2012 -0300

    qemu-option: introduce qemu_opt_set_err()
    
    This is like qemu_opt_set(), except that it takes an Error argument.
    
    This new function allows for a incremental conversion of code using
    qemu_opt_set().
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-By: Laszlo Ersek <lersek at redhat.com>

diff --git a/qemu-option.c b/qemu-option.c
index 7af2b50..1cddb9d 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -669,6 +669,12 @@ int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
     return 0;
 }
 
+void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value,
+                      Error **errp)
+{
+    opt_set(opts, name, value, false, errp);
+}
+
 int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val)
 {
     QemuOpt *opt;
diff --git a/qemu-option.h b/qemu-option.h
index e9fbbb5..c0e022b 100644
--- a/qemu-option.h
+++ b/qemu-option.h
@@ -111,6 +111,8 @@ bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval);
 uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval);
 uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval);
 int qemu_opt_set(QemuOpts *opts, const char *name, const char *value);
+void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value,
+                      Error **errp);
 int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val);
 typedef int (*qemu_opt_loopfunc)(const char *name, const char *value, void *opaque);
 int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
commit 584d4064c6de5c9f2f555d7afebbbde59c741b8f
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Mar 21 16:13:24 2012 -0300

    qemu-option: opt_set(): use error_set()
    
    The functions qemu_opt_set() and opts_do_parse() both call opt_set(),
    but their callers expect QError semantics. Thus, both functions call
    qerro_report_err() to keep the expected semantics.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-By: Laszlo Ersek <lersek at redhat.com>

diff --git a/qemu-option.c b/qemu-option.c
index eee3b45..7af2b50 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -612,8 +612,8 @@ static void qemu_opt_del(QemuOpt *opt)
     g_free(opt);
 }
 
-static int opt_set(QemuOpts *opts, const char *name, const char *value,
-                   bool prepend)
+static void opt_set(QemuOpts *opts, const char *name, const char *value,
+                    bool prepend, Error **errp)
 {
     QemuOpt *opt;
     const QemuOptDesc *desc = opts->list->desc;
@@ -629,8 +629,8 @@ static int opt_set(QemuOpts *opts, const char *name, const char *value,
         if (i == 0) {
             /* empty list -> allow any */;
         } else {
-            qerror_report(QERR_INVALID_PARAMETER, name);
-            return -1;
+            error_set(errp, QERR_INVALID_PARAMETER, name);
+            return;
         }
     }
 
@@ -650,18 +650,23 @@ static int opt_set(QemuOpts *opts, const char *name, const char *value,
     }
     qemu_opt_parse(opt, &local_err);
     if (error_is_set(&local_err)) {
-        qerror_report_err(local_err);
-        error_free(local_err);
+        error_propagate(errp, local_err);
         qemu_opt_del(opt);
-        return -1;
     }
-
-    return 0;
 }
 
 int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
 {
-    return opt_set(opts, name, value, false);
+    Error *local_err = NULL;
+
+    opt_set(opts, name, value, false, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+        return -1;
+    }
+
+    return 0;
 }
 
 int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val)
@@ -847,6 +852,7 @@ static int opts_do_parse(QemuOpts *opts, const char *params,
 {
     char option[128], value[1024];
     const char *p,*pe,*pc;
+    Error *local_err = NULL;
 
     for (p = params; *p != '\0'; p++) {
         pe = strchr(p, '=');
@@ -878,7 +884,10 @@ static int opts_do_parse(QemuOpts *opts, const char *params,
         }
         if (strcmp(option, "id") != 0) {
             /* store and parse */
-            if (opt_set(opts, option, value, prepend) == -1) {
+            opt_set(opts, option, value, prepend, &local_err);
+            if (error_is_set(&local_err)) {
+                qerror_report_err(local_err);
+                error_free(local_err);
                 return -1;
             }
         }
commit 299528668c759f40b2cc78914e2ca2c832f82834
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Thu Apr 12 11:58:57 2012 -0300

    qemu-option: qemu_opts_validate(): use error_set()
    
    net_client_init() propagates the error up by calling qerror_report_err(),
    because its users expect QError semantics.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-By: Laszlo Ersek <lersek at redhat.com>

diff --git a/net.c b/net.c
index 1922d8a..f5d9cc7 100644
--- a/net.c
+++ b/net.c
@@ -1136,10 +1136,14 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
     for (i = 0; i < NET_CLIENT_TYPE_MAX; i++) {
         if (net_client_types[i].type != NULL &&
             !strcmp(net_client_types[i].type, type)) {
+            Error *local_err = NULL;
             VLANState *vlan = NULL;
             int ret;
 
-            if (qemu_opts_validate(opts, &net_client_types[i].desc[0]) == -1) {
+            qemu_opts_validate(opts, &net_client_types[i].desc[0], &local_err);
+            if (error_is_set(&local_err)) {
+                qerror_report_err(local_err);
+                error_free(local_err);
                 return -1;
             }
 
diff --git a/qemu-option.c b/qemu-option.c
index 6d36970..eee3b45 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -1041,7 +1041,7 @@ QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
 /* Validate parsed opts against descriptions where no
  * descriptions were provided in the QemuOptsList.
  */
-int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc)
+void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp)
 {
     QemuOpt *opt;
     Error *local_err = NULL;
@@ -1057,21 +1057,18 @@ int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc)
             }
         }
         if (desc[i].name == NULL) {
-            qerror_report(QERR_INVALID_PARAMETER, opt->name);
-            return -1;
+            error_set(errp, QERR_INVALID_PARAMETER, opt->name);
+            return;
         }
 
         opt->desc = &desc[i];
 
         qemu_opt_parse(opt, &local_err);
         if (error_is_set(&local_err)) {
-            qerror_report_err(local_err);
-            error_free(local_err);
-            return -1;
+            error_propagate(errp, local_err);
+            return;
         }
     }
-
-    return 0;
 }
 
 int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,
diff --git a/qemu-option.h b/qemu-option.h
index 4d5b3d3..e9fbbb5 100644
--- a/qemu-option.h
+++ b/qemu-option.h
@@ -125,7 +125,7 @@ int qemu_opts_set(QemuOptsList *list, const char *id,
                   const char *name, const char *value);
 const char *qemu_opts_id(QemuOpts *opts);
 void qemu_opts_del(QemuOpts *opts);
-int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc);
+void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp);
 int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname);
 QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, int permit_abbrev);
 void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
commit 6c5194046a34ff9f84e294d4ef926ec509741493
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Mar 21 15:21:26 2012 -0300

    qemu-option: qemu_opt_parse(): use error_set()
    
    The functions opt_set() and qemu_opts_validate() both call qemu_opt_parse(),
    but their callers expect QError semantics. Thus, both functions call
    qerro_report_err() to keep the expected semantics.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-By: Laszlo Ersek <lersek at redhat.com>

diff --git a/qemu-option.c b/qemu-option.c
index 42bb685..6d36970 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -581,38 +581,27 @@ uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
     return opt->value.uint;
 }
 
-static int qemu_opt_parse(QemuOpt *opt)
+static void qemu_opt_parse(QemuOpt *opt, Error **errp)
 {
-    Error *local_err = NULL;
-
     if (opt->desc == NULL)
-        return 0;
+        return;
 
     switch (opt->desc->type) {
     case QEMU_OPT_STRING:
         /* nothing */
-        return 0;
+        return;
     case QEMU_OPT_BOOL:
-        parse_option_bool(opt->name, opt->str, &opt->value.boolean, &local_err);
+        parse_option_bool(opt->name, opt->str, &opt->value.boolean, errp);
         break;
     case QEMU_OPT_NUMBER:
-        parse_option_number(opt->name, opt->str, &opt->value.uint,
-                            &local_err);
+        parse_option_number(opt->name, opt->str, &opt->value.uint, errp);
         break;
     case QEMU_OPT_SIZE:
-        parse_option_size(opt->name, opt->str, &opt->value.uint, &local_err);
+        parse_option_size(opt->name, opt->str, &opt->value.uint, errp);
         break;
     default:
         abort();
     }
-
-    if (error_is_set(&local_err)) {
-        qerror_report_err(local_err);
-        error_free(local_err);
-        return -1;
-    }
-
-    return 0;
 }
 
 static void qemu_opt_del(QemuOpt *opt)
@@ -628,6 +617,7 @@ static int opt_set(QemuOpts *opts, const char *name, const char *value,
 {
     QemuOpt *opt;
     const QemuOptDesc *desc = opts->list->desc;
+    Error *local_err = NULL;
     int i;
 
     for (i = 0; desc[i].name != NULL; i++) {
@@ -658,10 +648,14 @@ static int opt_set(QemuOpts *opts, const char *name, const char *value,
     if (value) {
         opt->str = g_strdup(value);
     }
-    if (qemu_opt_parse(opt) < 0) {
+    qemu_opt_parse(opt, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
         qemu_opt_del(opt);
         return -1;
     }
+
     return 0;
 }
 
@@ -1050,6 +1044,7 @@ QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
 int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc)
 {
     QemuOpt *opt;
+    Error *local_err = NULL;
 
     assert(opts->list->desc[0].name == NULL);
 
@@ -1068,7 +1063,10 @@ int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc)
 
         opt->desc = &desc[i];
 
-        if (qemu_opt_parse(opt) < 0) {
+        qemu_opt_parse(opt, &local_err);
+        if (error_is_set(&local_err)) {
+            qerror_report_err(local_err);
+            error_free(local_err);
             return -1;
         }
     }
commit ec7b2ccb4a6366784ff2c793b43b4c0940909f44
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Mar 21 15:03:45 2012 -0300

    qemu-option: parse_option_size(): use error_set()
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-By: Laszlo Ersek <lersek at redhat.com>

diff --git a/qemu-option.c b/qemu-option.c
index b5da116..42bb685 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -203,7 +203,8 @@ static void parse_option_number(const char *name, const char *value,
     }
 }
 
-static int parse_option_size(const char *name, const char *value, uint64_t *ret)
+static void parse_option_size(const char *name, const char *value,
+                              uint64_t *ret, Error **errp)
 {
     char *postfix;
     double sizef;
@@ -229,16 +230,14 @@ static int parse_option_size(const char *name, const char *value, uint64_t *ret)
             *ret = (uint64_t) sizef;
             break;
         default:
-            qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a size");
+            error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size");
             error_printf_unless_qmp("You may use k, M, G or T suffixes for "
                     "kilobytes, megabytes, gigabytes and terabytes.\n");
-            return -1;
+            return;
         }
     } else {
-        qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a size");
-        return -1;
+        error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size");
     }
-    return 0;
 }
 
 /*
@@ -290,8 +289,7 @@ int set_option_parameter(QEMUOptionParameter *list, const char *name,
         break;
 
     case OPT_SIZE:
-        if (parse_option_size(name, value, &list->value.n) == -1)
-            return -1;
+        parse_option_size(name, value, &list->value.n, &local_err);
         break;
 
     default:
@@ -602,7 +600,8 @@ static int qemu_opt_parse(QemuOpt *opt)
                             &local_err);
         break;
     case QEMU_OPT_SIZE:
-        return parse_option_size(opt->name, opt->str, &opt->value.uint);
+        parse_option_size(opt->name, opt->str, &opt->value.uint, &local_err);
+        break;
     default:
         abort();
     }
commit cf62adfabf29c0b7833a5306023cab5c0bc3b6d5
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Mar 21 14:54:42 2012 -0300

    qemu-option: parse_option_bool(): use error_set()
    
    Note that set_option_parameter() callers still expect automatic error
    reporting with QError, so set_option_parameter() calls
    qerror_report_err() to keep the same semantics.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-By: Laszlo Ersek <lersek at redhat.com>

diff --git a/qemu-option.c b/qemu-option.c
index 72dcb56..b5da116 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -169,7 +169,8 @@ QEMUOptionParameter *get_option_parameter(QEMUOptionParameter *list,
     return NULL;
 }
 
-static int parse_option_bool(const char *name, const char *value, bool *ret)
+static void parse_option_bool(const char *name, const char *value, bool *ret,
+                              Error **errp)
 {
     if (value != NULL) {
         if (!strcmp(value, "on")) {
@@ -177,13 +178,11 @@ static int parse_option_bool(const char *name, const char *value, bool *ret)
         } else if (!strcmp(value, "off")) {
             *ret = 0;
         } else {
-            qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "'on' or 'off'");
-            return -1;
+            error_set(errp,QERR_INVALID_PARAMETER_VALUE, name, "'on' or 'off'");
         }
     } else {
         *ret = 1;
     }
-    return 0;
 }
 
 static void parse_option_number(const char *name, const char *value,
@@ -263,6 +262,7 @@ int set_option_parameter(QEMUOptionParameter *list, const char *name,
     const char *value)
 {
     bool flag;
+    Error *local_err = NULL;
 
     // Find a matching parameter
     list = get_option_parameter(list, name);
@@ -274,9 +274,10 @@ int set_option_parameter(QEMUOptionParameter *list, const char *name,
     // Process parameter
     switch (list->type) {
     case OPT_FLAG:
-        if (parse_option_bool(name, value, &flag) == -1)
-            return -1;
-        list->value.n = flag;
+        parse_option_bool(name, value, &flag, &local_err);
+        if (!error_is_set(&local_err)) {
+            list->value.n = flag;
+        }
         break;
 
     case OPT_STRING:
@@ -298,6 +299,12 @@ int set_option_parameter(QEMUOptionParameter *list, const char *name,
         return -1;
     }
 
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+        return -1;
+    }
+
     return 0;
 }
 
@@ -588,7 +595,8 @@ static int qemu_opt_parse(QemuOpt *opt)
         /* nothing */
         return 0;
     case QEMU_OPT_BOOL:
-        return parse_option_bool(opt->name, opt->str, &opt->value.boolean);
+        parse_option_bool(opt->name, opt->str, &opt->value.boolean, &local_err);
+        break;
     case QEMU_OPT_NUMBER:
         parse_option_number(opt->name, opt->str, &opt->value.uint,
                             &local_err);
commit 2f39df5b0da6a030cc04c80e4e78ccd7002176b0
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Mar 21 14:37:44 2012 -0300

    qemu-option: parse_option_number(): use error_set()
    
    Note that qemu_opt_parse() callers still expect automatic error reporting
    with QError, so qemu_opts_parse() calls qerror_report_err() to keep the
    same semantics.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-By: Laszlo Ersek <lersek at redhat.com>

diff --git a/qemu-option.c b/qemu-option.c
index 9f531c8..72dcb56 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -186,7 +186,8 @@ static int parse_option_bool(const char *name, const char *value, bool *ret)
     return 0;
 }
 
-static int parse_option_number(const char *name, const char *value, uint64_t *ret)
+static void parse_option_number(const char *name, const char *value,
+                                uint64_t *ret, Error **errp)
 {
     char *postfix;
     uint64_t number;
@@ -194,15 +195,13 @@ static int parse_option_number(const char *name, const char *value, uint64_t *re
     if (value != NULL) {
         number = strtoull(value, &postfix, 0);
         if (*postfix != '\0') {
-            qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a number");
-            return -1;
+            error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number");
+            return;
         }
         *ret = number;
     } else {
-        qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a number");
-        return -1;
+        error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number");
     }
-    return 0;
 }
 
 static int parse_option_size(const char *name, const char *value, uint64_t *ret)
@@ -579,8 +578,11 @@ uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
 
 static int qemu_opt_parse(QemuOpt *opt)
 {
+    Error *local_err = NULL;
+
     if (opt->desc == NULL)
         return 0;
+
     switch (opt->desc->type) {
     case QEMU_OPT_STRING:
         /* nothing */
@@ -588,12 +590,22 @@ static int qemu_opt_parse(QemuOpt *opt)
     case QEMU_OPT_BOOL:
         return parse_option_bool(opt->name, opt->str, &opt->value.boolean);
     case QEMU_OPT_NUMBER:
-        return parse_option_number(opt->name, opt->str, &opt->value.uint);
+        parse_option_number(opt->name, opt->str, &opt->value.uint,
+                            &local_err);
+        break;
     case QEMU_OPT_SIZE:
         return parse_option_size(opt->name, opt->str, &opt->value.uint);
     default:
         abort();
     }
+
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+        return -1;
+    }
+
+    return 0;
 }
 
 static void qemu_opt_del(QemuOpt *opt)
commit 8be7e7e4c72c048b90e3482557954a24bba43ba7
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Tue Mar 20 15:51:57 2012 -0300

    qemu-option: qemu_opts_create(): use error_set()
    
    This commit converts qemu_opts_create() from qerror_report() to
    error_set().
    
    Currently, most calls to qemu_opts_create() can't fail, so most
    callers don't need any changes.
    
    The two cases where code checks for qemu_opts_create() erros are:
    
     1. Initialization code in vl.c. All of them print their own
        error messages directly to stderr, no need to pass the Error
        object
    
     2. The functions opts_parse(), qemu_opts_from_qdict() and
        qemu_chr_parse_compat() make use of the error information and
        they can be called from HMP or QMP. In this case, to allow for
        incremental conversion, we propagate the error up using
        qerror_report_err(), which keeps the QError semantics
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-By: Laszlo Ersek <lersek at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 67895b2..622ecba 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -569,7 +569,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
         break;
     case IF_VIRTIO:
         /* add virtio block device */
-        opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
+        opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0, NULL);
         if (arch_type == QEMU_ARCH_S390X) {
             qemu_opt_set(opts, "driver", "virtio-blk-s390");
         } else {
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index ae22fb1..a96c0b9 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -584,7 +584,7 @@ static USBDevice *usb_msd_init(USBBus *bus, const char *filename)
 
     /* parse -usbdevice disk: syntax into drive opts */
     snprintf(id, sizeof(id), "usb%d", nr++);
-    opts = qemu_opts_create(qemu_find_opts("drive"), id, 0);
+    opts = qemu_opts_create(qemu_find_opts("drive"), id, 0, NULL);
 
     p1 = strchr(filename, ':');
     if (p1++) {
diff --git a/hw/watchdog.c b/hw/watchdog.c
index 4c18965..a42124d 100644
--- a/hw/watchdog.c
+++ b/hw/watchdog.c
@@ -66,7 +66,7 @@ int select_watchdog(const char *p)
     QLIST_FOREACH(model, &watchdog_list, entry) {
         if (strcasecmp(model->wdt_name, p) == 0) {
             /* add the device */
-            opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
+            opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0, NULL);
             qemu_opt_set(opts, "driver", p);
             return 0;
         }
diff --git a/qemu-char.c b/qemu-char.c
index fe1126f..0bd903f 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2584,10 +2584,14 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
     int pos;
     const char *p;
     QemuOpts *opts;
+    Error *local_err = NULL;
 
-    opts = qemu_opts_create(qemu_find_opts("chardev"), label, 1);
-    if (NULL == opts)
+    opts = qemu_opts_create(qemu_find_opts("chardev"), label, 1, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
         return NULL;
+    }
 
     if (strstart(filename, "mon:", &p)) {
         filename = p;
diff --git a/qemu-config.c b/qemu-config.c
index be84a03..f876646 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -709,7 +709,7 @@ int qemu_global_option(const char *str)
         return -1;
     }
 
-    opts = qemu_opts_create(&qemu_global_opts, NULL, 0);
+    opts = qemu_opts_create(&qemu_global_opts, NULL, 0, NULL);
     qemu_opt_set(opts, "driver", driver);
     qemu_opt_set(opts, "property", property);
     qemu_opt_set(opts, "value", str+offset+1);
@@ -781,7 +781,7 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
             list = find_list(lists, group);
             if (list == NULL)
                 goto out;
-            opts = qemu_opts_create(list, id, 1);
+            opts = qemu_opts_create(list, id, 1, NULL);
             continue;
         }
         if (sscanf(line, "[%63[^]]]", group) == 1) {
@@ -789,7 +789,7 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
             list = find_list(lists, group);
             if (list == NULL)
                 goto out;
-            opts = qemu_opts_create(list, NULL, 0);
+            opts = qemu_opts_create(list, NULL, 0, NULL);
             continue;
         }
         if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) {
diff --git a/qemu-option.c b/qemu-option.c
index 35cd609..9f531c8 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -30,6 +30,7 @@
 #include "qemu-error.h"
 #include "qemu-objects.h"
 #include "qemu-option.h"
+#include "error.h"
 #include "qerror.h"
 
 /*
@@ -729,20 +730,21 @@ static int id_wellformed(const char *id)
     return 1;
 }
 
-QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exists)
+QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
+                           int fail_if_exists, Error **errp)
 {
     QemuOpts *opts = NULL;
 
     if (id) {
         if (!id_wellformed(id)) {
-            qerror_report(QERR_INVALID_PARAMETER_VALUE, "id", "an identifier");
+            error_set(errp,QERR_INVALID_PARAMETER_VALUE, "id", "an identifier");
             error_printf_unless_qmp("Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.\n");
             return NULL;
         }
         opts = qemu_opts_find(list, id);
         if (opts != NULL) {
             if (fail_if_exists && !list->merge_lists) {
-                qerror_report(QERR_DUPLICATE_ID, id, list->name);
+                error_set(errp, QERR_DUPLICATE_ID, id, list->name);
                 return NULL;
             } else {
                 return opts;
@@ -783,9 +785,12 @@ int qemu_opts_set(QemuOptsList *list, const char *id,
                   const char *name, const char *value)
 {
     QemuOpts *opts;
+    Error *local_err = NULL;
 
-    opts = qemu_opts_create(list, id, 1);
-    if (opts == NULL) {
+    opts = qemu_opts_create(list, id, 1, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
         return -1;
     }
     return qemu_opt_set(opts, name, value);
@@ -883,6 +888,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
     char value[1024], *id = NULL;
     const char *p;
     QemuOpts *opts;
+    Error *local_err = NULL;
 
     assert(!permit_abbrev || list->implied_opt_name);
     firstname = permit_abbrev ? list->implied_opt_name : NULL;
@@ -898,13 +904,18 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
         if (!id && !QTAILQ_EMPTY(&list->head)) {
             opts = qemu_opts_find(list, NULL);
         } else {
-            opts = qemu_opts_create(list, id, 0);
+            opts = qemu_opts_create(list, id, 0, &local_err);
         }
     } else {
-        opts = qemu_opts_create(list, id, 1);
+        opts = qemu_opts_create(list, id, 1, &local_err);
     }
-    if (opts == NULL)
+    if (opts == NULL) {
+        if (error_is_set(&local_err)) {
+            qerror_report_err(local_err);
+            error_free(local_err);
+        }
         return NULL;
+    }
 
     if (opts_do_parse(opts, params, firstname, defaults) != 0) {
         qemu_opts_del(opts);
@@ -975,11 +986,17 @@ static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
 QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict)
 {
     QemuOpts *opts;
+    Error *local_err = NULL;
 
-    opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1);
-    if (opts == NULL)
+    opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1,
+                            &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
         return NULL;
+    }
 
+    assert(opts != NULL);
     qdict_iter(qdict, qemu_opts_from_qdict_1, opts);
     return opts;
 }
diff --git a/qemu-option.h b/qemu-option.h
index 3ca00c3..4d5b3d3 100644
--- a/qemu-option.h
+++ b/qemu-option.h
@@ -28,6 +28,7 @@
 
 #include <stdint.h>
 #include "qemu-queue.h"
+#include "error.h"
 #include "qdict.h"
 
 enum QEMUOptionParType {
@@ -116,7 +117,8 @@ int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
                      int abort_on_failure);
 
 QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id);
-QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exists);
+QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
+                           int fail_if_exists, Error **errp);
 void qemu_opts_reset(QemuOptsList *list);
 void qemu_opts_loc_restore(QemuOpts *opts);
 int qemu_opts_set(QemuOptsList *list, const char *id,
diff --git a/qemu-sockets.c b/qemu-sockets.c
index 46c7619..2ae715d 100644
--- a/qemu-sockets.c
+++ b/qemu-sockets.c
@@ -461,7 +461,7 @@ int inet_listen(const char *str, char *ostr, int olen,
     char *optstr;
     int sock = -1;
 
-    opts = qemu_opts_create(&dummy_opts, NULL, 0);
+    opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
     if (inet_parse(opts, str) == 0) {
         sock = inet_listen_opts(opts, port_offset, errp);
         if (sock != -1 && ostr) {
@@ -490,7 +490,7 @@ int inet_connect(const char *str, bool block, Error **errp)
     QemuOpts *opts;
     int sock = -1;
 
-    opts = qemu_opts_create(&dummy_opts, NULL, 0);
+    opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
     if (inet_parse(opts, str) == 0) {
         if (block) {
             qemu_opt_set(opts, "block", "on");
@@ -589,7 +589,7 @@ int unix_listen(const char *str, char *ostr, int olen)
     char *path, *optstr;
     int sock, len;
 
-    opts = qemu_opts_create(&dummy_opts, NULL, 0);
+    opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
 
     optstr = strchr(str, ',');
     if (optstr) {
@@ -617,7 +617,7 @@ int unix_connect(const char *path)
     QemuOpts *opts;
     int sock;
 
-    opts = qemu_opts_create(&dummy_opts, NULL, 0);
+    opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
     qemu_opt_set(opts, "path", path);
     sock = unix_connect_opts(opts);
     qemu_opts_del(opts);
diff --git a/vl.c b/vl.c
index 23ab3a3..1485426 100644
--- a/vl.c
+++ b/vl.c
@@ -1786,7 +1786,7 @@ static int balloon_parse(const char *arg)
                 return  -1;
         } else {
             /* create empty opts */
-            opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
+            opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0, NULL);
         }
         qemu_opt_set(opts, "driver", "virtio-balloon");
         return 0;
@@ -1921,7 +1921,7 @@ static void monitor_parse(const char *optarg, const char *mode)
         }
     }
 
-    opts = qemu_opts_create(qemu_find_opts("mon"), label, 1);
+    opts = qemu_opts_create(qemu_find_opts("mon"), label, 1, NULL);
     if (!opts) {
         fprintf(stderr, "duplicate chardev: %s\n", label);
         exit(1);
@@ -2035,14 +2035,14 @@ static int virtcon_parse(const char *devname)
         exit(1);
     }
 
-    bus_opts = qemu_opts_create(device, NULL, 0);
+    bus_opts = qemu_opts_create(device, NULL, 0, NULL);
     if (arch_type == QEMU_ARCH_S390X) {
         qemu_opt_set(bus_opts, "driver", "virtio-serial-s390");
     } else {
         qemu_opt_set(bus_opts, "driver", "virtio-serial-pci");
     } 
 
-    dev_opts = qemu_opts_create(device, NULL, 0);
+    dev_opts = qemu_opts_create(device, NULL, 0, NULL);
     qemu_opt_set(dev_opts, "driver", "virtconsole");
 
     snprintf(label, sizeof(label), "virtcon%d", index);
@@ -2065,7 +2065,7 @@ static int debugcon_parse(const char *devname)
     if (!qemu_chr_new("debugcon", devname, NULL)) {
         exit(1);
     }
-    opts = qemu_opts_create(qemu_find_opts("device"), "debugcon", 1);
+    opts = qemu_opts_create(qemu_find_opts("device"), "debugcon", 1, NULL);
     if (!opts) {
         fprintf(stderr, "qemu: already have a debugcon device\n");
         exit(1);
@@ -2813,7 +2813,8 @@ int main(int argc, char **argv, char **envp)
                     exit(1);
                 }
                 fsdev = qemu_opts_create(qemu_find_opts("fsdev"),
-                                         qemu_opt_get(opts, "mount_tag"), 1);
+                                         qemu_opt_get(opts, "mount_tag"),
+                                         1, NULL);
                 if (!fsdev) {
                     fprintf(stderr, "duplicate fsdev id: %s\n",
                             qemu_opt_get(opts, "mount_tag"));
@@ -2845,7 +2846,8 @@ int main(int argc, char **argv, char **envp)
 
                 qemu_opt_set_bool(fsdev, "readonly",
                                 qemu_opt_get_bool(opts, "readonly", 0));
-                device = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
+                device = qemu_opts_create(qemu_find_opts("device"), NULL, 0,
+                                          NULL);
                 qemu_opt_set(device, "driver", "virtio-9p-pci");
                 qemu_opt_set(device, "fsdev",
                              qemu_opt_get(opts, "mount_tag"));
@@ -2857,14 +2859,16 @@ int main(int argc, char **argv, char **envp)
                 QemuOpts *fsdev;
                 QemuOpts *device;
 
-                fsdev = qemu_opts_create(qemu_find_opts("fsdev"), "v_synth", 1);
+                fsdev = qemu_opts_create(qemu_find_opts("fsdev"), "v_synth",
+                                         1, NULL);
                 if (!fsdev) {
                     fprintf(stderr, "duplicate option: %s\n", "virtfs_synth");
                     exit(1);
                 }
                 qemu_opt_set(fsdev, "fsdriver", "synth");
 
-                device = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
+                device = qemu_opts_create(qemu_find_opts("device"), NULL, 0,
+                                          NULL);
                 qemu_opt_set(device, "driver", "virtio-9p-pci");
                 qemu_opt_set(device, "fsdev", "v_synth");
                 qemu_opt_set(device, "mount_tag", "v_synth");
commit 783e9b4826b95e53e33c42db6b4bd7d89bdff147
Author: Wen Congyang <wency at cn.fujitsu.com>
Date:   Mon May 7 12:10:47 2012 +0800

    introduce a new monitor command 'dump-guest-memory' to dump guest's memory
    
    The command's usage:
       dump-guest-memory [-p] protocol [begin] [length]
    The supported protocol can be file or fd:
    1. file: the protocol starts with "file:", and the following string is
       the file's path.
    2. fd: the protocol starts with "fd:", and the following string is the
       fd's name.
    
    Note:
      1. If you want to use gdb to process the core, please specify -p option.
         The reason why the -p option is not default is:
           a. guest machine in a catastrophic state can have corrupted memory,
              which we cannot trust.
           b. The guest machine can be in read-mode even if paging is enabled.
              For example: the guest machine uses ACPI to sleep, and ACPI sleep
              state goes in real-mode.
      2. If you don't want to dump all guest's memory, please specify the start
         physical address and the length.
    
    Signed-off-by: Wen Congyang <wency at cn.fujitsu.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/Makefile.target b/Makefile.target
index cf05831..c94abfd 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -405,6 +405,8 @@ obj-y += $(addprefix ../, $(trace-obj-y))
 
 endif # CONFIG_SOFTMMU
 
+obj-y += dump.o
+
 ifndef CONFIG_LINUX_USER
 ifndef CONFIG_BSD_USER
 # libcacard needs qemu-thread support, and besides is only needed by devices
diff --git a/dump.c b/dump.c
new file mode 100644
index 0000000..0ca14f8
--- /dev/null
+++ b/dump.c
@@ -0,0 +1,883 @@
+/*
+ * QEMU dump
+ *
+ * Copyright Fujitsu, Corp. 2011, 2012
+ *
+ * Authors:
+ *     Wen Congyang <wency at cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include <unistd.h>
+#include "elf.h"
+#include <sys/procfs.h>
+#include <glib.h>
+#include "cpu.h"
+#include "cpu-all.h"
+#include "targphys.h"
+#include "monitor.h"
+#include "kvm.h"
+#include "dump.h"
+#include "sysemu.h"
+#include "bswap.h"
+#include "memory_mapping.h"
+#include "error.h"
+#include "qmp-commands.h"
+#include "gdbstub.h"
+
+#if defined(CONFIG_HAVE_CORE_DUMP)
+static uint16_t cpu_convert_to_target16(uint16_t val, int endian)
+{
+    if (endian == ELFDATA2LSB) {
+        val = cpu_to_le16(val);
+    } else {
+        val = cpu_to_be16(val);
+    }
+
+    return val;
+}
+
+static uint32_t cpu_convert_to_target32(uint32_t val, int endian)
+{
+    if (endian == ELFDATA2LSB) {
+        val = cpu_to_le32(val);
+    } else {
+        val = cpu_to_be32(val);
+    }
+
+    return val;
+}
+
+static uint64_t cpu_convert_to_target64(uint64_t val, int endian)
+{
+    if (endian == ELFDATA2LSB) {
+        val = cpu_to_le64(val);
+    } else {
+        val = cpu_to_be64(val);
+    }
+
+    return val;
+}
+
+typedef struct DumpState {
+    ArchDumpInfo dump_info;
+    MemoryMappingList list;
+    uint16_t phdr_num;
+    uint32_t sh_info;
+    bool have_section;
+    bool resume;
+    size_t note_size;
+    target_phys_addr_t memory_offset;
+    int fd;
+
+    RAMBlock *block;
+    ram_addr_t start;
+    bool has_filter;
+    int64_t begin;
+    int64_t length;
+    Error **errp;
+} DumpState;
+
+static int dump_cleanup(DumpState *s)
+{
+    int ret = 0;
+
+    memory_mapping_list_free(&s->list);
+    if (s->fd != -1) {
+        close(s->fd);
+    }
+    if (s->resume) {
+        vm_start();
+    }
+
+    return ret;
+}
+
+static void dump_error(DumpState *s, const char *reason)
+{
+    dump_cleanup(s);
+}
+
+static int fd_write_vmcore(void *buf, size_t size, void *opaque)
+{
+    DumpState *s = opaque;
+    int fd = s->fd;
+    size_t writen_size;
+
+    /* The fd may be passed from user, and it can be non-blocked */
+    while (size) {
+        writen_size = qemu_write_full(fd, buf, size);
+        if (writen_size != size && errno != EAGAIN) {
+            return -1;
+        }
+
+        buf += writen_size;
+        size -= writen_size;
+    }
+
+    return 0;
+}
+
+static int write_elf64_header(DumpState *s)
+{
+    Elf64_Ehdr elf_header;
+    int ret;
+    int endian = s->dump_info.d_endian;
+
+    memset(&elf_header, 0, sizeof(Elf64_Ehdr));
+    memcpy(&elf_header, ELFMAG, SELFMAG);
+    elf_header.e_ident[EI_CLASS] = ELFCLASS64;
+    elf_header.e_ident[EI_DATA] = s->dump_info.d_endian;
+    elf_header.e_ident[EI_VERSION] = EV_CURRENT;
+    elf_header.e_type = cpu_convert_to_target16(ET_CORE, endian);
+    elf_header.e_machine = cpu_convert_to_target16(s->dump_info.d_machine,
+                                                   endian);
+    elf_header.e_version = cpu_convert_to_target32(EV_CURRENT, endian);
+    elf_header.e_ehsize = cpu_convert_to_target16(sizeof(elf_header), endian);
+    elf_header.e_phoff = cpu_convert_to_target64(sizeof(Elf64_Ehdr), endian);
+    elf_header.e_phentsize = cpu_convert_to_target16(sizeof(Elf64_Phdr),
+                                                     endian);
+    elf_header.e_phnum = cpu_convert_to_target16(s->phdr_num, endian);
+    if (s->have_section) {
+        uint64_t shoff = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) * s->sh_info;
+
+        elf_header.e_shoff = cpu_convert_to_target64(shoff, endian);
+        elf_header.e_shentsize = cpu_convert_to_target16(sizeof(Elf64_Shdr),
+                                                         endian);
+        elf_header.e_shnum = cpu_convert_to_target16(1, endian);
+    }
+
+    ret = fd_write_vmcore(&elf_header, sizeof(elf_header), s);
+    if (ret < 0) {
+        dump_error(s, "dump: failed to write elf header.\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int write_elf32_header(DumpState *s)
+{
+    Elf32_Ehdr elf_header;
+    int ret;
+    int endian = s->dump_info.d_endian;
+
+    memset(&elf_header, 0, sizeof(Elf32_Ehdr));
+    memcpy(&elf_header, ELFMAG, SELFMAG);
+    elf_header.e_ident[EI_CLASS] = ELFCLASS32;
+    elf_header.e_ident[EI_DATA] = endian;
+    elf_header.e_ident[EI_VERSION] = EV_CURRENT;
+    elf_header.e_type = cpu_convert_to_target16(ET_CORE, endian);
+    elf_header.e_machine = cpu_convert_to_target16(s->dump_info.d_machine,
+                                                   endian);
+    elf_header.e_version = cpu_convert_to_target32(EV_CURRENT, endian);
+    elf_header.e_ehsize = cpu_convert_to_target16(sizeof(elf_header), endian);
+    elf_header.e_phoff = cpu_convert_to_target32(sizeof(Elf32_Ehdr), endian);
+    elf_header.e_phentsize = cpu_convert_to_target16(sizeof(Elf32_Phdr),
+                                                     endian);
+    elf_header.e_phnum = cpu_convert_to_target16(s->phdr_num, endian);
+    if (s->have_section) {
+        uint32_t shoff = sizeof(Elf32_Ehdr) + sizeof(Elf32_Phdr) * s->sh_info;
+
+        elf_header.e_shoff = cpu_convert_to_target32(shoff, endian);
+        elf_header.e_shentsize = cpu_convert_to_target16(sizeof(Elf32_Shdr),
+                                                         endian);
+        elf_header.e_shnum = cpu_convert_to_target16(1, endian);
+    }
+
+    ret = fd_write_vmcore(&elf_header, sizeof(elf_header), s);
+    if (ret < 0) {
+        dump_error(s, "dump: failed to write elf header.\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int write_elf64_load(DumpState *s, MemoryMapping *memory_mapping,
+                            int phdr_index, target_phys_addr_t offset)
+{
+    Elf64_Phdr phdr;
+    int ret;
+    int endian = s->dump_info.d_endian;
+
+    memset(&phdr, 0, sizeof(Elf64_Phdr));
+    phdr.p_type = cpu_convert_to_target32(PT_LOAD, endian);
+    phdr.p_offset = cpu_convert_to_target64(offset, endian);
+    phdr.p_paddr = cpu_convert_to_target64(memory_mapping->phys_addr, endian);
+    if (offset == -1) {
+        /* When the memory is not stored into vmcore, offset will be -1 */
+        phdr.p_filesz = 0;
+    } else {
+        phdr.p_filesz = cpu_convert_to_target64(memory_mapping->length, endian);
+    }
+    phdr.p_memsz = cpu_convert_to_target64(memory_mapping->length, endian);
+    phdr.p_vaddr = cpu_convert_to_target64(memory_mapping->virt_addr, endian);
+
+    ret = fd_write_vmcore(&phdr, sizeof(Elf64_Phdr), s);
+    if (ret < 0) {
+        dump_error(s, "dump: failed to write program header table.\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int write_elf32_load(DumpState *s, MemoryMapping *memory_mapping,
+                            int phdr_index, target_phys_addr_t offset)
+{
+    Elf32_Phdr phdr;
+    int ret;
+    int endian = s->dump_info.d_endian;
+
+    memset(&phdr, 0, sizeof(Elf32_Phdr));
+    phdr.p_type = cpu_convert_to_target32(PT_LOAD, endian);
+    phdr.p_offset = cpu_convert_to_target32(offset, endian);
+    phdr.p_paddr = cpu_convert_to_target32(memory_mapping->phys_addr, endian);
+    if (offset == -1) {
+        /* When the memory is not stored into vmcore, offset will be -1 */
+        phdr.p_filesz = 0;
+    } else {
+        phdr.p_filesz = cpu_convert_to_target32(memory_mapping->length, endian);
+    }
+    phdr.p_memsz = cpu_convert_to_target32(memory_mapping->length, endian);
+    phdr.p_vaddr = cpu_convert_to_target32(memory_mapping->virt_addr, endian);
+
+    ret = fd_write_vmcore(&phdr, sizeof(Elf32_Phdr), s);
+    if (ret < 0) {
+        dump_error(s, "dump: failed to write program header table.\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int write_elf64_note(DumpState *s)
+{
+    Elf64_Phdr phdr;
+    int endian = s->dump_info.d_endian;
+    target_phys_addr_t begin = s->memory_offset - s->note_size;
+    int ret;
+
+    memset(&phdr, 0, sizeof(Elf64_Phdr));
+    phdr.p_type = cpu_convert_to_target32(PT_NOTE, endian);
+    phdr.p_offset = cpu_convert_to_target64(begin, endian);
+    phdr.p_paddr = 0;
+    phdr.p_filesz = cpu_convert_to_target64(s->note_size, endian);
+    phdr.p_memsz = cpu_convert_to_target64(s->note_size, endian);
+    phdr.p_vaddr = 0;
+
+    ret = fd_write_vmcore(&phdr, sizeof(Elf64_Phdr), s);
+    if (ret < 0) {
+        dump_error(s, "dump: failed to write program header table.\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int write_elf64_notes(DumpState *s)
+{
+    CPUArchState *env;
+    int ret;
+    int id;
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        id = cpu_index(env);
+        ret = cpu_write_elf64_note(fd_write_vmcore, env, id, s);
+        if (ret < 0) {
+            dump_error(s, "dump: failed to write elf notes.\n");
+            return -1;
+        }
+    }
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        ret = cpu_write_elf64_qemunote(fd_write_vmcore, env, s);
+        if (ret < 0) {
+            dump_error(s, "dump: failed to write CPU status.\n");
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+static int write_elf32_note(DumpState *s)
+{
+    target_phys_addr_t begin = s->memory_offset - s->note_size;
+    Elf32_Phdr phdr;
+    int endian = s->dump_info.d_endian;
+    int ret;
+
+    memset(&phdr, 0, sizeof(Elf32_Phdr));
+    phdr.p_type = cpu_convert_to_target32(PT_NOTE, endian);
+    phdr.p_offset = cpu_convert_to_target32(begin, endian);
+    phdr.p_paddr = 0;
+    phdr.p_filesz = cpu_convert_to_target32(s->note_size, endian);
+    phdr.p_memsz = cpu_convert_to_target32(s->note_size, endian);
+    phdr.p_vaddr = 0;
+
+    ret = fd_write_vmcore(&phdr, sizeof(Elf32_Phdr), s);
+    if (ret < 0) {
+        dump_error(s, "dump: failed to write program header table.\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int write_elf32_notes(DumpState *s)
+{
+    CPUArchState *env;
+    int ret;
+    int id;
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        id = cpu_index(env);
+        ret = cpu_write_elf32_note(fd_write_vmcore, env, id, s);
+        if (ret < 0) {
+            dump_error(s, "dump: failed to write elf notes.\n");
+            return -1;
+        }
+    }
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        ret = cpu_write_elf32_qemunote(fd_write_vmcore, env, s);
+        if (ret < 0) {
+            dump_error(s, "dump: failed to write CPU status.\n");
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+static int write_elf_section(DumpState *s, int type)
+{
+    Elf32_Shdr shdr32;
+    Elf64_Shdr shdr64;
+    int endian = s->dump_info.d_endian;
+    int shdr_size;
+    void *shdr;
+    int ret;
+
+    if (type == 0) {
+        shdr_size = sizeof(Elf32_Shdr);
+        memset(&shdr32, 0, shdr_size);
+        shdr32.sh_info = cpu_convert_to_target32(s->sh_info, endian);
+        shdr = &shdr32;
+    } else {
+        shdr_size = sizeof(Elf64_Shdr);
+        memset(&shdr64, 0, shdr_size);
+        shdr64.sh_info = cpu_convert_to_target32(s->sh_info, endian);
+        shdr = &shdr64;
+    }
+
+    ret = fd_write_vmcore(&shdr, shdr_size, s);
+    if (ret < 0) {
+        dump_error(s, "dump: failed to write section header table.\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int write_data(DumpState *s, void *buf, int length)
+{
+    int ret;
+
+    ret = fd_write_vmcore(buf, length, s);
+    if (ret < 0) {
+        dump_error(s, "dump: failed to save memory.\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+/* write the memroy to vmcore. 1 page per I/O. */
+static int write_memory(DumpState *s, RAMBlock *block, ram_addr_t start,
+                        int64_t size)
+{
+    int64_t i;
+    int ret;
+
+    for (i = 0; i < size / TARGET_PAGE_SIZE; i++) {
+        ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE,
+                         TARGET_PAGE_SIZE);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    if ((size % TARGET_PAGE_SIZE) != 0) {
+        ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE,
+                         size % TARGET_PAGE_SIZE);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    return 0;
+}
+
+/* get the memory's offset in the vmcore */
+static target_phys_addr_t get_offset(target_phys_addr_t phys_addr,
+                                     DumpState *s)
+{
+    RAMBlock *block;
+    target_phys_addr_t offset = s->memory_offset;
+    int64_t size_in_block, start;
+
+    if (s->has_filter) {
+        if (phys_addr < s->begin || phys_addr >= s->begin + s->length) {
+            return -1;
+        }
+    }
+
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        if (s->has_filter) {
+            if (block->offset >= s->begin + s->length ||
+                block->offset + block->length <= s->begin) {
+                /* This block is out of the range */
+                continue;
+            }
+
+            if (s->begin <= block->offset) {
+                start = block->offset;
+            } else {
+                start = s->begin;
+            }
+
+            size_in_block = block->length - (start - block->offset);
+            if (s->begin + s->length < block->offset + block->length) {
+                size_in_block -= block->offset + block->length -
+                                 (s->begin + s->length);
+            }
+        } else {
+            start = block->offset;
+            size_in_block = block->length;
+        }
+
+        if (phys_addr >= start && phys_addr < start + size_in_block) {
+            return phys_addr - start + offset;
+        }
+
+        offset += size_in_block;
+    }
+
+    return -1;
+}
+
+static int write_elf_loads(DumpState *s)
+{
+    target_phys_addr_t offset;
+    MemoryMapping *memory_mapping;
+    uint32_t phdr_index = 1;
+    int ret;
+    uint32_t max_index;
+
+    if (s->have_section) {
+        max_index = s->sh_info;
+    } else {
+        max_index = s->phdr_num;
+    }
+
+    QTAILQ_FOREACH(memory_mapping, &s->list.head, next) {
+        offset = get_offset(memory_mapping->phys_addr, s);
+        if (s->dump_info.d_class == ELFCLASS64) {
+            ret = write_elf64_load(s, memory_mapping, phdr_index++, offset);
+        } else {
+            ret = write_elf32_load(s, memory_mapping, phdr_index++, offset);
+        }
+
+        if (ret < 0) {
+            return -1;
+        }
+
+        if (phdr_index >= max_index) {
+            break;
+        }
+    }
+
+    return 0;
+}
+
+/* write elf header, PT_NOTE and elf note to vmcore. */
+static int dump_begin(DumpState *s)
+{
+    int ret;
+
+    /*
+     * the vmcore's format is:
+     *   --------------
+     *   |  elf header |
+     *   --------------
+     *   |  PT_NOTE    |
+     *   --------------
+     *   |  PT_LOAD    |
+     *   --------------
+     *   |  ......     |
+     *   --------------
+     *   |  PT_LOAD    |
+     *   --------------
+     *   |  sec_hdr    |
+     *   --------------
+     *   |  elf note   |
+     *   --------------
+     *   |  memory     |
+     *   --------------
+     *
+     * we only know where the memory is saved after we write elf note into
+     * vmcore.
+     */
+
+    /* write elf header to vmcore */
+    if (s->dump_info.d_class == ELFCLASS64) {
+        ret = write_elf64_header(s);
+    } else {
+        ret = write_elf32_header(s);
+    }
+    if (ret < 0) {
+        return -1;
+    }
+
+    if (s->dump_info.d_class == ELFCLASS64) {
+        /* write PT_NOTE to vmcore */
+        if (write_elf64_note(s) < 0) {
+            return -1;
+        }
+
+        /* write all PT_LOAD to vmcore */
+        if (write_elf_loads(s) < 0) {
+            return -1;
+        }
+
+        /* write section to vmcore */
+        if (s->have_section) {
+            if (write_elf_section(s, 1) < 0) {
+                return -1;
+            }
+        }
+
+        /* write notes to vmcore */
+        if (write_elf64_notes(s) < 0) {
+            return -1;
+        }
+
+    } else {
+        /* write PT_NOTE to vmcore */
+        if (write_elf32_note(s) < 0) {
+            return -1;
+        }
+
+        /* write all PT_LOAD to vmcore */
+        if (write_elf_loads(s) < 0) {
+            return -1;
+        }
+
+        /* write section to vmcore */
+        if (s->have_section) {
+            if (write_elf_section(s, 0) < 0) {
+                return -1;
+            }
+        }
+
+        /* write notes to vmcore */
+        if (write_elf32_notes(s) < 0) {
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+/* write PT_LOAD to vmcore */
+static int dump_completed(DumpState *s)
+{
+    dump_cleanup(s);
+    return 0;
+}
+
+static int get_next_block(DumpState *s, RAMBlock *block)
+{
+    while (1) {
+        block = QLIST_NEXT(block, next);
+        if (!block) {
+            /* no more block */
+            return 1;
+        }
+
+        s->start = 0;
+        s->block = block;
+        if (s->has_filter) {
+            if (block->offset >= s->begin + s->length ||
+                block->offset + block->length <= s->begin) {
+                /* This block is out of the range */
+                continue;
+            }
+
+            if (s->begin > block->offset) {
+                s->start = s->begin - block->offset;
+            }
+        }
+
+        return 0;
+    }
+}
+
+/* write all memory to vmcore */
+static int dump_iterate(DumpState *s)
+{
+    RAMBlock *block;
+    int64_t size;
+    int ret;
+
+    while (1) {
+        block = s->block;
+
+        size = block->length;
+        if (s->has_filter) {
+            size -= s->start;
+            if (s->begin + s->length < block->offset + block->length) {
+                size -= block->offset + block->length - (s->begin + s->length);
+            }
+        }
+        ret = write_memory(s, block, s->start, size);
+        if (ret == -1) {
+            return ret;
+        }
+
+        ret = get_next_block(s, block);
+        if (ret == 1) {
+            dump_completed(s);
+            return 0;
+        }
+    }
+}
+
+static int create_vmcore(DumpState *s)
+{
+    int ret;
+
+    ret = dump_begin(s);
+    if (ret < 0) {
+        return -1;
+    }
+
+    ret = dump_iterate(s);
+    if (ret < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+static ram_addr_t get_start_block(DumpState *s)
+{
+    RAMBlock *block;
+
+    if (!s->has_filter) {
+        s->block = QLIST_FIRST(&ram_list.blocks);
+        return 0;
+    }
+
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        if (block->offset >= s->begin + s->length ||
+            block->offset + block->length <= s->begin) {
+            /* This block is out of the range */
+            continue;
+        }
+
+        s->block = block;
+        if (s->begin > block->offset) {
+            s->start = s->begin - block->offset;
+        } else {
+            s->start = 0;
+        }
+        return s->start;
+    }
+
+    return -1;
+}
+
+static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
+                     int64_t begin, int64_t length, Error **errp)
+{
+    CPUArchState *env;
+    int nr_cpus;
+    int ret;
+
+    if (runstate_is_running()) {
+        vm_stop(RUN_STATE_SAVE_VM);
+        s->resume = true;
+    } else {
+        s->resume = false;
+    }
+
+    s->errp = errp;
+    s->fd = fd;
+    s->has_filter = has_filter;
+    s->begin = begin;
+    s->length = length;
+    s->start = get_start_block(s);
+    if (s->start == -1) {
+        error_set(errp, QERR_INVALID_PARAMETER, "begin");
+        goto cleanup;
+    }
+
+    /*
+     * get dump info: endian, class and architecture.
+     * If the target architecture is not supported, cpu_get_dump_info() will
+     * return -1.
+     *
+     * if we use kvm, we should synchronize the register before we get dump
+     * info.
+     */
+    nr_cpus = 0;
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        cpu_synchronize_state(env);
+        nr_cpus++;
+    }
+
+    ret = cpu_get_dump_info(&s->dump_info);
+    if (ret < 0) {
+        error_set(errp, QERR_UNSUPPORTED);
+        goto cleanup;
+    }
+
+    /* get memory mapping */
+    memory_mapping_list_init(&s->list);
+    if (paging) {
+        qemu_get_guest_memory_mapping(&s->list);
+    } else {
+        qemu_get_guest_simple_memory_mapping(&s->list);
+    }
+
+    if (s->has_filter) {
+        memory_mapping_filter(&s->list, s->begin, s->length);
+    }
+
+    /*
+     * calculate phdr_num
+     *
+     * the type of ehdr->e_phnum is uint16_t, so we should avoid overflow
+     */
+    s->phdr_num = 1; /* PT_NOTE */
+    if (s->list.num < UINT16_MAX - 2) {
+        s->phdr_num += s->list.num;
+        s->have_section = false;
+    } else {
+        s->have_section = true;
+        s->phdr_num = PN_XNUM;
+        s->sh_info = 1; /* PT_NOTE */
+
+        /* the type of shdr->sh_info is uint32_t, so we should avoid overflow */
+        if (s->list.num <= UINT32_MAX - 1) {
+            s->sh_info += s->list.num;
+        } else {
+            s->sh_info = UINT32_MAX;
+        }
+    }
+
+    s->note_size = cpu_get_note_size(s->dump_info.d_class,
+                                     s->dump_info.d_machine, nr_cpus);
+    if (s->dump_info.d_class == ELFCLASS64) {
+        if (s->have_section) {
+            s->memory_offset = sizeof(Elf64_Ehdr) +
+                               sizeof(Elf64_Phdr) * s->sh_info +
+                               sizeof(Elf64_Shdr) + s->note_size;
+        } else {
+            s->memory_offset = sizeof(Elf64_Ehdr) +
+                               sizeof(Elf64_Phdr) * s->phdr_num + s->note_size;
+        }
+    } else {
+        if (s->have_section) {
+            s->memory_offset = sizeof(Elf32_Ehdr) +
+                               sizeof(Elf32_Phdr) * s->sh_info +
+                               sizeof(Elf32_Shdr) + s->note_size;
+        } else {
+            s->memory_offset = sizeof(Elf32_Ehdr) +
+                               sizeof(Elf32_Phdr) * s->phdr_num + s->note_size;
+        }
+    }
+
+    return 0;
+
+cleanup:
+    if (s->resume) {
+        vm_start();
+    }
+
+    return -1;
+}
+
+void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
+                           int64_t begin, bool has_length, int64_t length,
+                           Error **errp)
+{
+    const char *p;
+    int fd = -1;
+    DumpState *s;
+    int ret;
+
+    if (has_begin && !has_length) {
+        error_set(errp, QERR_MISSING_PARAMETER, "length");
+        return;
+    }
+    if (!has_begin && has_length) {
+        error_set(errp, QERR_MISSING_PARAMETER, "begin");
+        return;
+    }
+
+#if !defined(WIN32)
+    if (strstart(file, "fd:", &p)) {
+        fd = monitor_get_fd(cur_mon, p);
+        if (fd == -1) {
+            error_set(errp, QERR_FD_NOT_FOUND, p);
+            return;
+        }
+    }
+#endif
+
+    if  (strstart(file, "file:", &p)) {
+        fd = qemu_open(p, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR);
+        if (fd < 0) {
+            error_set(errp, QERR_OPEN_FILE_FAILED, p);
+            return;
+        }
+    }
+
+    if (fd == -1) {
+        error_set(errp, QERR_INVALID_PARAMETER, "protocol");
+        return;
+    }
+
+    s = g_malloc(sizeof(DumpState));
+
+    ret = dump_init(s, fd, paging, has_begin, begin, length, errp);
+    if (ret < 0) {
+        g_free(s);
+        return;
+    }
+
+    if (create_vmcore(s) < 0 && !error_is_set(s->errp)) {
+        error_set(errp, QERR_IO_ERROR);
+    }
+
+    g_free(s);
+}
+
+#else
+/* we need this function in hmp.c */
+void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
+                           int64_t begin, bool has_length, int64_t length,
+                           Error **errp)
+{
+    error_set(errp, QERR_UNSUPPORTED);
+}
+#endif
diff --git a/elf.h b/elf.h
index e1422b8..9c9acfa 100644
--- a/elf.h
+++ b/elf.h
@@ -1037,6 +1037,11 @@ typedef struct elf64_sym {
 
 #define EI_NIDENT	16
 
+/* Special value for e_phnum.  This indicates that the real number of
+   program headers is too large to fit into e_phnum.  Instead the real
+   value is in the field sh_info of section 0.  */
+#define PN_XNUM         0xffff
+
 typedef struct elf32_hdr{
   unsigned char	e_ident[EI_NIDENT];
   Elf32_Half	e_type;
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 18cb415..81723c8 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -878,6 +878,34 @@ server will ask the spice/vnc client to automatically reconnect using the
 new parameters (if specified) once the vm migration finished successfully.
 ETEXI
 
+#if defined(CONFIG_HAVE_CORE_DUMP)
+    {
+        .name       = "dump-guest-memory",
+        .args_type  = "paging:-p,protocol:s,begin:i?,length:i?",
+        .params     = "[-p] protocol [begin] [length]",
+        .help       = "dump guest memory to file"
+                      "\n\t\t\t begin(optional): the starting physical address"
+                      "\n\t\t\t length(optional): the memory size, in bytes",
+        .user_print = monitor_user_noop,
+        .mhandler.cmd = hmp_dump_guest_memory,
+    },
+
+
+STEXI
+ at item dump-guest-memory [-p] @var{protocol} @var{begin} @var{length}
+ at findex dump-guest-memory
+Dump guest memory to @var{protocol}. The file can be processed with crash or
+gdb.
+  protocol: destination file(started with "file:") or destination file
+            descriptor (started with "fd:")
+    paging: do paging to get guest's memory mapping
+     begin: the starting physical address. It's optional, and should be
+            specified with length together.
+    length: the memory size, in bytes. It's optional, and should be specified
+            with begin together.
+ETEXI
+#endif
+
     {
         .name       = "snapshot_blkdev",
         .args_type  = "reuse:-n,device:B,snapshot-file:s?,format:s?",
diff --git a/hmp.c b/hmp.c
index bb0952e..42ced2a 100644
--- a/hmp.c
+++ b/hmp.c
@@ -947,3 +947,25 @@ void hmp_device_del(Monitor *mon, const QDict *qdict)
     qmp_device_del(id, &err);
     hmp_handle_error(mon, &err);
 }
+
+void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
+{
+    Error *errp = NULL;
+    int paging = qdict_get_try_bool(qdict, "paging", 0);
+    const char *file = qdict_get_str(qdict, "protocol");
+    bool has_begin = qdict_haskey(qdict, "begin");
+    bool has_length = qdict_haskey(qdict, "length");
+    int64_t begin = 0;
+    int64_t length = 0;
+
+    if (has_begin) {
+        begin = qdict_get_int(qdict, "begin");
+    }
+    if (has_length) {
+        length = qdict_get_int(qdict, "length");
+    }
+
+    qmp_dump_guest_memory(paging, file, has_begin, begin, has_length, length,
+                          &errp);
+    hmp_handle_error(mon, &errp);
+}
diff --git a/hmp.h b/hmp.h
index 443b812..5cf3241 100644
--- a/hmp.h
+++ b/hmp.h
@@ -61,5 +61,6 @@ 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);
+void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/memory_mapping.c b/memory_mapping.c
index adb1595..8810bb0 100644
--- a/memory_mapping.c
+++ b/memory_mapping.c
@@ -220,3 +220,30 @@ void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list)
         create_new_memory_mapping(list, block->offset, 0, block->length);
     }
 }
+
+void memory_mapping_filter(MemoryMappingList *list, int64_t begin,
+                           int64_t length)
+{
+    MemoryMapping *cur, *next;
+
+    QTAILQ_FOREACH_SAFE(cur, &list->head, next, next) {
+        if (cur->phys_addr >= begin + length ||
+            cur->phys_addr + cur->length <= begin) {
+            QTAILQ_REMOVE(&list->head, cur, next);
+            list->num--;
+            continue;
+        }
+
+        if (cur->phys_addr < begin) {
+            cur->length -= begin - cur->phys_addr;
+            if (cur->virt_addr) {
+                cur->virt_addr += begin - cur->phys_addr;
+            }
+            cur->phys_addr = begin;
+        }
+
+        if (cur->phys_addr + cur->length > begin + length) {
+            cur->length -= cur->phys_addr + cur->length - begin - length;
+        }
+    }
+}
diff --git a/memory_mapping.h b/memory_mapping.h
index 190de12..a1aa64f 100644
--- a/memory_mapping.h
+++ b/memory_mapping.h
@@ -63,6 +63,9 @@ static inline int qemu_get_guest_memory_mapping(MemoryMappingList *list)
 /* get guest's memory mapping without do paging(virtual address is 0). */
 void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list);
 
+void memory_mapping_filter(MemoryMappingList *list, int64_t begin,
+                           int64_t length);
+
 #else
 
 /* We use MemoryMappingList* in cpu-all.h */
diff --git a/qapi-schema.json b/qapi-schema.json
index 2ca7195..dfa0e1f 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1755,3 +1755,46 @@
 # Since: 0.14.0
 ##
 { 'command': 'device_del', 'data': {'id': 'str'} }
+
+##
+# @dump-guest-memory
+#
+# Dump guest's memory to vmcore. It is a synchronous operation that can take
+# very long depending on the amount of guest memory. This command is only
+# supported only on i386 and x86_64
+#
+# @paging: if true, do paging to get guest's memory mapping. The @paging's
+# default value of @paging is false, If you want to use gdb to process the
+# core, please set @paging to true. The reason why the @paging's value is
+# false:
+#   1. guest machine in a catastrophic state can have corrupted memory,
+#      which we cannot trust.
+#   2. The guest machine can be in read-mode even if paging is enabled.
+#      For example: the guest machine uses ACPI to sleep, and ACPI sleep
+#      state goes in real-mode
+# @protocol: the filename or file descriptor of the vmcore. The supported
+# protocol can be file or fd:
+#   1. file: the protocol starts with "file:", and the following string is
+#      the file's path.
+#   2. fd: the protocol starts with "fd:", and the following string is the
+#      fd's name.
+# @begin: #optional if specified, the starting physical address.
+# @length: #optional if specified, the memory size, in bytes. If you don't
+# want to dump all guest's memory, please specify the start @begin and
+# @length
+#
+# Returns: nothing on success
+#          If @begin contains an invalid address, InvalidParameter
+#          If only one of @begin and @length is specified, MissingParameter
+#          If @protocol stats with "fd:", and the fd cannot be found, FdNotFound
+#          If @protocol starts with "file:", and the file cannot be
+#          opened, OpenFileFailed
+#          If @protocol does not start with "fd:" or "file:", InvalidParameter
+#          If an I/O error occurs while writing the file, IOError
+#          If the target does not support this command, Unsupported
+#
+# Since: 1.2
+##
+{ 'command': 'dump-guest-memory',
+  'data': { 'paging': 'bool', 'protocol': 'str', '*begin': 'int',
+            '*length': 'int' } }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index db980fa..2aa64ad 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -604,6 +604,42 @@ Example:
 EQMP
 
     {
+        .name       = "dump-guest-memory",
+        .args_type  = "paging:b,protocol:s,begin:i?,end:i?",
+        .params     = "-p protocol [begin] [length]",
+        .help       = "dump guest memory to file",
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = qmp_marshal_input_dump_guest_memory,
+    },
+
+SQMP
+dump
+
+
+Dump guest memory to file. The file can be processed with crash or gdb.
+
+Arguments:
+
+- "paging": do paging to get guest's memory mapping (json-bool)
+- "protocol": destination file(started with "file:") or destination file
+              descriptor (started with "fd:") (json-string)
+- "begin": the starting physical address. It's optional, and should be specified
+           with length together (json-int)
+- "length": the memory size, in bytes. It's optional, and should be specified
+            with begin together (json-int)
+
+Example:
+
+-> { "execute": "dump-guest-memory", "arguments": { "protocol": "fd:dump" } }
+<- { "return": {} }
+
+Notes:
+
+(1) All boolean arguments default to false
+
+EQMP
+
+    {
         .name       = "netdev_add",
         .args_type  = "netdev:O",
         .params     = "[user|tap|socket],id=str[,prop=value][,...]",
commit 68f4730c714b7c30ca912d7c03e199f181739da0
Author: Wen Congyang <wency at cn.fujitsu.com>
Date:   Mon May 7 12:10:05 2012 +0800

    make gdb_id() generally avialable and rename it to cpu_index()
    
    The following patch also needs this API, so make it generally avialable.
    The function gdb_id() will not be used in gdbstub.c now, so its name is
    not suitable, and rename it to cpu_index()
    
    Signed-off-by: Wen Congyang <wency at cn.fujitsu.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/gdbstub.c b/gdbstub.c
index 6a77a66..08cf864 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1937,21 +1937,12 @@ static void gdb_set_cpu_pc(GDBState *s, target_ulong pc)
 #endif
 }
 
-static inline int gdb_id(CPUArchState *env)
-{
-#if defined(CONFIG_USER_ONLY) && defined(CONFIG_USE_NPTL)
-    return env->host_tid;
-#else
-    return env->cpu_index + 1;
-#endif
-}
-
 static CPUArchState *find_cpu(uint32_t thread_id)
 {
     CPUArchState *env;
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        if (gdb_id(env) == thread_id) {
+        if (cpu_index(env) == thread_id) {
             return env;
         }
     }
@@ -1979,7 +1970,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
     case '?':
         /* TODO: Make this return the correct value for user-mode.  */
         snprintf(buf, sizeof(buf), "T%02xthread:%02x;", GDB_SIGNAL_TRAP,
-                 gdb_id(s->c_cpu));
+                 cpu_index(s->c_cpu));
         put_packet(s, buf);
         /* Remove all the breakpoints when this query is issued,
          * because gdb is doing and initial connect and the state
@@ -2274,7 +2265,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
         } else if (strcmp(p,"sThreadInfo") == 0) {
         report_cpuinfo:
             if (s->query_cpu) {
-                snprintf(buf, sizeof(buf), "m%x", gdb_id(s->query_cpu));
+                snprintf(buf, sizeof(buf), "m%x", cpu_index(s->query_cpu));
                 put_packet(s, buf);
                 s->query_cpu = s->query_cpu->next_cpu;
             } else
@@ -2422,7 +2413,7 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
             }
             snprintf(buf, sizeof(buf),
                      "T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";",
-                     GDB_SIGNAL_TRAP, gdb_id(env), type,
+                     GDB_SIGNAL_TRAP, cpu_index(env), type,
                      env->watchpoint_hit->vaddr);
             env->watchpoint_hit = NULL;
             goto send_packet;
@@ -2455,7 +2446,7 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
         ret = GDB_SIGNAL_UNKNOWN;
         break;
     }
-    snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, gdb_id(env));
+    snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, cpu_index(env));
 
 send_packet:
     put_packet(s, buf);
diff --git a/gdbstub.h b/gdbstub.h
index b44e275..668de66 100644
--- a/gdbstub.h
+++ b/gdbstub.h
@@ -30,6 +30,15 @@ void gdb_register_coprocessor(CPUArchState *env,
                               gdb_reg_cb get_reg, gdb_reg_cb set_reg,
                               int num_regs, const char *xml, int g_pos);
 
+static inline int cpu_index(CPUArchState *env)
+{
+#if defined(CONFIG_USER_ONLY) && defined(CONFIG_USE_NPTL)
+    return env->host_tid;
+#else
+    return env->cpu_index + 1;
+#endif
+}
+
 #endif
 
 #ifdef CONFIG_USER_ONLY
commit 0038ffb09692955b8f8f363958cbf58c205ae772
Author: Wen Congyang <wency at cn.fujitsu.com>
Date:   Mon May 7 12:09:36 2012 +0800

    target-i386: Add API to get note's size
    
    We should know where the note and memory is stored before writing
    them to vmcore. If we know this, we can avoid using lseek() when
    creating vmcore.
    
    Signed-off-by: Wen Congyang <wency at cn.fujitsu.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/cpu-all.h b/cpu-all.h
index 7e07c91..2b77f66 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -553,6 +553,7 @@ int cpu_write_elf64_qemunote(write_core_dump_function f, CPUArchState *env,
 int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env,
                              void *opaque);
 int cpu_get_dump_info(ArchDumpInfo *info);
+size_t cpu_get_note_size(int class, int machine, int nr_cpus);
 #else
 static inline int cpu_write_elf64_note(write_core_dump_function f,
                                        CPUArchState *env, int cpuid,
@@ -586,6 +587,11 @@ static inline int cpu_get_dump_info(ArchDumpInfo *info)
 {
     return -1;
 }
+
+static inline int cpu_get_note_size(int class, int machine, int nr_cpus)
+{
+    return -1;
+}
 #endif
 
 #endif /* CPU_ALL_H */
diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c
index e378579..135d855 100644
--- a/target-i386/arch_dump.c
+++ b/target-i386/arch_dump.c
@@ -414,3 +414,36 @@ int cpu_get_dump_info(ArchDumpInfo *info)
 
     return 0;
 }
+
+size_t cpu_get_note_size(int class, int machine, int nr_cpus)
+{
+    int name_size = 5; /* "CORE" or "QEMU" */
+    size_t elf_note_size = 0;
+    size_t qemu_note_size = 0;
+    int elf_desc_size = 0;
+    int qemu_desc_size = 0;
+    int note_head_size;
+
+    if (class == ELFCLASS32) {
+        note_head_size = sizeof(Elf32_Nhdr);
+    } else {
+        note_head_size = sizeof(Elf64_Nhdr);
+    }
+
+    if (machine == EM_386) {
+        elf_desc_size = sizeof(x86_elf_prstatus);
+    }
+#ifdef TARGET_X86_64
+    else {
+        elf_desc_size = sizeof(x86_64_elf_prstatus);
+    }
+#endif
+    qemu_desc_size = sizeof(QEMUCPUState);
+
+    elf_note_size = ((note_head_size + 3) / 4 + (name_size + 3) / 4 +
+                     (elf_desc_size + 3) / 4) * 4;
+    qemu_note_size = ((note_head_size + 3) / 4 + (name_size + 3) / 4 +
+                      (qemu_desc_size + 3) / 4) * 4;
+
+    return (elf_note_size + qemu_note_size) * nr_cpus;
+}
commit 25ae9c1d8bbfeb6c00eccb4297a5937d8375a44a
Author: Wen Congyang <wency at cn.fujitsu.com>
Date:   Mon May 7 12:08:56 2012 +0800

    target-i386: add API to get dump info
    
    Dump info contains: endian, class and architecture. The next
    patch will use these information to create vmcore. Note: on
    x86 box, the  class is ELFCLASS64 if the memory is larger than 4G.
    
    Signed-off-by: Wen Congyang <wency at cn.fujitsu.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/cpu-all.h b/cpu-all.h
index a167bac..7e07c91 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -23,6 +23,7 @@
 #include "qemu-tls.h"
 #include "cpu-common.h"
 #include "memory_mapping.h"
+#include "dump.h"
 
 /* some important defines:
  *
@@ -551,6 +552,7 @@ int cpu_write_elf64_qemunote(write_core_dump_function f, CPUArchState *env,
                              void *opaque);
 int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env,
                              void *opaque);
+int cpu_get_dump_info(ArchDumpInfo *info);
 #else
 static inline int cpu_write_elf64_note(write_core_dump_function f,
                                        CPUArchState *env, int cpuid,
@@ -579,6 +581,11 @@ static inline int cpu_write_elf32_qemunote(write_core_dump_function f,
 {
     return -1;
 }
+
+static inline int cpu_get_dump_info(ArchDumpInfo *info)
+{
+    return -1;
+}
 #endif
 
 #endif /* CPU_ALL_H */
diff --git a/dump.h b/dump.h
new file mode 100644
index 0000000..28340cf
--- /dev/null
+++ b/dump.h
@@ -0,0 +1,23 @@
+/*
+ * QEMU dump
+ *
+ * Copyright Fujitsu, Corp. 2011, 2012
+ *
+ * Authors:
+ *     Wen Congyang <wency at cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef DUMP_H
+#define DUMP_H
+
+typedef struct ArchDumpInfo {
+    int d_machine;  /* Architecture */
+    int d_endian;   /* ELFDATA2LSB or ELFDATA2MSB */
+    int d_class;    /* ELFCLASS32 or ELFCLASS64 */
+} ArchDumpInfo;
+
+#endif
diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c
index ddbe20c..e378579 100644
--- a/target-i386/arch_dump.c
+++ b/target-i386/arch_dump.c
@@ -13,6 +13,7 @@
 
 #include "cpu.h"
 #include "cpu-all.h"
+#include "dump.h"
 #include "elf.h"
 
 #ifdef TARGET_X86_64
@@ -380,3 +381,36 @@ int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env,
 {
     return cpu_write_qemu_note(f, env, opaque, 0);
 }
+
+int cpu_get_dump_info(ArchDumpInfo *info)
+{
+    bool lma = false;
+    RAMBlock *block;
+
+#ifdef TARGET_X86_64
+    lma = !!(first_cpu->hflags & HF_LMA_MASK);
+#endif
+
+    if (lma) {
+        info->d_machine = EM_X86_64;
+    } else {
+        info->d_machine = EM_386;
+    }
+    info->d_endian = ELFDATA2LSB;
+
+    if (lma) {
+        info->d_class = ELFCLASS64;
+    } else {
+        info->d_class = ELFCLASS32;
+
+        QLIST_FOREACH(block, &ram_list.blocks, next) {
+            if (block->offset + block->length > UINT_MAX) {
+                /* The memory size is greater than 4G */
+                info->d_class = ELFCLASS64;
+                break;
+            }
+        }
+    }
+
+    return 0;
+}
commit 90166b71c4d75823b48a132e9394af35b9c90aaf
Author: Wen Congyang <wency at cn.fujitsu.com>
Date:   Mon May 7 12:08:22 2012 +0800

    target-i386: Add API to write cpu status to core file
    
    The core file has register's value. But it does not include all registers value.
    Store the cpu status into QEMU note, and the user can get more information
    from vmcore. If you change QEMUCPUState, please count up QEMUCPUSTATE_VERSION.
    
    Signed-off-by: Wen Congyang <wency at cn.fujitsu.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/cpu-all.h b/cpu-all.h
index a71e887..a167bac 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -547,6 +547,10 @@ int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env,
                          int cpuid, void *opaque);
 int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env,
                          int cpuid, void *opaque);
+int cpu_write_elf64_qemunote(write_core_dump_function f, CPUArchState *env,
+                             void *opaque);
+int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env,
+                             void *opaque);
 #else
 static inline int cpu_write_elf64_note(write_core_dump_function f,
                                        CPUArchState *env, int cpuid,
@@ -561,6 +565,20 @@ static inline int cpu_write_elf32_note(write_core_dump_function f,
 {
     return -1;
 }
+
+static inline int cpu_write_elf64_qemunote(write_core_dump_function f,
+                                           CPUArchState *env,
+                                           void *opaque)
+{
+    return -1;
+}
+
+static inline int cpu_write_elf32_qemunote(write_core_dump_function f,
+                                           CPUArchState *env,
+                                           void *opaque)
+{
+    return -1;
+}
 #endif
 
 #endif /* CPU_ALL_H */
diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c
index d55c2ce..ddbe20c 100644
--- a/target-i386/arch_dump.c
+++ b/target-i386/arch_dump.c
@@ -231,3 +231,152 @@ int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env,
 
     return 0;
 }
+
+/*
+ * please count up QEMUCPUSTATE_VERSION if you have changed definition of
+ * QEMUCPUState, and modify the tools using this information accordingly.
+ */
+#define QEMUCPUSTATE_VERSION (1)
+
+struct QEMUCPUSegment {
+    uint32_t selector;
+    uint32_t limit;
+    uint32_t flags;
+    uint32_t pad;
+    uint64_t base;
+};
+
+typedef struct QEMUCPUSegment QEMUCPUSegment;
+
+struct QEMUCPUState {
+    uint32_t version;
+    uint32_t size;
+    uint64_t rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp;
+    uint64_t r8, r9, r10, r11, r12, r13, r14, r15;
+    uint64_t rip, rflags;
+    QEMUCPUSegment cs, ds, es, fs, gs, ss;
+    QEMUCPUSegment ldt, tr, gdt, idt;
+    uint64_t cr[5];
+};
+
+typedef struct QEMUCPUState QEMUCPUState;
+
+static void copy_segment(QEMUCPUSegment *d, SegmentCache *s)
+{
+    d->pad = 0;
+    d->selector = s->selector;
+    d->limit = s->limit;
+    d->flags = s->flags;
+    d->base = s->base;
+}
+
+static void qemu_get_cpustate(QEMUCPUState *s, CPUArchState *env)
+{
+    memset(s, 0, sizeof(QEMUCPUState));
+
+    s->version = QEMUCPUSTATE_VERSION;
+    s->size = sizeof(QEMUCPUState);
+
+    s->rax = env->regs[R_EAX];
+    s->rbx = env->regs[R_EBX];
+    s->rcx = env->regs[R_ECX];
+    s->rdx = env->regs[R_EDX];
+    s->rsi = env->regs[R_ESI];
+    s->rdi = env->regs[R_EDI];
+    s->rsp = env->regs[R_ESP];
+    s->rbp = env->regs[R_EBP];
+#ifdef TARGET_X86_64
+    s->r8  = env->regs[8];
+    s->r9  = env->regs[9];
+    s->r10 = env->regs[10];
+    s->r11 = env->regs[11];
+    s->r12 = env->regs[12];
+    s->r13 = env->regs[13];
+    s->r14 = env->regs[14];
+    s->r15 = env->regs[15];
+#endif
+    s->rip = env->eip;
+    s->rflags = env->eflags;
+
+    copy_segment(&s->cs, &env->segs[R_CS]);
+    copy_segment(&s->ds, &env->segs[R_DS]);
+    copy_segment(&s->es, &env->segs[R_ES]);
+    copy_segment(&s->fs, &env->segs[R_FS]);
+    copy_segment(&s->gs, &env->segs[R_GS]);
+    copy_segment(&s->ss, &env->segs[R_SS]);
+    copy_segment(&s->ldt, &env->ldt);
+    copy_segment(&s->tr, &env->tr);
+    copy_segment(&s->gdt, &env->gdt);
+    copy_segment(&s->idt, &env->idt);
+
+    s->cr[0] = env->cr[0];
+    s->cr[1] = env->cr[1];
+    s->cr[2] = env->cr[2];
+    s->cr[3] = env->cr[3];
+    s->cr[4] = env->cr[4];
+}
+
+static inline int cpu_write_qemu_note(write_core_dump_function f,
+                                      CPUArchState *env,
+                                      void *opaque,
+                                      int type)
+{
+    QEMUCPUState state;
+    Elf64_Nhdr *note64;
+    Elf32_Nhdr *note32;
+    void *note;
+    char *buf;
+    int descsz, note_size, name_size = 5, note_head_size;
+    const char *name = "QEMU";
+    int ret;
+
+    qemu_get_cpustate(&state, env);
+
+    descsz = sizeof(state);
+    if (type == 0) {
+        note_head_size = sizeof(Elf32_Nhdr);
+    } else {
+        note_head_size = sizeof(Elf64_Nhdr);
+    }
+    note_size = ((note_head_size + 3) / 4 + (name_size + 3) / 4 +
+                (descsz + 3) / 4) * 4;
+    note = g_malloc(note_size);
+
+    memset(note, 0, note_size);
+    if (type == 0) {
+        note32 = note;
+        note32->n_namesz = cpu_to_le32(name_size);
+        note32->n_descsz = cpu_to_le32(descsz);
+        note32->n_type = 0;
+    } else {
+        note64 = note;
+        note64->n_namesz = cpu_to_le32(name_size);
+        note64->n_descsz = cpu_to_le32(descsz);
+        note64->n_type = 0;
+    }
+    buf = note;
+    buf += ((note_head_size + 3) / 4) * 4;
+    memcpy(buf, name, name_size);
+    buf += ((name_size + 3) / 4) * 4;
+    memcpy(buf, &state, sizeof(state));
+
+    ret = f(note, note_size, opaque);
+    g_free(note);
+    if (ret < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+int cpu_write_elf64_qemunote(write_core_dump_function f, CPUArchState *env,
+                             void *opaque)
+{
+    return cpu_write_qemu_note(f, env, opaque, 1);
+}
+
+int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env,
+                             void *opaque)
+{
+    return cpu_write_qemu_note(f, env, opaque, 0);
+}
commit 9fecbed0c03ddad63c27f1622e2002fdfc2f45e4
Author: Wen Congyang <wency at cn.fujitsu.com>
Date:   Mon May 7 12:07:48 2012 +0800

    target-i386: Add API to write elf notes to core file
    
    The core file contains register's value. These APIs write registers to
    core file, and them will be called in the following patch.
    
    Signed-off-by: Wen Congyang <wency at cn.fujitsu.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/Makefile.target b/Makefile.target
index 18ffaef..cf05831 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -194,6 +194,7 @@ obj-$(CONFIG_VGA) += vga.o
 obj-y += memory.o savevm.o cputlb.o
 obj-y += memory_mapping.o
 obj-$(CONFIG_HAVE_GET_MEMORY_MAPPING) += arch_memory_mapping.o
+obj-$(CONFIG_HAVE_CORE_DUMP) += arch_dump.o
 LIBS+=-lz
 
 obj-i386-$(CONFIG_KVM) += hyperv.o
diff --git a/configure b/configure
index 20608c5..76dd57f 100755
--- a/configure
+++ b/configure
@@ -3748,6 +3748,10 @@ if test "$target_softmmu" = "yes" ; then
   if test "$smartcard_nss" = "yes" ; then
     echo "subdir-$target: subdir-libcacard" >> $config_host_mak
   fi
+  case "$target_arch2" in
+    i386|x86_64)
+      echo "CONFIG_HAVE_CORE_DUMP=y" >> $config_target_mak
+  esac
 fi
 if test "$target_user_only" = "yes" ; then
   echo "CONFIG_USER_ONLY=y" >> $config_target_mak
diff --git a/cpu-all.h b/cpu-all.h
index 76439b4..a71e887 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -541,4 +541,26 @@ static inline bool cpu_paging_enabled(CPUArchState *env)
 }
 #endif
 
+typedef int (*write_core_dump_function)(void *buf, size_t size, void *opaque);
+#if defined(CONFIG_HAVE_CORE_DUMP)
+int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env,
+                         int cpuid, void *opaque);
+int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env,
+                         int cpuid, void *opaque);
+#else
+static inline int cpu_write_elf64_note(write_core_dump_function f,
+                                       CPUArchState *env, int cpuid,
+                                       void *opaque)
+{
+    return -1;
+}
+
+static inline int cpu_write_elf32_note(write_core_dump_function f,
+                                       CPUArchState *env, int cpuid,
+                                       void *opaque)
+{
+    return -1;
+}
+#endif
+
 #endif /* CPU_ALL_H */
diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c
new file mode 100644
index 0000000..d55c2ce
--- /dev/null
+++ b/target-i386/arch_dump.c
@@ -0,0 +1,233 @@
+/*
+ * i386 memory mapping
+ *
+ * Copyright Fujitsu, Corp. 2011, 2012
+ *
+ * Authors:
+ *     Wen Congyang <wency at cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "cpu.h"
+#include "cpu-all.h"
+#include "elf.h"
+
+#ifdef TARGET_X86_64
+typedef struct {
+    target_ulong r15, r14, r13, r12, rbp, rbx, r11, r10;
+    target_ulong r9, r8, rax, rcx, rdx, rsi, rdi, orig_rax;
+    target_ulong rip, cs, eflags;
+    target_ulong rsp, ss;
+    target_ulong fs_base, gs_base;
+    target_ulong ds, es, fs, gs;
+} x86_64_user_regs_struct;
+
+typedef struct {
+    char pad1[32];
+    uint32_t pid;
+    char pad2[76];
+    x86_64_user_regs_struct regs;
+    char pad3[8];
+} x86_64_elf_prstatus;
+
+static int x86_64_write_elf64_note(write_core_dump_function f,
+                                   CPUArchState *env, int id,
+                                   void *opaque)
+{
+    x86_64_user_regs_struct regs;
+    Elf64_Nhdr *note;
+    char *buf;
+    int descsz, note_size, name_size = 5;
+    const char *name = "CORE";
+    int ret;
+
+    regs.r15 = env->regs[15];
+    regs.r14 = env->regs[14];
+    regs.r13 = env->regs[13];
+    regs.r12 = env->regs[12];
+    regs.r11 = env->regs[11];
+    regs.r10 = env->regs[10];
+    regs.r9  = env->regs[9];
+    regs.r8  = env->regs[8];
+    regs.rbp = env->regs[R_EBP];
+    regs.rsp = env->regs[R_ESP];
+    regs.rdi = env->regs[R_EDI];
+    regs.rsi = env->regs[R_ESI];
+    regs.rdx = env->regs[R_EDX];
+    regs.rcx = env->regs[R_ECX];
+    regs.rbx = env->regs[R_EBX];
+    regs.rax = env->regs[R_EAX];
+    regs.rip = env->eip;
+    regs.eflags = env->eflags;
+
+    regs.orig_rax = 0; /* FIXME */
+    regs.cs = env->segs[R_CS].selector;
+    regs.ss = env->segs[R_SS].selector;
+    regs.fs_base = env->segs[R_FS].base;
+    regs.gs_base = env->segs[R_GS].base;
+    regs.ds = env->segs[R_DS].selector;
+    regs.es = env->segs[R_ES].selector;
+    regs.fs = env->segs[R_FS].selector;
+    regs.gs = env->segs[R_GS].selector;
+
+    descsz = sizeof(x86_64_elf_prstatus);
+    note_size = ((sizeof(Elf64_Nhdr) + 3) / 4 + (name_size + 3) / 4 +
+                (descsz + 3) / 4) * 4;
+    note = g_malloc(note_size);
+
+    memset(note, 0, note_size);
+    note->n_namesz = cpu_to_le32(name_size);
+    note->n_descsz = cpu_to_le32(descsz);
+    note->n_type = cpu_to_le32(NT_PRSTATUS);
+    buf = (char *)note;
+    buf += ((sizeof(Elf64_Nhdr) + 3) / 4) * 4;
+    memcpy(buf, name, name_size);
+    buf += ((name_size + 3) / 4) * 4;
+    memcpy(buf + 32, &id, 4); /* pr_pid */
+    buf += descsz - sizeof(x86_64_user_regs_struct)-sizeof(target_ulong);
+    memcpy(buf, &regs, sizeof(x86_64_user_regs_struct));
+
+    ret = f(note, note_size, opaque);
+    g_free(note);
+    if (ret < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+#endif
+
+typedef struct {
+    uint32_t ebx, ecx, edx, esi, edi, ebp, eax;
+    unsigned short ds, __ds, es, __es;
+    unsigned short fs, __fs, gs, __gs;
+    uint32_t orig_eax, eip;
+    unsigned short cs, __cs;
+    uint32_t eflags, esp;
+    unsigned short ss, __ss;
+} x86_user_regs_struct;
+
+typedef struct {
+    char pad1[24];
+    uint32_t pid;
+    char pad2[44];
+    x86_user_regs_struct regs;
+    char pad3[4];
+} x86_elf_prstatus;
+
+static void x86_fill_elf_prstatus(x86_elf_prstatus *prstatus, CPUArchState *env,
+                                  int id)
+{
+    memset(prstatus, 0, sizeof(x86_elf_prstatus));
+    prstatus->regs.ebp = env->regs[R_EBP] & 0xffffffff;
+    prstatus->regs.esp = env->regs[R_ESP] & 0xffffffff;
+    prstatus->regs.edi = env->regs[R_EDI] & 0xffffffff;
+    prstatus->regs.esi = env->regs[R_ESI] & 0xffffffff;
+    prstatus->regs.edx = env->regs[R_EDX] & 0xffffffff;
+    prstatus->regs.ecx = env->regs[R_ECX] & 0xffffffff;
+    prstatus->regs.ebx = env->regs[R_EBX] & 0xffffffff;
+    prstatus->regs.eax = env->regs[R_EAX] & 0xffffffff;
+    prstatus->regs.eip = env->eip & 0xffffffff;
+    prstatus->regs.eflags = env->eflags & 0xffffffff;
+
+    prstatus->regs.cs = env->segs[R_CS].selector;
+    prstatus->regs.ss = env->segs[R_SS].selector;
+    prstatus->regs.ds = env->segs[R_DS].selector;
+    prstatus->regs.es = env->segs[R_ES].selector;
+    prstatus->regs.fs = env->segs[R_FS].selector;
+    prstatus->regs.gs = env->segs[R_GS].selector;
+
+    prstatus->pid = id;
+}
+
+static int x86_write_elf64_note(write_core_dump_function f, CPUArchState *env,
+                                int id, void *opaque)
+{
+    x86_elf_prstatus prstatus;
+    Elf64_Nhdr *note;
+    char *buf;
+    int descsz, note_size, name_size = 5;
+    const char *name = "CORE";
+    int ret;
+
+    x86_fill_elf_prstatus(&prstatus, env, id);
+    descsz = sizeof(x86_elf_prstatus);
+    note_size = ((sizeof(Elf64_Nhdr) + 3) / 4 + (name_size + 3) / 4 +
+                (descsz + 3) / 4) * 4;
+    note = g_malloc(note_size);
+
+    memset(note, 0, note_size);
+    note->n_namesz = cpu_to_le32(name_size);
+    note->n_descsz = cpu_to_le32(descsz);
+    note->n_type = cpu_to_le32(NT_PRSTATUS);
+    buf = (char *)note;
+    buf += ((sizeof(Elf64_Nhdr) + 3) / 4) * 4;
+    memcpy(buf, name, name_size);
+    buf += ((name_size + 3) / 4) * 4;
+    memcpy(buf, &prstatus, sizeof(prstatus));
+
+    ret = f(note, note_size, opaque);
+    g_free(note);
+    if (ret < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env,
+                         int cpuid, void *opaque)
+{
+    int ret;
+#ifdef TARGET_X86_64
+    bool lma = !!(first_cpu->hflags & HF_LMA_MASK);
+
+    if (lma) {
+        ret = x86_64_write_elf64_note(f, env, cpuid, opaque);
+    } else {
+#endif
+        ret = x86_write_elf64_note(f, env, cpuid, opaque);
+#ifdef TARGET_X86_64
+    }
+#endif
+
+    return ret;
+}
+
+int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env,
+                         int cpuid, void *opaque)
+{
+    x86_elf_prstatus prstatus;
+    Elf32_Nhdr *note;
+    char *buf;
+    int descsz, note_size, name_size = 5;
+    const char *name = "CORE";
+    int ret;
+
+    x86_fill_elf_prstatus(&prstatus, env, cpuid);
+    descsz = sizeof(x86_elf_prstatus);
+    note_size = ((sizeof(Elf32_Nhdr) + 3) / 4 + (name_size + 3) / 4 +
+                (descsz + 3) / 4) * 4;
+    note = g_malloc(note_size);
+
+    memset(note, 0, note_size);
+    note->n_namesz = cpu_to_le32(name_size);
+    note->n_descsz = cpu_to_le32(descsz);
+    note->n_type = cpu_to_le32(NT_PRSTATUS);
+    buf = (char *)note;
+    buf += ((sizeof(Elf32_Nhdr) + 3) / 4) * 4;
+    memcpy(buf, name, name_size);
+    buf += ((name_size + 3) / 4) * 4;
+    memcpy(buf, &prstatus, sizeof(prstatus));
+
+    ret = f(note, note_size, opaque);
+    g_free(note);
+    if (ret < 0) {
+        return -1;
+    }
+
+    return 0;
+}
commit 2b05ab5229f880720ab6ca0e52577089889c10f9
Author: Wen Congyang <wency at cn.fujitsu.com>
Date:   Mon May 7 12:07:07 2012 +0800

    Add API to get memory mapping without do paging
    
    crash does not need the virtual address and physical address mapping, and the
    mapping does not include the memory that is not referenced by the page table.
    crash does not use the virtual address, so we can create the mapping for all
    physical memory(virtual address is always 0). This patch provides a API to do
    this thing, and it will be used in the following patch.
    
    Signed-off-by: Wen Congyang <wency at cn.fujitsu.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/memory_mapping.c b/memory_mapping.c
index 627397a..adb1595 100644
--- a/memory_mapping.c
+++ b/memory_mapping.c
@@ -211,3 +211,12 @@ int qemu_get_guest_memory_mapping(MemoryMappingList *list)
     return 0;
 }
 #endif
+
+void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list)
+{
+    RAMBlock *block;
+
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        create_new_memory_mapping(list, block->offset, 0, block->length);
+    }
+}
diff --git a/memory_mapping.h b/memory_mapping.h
index 7f3c256..190de12 100644
--- a/memory_mapping.h
+++ b/memory_mapping.h
@@ -60,6 +60,9 @@ static inline int qemu_get_guest_memory_mapping(MemoryMappingList *list)
 }
 #endif
 
+/* get guest's memory mapping without do paging(virtual address is 0). */
+void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list);
+
 #else
 
 /* We use MemoryMappingList* in cpu-all.h */
commit c517076dae5540241a5d8947471b46fe3248f6cd
Author: Wen Congyang <wency at cn.fujitsu.com>
Date:   Mon May 7 12:06:40 2012 +0800

    Add API to get memory mapping
    
    Add API to get all virtual address and physical address mapping.
    If the guest doesn't use paging, the virtual address is equal to the phyical
    address. The virtual address and physical address mapping is for gdb's user, and
    it does not include the memory that is not referenced by the page table. So if
    you want to use crash to anaylze the vmcore, please do not specify -p option.
    the reason why the -p option is not default explicitly: guest machine in a
    catastrophic state can have corrupted memory, which we cannot trust.
    
    Signed-off-by: Wen Congyang <wency at cn.fujitsu.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/memory_mapping.c b/memory_mapping.c
index 718f271..627397a 100644
--- a/memory_mapping.c
+++ b/memory_mapping.c
@@ -164,3 +164,50 @@ void memory_mapping_list_init(MemoryMappingList *list)
     list->last_mapping = NULL;
     QTAILQ_INIT(&list->head);
 }
+
+#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING)
+
+static CPUArchState *find_paging_enabled_cpu(CPUArchState *start_cpu)
+{
+    CPUArchState *env;
+
+    for (env = start_cpu; env != NULL; env = env->next_cpu) {
+        if (cpu_paging_enabled(env)) {
+            return env;
+        }
+    }
+
+    return NULL;
+}
+
+int qemu_get_guest_memory_mapping(MemoryMappingList *list)
+{
+    CPUArchState *env, *first_paging_enabled_cpu;
+    RAMBlock *block;
+    ram_addr_t offset, length;
+    int ret;
+
+    first_paging_enabled_cpu = find_paging_enabled_cpu(first_cpu);
+    if (first_paging_enabled_cpu) {
+        for (env = first_paging_enabled_cpu; env != NULL; env = env->next_cpu) {
+            ret = cpu_get_memory_mapping(list, env);
+            if (ret < 0) {
+                return -1;
+            }
+        }
+        return 0;
+    }
+
+    /*
+     * If the guest doesn't use paging, the virtual address is equal to physical
+     * address.
+     */
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        offset = block->offset;
+        length = block->length;
+        create_new_memory_mapping(list, offset, offset, length);
+    }
+
+    return 0;
+}
+#endif
diff --git a/memory_mapping.h b/memory_mapping.h
index e486d10..7f3c256 100644
--- a/memory_mapping.h
+++ b/memory_mapping.h
@@ -45,6 +45,21 @@ void memory_mapping_list_free(MemoryMappingList *list);
 
 void memory_mapping_list_init(MemoryMappingList *list);
 
+/*
+ * Return value:
+ *    0: success
+ *   -1: failed
+ *   -2: unsupported
+ */
+#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING)
+int qemu_get_guest_memory_mapping(MemoryMappingList *list);
+#else
+static inline int qemu_get_guest_memory_mapping(MemoryMappingList *list)
+{
+    return -2;
+}
+#endif
+
 #else
 
 /* We use MemoryMappingList* in cpu-all.h */
commit 31a2207a8e1c39bcf88e527ac62f4e12316920a4
Author: Wen Congyang <wency at cn.fujitsu.com>
Date:   Mon May 7 12:05:42 2012 +0800

    Add API to check whether paging mode is enabled
    
    This API will be used in the following patch.
    
    Signed-off-by: Wen Congyang <wency at cn.fujitsu.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/cpu-all.h b/cpu-all.h
index 2688bac..76439b4 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -527,12 +527,18 @@ int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr,
 
 #if defined(CONFIG_HAVE_GET_MEMORY_MAPPING)
 int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env);
+bool cpu_paging_enabled(CPUArchState *env);
 #else
 static inline int cpu_get_memory_mapping(MemoryMappingList *list,
                                          CPUArchState *env)
 {
     return -1;
 }
+
+static inline bool cpu_paging_enabled(CPUArchState *env)
+{
+    return true;
+}
 #endif
 
 #endif /* CPU_ALL_H */
diff --git a/target-i386/arch_memory_mapping.c b/target-i386/arch_memory_mapping.c
index dd64bec..bd50e11 100644
--- a/target-i386/arch_memory_mapping.c
+++ b/target-i386/arch_memory_mapping.c
@@ -233,7 +233,7 @@ static void walk_pml4e(MemoryMappingList *list,
 
 int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env)
 {
-    if (!(env->cr[0] & CR0_PG_MASK)) {
+    if (!cpu_paging_enabled(env)) {
         /* paging is disabled */
         return 0;
     }
@@ -264,3 +264,8 @@ int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env)
 
     return 0;
 }
+
+bool cpu_paging_enabled(CPUArchState *env)
+{
+    return env->cr[0] & CR0_PG_MASK;
+}
commit fae001f55190b4de511269ca63eb635646d1c7c9
Author: Wen Congyang <wency at cn.fujitsu.com>
Date:   Mon May 7 12:04:57 2012 +0800

    implement cpu_get_memory_mapping()
    
    Walk cpu's page table and collect all virtual address and physical address mapping.
    Then, add these mapping into memory mapping list. If the guest does not use paging,
    it will do nothing. Note: the I/O memory will be skipped.
    
    Signed-off-by: Wen Congyang <wency at cn.fujitsu.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/Makefile.target b/Makefile.target
index 005fc49..18ffaef 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -193,6 +193,7 @@ obj-$(CONFIG_NO_KVM) += kvm-stub.o
 obj-$(CONFIG_VGA) += vga.o
 obj-y += memory.o savevm.o cputlb.o
 obj-y += memory_mapping.o
+obj-$(CONFIG_HAVE_GET_MEMORY_MAPPING) += arch_memory_mapping.o
 LIBS+=-lz
 
 obj-i386-$(CONFIG_KVM) += hyperv.o
diff --git a/configure b/configure
index 1f338f8..20608c5 100755
--- a/configure
+++ b/configure
@@ -3729,6 +3729,10 @@ case "$target_arch2" in
       fi
     fi
 esac
+case "$target_arch2" in
+  i386|x86_64)
+    echo "CONFIG_HAVE_GET_MEMORY_MAPPING=y" >> $config_target_mak
+esac
 if test "$target_arch2" = "ppc64" -a "$fdt" = "yes"; then
   echo "CONFIG_PSERIES=y" >> $config_target_mak
 fi
diff --git a/cpu-all.h b/cpu-all.h
index 028528f..2688bac 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -22,6 +22,7 @@
 #include "qemu-common.h"
 #include "qemu-tls.h"
 #include "cpu-common.h"
+#include "memory_mapping.h"
 
 /* some important defines:
  *
@@ -524,4 +525,14 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf);
 int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr,
                         uint8_t *buf, int len, int is_write);
 
+#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING)
+int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env);
+#else
+static inline int cpu_get_memory_mapping(MemoryMappingList *list,
+                                         CPUArchState *env)
+{
+    return -1;
+}
+#endif
+
 #endif /* CPU_ALL_H */
diff --git a/memory_mapping.h b/memory_mapping.h
index 836b047..e486d10 100644
--- a/memory_mapping.h
+++ b/memory_mapping.h
@@ -16,6 +16,7 @@
 
 #include "qemu-queue.h"
 
+#ifndef CONFIG_USER_ONLY
 /* The physical and virtual address in the memory mapping are contiguous. */
 typedef struct MemoryMapping {
     target_phys_addr_t phys_addr;
@@ -44,4 +45,9 @@ void memory_mapping_list_free(MemoryMappingList *list);
 
 void memory_mapping_list_init(MemoryMappingList *list);
 
+#else
+
+/* We use MemoryMappingList* in cpu-all.h */
+typedef struct MemoryMappingList MemoryMappingList;
+#endif
 #endif
diff --git a/target-i386/arch_memory_mapping.c b/target-i386/arch_memory_mapping.c
new file mode 100644
index 0000000..dd64bec
--- /dev/null
+++ b/target-i386/arch_memory_mapping.c
@@ -0,0 +1,266 @@
+/*
+ * i386 memory mapping
+ *
+ * Copyright Fujitsu, Corp. 2011, 2012
+ *
+ * Authors:
+ *     Wen Congyang <wency at cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "cpu.h"
+#include "cpu-all.h"
+
+/* PAE Paging or IA-32e Paging */
+static void walk_pte(MemoryMappingList *list, target_phys_addr_t pte_start_addr,
+                     int32_t a20_mask, target_ulong start_line_addr)
+{
+    target_phys_addr_t pte_addr, start_paddr;
+    uint64_t pte;
+    target_ulong start_vaddr;
+    int i;
+
+    for (i = 0; i < 512; i++) {
+        pte_addr = (pte_start_addr + i * 8) & a20_mask;
+        pte = ldq_phys(pte_addr);
+        if (!(pte & PG_PRESENT_MASK)) {
+            /* not present */
+            continue;
+        }
+
+        start_paddr = (pte & ~0xfff) & ~(0x1ULL << 63);
+        if (cpu_physical_memory_is_io(start_paddr)) {
+            /* I/O region */
+            continue;
+        }
+
+        start_vaddr = start_line_addr | ((i & 0x1fff) << 12);
+        memory_mapping_list_add_merge_sorted(list, start_paddr,
+                                             start_vaddr, 1 << 12);
+    }
+}
+
+/* 32-bit Paging */
+static void walk_pte2(MemoryMappingList *list,
+                      target_phys_addr_t pte_start_addr, int32_t a20_mask,
+                      target_ulong start_line_addr)
+{
+    target_phys_addr_t pte_addr, start_paddr;
+    uint32_t pte;
+    target_ulong start_vaddr;
+    int i;
+
+    for (i = 0; i < 1024; i++) {
+        pte_addr = (pte_start_addr + i * 4) & a20_mask;
+        pte = ldl_phys(pte_addr);
+        if (!(pte & PG_PRESENT_MASK)) {
+            /* not present */
+            continue;
+        }
+
+        start_paddr = pte & ~0xfff;
+        if (cpu_physical_memory_is_io(start_paddr)) {
+            /* I/O region */
+            continue;
+        }
+
+        start_vaddr = start_line_addr | ((i & 0x3ff) << 12);
+        memory_mapping_list_add_merge_sorted(list, start_paddr,
+                                             start_vaddr, 1 << 12);
+    }
+}
+
+/* PAE Paging or IA-32e Paging */
+static void walk_pde(MemoryMappingList *list, target_phys_addr_t pde_start_addr,
+                     int32_t a20_mask, target_ulong start_line_addr)
+{
+    target_phys_addr_t pde_addr, pte_start_addr, start_paddr;
+    uint64_t pde;
+    target_ulong line_addr, start_vaddr;
+    int i;
+
+    for (i = 0; i < 512; i++) {
+        pde_addr = (pde_start_addr + i * 8) & a20_mask;
+        pde = ldq_phys(pde_addr);
+        if (!(pde & PG_PRESENT_MASK)) {
+            /* not present */
+            continue;
+        }
+
+        line_addr = start_line_addr | ((i & 0x1ff) << 21);
+        if (pde & PG_PSE_MASK) {
+            /* 2 MB page */
+            start_paddr = (pde & ~0x1fffff) & ~(0x1ULL << 63);
+            if (cpu_physical_memory_is_io(start_paddr)) {
+                /* I/O region */
+                continue;
+            }
+            start_vaddr = line_addr;
+            memory_mapping_list_add_merge_sorted(list, start_paddr,
+                                                 start_vaddr, 1 << 21);
+            continue;
+        }
+
+        pte_start_addr = (pde & ~0xfff) & a20_mask;
+        walk_pte(list, pte_start_addr, a20_mask, line_addr);
+    }
+}
+
+/* 32-bit Paging */
+static void walk_pde2(MemoryMappingList *list,
+                      target_phys_addr_t pde_start_addr, int32_t a20_mask,
+                      bool pse)
+{
+    target_phys_addr_t pde_addr, pte_start_addr, start_paddr;
+    uint32_t pde;
+    target_ulong line_addr, start_vaddr;
+    int i;
+
+    for (i = 0; i < 1024; i++) {
+        pde_addr = (pde_start_addr + i * 4) & a20_mask;
+        pde = ldl_phys(pde_addr);
+        if (!(pde & PG_PRESENT_MASK)) {
+            /* not present */
+            continue;
+        }
+
+        line_addr = (((unsigned int)i & 0x3ff) << 22);
+        if ((pde & PG_PSE_MASK) && pse) {
+            /* 4 MB page */
+            start_paddr = (pde & ~0x3fffff) | ((pde & 0x1fe000) << 19);
+            if (cpu_physical_memory_is_io(start_paddr)) {
+                /* I/O region */
+                continue;
+            }
+            start_vaddr = line_addr;
+            memory_mapping_list_add_merge_sorted(list, start_paddr,
+                                                 start_vaddr, 1 << 22);
+            continue;
+        }
+
+        pte_start_addr = (pde & ~0xfff) & a20_mask;
+        walk_pte2(list, pte_start_addr, a20_mask, line_addr);
+    }
+}
+
+/* PAE Paging */
+static void walk_pdpe2(MemoryMappingList *list,
+                       target_phys_addr_t pdpe_start_addr, int32_t a20_mask)
+{
+    target_phys_addr_t pdpe_addr, pde_start_addr;
+    uint64_t pdpe;
+    target_ulong line_addr;
+    int i;
+
+    for (i = 0; i < 4; i++) {
+        pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask;
+        pdpe = ldq_phys(pdpe_addr);
+        if (!(pdpe & PG_PRESENT_MASK)) {
+            /* not present */
+            continue;
+        }
+
+        line_addr = (((unsigned int)i & 0x3) << 30);
+        pde_start_addr = (pdpe & ~0xfff) & a20_mask;
+        walk_pde(list, pde_start_addr, a20_mask, line_addr);
+    }
+}
+
+#ifdef TARGET_X86_64
+/* IA-32e Paging */
+static void walk_pdpe(MemoryMappingList *list,
+                      target_phys_addr_t pdpe_start_addr, int32_t a20_mask,
+                      target_ulong start_line_addr)
+{
+    target_phys_addr_t pdpe_addr, pde_start_addr, start_paddr;
+    uint64_t pdpe;
+    target_ulong line_addr, start_vaddr;
+    int i;
+
+    for (i = 0; i < 512; i++) {
+        pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask;
+        pdpe = ldq_phys(pdpe_addr);
+        if (!(pdpe & PG_PRESENT_MASK)) {
+            /* not present */
+            continue;
+        }
+
+        line_addr = start_line_addr | ((i & 0x1ffULL) << 30);
+        if (pdpe & PG_PSE_MASK) {
+            /* 1 GB page */
+            start_paddr = (pdpe & ~0x3fffffff) & ~(0x1ULL << 63);
+            if (cpu_physical_memory_is_io(start_paddr)) {
+                /* I/O region */
+                continue;
+            }
+            start_vaddr = line_addr;
+            memory_mapping_list_add_merge_sorted(list, start_paddr,
+                                                 start_vaddr, 1 << 30);
+            continue;
+        }
+
+        pde_start_addr = (pdpe & ~0xfff) & a20_mask;
+        walk_pde(list, pde_start_addr, a20_mask, line_addr);
+    }
+}
+
+/* IA-32e Paging */
+static void walk_pml4e(MemoryMappingList *list,
+                       target_phys_addr_t pml4e_start_addr, int32_t a20_mask)
+{
+    target_phys_addr_t pml4e_addr, pdpe_start_addr;
+    uint64_t pml4e;
+    target_ulong line_addr;
+    int i;
+
+    for (i = 0; i < 512; i++) {
+        pml4e_addr = (pml4e_start_addr + i * 8) & a20_mask;
+        pml4e = ldq_phys(pml4e_addr);
+        if (!(pml4e & PG_PRESENT_MASK)) {
+            /* not present */
+            continue;
+        }
+
+        line_addr = ((i & 0x1ffULL) << 39) | (0xffffULL << 48);
+        pdpe_start_addr = (pml4e & ~0xfff) & a20_mask;
+        walk_pdpe(list, pdpe_start_addr, a20_mask, line_addr);
+    }
+}
+#endif
+
+int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env)
+{
+    if (!(env->cr[0] & CR0_PG_MASK)) {
+        /* paging is disabled */
+        return 0;
+    }
+
+    if (env->cr[4] & CR4_PAE_MASK) {
+#ifdef TARGET_X86_64
+        if (env->hflags & HF_LMA_MASK) {
+            target_phys_addr_t pml4e_addr;
+
+            pml4e_addr = (env->cr[3] & ~0xfff) & env->a20_mask;
+            walk_pml4e(list, pml4e_addr, env->a20_mask);
+        } else
+#endif
+        {
+            target_phys_addr_t pdpe_addr;
+
+            pdpe_addr = (env->cr[3] & ~0x1f) & env->a20_mask;
+            walk_pdpe2(list, pdpe_addr, env->a20_mask);
+        }
+    } else {
+        target_phys_addr_t pde_addr;
+        bool pse;
+
+        pde_addr = (env->cr[3] & ~0xfff) & env->a20_mask;
+        pse = !!(env->cr[4] & CR4_PSE_MASK);
+        walk_pde2(list, pde_addr, env->a20_mask, pse);
+    }
+
+    return 0;
+}
commit 76f3553883b868e99c78212b9d12309e8e1e5d81
Author: Wen Congyang <wency at cn.fujitsu.com>
Date:   Mon May 7 12:04:18 2012 +0800

    Add API to check whether a physical address is I/O address
    
    This API will be used in the following patch.
    
    Signed-off-by: Wen Congyang <wency at cn.fujitsu.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/cpu-common.h b/cpu-common.h
index dca5175..1fe3280 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -71,6 +71,10 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
 void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque));
 void cpu_unregister_map_client(void *cookie);
 
+#ifndef CONFIG_USER_ONLY
+bool cpu_physical_memory_is_io(target_phys_addr_t phys_addr);
+#endif
+
 /* Coalesced MMIO regions are areas where write operations can be reordered.
  * This usually implies that write operations are side-effect free.  This allows
  * batching which can make a major impact on performance when using
diff --git a/exec.c b/exec.c
index a0494c7..1b65859 100644
--- a/exec.c
+++ b/exec.c
@@ -4336,3 +4336,15 @@ bool virtio_is_big_endian(void)
 }
 
 #endif
+
+#ifndef CONFIG_USER_ONLY
+bool cpu_physical_memory_is_io(target_phys_addr_t phys_addr)
+{
+    MemoryRegionSection *section;
+
+    section = phys_page_find(phys_addr >> TARGET_PAGE_BITS);
+
+    return !(memory_region_is_ram(section->mr) ||
+             memory_region_is_romd(section->mr));
+}
+#endif
commit 80167a8a31d7c42e3e33ec23592eb14938c88098
Author: Wen Congyang <wency at cn.fujitsu.com>
Date:   Mon May 7 12:03:46 2012 +0800

    Add API to create memory mapping list
    
    The memory mapping list stores virtual address and physical address mapping.
    The virtual address and physical address are contiguous in the mapping.
    The folloing patch will use this information to create PT_LOAD in the vmcore.
    
    Signed-off-by: Wen Congyang <wency at cn.fujitsu.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/Makefile.target b/Makefile.target
index 1582904..005fc49 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -192,6 +192,7 @@ obj-$(CONFIG_KVM) += kvm.o kvm-all.o
 obj-$(CONFIG_NO_KVM) += kvm-stub.o
 obj-$(CONFIG_VGA) += vga.o
 obj-y += memory.o savevm.o cputlb.o
+obj-y += memory_mapping.o
 LIBS+=-lz
 
 obj-i386-$(CONFIG_KVM) += hyperv.o
diff --git a/memory_mapping.c b/memory_mapping.c
new file mode 100644
index 0000000..718f271
--- /dev/null
+++ b/memory_mapping.c
@@ -0,0 +1,166 @@
+/*
+ * QEMU memory mapping
+ *
+ * Copyright Fujitsu, Corp. 2011, 2012
+ *
+ * Authors:
+ *     Wen Congyang <wency at cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "cpu.h"
+#include "cpu-all.h"
+#include "memory_mapping.h"
+
+static void memory_mapping_list_add_mapping_sorted(MemoryMappingList *list,
+                                                   MemoryMapping *mapping)
+{
+    MemoryMapping *p;
+
+    QTAILQ_FOREACH(p, &list->head, next) {
+        if (p->phys_addr >= mapping->phys_addr) {
+            QTAILQ_INSERT_BEFORE(p, mapping, next);
+            return;
+        }
+    }
+    QTAILQ_INSERT_TAIL(&list->head, mapping, next);
+}
+
+static void create_new_memory_mapping(MemoryMappingList *list,
+                                      target_phys_addr_t phys_addr,
+                                      target_phys_addr_t virt_addr,
+                                      ram_addr_t length)
+{
+    MemoryMapping *memory_mapping;
+
+    memory_mapping = g_malloc(sizeof(MemoryMapping));
+    memory_mapping->phys_addr = phys_addr;
+    memory_mapping->virt_addr = virt_addr;
+    memory_mapping->length = length;
+    list->last_mapping = memory_mapping;
+    list->num++;
+    memory_mapping_list_add_mapping_sorted(list, memory_mapping);
+}
+
+static inline bool mapping_contiguous(MemoryMapping *map,
+                                      target_phys_addr_t phys_addr,
+                                      target_phys_addr_t virt_addr)
+{
+    return phys_addr == map->phys_addr + map->length &&
+           virt_addr == map->virt_addr + map->length;
+}
+
+/*
+ * [map->phys_addr, map->phys_addr + map->length) and
+ * [phys_addr, phys_addr + length) have intersection?
+ */
+static inline bool mapping_have_same_region(MemoryMapping *map,
+                                            target_phys_addr_t phys_addr,
+                                            ram_addr_t length)
+{
+    return !(phys_addr + length < map->phys_addr ||
+             phys_addr >= map->phys_addr + map->length);
+}
+
+/*
+ * [map->phys_addr, map->phys_addr + map->length) and
+ * [phys_addr, phys_addr + length) have intersection. The virtual address in the
+ * intersection are the same?
+ */
+static inline bool mapping_conflict(MemoryMapping *map,
+                                    target_phys_addr_t phys_addr,
+                                    target_phys_addr_t virt_addr)
+{
+    return virt_addr - map->virt_addr != phys_addr - map->phys_addr;
+}
+
+/*
+ * [map->virt_addr, map->virt_addr + map->length) and
+ * [virt_addr, virt_addr + length) have intersection. And the physical address
+ * in the intersection are the same.
+ */
+static inline void mapping_merge(MemoryMapping *map,
+                                 target_phys_addr_t virt_addr,
+                                 ram_addr_t length)
+{
+    if (virt_addr < map->virt_addr) {
+        map->length += map->virt_addr - virt_addr;
+        map->virt_addr = virt_addr;
+    }
+
+    if ((virt_addr + length) >
+        (map->virt_addr + map->length)) {
+        map->length = virt_addr + length - map->virt_addr;
+    }
+}
+
+void memory_mapping_list_add_merge_sorted(MemoryMappingList *list,
+                                          target_phys_addr_t phys_addr,
+                                          target_phys_addr_t virt_addr,
+                                          ram_addr_t length)
+{
+    MemoryMapping *memory_mapping, *last_mapping;
+
+    if (QTAILQ_EMPTY(&list->head)) {
+        create_new_memory_mapping(list, phys_addr, virt_addr, length);
+        return;
+    }
+
+    last_mapping = list->last_mapping;
+    if (last_mapping) {
+        if (mapping_contiguous(last_mapping, phys_addr, virt_addr)) {
+            last_mapping->length += length;
+            return;
+        }
+    }
+
+    QTAILQ_FOREACH(memory_mapping, &list->head, next) {
+        if (mapping_contiguous(memory_mapping, phys_addr, virt_addr)) {
+            memory_mapping->length += length;
+            list->last_mapping = memory_mapping;
+            return;
+        }
+
+        if (phys_addr + length < memory_mapping->phys_addr) {
+            /* create a new region before memory_mapping */
+            break;
+        }
+
+        if (mapping_have_same_region(memory_mapping, phys_addr, length)) {
+            if (mapping_conflict(memory_mapping, phys_addr, virt_addr)) {
+                continue;
+            }
+
+            /* merge this region into memory_mapping */
+            mapping_merge(memory_mapping, virt_addr, length);
+            list->last_mapping = memory_mapping;
+            return;
+        }
+    }
+
+    /* this region can not be merged into any existed memory mapping. */
+    create_new_memory_mapping(list, phys_addr, virt_addr, length);
+}
+
+void memory_mapping_list_free(MemoryMappingList *list)
+{
+    MemoryMapping *p, *q;
+
+    QTAILQ_FOREACH_SAFE(p, &list->head, next, q) {
+        QTAILQ_REMOVE(&list->head, p, next);
+        g_free(p);
+    }
+
+    list->num = 0;
+    list->last_mapping = NULL;
+}
+
+void memory_mapping_list_init(MemoryMappingList *list)
+{
+    list->num = 0;
+    list->last_mapping = NULL;
+    QTAILQ_INIT(&list->head);
+}
diff --git a/memory_mapping.h b/memory_mapping.h
new file mode 100644
index 0000000..836b047
--- /dev/null
+++ b/memory_mapping.h
@@ -0,0 +1,47 @@
+/*
+ * QEMU memory mapping
+ *
+ * Copyright Fujitsu, Corp. 2011, 2012
+ *
+ * Authors:
+ *     Wen Congyang <wency at cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef MEMORY_MAPPING_H
+#define MEMORY_MAPPING_H
+
+#include "qemu-queue.h"
+
+/* The physical and virtual address in the memory mapping are contiguous. */
+typedef struct MemoryMapping {
+    target_phys_addr_t phys_addr;
+    target_ulong virt_addr;
+    ram_addr_t length;
+    QTAILQ_ENTRY(MemoryMapping) next;
+} MemoryMapping;
+
+typedef struct MemoryMappingList {
+    unsigned int num;
+    MemoryMapping *last_mapping;
+    QTAILQ_HEAD(, MemoryMapping) head;
+} MemoryMappingList;
+
+/*
+ * add or merge the memory region [phys_addr, phys_addr + length) into the
+ * memory mapping's list. The region's virtual address starts with virt_addr,
+ * and is contiguous. The list is sorted by phys_addr.
+ */
+void memory_mapping_list_add_merge_sorted(MemoryMappingList *list,
+                                          target_phys_addr_t phys_addr,
+                                          target_phys_addr_t virt_addr,
+                                          ram_addr_t length);
+
+void memory_mapping_list_free(MemoryMappingList *list);
+
+void memory_mapping_list_init(MemoryMappingList *list);
+
+#endif
commit 8cc9b43f7c5f826b39af4b012ad89bb55faac29c
Author: Peter A. G. Crosthwaite <peter.crosthwaite at petalogix.com>
Date:   Fri Jun 1 13:23:28 2012 +1000

    target-microblaze: lwx/swx: first implementation
    
    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/cpu.c b/target-microblaze/cpu.c
index 9c3b74e..34b3a9b 100644
--- a/target-microblaze/cpu.c
+++ b/target-microblaze/cpu.c
@@ -39,6 +39,7 @@ static void mb_cpu_reset(CPUState *s)
     mcc->parent_reset(s);
 
     memset(env, 0, offsetof(CPUMBState, breakpoints));
+    env->res_addr = RES_ADDR_NONE;
     tlb_flush(env, 1);
 
     /* Disable stack protector.  */
diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index 718d5bb..b0ba9fe 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -243,6 +243,10 @@ struct CPUMBState {
     /* Stack protectors. Yes, it's a hw feature.  */
     uint32_t slr, shr;
 
+    /* lwx/swx reserved address */
+#define RES_ADDR_NONE 0xffffffff /* Use 0xffffffff to indicate no reservation */
+    uint32_t res_addr;
+
     /* Internal flags.  */
 #define IMM_FLAG	4
 #define MSR_EE_FLAG     (1 << 8)
diff --git a/target-microblaze/helper.c b/target-microblaze/helper.c
index 2412a58..74fce26 100644
--- a/target-microblaze/helper.c
+++ b/target-microblaze/helper.c
@@ -29,6 +29,7 @@
 void do_interrupt (CPUMBState *env)
 {
     env->exception_index = -1;
+    env->res_addr = RES_ADDR_NONE;
     env->regs[14] = env->sregs[SR_PC];
 }
 
@@ -116,6 +117,7 @@ void do_interrupt(CPUMBState *env)
     assert(!((env->iflags & D_FLAG) && (env->iflags & IMM_FLAG)));
     assert(!(env->iflags & (DRTI_FLAG | DRTE_FLAG | DRTB_FLAG)));
 /*    assert(env->sregs[SR_MSR] & (MSR_EE)); Only for HW exceptions.  */
+    env->res_addr = RES_ADDR_NONE;
     switch (env->exception_index) {
         case EXCP_HW_EXCP:
             if (!(env->pvr.regs[0] & PVR0_USE_EXC_MASK)) {
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index a362938..f0ebd59 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -162,6 +162,14 @@ static void write_carry(DisasContext *dc, TCGv v)
     tcg_temp_free(t0);
 }
 
+static void write_carryi(DisasContext *dc, int carry)
+{
+    TCGv t0 = tcg_temp_new();
+    tcg_gen_movi_tl(t0, carry ? 1 : 0);
+    write_carry(dc, t0);
+    tcg_temp_free(t0);
+}
+
 /* True if ALU operand b is a small immediate that may deserve
    faster treatment.  */
 static inline int dec_alu_op_b_is_small_imm(DisasContext *dc)
@@ -948,12 +956,13 @@ static inline void dec_byteswap(DisasContext *dc, TCGv dst, TCGv src, int size)
 static void dec_load(DisasContext *dc)
 {
     TCGv t, *addr;
-    unsigned int size, rev = 0;
+    unsigned int size, rev = 0, ex = 0;
 
     size = 1 << (dc->opcode & 3);
 
     if (!dc->type_b) {
         rev = (dc->ir >> 9) & 1;
+        ex = (dc->ir >> 10) & 1;
     }
 
     if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
@@ -963,7 +972,8 @@ static void dec_load(DisasContext *dc)
         return;
     }
 
-    LOG_DIS("l%d%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "");
+    LOG_DIS("l%d%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "",
+                                                        ex ? "x" : "");
 
     t_sync_flags(dc);
     addr = compute_ldst_addr(dc, &t);
@@ -1019,6 +1029,17 @@ static void dec_load(DisasContext *dc)
         }
     }
 
+    /* lwx does not throw unaligned access errors, so force alignment */
+    if (ex) {
+        /* Force addr into the temp.  */
+        if (addr != &t) {
+            t = tcg_temp_new();
+            tcg_gen_mov_tl(t, *addr);
+            addr = &t;
+        }
+        tcg_gen_andi_tl(t, t, ~3);
+    }
+
     /* If we get a fault on a dslot, the jmpstate better be in sync.  */
     sync_jmpstate(dc);
 
@@ -1057,6 +1078,12 @@ static void dec_load(DisasContext *dc)
         }
     }
 
+    if (ex) { /* lwx */
+        /* no support for for AXI exclusive so always clear C */
+        write_carryi(dc, 0);
+        tcg_gen_st_tl(*addr, cpu_env, offsetof(CPUMBState, res_addr));
+    }
+
     if (addr == &t)
         tcg_temp_free(t);
 }
@@ -1078,12 +1105,14 @@ static void gen_store(DisasContext *dc, TCGv addr, TCGv val,
 
 static void dec_store(DisasContext *dc)
 {
-    TCGv t, *addr;
-    unsigned int size, rev = 0;
+    TCGv t, *addr, swx_addr, r_check = 0;
+    int swx_skip = 0;
+    unsigned int size, rev = 0, ex = 0;
 
     size = 1 << (dc->opcode & 3);
     if (!dc->type_b) {
         rev = (dc->ir >> 9) & 1;
+        ex = (dc->ir >> 10) & 1;
     }
 
     if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
@@ -1093,12 +1122,30 @@ static void dec_store(DisasContext *dc)
         return;
     }
 
-    LOG_DIS("s%d%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "");
+    LOG_DIS("s%d%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "",
+                                                        ex ? "x" : "");
     t_sync_flags(dc);
     /* If we get a fault on a dslot, the jmpstate better be in sync.  */
     sync_jmpstate(dc);
     addr = compute_ldst_addr(dc, &t);
 
+    if (ex) { /* swx */
+        r_check = tcg_temp_new();
+        swx_addr = tcg_temp_local_new();
+
+        /* Force addr into the swx_addr. */
+        tcg_gen_mov_tl(swx_addr, *addr);
+        addr = &swx_addr;
+        /* swx does not throw unaligned access errors, so force alignment */
+        tcg_gen_andi_tl(swx_addr, swx_addr, ~3);
+
+        tcg_gen_ld_tl(r_check, cpu_env, offsetof(CPUMBState, res_addr));
+        write_carryi(dc, 1);
+        swx_skip = gen_new_label();
+        tcg_gen_brcond_tl(TCG_COND_NE, r_check, swx_addr, swx_skip);
+        write_carryi(dc, 0);
+    }
+
     if (rev && size != 4) {
         /* Endian reverse the address. t is addr.  */
         switch (size) {
@@ -1174,6 +1221,11 @@ static void dec_store(DisasContext *dc)
         gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
                             tcg_const_tl(1), tcg_const_tl(size - 1));
     }
+    if (ex) {
+        gen_set_label(swx_skip);
+        tcg_temp_free(r_check);
+        tcg_temp_free(swx_addr);
+    }
 
     if (addr == &t)
         tcg_temp_free(t);
commit 9c92bf7f6c3f675e60b8ba8a5287bb88ea1eac36
Author: Jason Wang <jasowang at redhat.com>
Date:   Thu May 10 16:37:22 2012 +0800

    Revert "rtl8139: do the network/host communication only in normal operating mode"
    
    This reverts commit ff71f2e8cacefae99179993204172bc65e4303df. This is because
    the linux 8139cp driver would leave the card in "Config Register Write Enable"
    mode after the eeprom were read or write ( which is unexpected in the spec
    ). Also a physical 8139 card can still DMA into host memory in modes other than
    Normal mode, so we need revert this commit to align with the behavior of
    physical card.
    
    The issue of 8139cp driver should be fixed in linux seperately.
    
    Signed-off-by: Jason Wang <jasowang at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index eb22d04..2413bc3 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -791,9 +791,6 @@ 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.
@@ -836,12 +833,6 @@ 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 74f4d2279b12a970d499558e4c38421724777827
Merge: 2eb02f2... 7d37d35...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Sun Jun 3 07:56:23 2012 +0800

    Merge remote-tracking branch 'qemu-kvm/uq/master' into staging
    
    * qemu-kvm/uq/master:
      virtio/vhost: Add support for KVM in-kernel MSI injection
      msix: Add msix_nr_vectors_allocated
      kvm: Enable use of kvm_irqchip_in_kernel in hwlib code
      kvm: Introduce kvm_irqchip_add/remove_irqfd
      kvm: Make kvm_irqchip_commit_routes an internal service
      kvm: Publicize kvm_irqchip_release_virq
      kvm: Introduce kvm_irqchip_add_msi_route
      kvm: Rename kvm_irqchip_add_route to kvm_irqchip_add_irq_route
      msix: Introduce vector notifiers
      msix: Invoke msix_handle_mask_update on msix_mask_all
      msix: Factor out msix_get_message
      kvm: update vmxcap for EPT A/D, INVPCID, RDRAND, VMFUNC
      kvm: Enable in-kernel irqchip support by default
      kvm: Add support for direct MSI injections
      kvm: Update kernel headers
      kvm: x86: Wire up MSI support for in-kernel irqchip
      pc: Enable MSI support at APIC level
      kvm: Introduce basic MSI support for in-kernel irqchips
      Introduce MSIMessage structure
      kvm: Refactor KVMState::max_gsi to gsi_count

commit 2eb02f28269dc47b38aa3becbaff1cc6300210da
Merge: a854972... 4bb9c93...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Sun Jun 3 07:54:05 2012 +0800

    Merge remote-tracking branch 'kwolf/for-anthony' into staging
    
    * kwolf/for-anthony:
      ahci: SATA FIS is 20 bytes, not 0x20
      virtio-blk: Fix geometry sector calculation
      block: prevent snapshot mode $TMPDIR symlink attack
      sheepdog: fix return value of do_load_save_vm_state
      virtio: Fix compiler warning for non Linux hosts

commit a854972f8cdec0148087789d62777d8f7176933d
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Jun 1 16:56:16 2012 +0800

    Update version to open the 1.2 development branch
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/VERSION b/VERSION
index 9084fa2..da44c7f 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.1.0
+1.1.50
commit 78260a5f085d34e4ae46e42bdc010dfcd6f6cc31
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Jun 1 16:55:34 2012 +0800

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

diff --git a/VERSION b/VERSION
index 00572ce..9084fa2 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.0.94
+1.1.0
commit b3dbb9546ade0108156a04b4983cd3057fd77563
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu May 31 08:53:39 2012 +0800

    Update version for 1.1.0-rc4 release
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/VERSION b/VERSION
index 87903b6..00572ce 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.0.93
+1.0.94
commit 272d28ecf2a2158c4bd89b42e5f45eb9e6201fde
Merge: d611150... 6f12926...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu May 31 08:49:46 2012 +0800

    Merge remote-tracking branch 'origin/master' into staging
    
    * origin/master:
      pc-bios: Update OpenBIOS images

commit 6f12926142bd3ab5bea700decdeb59a16b9cd8ae
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Wed May 30 17:04:41 2012 +0000

    pc-bios: Update OpenBIOS images
    
    Update OpenBIOS images to r1060 built from submodule.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/pc-bios/README b/pc-bios/README
index 6b64d68..e56e9e5 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -12,7 +12,7 @@
   1275-1994 (referred to as Open Firmware) compliant firmware.
   The included images for PowerPC (for 32 and 64 bit PPC CPUs),
   Sparc32 and Sparc64 are built from OpenBIOS SVN revision
-  1056.
+  1060.
 
 - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
   implementation for certain IBM POWER hardware.  The sources are at
diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc
index d4656db..aeae265 100644
Binary files a/pc-bios/openbios-ppc and b/pc-bios/openbios-ppc differ
diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32
index 4312c69..d90c4e5 100644
Binary files a/pc-bios/openbios-sparc32 and b/pc-bios/openbios-sparc32 differ
diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64
index b186105..457d264 100644
Binary files a/pc-bios/openbios-sparc64 and b/pc-bios/openbios-sparc64 differ
diff --git a/roms/openbios b/roms/openbios
index ff61d97..d1d2787 160000
--- a/roms/openbios
+++ b/roms/openbios
@@ -1 +1 @@
-Subproject commit ff61d973e5a4a68b29e485b3f88e6a2d1d96cf45
+Subproject commit d1d2787f87167edf487a60e61b9168514d5a7434
commit 4bb9c939a57103898f5a51aa6a7336eb3320d923
Author: Daniel Verkamp <daniel at drv.nu>
Date:   Tue May 22 16:26:42 2012 -0700

    ahci: SATA FIS is 20 bytes, not 0x20
    
    As in the SATA and AHCI specifications, a FIS is 5 Dwords of 4 bytes
    each, which comes to 20 bytes (decimal), not 0x20.
    
    Signed-off-by: Daniel Verkamp <daniel at drv.nu>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index a883a92..2d7d03d 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -462,7 +462,7 @@ static void ahci_check_cmd_bh(void *opaque)
 
 static void ahci_init_d2h(AHCIDevice *ad)
 {
-    uint8_t init_fis[0x20];
+    uint8_t init_fis[20];
     IDEState *ide_state = &ad->port.ifs[0];
 
     memset(init_fis, 0, sizeof(init_fis));
@@ -619,7 +619,7 @@ static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis)
     d2h_fis[11] = cmd_fis[11];
     d2h_fis[12] = cmd_fis[12];
     d2h_fis[13] = cmd_fis[13];
-    for (i = 14; i < 0x20; i++) {
+    for (i = 14; i < 20; i++) {
         d2h_fis[i] = 0;
     }
 
commit 136be99e6e2130d3cd960b6b7d0ca86b6f011e5f
Author: Christian Borntraeger <borntraeger at de.ibm.com>
Date:   Thu May 24 13:22:55 2012 +0200

    virtio-blk: Fix geometry sector calculation
    
    Currently the sector value for the geometry is masked, even if the
    user usesa command line parameter that explicitely gives a number.
    This breaks dasd devices on s390. A dasd device can have
    a physical block size of 4096 (== same for logical block size)
    and a typcial geometry of 15 heads and 12 sectors per cyl.
    The ibm partition detection relies on a correct geometry
    reported by the device. Unfortunately the current code changes
    12 to 8. This would be necessary if the total size is
    not a multiple of logical sector size,  but for dasd this
    is not the case.
    
    This patch checks the device size and only applies sector
    mask if necessary.
    
    Signed-off-by: Christian Borntraeger <borntraeger at de.ibm.com>
    CC: Christoph Hellwig <hch at lst.de>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 60750cb..fe07746 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -491,7 +491,22 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
     stw_raw(&blkcfg.min_io_size, s->conf->min_io_size / blk_size);
     stw_raw(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size);
     blkcfg.heads = heads;
-    blkcfg.sectors = secs & ~s->sector_mask;
+    /*
+     * We must ensure that the block device capacity is a multiple of
+     * the logical block size. If that is not the case, lets use
+     * sector_mask to adopt the geometry to have a correct picture.
+     * For those devices where the capacity is ok for the given geometry
+     * we dont touch the sector value of the geometry, since some devices
+     * (like s390 dasd) need a specific value. Here the capacity is already
+     * cyls*heads*secs*blk_size and the sector value is not block size
+     * divided by 512 - instead it is the amount of blk_size blocks
+     * per track (cylinder).
+     */
+    if (bdrv_getlength(s->bs) /  heads / secs % blk_size) {
+        blkcfg.sectors = secs & ~s->sector_mask;
+    } else {
+        blkcfg.sectors = secs;
+    }
     blkcfg.size_max = 0;
     blkcfg.physical_block_exp = get_physical_block_exp(s->conf);
     blkcfg.alignment_offset = 0;
commit c2d76497b6eafcaedc806e07804e7bed55a98a0b
Author: Jim Meyering <jim at meyering.net>
Date:   Mon May 28 09:27:54 2012 +0200

    block: prevent snapshot mode $TMPDIR symlink attack
    
    In snapshot mode, bdrv_open creates an empty temporary file without
    checking for mkstemp or close failure, and ignoring the possibility
    of a buffer overrun given a surprisingly long $TMPDIR.
    Change the get_tmp_filename function to return int (not void),
    so that it can inform its two callers of those failures.
    Also avoid the risk of buffer overrun and do not ignore mkstemp
    or close failure.
    Update both callers (in block.c and vvfat.c) to propagate
    temp-file-creation failure to their callers.
    
    get_tmp_filename creates and closes an empty file, while its
    callers later open that presumed-existing file with O_CREAT.
    The problem was that a malicious user could provoke mkstemp failure
    and race to create a symlink with the selected temporary file name,
    thus causing the qemu process (usually root owned) to open through
    the symlink, overwriting an attacker-chosen file.
    
    This addresses CVE-2012-2652.
    http://bugzilla.redhat.com/CVE-2012-2652
    
    Signed-off-by: Jim Meyering <meyering 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 af2ab4f..7547051 100644
--- a/block.c
+++ b/block.c
@@ -409,28 +409,36 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options)
     return bdrv_create(drv, filename, options);
 }
 
-#ifdef _WIN32
-void get_tmp_filename(char *filename, int size)
+/*
+ * Create a uniquely-named empty temporary file.
+ * Return 0 upon success, otherwise a negative errno value.
+ */
+int get_tmp_filename(char *filename, int size)
 {
+#ifdef _WIN32
     char temp_dir[MAX_PATH];
-
-    GetTempPath(MAX_PATH, temp_dir);
-    GetTempFileName(temp_dir, "qem", 0, filename);
-}
+    /* GetTempFileName requires that its output buffer (4th param)
+       have length MAX_PATH or greater.  */
+    assert(size >= MAX_PATH);
+    return (GetTempPath(MAX_PATH, temp_dir)
+            && GetTempFileName(temp_dir, "qem", 0, filename)
+            ? 0 : -GetLastError());
 #else
-void get_tmp_filename(char *filename, int size)
-{
     int fd;
     const char *tmpdir;
-    /* XXX: race condition possible */
     tmpdir = getenv("TMPDIR");
     if (!tmpdir)
         tmpdir = "/tmp";
-    snprintf(filename, size, "%s/vl.XXXXXX", tmpdir);
+    if (snprintf(filename, size, "%s/vl.XXXXXX", tmpdir) >= size) {
+        return -EOVERFLOW;
+    }
     fd = mkstemp(filename);
-    close(fd);
-}
+    if (fd < 0 || close(fd)) {
+        return -errno;
+    }
+    return 0;
 #endif
+}
 
 /*
  * Detect host devices. By convention, /dev/cdrom[N] is always
@@ -753,7 +761,10 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
 
         bdrv_delete(bs1);
 
-        get_tmp_filename(tmp_filename, sizeof(tmp_filename));
+        ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename));
+        if (ret < 0) {
+            return ret;
+        }
 
         /* Real path is meaningless for protocols */
         if (is_protocol)
diff --git a/block/vvfat.c b/block/vvfat.c
index 2dc9d50..0fd3367 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -2808,7 +2808,12 @@ static int enable_write_target(BDRVVVFATState *s)
     array_init(&(s->commits), sizeof(commit_t));
 
     s->qcow_filename = g_malloc(1024);
-    get_tmp_filename(s->qcow_filename, 1024);
+    ret = get_tmp_filename(s->qcow_filename, 1024);
+    if (ret < 0) {
+        g_free(s->qcow_filename);
+        s->qcow_filename = NULL;
+        return ret;
+    }
 
     bdrv_qcow = bdrv_find_format("qcow");
     options = parse_option_parameters("", bdrv_qcow->create_options, NULL);
diff --git a/block_int.h b/block_int.h
index b80e66d..3d4abc6 100644
--- a/block_int.h
+++ b/block_int.h
@@ -335,7 +335,7 @@ struct BlockDriverState {
     BlockJob *job;
 };
 
-void get_tmp_filename(char *filename, int size);
+int get_tmp_filename(char *filename, int size);
 
 void bdrv_set_io_limits(BlockDriverState *bs,
                         BlockIOLimit *io_limits);
commit 6f3c714eb7730630241fd0b33b799352d7feb876
Author: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Date:   Wed May 30 01:05:15 2012 +0900

    sheepdog: fix return value of do_load_save_vm_state
    
    bdrv_save_vmstate and bdrv_load_vmstate should return the vmstate size
    on success, and -errno on error.
    
    Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/sheepdog.c b/block/sheepdog.c
index 6d52277..f46ca8f 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -1957,7 +1957,7 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
                                 int64_t pos, int size, int load)
 {
     int fd, create;
-    int ret = 0;
+    int ret = 0, remaining = size;
     unsigned int data_len;
     uint64_t vmstate_oid;
     uint32_t vdi_index;
@@ -1968,11 +1968,11 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
         return fd;
     }
 
-    while (size) {
+    while (remaining) {
         vdi_index = pos / SD_DATA_OBJ_SIZE;
         offset = pos % SD_DATA_OBJ_SIZE;
 
-        data_len = MIN(size, SD_DATA_OBJ_SIZE);
+        data_len = MIN(remaining, SD_DATA_OBJ_SIZE);
 
         vmstate_oid = vid_to_vmstate_oid(s->inode.vdi_id, vdi_index);
 
@@ -1993,9 +1993,9 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
         }
 
         pos += data_len;
-        size -= data_len;
-        ret += data_len;
+        remaining -= data_len;
     }
+    ret = size;
 cleanup:
     closesocket(fd);
     return ret;
commit 47ce9ef7f89032c4079bf5132a12d1bfd4d5bca5
Author: Stefan Weil <sw at weilnetz.de>
Date:   Tue May 22 23:23:32 2012 +0200

    virtio: Fix compiler warning for non Linux hosts
    
    The local variables ret, i are only used if __linux__ is defined.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index f9e1896..60750cb 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -147,9 +147,11 @@ static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s)
 
 static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
 {
+#ifdef __linux__
     int ret;
-    int status = VIRTIO_BLK_S_OK;
     int i;
+#endif
+    int status = VIRTIO_BLK_S_OK;
 
     /*
      * We require at least one output segment each for the virtio_blk_outhdr
commit d6111501c15972e48b20a60ab0fdd726e84a3ed1
Merge: eba2505... 9e2fa41...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed May 30 15:02:03 2012 +0800

    Merge remote-tracking branch 'mdroth/qga-pull-5-29-12-v2' into staging
    
    * mdroth/qga-pull-5-29-12-v2:
      qemu-ga: avoid blocking on atime update when reading /etc/mtab
      qemu-ga: Fix use of environ on Darwin

commit eba25057b9a5e19d10ace2bc7716667a31297169
Author: Jim Meyering <jim at meyering.net>
Date:   Mon May 28 09:27:54 2012 +0200

    block: prevent snapshot mode $TMPDIR symlink attack
    
    In snapshot mode, bdrv_open creates an empty temporary file without
    checking for mkstemp or close failure, and ignoring the possibility
    of a buffer overrun given a surprisingly long $TMPDIR.
    Change the get_tmp_filename function to return int (not void),
    so that it can inform its two callers of those failures.
    Also avoid the risk of buffer overrun and do not ignore mkstemp
    or close failure.
    Update both callers (in block.c and vvfat.c) to propagate
    temp-file-creation failure to their callers.
    
    get_tmp_filename creates and closes an empty file, while its
    callers later open that presumed-existing file with O_CREAT.
    The problem was that a malicious user could provoke mkstemp failure
    and race to create a symlink with the selected temporary file name,
    thus causing the qemu process (usually root owned) to open through
    the symlink, overwriting an attacker-chosen file.
    
    This addresses CVE-2012-2652.
    http://bugzilla.redhat.com/CVE-2012-2652
    
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Jim Meyering <meyering at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/block.c b/block.c
index af2ab4f..7547051 100644
--- a/block.c
+++ b/block.c
@@ -409,28 +409,36 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options)
     return bdrv_create(drv, filename, options);
 }
 
-#ifdef _WIN32
-void get_tmp_filename(char *filename, int size)
+/*
+ * Create a uniquely-named empty temporary file.
+ * Return 0 upon success, otherwise a negative errno value.
+ */
+int get_tmp_filename(char *filename, int size)
 {
+#ifdef _WIN32
     char temp_dir[MAX_PATH];
-
-    GetTempPath(MAX_PATH, temp_dir);
-    GetTempFileName(temp_dir, "qem", 0, filename);
-}
+    /* GetTempFileName requires that its output buffer (4th param)
+       have length MAX_PATH or greater.  */
+    assert(size >= MAX_PATH);
+    return (GetTempPath(MAX_PATH, temp_dir)
+            && GetTempFileName(temp_dir, "qem", 0, filename)
+            ? 0 : -GetLastError());
 #else
-void get_tmp_filename(char *filename, int size)
-{
     int fd;
     const char *tmpdir;
-    /* XXX: race condition possible */
     tmpdir = getenv("TMPDIR");
     if (!tmpdir)
         tmpdir = "/tmp";
-    snprintf(filename, size, "%s/vl.XXXXXX", tmpdir);
+    if (snprintf(filename, size, "%s/vl.XXXXXX", tmpdir) >= size) {
+        return -EOVERFLOW;
+    }
     fd = mkstemp(filename);
-    close(fd);
-}
+    if (fd < 0 || close(fd)) {
+        return -errno;
+    }
+    return 0;
 #endif
+}
 
 /*
  * Detect host devices. By convention, /dev/cdrom[N] is always
@@ -753,7 +761,10 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
 
         bdrv_delete(bs1);
 
-        get_tmp_filename(tmp_filename, sizeof(tmp_filename));
+        ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename));
+        if (ret < 0) {
+            return ret;
+        }
 
         /* Real path is meaningless for protocols */
         if (is_protocol)
diff --git a/block/vvfat.c b/block/vvfat.c
index 2dc9d50..0fd3367 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -2808,7 +2808,12 @@ static int enable_write_target(BDRVVVFATState *s)
     array_init(&(s->commits), sizeof(commit_t));
 
     s->qcow_filename = g_malloc(1024);
-    get_tmp_filename(s->qcow_filename, 1024);
+    ret = get_tmp_filename(s->qcow_filename, 1024);
+    if (ret < 0) {
+        g_free(s->qcow_filename);
+        s->qcow_filename = NULL;
+        return ret;
+    }
 
     bdrv_qcow = bdrv_find_format("qcow");
     options = parse_option_parameters("", bdrv_qcow->create_options, NULL);
diff --git a/block_int.h b/block_int.h
index b80e66d..3d4abc6 100644
--- a/block_int.h
+++ b/block_int.h
@@ -335,7 +335,7 @@ struct BlockDriverState {
     BlockJob *job;
 };
 
-void get_tmp_filename(char *filename, int size);
+int get_tmp_filename(char *filename, int size);
 
 void bdrv_set_io_limits(BlockDriverState *bs,
                         BlockIOLimit *io_limits);
commit e78bd5ab07d65fec77fcae468b2836c79a836d49
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue May 29 11:20:31 2012 +0200

    xhci: add usage info to docs
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/docs/usb2.txt b/docs/usb2.txt
index 228aa33..d17e3c0 100644
--- a/docs/usb2.txt
+++ b/docs/usb2.txt
@@ -55,6 +55,21 @@ try ...
 ... then use "bus=ehci.0" to assign your usb devices to that bus.
 
 
+xhci controller support
+-----------------------
+
+There also is xhci host controller support available.  It got alot
+less testing than ehci and there are a bunch of known limitations, so
+ehci may work better for you.  On the other hand the xhci hardware
+design is much more virtualization-friendly, thus xhci emulation uses
+less ressources (especially cpu).  If you wanna give xhci a try
+use this to add the host controller ...
+
+    qemu -device nec-usb-xhci,id=xhci
+
+... then use "bus=xhci.0" when assigning usb devices.
+
+
 More USB tips & tricks
 ======================
 
commit 1643f2b232628905e8f32965ff36a87bd53b93c5
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu May 24 10:55:01 2012 +0200

    vnc: fix segfault in vnc_display_pw_expire()
    
    NULL pointer dereference in case no vnc server is configured.
    Catch this and return -EINVAL like vnc_display_password() does.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc.c b/ui/vnc.c
index be384a5..54bc5ad 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2849,6 +2849,10 @@ int vnc_display_pw_expire(DisplayState *ds, time_t expires)
 {
     VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
 
+    if (!vs) {
+        return -EINVAL;
+    }
+
     vs->expires = expires;
     return 0;
 }
commit 1352672860399b40965b5093dd026688979e60a5
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Mon May 21 11:27:02 2012 -0300

    Expose CPUID leaf 7 only for -cpu host
    
    Changes v2 -> v3;
      - Check for kvm_enabled() before setting cpuid_7_0_ebx_features
    
    Changes v1 -> v2:
      - Use kvm_arch_get_supported_cpuid() instead of host_cpuid() on
        cpu_x86_fill_host().
    
      We should use GET_SUPPORTED_CPUID for all bits on "-cpu host"
      eventually, but I am not changing all the other CPUID leaves because
      we may not be able to test such an intrusive change in time for 1.1.
    
    Description of the bug:
    
    Since QEMU 0.15, the CPUID information on CPUID[EAX=7,ECX=0] is being
    returned unfiltered to the guest, directly from the GET_SUPPORTED_CPUID
    return value.
    
    The problem is that this makes the resulting CPU feature flags
    unpredictable and dependent on the host CPU and kernel version. This
    breaks live-migration badly if migrating from a host CPU that supports
    some features on that CPUID leaf (running a recent kernel) to a kernel
    or host CPU that doesn't support it.
    
    Migration also is incorrect (the virtual CPU changes under the guest's
    feet) if you migrate in the opposite direction (from an old CPU/kernel
    to a new CPU/kernel), but with less serious consequences (guests
    normally query CPUID information only once on boot).
    
    Fortunately, the bug affects only users using cpudefs with level >= 7.
    
    The right behavior should be to explicitly enable those features on
    [cpudef] config sections or on the "-cpu" command-line arguments. Right
    now there is no predefined CPU model on QEMU that has those features:
    the latest Intel model we have is Sandy Bridge.
    
    I would like to get this fixed on 1.1, so I am submitting this patch,
    that enables those features only if "-cpu host" is being used (as we
    don't have any pre-defined CPU model that actually have those features).
    After 1.1 is released, we can make those features properly configurable
    on [cpudef] and -cpu configuration.
    
    One problem is: with this patch, users with the following setup:
    - Running QEMU 1.0;
    - Using a cpudef having level >= 7;
    - Running a kernel that supports the features on CPUID leaf 7; and
    - Running on a CPU that supports some features on CPUID leaf 7
    won't be able to live-migrate to QEMU 1.1. But for these users
    live-migration is already broken (they can't live-migrate to hosts with
    older CPUs or older kernels, already), I don't see how to avoid this
    problem.
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 89b4ac7..388bc5c 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -238,6 +238,8 @@ typedef struct x86_def_t {
     /* Store the results of Centaur's CPUID instructions */
     uint32_t ext4_features;
     uint32_t xlevel2;
+    /* The feature bits on CPUID[EAX=7,ECX=0].EBX */
+    uint32_t cpuid_7_0_ebx_features;
 } x86_def_t;
 
 #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
@@ -521,6 +523,12 @@ static int cpu_x86_fill_host(x86_def_t *x86_cpu_def)
     x86_cpu_def->ext_features = ecx;
     x86_cpu_def->features = edx;
 
+    if (kvm_enabled() && x86_cpu_def->level >= 7) {
+        x86_cpu_def->cpuid_7_0_ebx_features = kvm_arch_get_supported_cpuid(kvm_state, 0x7, 0, R_EBX);
+    } else {
+        x86_cpu_def->cpuid_7_0_ebx_features = 0;
+    }
+
     host_cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx);
     x86_cpu_def->xlevel = eax;
 
@@ -1185,6 +1193,7 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model)
     env->cpuid_kvm_features = def->kvm_features;
     env->cpuid_svm_features = def->svm_features;
     env->cpuid_ext4_features = def->ext4_features;
+    env->cpuid_7_0_ebx = def->cpuid_7_0_ebx_features;
     env->cpuid_xlevel2 = def->xlevel2;
     object_property_set_int(OBJECT(cpu), (int64_t)def->tsc_khz * 1000,
                             "tsc-frequency", &error);
@@ -1451,13 +1460,12 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
         *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);
+        /* Structured Extended Feature Flags Enumeration Leaf */
+        if (count == 0) {
+            *eax = 0; /* Maximum ECX value for sub-leaves */
+            *ebx = env->cpuid_7_0_ebx; /* Feature flags */
+            *ecx = 0; /* Reserved */
+            *edx = 0; /* Reserved */
         } else {
             *eax = 0;
             *ebx = 0;
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index b5b9a50..2460f63 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -741,6 +741,8 @@ typedef struct CPUX86State {
     /* Store the results of Centaur's CPUID instructions */
     uint32_t cpuid_xlevel2;
     uint32_t cpuid_ext4_features;
+    /* Flags from CPUID[EAX=7,ECX=0].EBX */
+    uint32_t cpuid_7_0_ebx;
 
     /* MTRRs */
     uint64_t mtrr_fixed[11];
commit 9e2fa418fbe71dd472fe5a9cd89ca26d5b594920
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue May 29 10:08:50 2012 -0500

    qemu-ga: avoid blocking on atime update when reading /etc/mtab
    
    Currently we re-read/re-process /etc/mtab to get an updated list of
    mounts when guest-fsfreeze-thaw is called. This can cause an atime
    update on /etc/mtab, which will block if we're in a frozen state.
    
    Instead, use /proc's version of mtab, which may not be up-to-date with
    options passed via -o remount, but is compatible for our use cases since
    we only care about the filesystem type.
    
    Reported-by: Matsuda, Daiki <matsudadik at intellilink.co.jp>
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 4a71c27..00d035d 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -345,7 +345,7 @@ static int guest_fsfreeze_build_mount_list(GuestFsfreezeMountList *mounts)
 {
     struct mntent *ment;
     GuestFsfreezeMount *mount;
-    char const *mtab = MOUNTED;
+    char const *mtab = "/proc/self/mounts";
     FILE *fp;
 
     fp = setmntent(mtab, "r");
commit eecae14724b64d43f9a44b9b4e69143961c201a3
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Sun May 27 17:02:20 2012 +0200

    qemu-ga: Fix use of environ on Darwin
    
    Use _NSGetEnviron() helper to access the environment.
    
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Cc: Charlie Somerville <charlie at charliesomerville.com>
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index dab3bf9..4a71c27 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -22,8 +22,13 @@
 #include "host-utils.h"
 
 #ifndef CONFIG_HAS_ENVIRON
+#ifdef __APPLE__
+#include <crt_externs.h>
+#define environ (*_NSGetEnviron())
+#else
 extern char **environ;
 #endif
+#endif
 
 #if defined(__linux__)
 #include <mntent.h>
commit a6de8ed80e1cf47d0f372e0856e6eeb6de9bbf0e
Author: Amos Kong <kongjianjun at gmail.com>
Date:   Sun May 20 17:57:45 2012 +0800

    pci: call object_unparent() before free_qdev()
    
    Start VM with 8 multiple-function block devs, hot-removing
    those block devs by 'device_del ...' would cause qemu abort.
    
    | (qemu) device_del virti0-0-0
    | (qemu) **
    |ERROR:qom/object.c:389:object_delete: assertion failed: (obj->ref == 0)
    
    It's a regression introduced by commit 57c9fafe
    
    The whole PCI slot should be removed once. Currently only one func
    is cleaned in pci_unplug_device(), if you try to remove a single
    func by monitor cmd.
    
    free_qdev() are called for all functions in slot,
    but unparent_delete() is only called for one
    function.
    
    Signed-off-by: XXXX
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 585da4e..0345490 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -299,6 +299,7 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
             if (pc->no_hotplug) {
                 slot_free = false;
             } else {
+                object_unparent(OBJECT(dev));
                 qdev_free(qdev);
             }
         }
diff --git a/hw/pci.c b/hw/pci.c
index b706e69..c1ebdde 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1527,7 +1527,6 @@ static int pci_unplug_device(DeviceState *qdev)
         qerror_report(QERR_DEVICE_NO_HOTPLUG, object_get_typename(OBJECT(dev)));
         return -1;
     }
-    object_unparent(OBJECT(dev));
     return dev->bus->hotplug(dev->bus->hotplug_qdev, dev,
                              PCI_HOTPLUG_DISABLED);
 }
commit 9c3a596a03cc10c2d9097f057b9ccb9d557a4d5f
Author: Scott Moser <smoser at ubuntu.com>
Date:   Mon Mar 26 15:27:00 2012 -0400

    fix multiboot loading if load_end_addr == 0
    
    The previous multiboot load code did not treat the case where
    load_end_addr was 0 specially.  The multiboot specification says the
    following:
     * load_end_addr
       Contains the physical address of the end of the data segment.
       (load_end_addr - load_addr) specifies how much data to load. This
       implies that the text and data segments must be consecutive in the
       OS image; this is true for existing a.out executable formats. If
       this field is zero, the boot loader assumes that the text and data
       segments occupy the whole OS image file.
    
    Signed-off-by: Scott Moser <smoser at ubuntu.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/multiboot.c b/hw/multiboot.c
index b4484a3..b1e04c5 100644
--- a/hw/multiboot.c
+++ b/hw/multiboot.c
@@ -202,10 +202,16 @@ int load_multiboot(void *fw_cfg,
         uint32_t mh_bss_end_addr = ldl_p(header+i+24);
         mh_load_addr = ldl_p(header+i+16);
         uint32_t mb_kernel_text_offset = i - (mh_header_addr - mh_load_addr);
-        uint32_t mb_load_size = mh_load_end_addr - mh_load_addr;
-
+        uint32_t mb_load_size = 0;
         mh_entry_addr = ldl_p(header+i+28);
-        mb_kernel_size = mh_bss_end_addr - mh_load_addr;
+
+        if (mh_load_end_addr) {
+            mb_kernel_size = mh_bss_end_addr - mh_load_addr;
+            mb_load_size = mh_load_end_addr - mh_load_addr;
+        } else {
+            mb_kernel_size = kernel_file_size - mb_kernel_text_offset;
+            mb_load_size = mb_kernel_size;
+        }
 
         /* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_VBE.
         uint32_t mh_mode_type = ldl_p(header+i+32);
commit 8294a64d7f9ecc428cd58ba36ad0b913084a8824
Author: Avi Kivity <avi at redhat.com>
Date:   Wed May 9 18:23:06 2012 +0300

    vga: fix vram double-mapping with -vga std and -M pc-0.12
    
    With pc-0.12, we map the video RAM both through the PCI BAR (the guest does
    this) and through a fixed mapping at 0xe0000000.  The memory API doesn't allow
    this double map, and aborts.
    
    Fix by using an alias.
    
    Reported-by: Michael Tokarev <mjt at tls.msk.ru>
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/vga.c b/hw/vga.c
index 5824f85..d784df7 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -2357,10 +2357,15 @@ void vga_init(VGACommonState *s, MemoryRegion *address_space,
 void vga_init_vbe(VGACommonState *s, MemoryRegion *system_memory)
 {
 #ifdef CONFIG_BOCHS_VBE
+    /* With pc-0.12 and below we map both the PCI BAR and the fixed VBE region,
+     * so use an alias to avoid double-mapping the same region.
+     */
+    memory_region_init_alias(&s->vram_vbe, "vram.vbe",
+                             &s->vram, 0, memory_region_size(&s->vram));
     /* XXX: use optimized standard vga accesses */
     memory_region_add_subregion(system_memory,
                                 VBE_DISPI_LFB_PHYSICAL_ADDRESS,
-                                &s->vram);
+                                &s->vram_vbe);
     s->vbe_mapped = 1;
 #endif 
 }
diff --git a/hw/vga_int.h b/hw/vga_int.h
index 7685b2b..d244d8f 100644
--- a/hw/vga_int.h
+++ b/hw/vga_int.h
@@ -105,6 +105,7 @@ typedef struct VGACommonState {
     MemoryRegion *legacy_address_space;
     uint8_t *vram_ptr;
     MemoryRegion vram;
+    MemoryRegion vram_vbe;
     uint32_t vram_size;
     uint32_t latch;
     MemoryRegion *chain4_alias;
commit 1c4ad9d2b4b5f2be08588a91e4193d13cc314282
Merge: dd86df7... 60b46aa...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue May 29 06:54:16 2012 -0500

    Merge remote-tracking branch 'afaerber-or/cocoa-for-upstream' into staging
    
    * afaerber-or/cocoa-for-upstream:
      cocoa: Suppress Cocoa frontend for -qtest
      arch_init: Fix AltiVec build on Darwin/ppc

commit 60b46aa2f3d40457d6f722cc79e3dbacd04b492f
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Mon May 28 03:18:31 2012 +0200

    cocoa: Suppress Cocoa frontend for -qtest
    
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>

diff --git a/ui/cocoa.m b/ui/cocoa.m
index e7d6e89..2383646 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -879,7 +879,8 @@ int main (int argc, const char * argv[]) {
                 !strcmp(opt, "-vnc") ||
                 !strcmp(opt, "-nographic") ||
                 !strcmp(opt, "-version") ||
-                !strcmp(opt, "-curses")) {
+                !strcmp(opt, "-curses") ||
+                !strcmp(opt, "-qtest")) {
                 return qemu_main(gArgc, gArgv, *_NSGetEnviron());
             }
         }
commit f283edc4827f6bfa82240e36433d7184ab106b0f
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Sun May 27 16:21:02 2012 +0200

    arch_init: Fix AltiVec build on Darwin/ppc
    
    Commit f29a56147b66845914d0a645bf9b4c5bb9a6af57 (implement
    -no-user-config command-line option (v3)) introduced uses of bool
    in arch_init.c. Shortly before that usage is support code for
    AltiVec (conditional to __ALTIVEC__).
    
    GCC's altivec.h may in a !__APPLE_ALTIVEC__ code path redefine bool,
    leading to type mismatches. altivec.h recommends to #undef for C++
    compatibility, but doing so in C leads to bool remaining undefined.
    
    Fix by redefining bool to _Bool as mandated for stdbool.h by POSIX.
    
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index 988adca..a9e8b74 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -100,6 +100,10 @@ const uint32_t arch_type = QEMU_ARCH;
 #define VECTYPE        vector unsigned char
 #define SPLAT(p)       vec_splat(vec_ld(0, p), 0)
 #define ALL_EQ(v1, v2) vec_all_eq(v1, v2)
+/* altivec.h may redefine the bool macro as vector type.
+ * Reset it to POSIX semantics. */
+#undef bool
+#define bool _Bool
 #elif defined __SSE2__
 #include <emmintrin.h>
 #define VECTYPE        __m128i
commit dd86df756e02b684718dd5378725927361b0ad36
Merge: 422831f... 180640e...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue May 29 04:32:13 2012 -0500

    Merge remote-tracking branch 'sstabellini/for_1.1_rc3' into staging
    
    * sstabellini/for_1.1_rc3:
      Call xc_domain_shutdown with the reboot flag when the guest requests a reboot.
      xen: Fix PV-on-HVM
      xen_disk: properly update stats in ioreq_release()
      xen_disk: use bdrv_aio_flush instead of bdrv_flush
      xen_disk: remove syncwrite option
      xen: disable rtc_clock
      xen: do not initialize the interval timer and PCSPK emulator

commit 422831fc81a4565d9687bc00bac685261a5dd67a
Merge: 3067615... 2c02cbf...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue May 29 04:31:29 2012 -0500

    Merge remote-tracking branch 'mdroth/qga-pull-5-24-12' into staging
    
    * mdroth/qga-pull-5-24-12:
      qemu-ga: Fix missing environ declaration
      configure: check if environ is declared

commit 306761537f03d31087dabe284523e08d050bc789
Merge: 7943df5... 7cd3316...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue May 29 04:30:49 2012 -0500

    Merge remote-tracking branch 'kwolf/for-anthony' into staging
    
    * kwolf/for-anthony:
      fdc-test: introduced qtest no_media_on_start and cmos qtest for floppy
      fdc: fix media detection
      fdc: floppy drive should be visible after start without media
      qemu-iotests: mark 035 qcow2-only
      qcow2: Check qcow2_alloc_clusters_at() return value
      sheepdog: use heap instead of stack for BDRVSheepdogState
      sheepdog: return -errno on error
      sheepdog: mark image as snapshot when tag is specified
      qemu-img: Explain how rebase operation can be used to perform a 'diff' operation.
      qcow2: don't leak buffer for unexpected qcow_version in header

commit 7943df571ae402862a6ace3a2539bd93153317f4
Merge: d501f84... 917cfc1...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue May 29 04:30:00 2012 -0500

    Merge remote-tracking branch 'kiszka/queues/slirp' into staging
    
    * kiszka/queues/slirp:
      slirp: Avoid redefining MAX_TCPOPTLEN
      slirp: Avoid statements without effect on Big Endian host
      slirp: Untangle TCPOLEN_* from TCPOPT_*

commit d501f8478a3c12f50b8cf18214795f3d7c3d94bd
Merge: 24f50d7... f4dfa67...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue May 29 04:28:59 2012 -0500

    Merge remote-tracking branch 'bonzini/scsi-next' into staging
    
    * bonzini/scsi-next:
      ISCSI: Switch to using READ16/WRITE16 for I/O to the LUN
      ISCSI: Only call READCAPACITY16 for SBC devices, use READCAPACITY10 for MMC
      ISCSI: get device type at connection time
      ISCSI: change num_blocks to 64-bit
      ISCSI: redo how we set up the events
      scsi: declare vmstate_info_scsi_requests to be static

commit 917cfc1f266b554ea9ab4d958fa048bd27bce58f
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Mon May 28 19:52:35 2012 +0200

    slirp: Avoid redefining MAX_TCPOPTLEN
    
    MAX_TCPOPTLEN is being defined as 32. Darwin already has it as 40,
    causing a warning. The value is only used to declare an array,
    into which currently 4 bytes are written at most.
    
    Therefore always override MAX_TCPOPTLEN for now.
    
    Suggested-by: Jan Kiszka <jan.kiszka at web.de>
    Reviewed-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>

diff --git a/slirp/tcp_output.c b/slirp/tcp_output.c
index 779314b..8aa3d90 100644
--- a/slirp/tcp_output.c
+++ b/slirp/tcp_output.c
@@ -47,6 +47,7 @@ static const u_char  tcp_outflags[TCP_NSTATES] = {
 };
 
 
+#undef MAX_TCPOPTLEN
 #define MAX_TCPOPTLEN	32	/* max # bytes that go in options */
 
 /*
commit 9b24d8e987d1249836cd4bccebf7c3a33025b293
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Mon May 28 19:34:20 2012 +0200

    slirp: Avoid statements without effect on Big Endian host
    
    Darwin has HTON*/NTOH* macros that on BE simply return the argument.
    This is incompatible with SLIRP's use of these macros as a statement.
    
    Undefine the macros in the HOST_WORDS_BIGENDIAN code path to redefine
    these macros as no-op, as already done when they were undefined.
    
    Suggested-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>

diff --git a/slirp/ip.h b/slirp/ip.h
index 88c903f..e2ee5e3 100644
--- a/slirp/ip.h
+++ b/slirp/ip.h
@@ -34,18 +34,14 @@
 #define _IP_H_
 
 #ifdef HOST_WORDS_BIGENDIAN
-# ifndef NTOHL
-#  define NTOHL(d)
-# endif
-# ifndef NTOHS
-#  define NTOHS(d)
-# endif
-# ifndef HTONL
-#  define HTONL(d)
-# endif
-# ifndef HTONS
-#  define HTONS(d)
-# endif
+# undef NTOHL
+# undef NTOHS
+# undef HTONL
+# undef HTONS
+# define NTOHL(d)
+# define NTOHS(d)
+# define HTONL(d)
+# define HTONS(d)
 #else
 # ifndef NTOHL
 #  define NTOHL(d) ((d) = ntohl((d)))
commit f4dfa67f04037c1b1a8f4e4ddc944c5ab308f35b
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Tue May 22 20:10:05 2012 +1000

    ISCSI: Switch to using READ16/WRITE16 for I/O to the LUN
    
    This allows using LUNs bigger than 2TB.  Keep using READ10 for other
    device types such as MMC.
    
    Signed-off-by: Ronnie Sahlberg <ronniesahlberg at gmail.com>

diff --git a/block/iscsi.c b/block/iscsi.c
index 472c853..22888a0 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -25,6 +25,7 @@
 #include "config-host.h"
 
 #include <poll.h>
+#include <arpa/inet.h>
 #include "qemu-common.h"
 #include "qemu-error.h"
 #include "block_int.h"
@@ -180,12 +181,12 @@ iscsi_readv_writev_bh_cb(void *p)
 
 
 static void
-iscsi_aio_write10_cb(struct iscsi_context *iscsi, int status,
+iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status,
                      void *command_data, void *opaque)
 {
     IscsiAIOCB *acb = opaque;
 
-    trace_iscsi_aio_write10_cb(iscsi, status, acb, acb->canceled);
+    trace_iscsi_aio_write16_cb(iscsi, status, acb, acb->canceled);
 
     g_free(acb->buf);
 
@@ -198,7 +199,7 @@ iscsi_aio_write10_cb(struct iscsi_context *iscsi, int status,
 
     acb->status = 0;
     if (status < 0) {
-        error_report("Failed to write10 data to iSCSI lun. %s",
+        error_report("Failed to write16 data to iSCSI lun. %s",
                      iscsi_get_error(iscsi));
         acb->status = -EIO;
     }
@@ -223,12 +224,9 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
     struct iscsi_context *iscsi = iscsilun->iscsi;
     IscsiAIOCB *acb;
     size_t size;
-    int fua = 0;
-
-    /* set FUA on writes when cache mode is write through */
-    if (!(bs->open_flags & BDRV_O_CACHE_WB)) {
-        fua = 1;
-    }
+    uint32_t num_sectors;
+    uint64_t lba;
+    struct iscsi_data data;
 
     acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
     trace_iscsi_aio_writev(iscsi, sector_num, nb_sectors, opaque, acb);
@@ -238,18 +236,44 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
 
     acb->canceled   = 0;
 
-    /* XXX we should pass the iovec to write10 to avoid the extra copy */
+    /* XXX we should pass the iovec to write16 to avoid the extra copy */
     /* this will allow us to get rid of 'buf' completely */
     size = nb_sectors * BDRV_SECTOR_SIZE;
     acb->buf = g_malloc(size);
     qemu_iovec_to_buffer(acb->qiov, acb->buf);
-    acb->task = iscsi_write10_task(iscsi, iscsilun->lun, acb->buf, size,
-                              sector_qemu2lun(sector_num, iscsilun),
-                              fua, 0, iscsilun->block_size,
-                              iscsi_aio_write10_cb, acb);
+
+
+    acb->task = malloc(sizeof(struct scsi_task));
     if (acb->task == NULL) {
-        error_report("iSCSI: Failed to send write10 command. %s",
-                     iscsi_get_error(iscsi));
+        error_report("iSCSI: Failed to allocate task for scsi WRITE16 "
+                     "command. %s", iscsi_get_error(iscsi));
+        qemu_aio_release(acb);
+        return NULL;
+    }
+    memset(acb->task, 0, sizeof(struct scsi_task));
+
+    acb->task->xfer_dir = SCSI_XFER_WRITE;
+    acb->task->cdb_size = 16;
+    acb->task->cdb[0] = 0x8a;
+    if (!(bs->open_flags & BDRV_O_CACHE_WB)) {
+        /* set FUA on writes when cache mode is write through */
+        acb->task->cdb[1] |= 0x04;
+    }
+    lba = sector_qemu2lun(sector_num, iscsilun);
+    *(uint32_t *)&acb->task->cdb[2]  = htonl(lba >> 32);
+    *(uint32_t *)&acb->task->cdb[6]  = htonl(lba & 0xffffffff);
+    num_sectors = size / iscsilun->block_size;
+    *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors);
+    acb->task->expxferlen = size;
+
+    data.data = acb->buf;
+    data.size = size;
+
+    if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
+                                 iscsi_aio_write16_cb,
+                                 &data,
+                                 acb) != 0) {
+        scsi_free_scsi_task(acb->task);
         g_free(acb->buf);
         qemu_aio_release(acb);
         return NULL;
@@ -261,12 +285,12 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
 }
 
 static void
-iscsi_aio_read10_cb(struct iscsi_context *iscsi, int status,
+iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status,
                     void *command_data, void *opaque)
 {
     IscsiAIOCB *acb = opaque;
 
-    trace_iscsi_aio_read10_cb(iscsi, status, acb, acb->canceled);
+    trace_iscsi_aio_read16_cb(iscsi, status, acb, acb->canceled);
 
     if (acb->canceled != 0) {
         qemu_aio_release(acb);
@@ -277,7 +301,7 @@ iscsi_aio_read10_cb(struct iscsi_context *iscsi, int status,
 
     acb->status = 0;
     if (status != 0) {
-        error_report("Failed to read10 data from iSCSI lun. %s",
+        error_report("Failed to read16 data from iSCSI lun. %s",
                      iscsi_get_error(iscsi));
         acb->status = -EIO;
     }
@@ -296,8 +320,10 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
     IscsiLun *iscsilun = bs->opaque;
     struct iscsi_context *iscsi = iscsilun->iscsi;
     IscsiAIOCB *acb;
-    size_t qemu_read_size, lun_read_size;
+    size_t qemu_read_size;
     int i;
+    uint64_t lba;
+    uint32_t num_sectors;
 
     qemu_read_size = BDRV_SECTOR_SIZE * (size_t)nb_sectors;
 
@@ -322,16 +348,44 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
         acb->read_offset  = bdrv_offset % iscsilun->block_size;
     }
 
-    lun_read_size  = (qemu_read_size + iscsilun->block_size
-                     + acb->read_offset - 1)
-                     / iscsilun->block_size * iscsilun->block_size;
-    acb->task = iscsi_read10_task(iscsi, iscsilun->lun,
-                             sector_qemu2lun(sector_num, iscsilun),
-                             lun_read_size, iscsilun->block_size,
-                             iscsi_aio_read10_cb, acb);
+    num_sectors  = (qemu_read_size + iscsilun->block_size
+                    + acb->read_offset - 1)
+                    / iscsilun->block_size;
+
+    acb->task = malloc(sizeof(struct scsi_task));
     if (acb->task == NULL) {
-        error_report("iSCSI: Failed to send read10 command. %s",
-                     iscsi_get_error(iscsi));
+        error_report("iSCSI: Failed to allocate task for scsi READ16 "
+                     "command. %s", iscsi_get_error(iscsi));
+        qemu_aio_release(acb);
+        return NULL;
+    }
+    memset(acb->task, 0, sizeof(struct scsi_task));
+
+    acb->task->xfer_dir = SCSI_XFER_READ;
+    lba = sector_qemu2lun(sector_num, iscsilun);
+    acb->task->expxferlen = qemu_read_size;
+
+    switch (iscsilun->type) {
+    case TYPE_DISK:
+        acb->task->cdb_size = 16;
+        acb->task->cdb[0]  = 0x88;
+        *(uint32_t *)&acb->task->cdb[2]  = htonl(lba >> 32);
+        *(uint32_t *)&acb->task->cdb[6]  = htonl(lba & 0xffffffff);
+        *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors);
+        break;
+    default:
+        acb->task->cdb_size = 10;
+        acb->task->cdb[0]  = 0x28;
+        *(uint32_t *)&acb->task->cdb[2] = htonl(lba);
+        *(uint16_t *)&acb->task->cdb[7] = htons(num_sectors);
+        break;
+    }
+    
+    if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
+                                 iscsi_aio_read16_cb,
+                                 NULL,
+                                 acb) != 0) {
+        scsi_free_scsi_task(acb->task);
         qemu_aio_release(acb);
         return NULL;
     }
diff --git a/trace-events b/trace-events
index 87cb96c..45c6bc1 100644
--- a/trace-events
+++ b/trace-events
@@ -602,9 +602,9 @@ escc_kbd_command(int val) "Command %d"
 escc_sunmouse_event(int dx, int dy, int buttons_state) "dx=%d dy=%d buttons=%01x"
 
 # block/iscsi.c
-iscsi_aio_write10_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d"
+iscsi_aio_write16_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d"
 iscsi_aio_writev(void *iscsi, int64_t sector_num, int nb_sectors, void *opaque, void *acb) "iscsi %p sector_num %"PRId64" nb_sectors %d opaque %p acb %p"
-iscsi_aio_read10_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d"
+iscsi_aio_read16_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d"
 iscsi_aio_readv(void *iscsi, int64_t sector_num, int nb_sectors, void *opaque, void *acb) "iscsi %p sector_num %"PRId64" nb_sectors %d opaque %p acb %p"
 
 # hw/esp.c
commit 6bcd1346bbfb051820e1c55bd4f04766f556bcdf
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Sat May 26 14:56:38 2012 +1000

    ISCSI: Only call READCAPACITY16 for SBC devices, use READCAPACITY10 for MMC
    
    Signed-off-by: Ronnie Sahlberg <ronniesahlberg at gmail.com>

diff --git a/block/iscsi.c b/block/iscsi.c
index 91cca83..472c853 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -510,6 +510,42 @@ iscsi_readcapacity16_cb(struct iscsi_context *iscsi, int status,
 }
 
 static void
+iscsi_readcapacity10_cb(struct iscsi_context *iscsi, int status,
+                        void *command_data, void *opaque)
+{
+    struct IscsiTask *itask = opaque;
+    struct scsi_readcapacity10 *rc10;
+    struct scsi_task *task