[Spice-commits] 395 commits - .gitignore MAINTAINERS Makefile Makefile.objs Makefile.target Makefile.user arm-semi.c block.c block.h block/qcow2-cache.c block/qcow2-cluster.c block/qcow2-refcount.c block/qcow2.c block/qcow2.h block/qed-l2-cache.c block/vmdk.c block_int.h blockdev.c bsd-user/main.c bsd-user/qemu.h bsd-user/signal.c cache-utils.h configure console.h coroutine-sigaltstack.c cpu-all.h cpu-common.h cpu-defs.h cpu-exec.c cpus.c cursor.c darwin-user/main.c darwin-user/qemu.h darwin-user/signal.c def-helper.h disas.c disas.h docs/libcacard.txt docs/tracing.txt dyngen-exec.h exec-all.h exec-obsolete.h exec.c fpu/softfloat-specialize.h fpu/softfloat.h gdbstub.c gdbstub.h gen-icount.h hmp-commands.hx hmp.c hw/9pfs hw/alpha_dp264.c hw/alpha_sys.h hw/alpha_typhoon.c hw/an5206.c hw/apb_pci.c hw/apb_pci.h hw/apic.c hw/apic.h hw/apic_common.c hw/apic_internal.h hw/arm-misc.h hw/arm11mpcore.c hw/arm_boot.c hw/arm_gic.c hw/arm_mptimer.c hw/arm_pic.c hw/armv7m.c hw/axis_dev88.c hw/cad ence_gem.c hw/cadence_ttc.c hw/cadence_uart.c hw/cris-boot.c hw/cris-boot.h hw/cris_pic_cpu.c hw/cuda.c hw/dummy_m68k.c hw/etraxfs.h hw/etraxfs_ser.c hw/exynos4210.h hw/exynos4210_mct.c hw/fdc.c hw/grlib.h hw/highbank.c hw/i8254.c hw/i8254.h hw/i8254_common.c hw/i8254_internal.h hw/ide hw/integratorcp.c hw/kvm hw/kvmvapic.c hw/leon3.c hw/lm32_boards.c hw/mc146818rtc.c hw/mcf.h hw/mcf5206.c hw/mcf5208.c hw/mcf_intc.c hw/microblaze_boot.c hw/microblaze_boot.h hw/microblaze_pic_cpu.c hw/microblaze_pic_cpu.h hw/milkymist.c hw/mips_cpudevs.h hw/mips_fulong2e.c hw/mips_int.c hw/mips_jazz.c hw/mips_malta.c hw/mips_mipssim.c hw/mips_r4k.c hw/mips_timer.c hw/mipsnet.c hw/mpc8544_guts.c hw/musicpal.c hw/nseries.c hw/omap.h hw/omap1.c hw/omap2.c hw/omap_i2c.c hw/opencores_eth.c hw/openpic.c hw/pc.c hw/pc_piix.c hw/petalogix_ml605_mmu.c hw/petalogix_s3adsp1800_mmu.c hw/ppc.c hw/ppc.h hw/ppc405.h hw/ppc405_uc.c hw/ppc440_bamboo.c hw/ppc4xx.h hw/ppc4xx_devs.c hw/ppc_booke.c hw/ppc_newworl d.c hw/ppc_oldworld.c hw/ppc_prep.c hw/ppce500_mpc8544ds.c hw/ppce500_spin.c hw/pxa.h hw/pxa2xx.c hw/pxa2xx_dma.c hw/pxa2xx_gpio.c hw/pxa2xx_lcd.c hw/pxa2xx_pic.c hw/qdev-properties.c hw/qxl-render.c hw/qxl.c hw/qxl.h hw/r2d.c hw/realview.c hw/s390-virtio-bus.c hw/s390-virtio.c hw/sh.h hw/sh7750.c hw/sh_intc.c hw/shix.c hw/spapr.c hw/spapr.h hw/spapr_hcall.c hw/spapr_llan.c hw/spapr_pci.c hw/spapr_pci.h hw/spapr_rtas.c hw/spapr_vio.c hw/spapr_vty.c hw/strongarm.h hw/sun4m.c hw/sun4u.c hw/usb hw/usb-audio.c hw/usb-bt.c hw/usb-bus.c hw/usb-ccid.c hw/usb-desc.c hw/usb-desc.h hw/usb-ehci.c hw/usb-hid.c hw/usb-hub.c hw/usb-libhw.c hw/usb-msd.c hw/usb-musb.c hw/usb-net.c hw/usb-ohci.c hw/usb-ohci.h hw/usb-serial.c hw/usb-uhci.c hw/usb-uhci.h hw/usb-wacom.c hw/usb-xhci.c hw/usb.c hw/usb.h hw/versatilepb.c hw/vexpress.c hw/vga.c hw/vhost.c hw/virtex_ml507.c hw/vmport.c hw/xen_machine_pv.c hw/xics.c hw/xics.h hw/xilinx_zynq.c hw/xtensa_lx60.c hw/xtensa_pic.c hw/xtensa_sim.c hw/zynq_s lcr.c include/qemu ioport.c ioport.h iorange.h kvm-all.c kvm-stub.c kvm.h libcacard/vcardt.h libcacard/vscclient.c linux-user/elfload.c linux-user/m68k linux-user/main.c linux-user/qemu.h linux-user/signal.c linux-user/syscall.c m68k-semi.c memory.c memory.h monitor.c osdep.h pc-bios/README pc-bios/kvmvapic.bin pc-bios/optionrom pc-bios/slof.bin poison.h qapi-schema-guest.json qapi-schema-test.json qapi-schema.json qemu-common.h qemu-config.c qemu-file.h qemu-ga.c qemu-img.c qemu-io.c qemu-options.hx qemu-tool.c qemu-user.c qga/commands-posix.c qga/commands-win32.c qga/commands.c qga/guest-agent-core.h qjson.h qmp-commands.hx qom/Makefile qom/cpu.c qom/object.c roms/SLOF savevm.c scripts/qapi-types.py scripts/qapi-visit.py scripts/tracetool slirp/bootp.c slirp/cksum.c slirp/if.c slirp/if.h slirp/ip_icmp.c slirp/ip_icmp.h slirp/ip_input.c slirp/mbuf.c slirp/mbuf.h slirp/slirp.c slirp/slirp.h slirp/tcp_subr.c slirp/udp.c slirp/udp.h softmmu-semi.h softmmu_defs.h softmmu_header .h softmmu_template.h sysconfigs/target target-alpha/cpu.h target-alpha/helper.c target-alpha/machine.c target-alpha/op_helper.c target-alpha/translate.c target-arm/cpu.h target-arm/helper.c target-arm/iwmmxt_helper.c target-arm/neon_helper.c target-arm/op_helper.c target-arm/translate.c target-cris/cpu.h target-cris/helper.c target-cris/mmu.c target-cris/mmu.h target-cris/op_helper.c target-cris/translate.c target-cris/translate_v10.c target-i386/cpu.h target-i386/cpuid.c target-i386/helper.c target-i386/kvm.c target-i386/machine.c target-i386/op_helper.c target-i386/translate.c target-lm32/cpu.h target-lm32/helper.c target-lm32/machine.c target-lm32/op_helper.c target-lm32/translate.c target-m68k/cpu.h target-m68k/helper.c target-m68k/op_helper.c target-m68k/translate.c target-microblaze/cpu.h target-microblaze/helper.c target-microblaze/mmu.c target-microblaze/mmu.h target-microblaze/op_helper.c target-microblaze/translate.c target-mips/cpu.h target-mips/helper.c target-m ips/machine.c target-mips/op_helper.c target-mips/translate.c target-ppc/cpu.h target-ppc/helper.c target-ppc/kvm.c target-ppc/kvm_ppc.h target-ppc/machine.c target-ppc/op_helper.c target-ppc/translate.c target-ppc/translate_init.c target-s390x/cpu.h target-s390x/helper.c target-s390x/helper.h target-s390x/helpers.h target-s390x/kvm.c target-s390x/op_helper.c target-s390x/translate.c target-sh4/cpu.h target-sh4/helper.c target-sh4/op_helper.c target-sh4/translate.c target-sparc/cc_helper.c target-sparc/cpu.h target-sparc/cpu_init.c target-sparc/fop_helper.c target-sparc/helper.c target-sparc/helper.h target-sparc/int32_helper.c target-sparc/int64_helper.c target-sparc/ldst_helper.c target-sparc/machine.c target-sparc/mmu_helper.c target-sparc/op_helper.c target-sparc/translate.c target-sparc/win_helper.c target-unicore32/cpu.h target-unicore32/helper.c target-unicore32/op_helper.c target-unicore32/translate.c target-xtensa/core-dc232b.c target-xtensa/core-fsf.c target-xtensa /cpu.h target-xtensa/helper.c target-xtensa/helpers.h target-xtensa/op_helper.c target-xtensa/overlay_tool.h target-xtensa/translate.c tcg/arm tcg/hppa tcg/i386 tcg/ia64 tcg/mips tcg/ppc tcg/ppc64 tcg/s390 tcg/sparc tcg/tcg.c tcg/tcg.h tcg/tci tci.c test-coroutine.c test-qmp-input-visitor.c test-qmp-output-visitor.c tests/Makefile tests/check-block.sh tests/qemu-iotests tests/qemu-iotests-quick.sh tests/tcg thunk.h trace-events trace/simple.c translate-all.c ui/sdl.c ui/spice-core.c ui/spice-display.c ui/spice-display.h ui/vnc-enc-hextile-template.h ui/vnc-jobs-async.c ui/vnc-jobs.h ui/vnc.c ui/vnc.h usb-bsd.c usb-linux.c usb-redir.c usb-stub.c user-exec.c vl.c xen-all.c xtensa-semi.c

Gerd Hoffmann kraxel at kemper.freedesktop.org
Mon Mar 19 06:12:50 PDT 2012


 .gitignore                           |    1 
 MAINTAINERS                          |    8 
 Makefile                             |   25 
 Makefile.objs                        |   56 
 Makefile.target                      |   29 
 Makefile.user                        |    1 
 arm-semi.c                           |   10 
 block.c                              |  186 +-
 block.h                              |   13 
 block/qcow2-cache.c                  |   18 
 block/qcow2-cluster.c                |  279 ++-
 block/qcow2-refcount.c               |   28 
 block/qcow2.c                        |   23 
 block/qcow2.h                        |    3 
 block/qed-l2-cache.c                 |   22 
 block/vmdk.c                         |    2 
 block_int.h                          |   17 
 blockdev.c                           |  207 +-
 bsd-user/main.c                      |   16 
 bsd-user/qemu.h                      |   12 
 bsd-user/signal.c                    |    2 
 cache-utils.h                        |    5 
 configure                            |  129 -
 console.h                            |    3 
 coroutine-sigaltstack.c              |  334 +++
 cpu-all.h                            |   78 
 cpu-common.h                         |    6 
 cpu-defs.h                           |    4 
 cpu-exec.c                           |   26 
 cpus.c                               |  102 -
 cursor.c                             |    3 
 darwin-user/main.c                   |   25 
 darwin-user/qemu.h                   |    6 
 darwin-user/signal.c                 |    8 
 def-helper.h                         |   28 
 disas.c                              |    4 
 disas.h                              |    2 
 docs/libcacard.txt                   |   26 
 docs/tracing.txt                     |   48 
 dyngen-exec.h                        |    4 
 exec-all.h                           |   49 
 exec-obsolete.h                      |    8 
 exec.c                               | 1095 +++++++------
 fpu/softfloat-specialize.h           |    8 
 fpu/softfloat.h                      |    2 
 gdbstub.c                            |  102 -
 gdbstub.h                            |   16 
 gen-icount.h                         |    8 
 hmp-commands.hx                      |   11 
 hmp.c                                |    6 
 hw/9pfs/virtio-9p.c                  |    8 
 hw/alpha_dp264.c                     |    2 
 hw/alpha_sys.h                       |    3 
 hw/alpha_typhoon.c                   |   14 
 hw/an5206.c                          |    2 
 hw/apb_pci.c                         |   49 
 hw/apb_pci.h                         |    3 
 hw/apic.c                            |  126 +
 hw/apic.h                            |    4 
 hw/apic_common.c                     |   69 
 hw/apic_internal.h                   |   27 
 hw/arm-misc.h                        |    9 
 hw/arm11mpcore.c                     |   22 
 hw/arm_boot.c                        |  112 +
 hw/arm_gic.c                         |   58 
 hw/arm_mptimer.c                     |    2 
 hw/arm_pic.c                         |    4 
 hw/armv7m.c                          |    4 
 hw/axis_dev88.c                      |    2 
 hw/cadence_gem.c                     | 1233 ++++++++++++++
 hw/cadence_ttc.c                     |  489 +++++
 hw/cadence_uart.c                    |  513 ++++++
 hw/cris-boot.c                       |    6 
 hw/cris-boot.h                       |    2 
 hw/cris_pic_cpu.c                    |    4 
 hw/cuda.c                            |    2 
 hw/dummy_m68k.c                      |    2 
 hw/etraxfs.h                         |    2 
 hw/etraxfs_ser.c                     |    4 
 hw/exynos4210.h                      |    2 
 hw/exynos4210_mct.c                  |    2 
 hw/fdc.c                             |  142 +
 hw/grlib.h                           |    2 
 hw/highbank.c                        |    8 
 hw/i8254.c                           |  281 ---
 hw/i8254.h                           |   11 
 hw/i8254_common.c                    |  311 +++
 hw/i8254_internal.h                  |   85 +
 hw/ide/ahci.c                        |    4 
 hw/ide/cmd646.c                      |    6 
 hw/ide/core.c                        |   24 
 hw/ide/macio.c                       |    2 
 hw/ide/piix.c                        |    2 
 hw/ide/via.c                         |    2 
 hw/integratorcp.c                    |    2 
 hw/kvm/apic.c                        |   34 
 hw/kvm/clock.c                       |    2 
 hw/kvm/i8254.c                       |  254 +++
 hw/kvmvapic.c                        |  807 +++++++++
 hw/leon3.c                           |   10 
 hw/lm32_boards.c                     |   12 
 hw/mc146818rtc.c                     |    7 
 hw/mcf.h                             |    4 
 hw/mcf5206.c                         |    4 
 hw/mcf5208.c                         |    2 
 hw/mcf_intc.c                        |    4 
 hw/microblaze_boot.c                 |  177 ++
 hw/microblaze_boot.h                 |   10 
 hw/microblaze_pic_cpu.c              |    4 
 hw/microblaze_pic_cpu.h              |    2 
 hw/milkymist.c                       |   10 
 hw/mips_cpudevs.h                    |    4 
 hw/mips_fulong2e.c                   |   19 
 hw/mips_int.c                        |    6 
 hw/mips_jazz.c                       |    8 
 hw/mips_malta.c                      |   99 -
 hw/mips_mipssim.c                    |    8 
 hw/mips_r4k.c                        |    8 
 hw/mips_timer.c                      |   20 
 hw/mipsnet.c                         |    2 
 hw/mpc8544_guts.c                    |    2 
 hw/musicpal.c                        |    2 
 hw/nseries.c                         |   12 
 hw/omap.h                            |   15 
 hw/omap1.c                           |   15 
 hw/omap2.c                           |   37 
 hw/omap_i2c.c                        |  107 -
 hw/opencores_eth.c                   |    4 
 hw/openpic.c                         |   12 
 hw/pc.c                              |   39 
 hw/pc_piix.c                         |   32 
 hw/petalogix_ml605_mmu.c             |  146 -
 hw/petalogix_s3adsp1800_mmu.c        |  149 -
 hw/ppc.c                             |  123 -
 hw/ppc.h                             |   28 
 hw/ppc405.h                          |    8 
 hw/ppc405_uc.c                       |   52 
 hw/ppc440_bamboo.c                   |    8 
 hw/ppc4xx.h                          |    8 
 hw/ppc4xx_devs.c                     |   17 
 hw/ppc_booke.c                       |   20 
 hw/ppc_newworld.c                    |   14 
 hw/ppc_oldworld.c                    |   14 
 hw/ppc_prep.c                        |   16 
 hw/ppce500_mpc8544ds.c               |   16 
 hw/ppce500_spin.c                    |   10 
 hw/pxa.h                             |    6 
 hw/pxa2xx.c                          |    5 
 hw/pxa2xx_dma.c                      |   12 
 hw/pxa2xx_gpio.c                     |    4 
 hw/pxa2xx_lcd.c                      |   12 
 hw/pxa2xx_pic.c                      |    4 
 hw/qdev-properties.c                 |    4 
 hw/qxl-render.c                      |  170 +-
 hw/qxl.c                             |  215 +-
 hw/qxl.h                             |   31 
 hw/r2d.c                             |    8 
 hw/realview.c                        |    5 
 hw/s390-virtio-bus.c                 |    6 
 hw/s390-virtio.c                     |   46 
 hw/sh.h                              |    2 
 hw/sh7750.c                          |    2 
 hw/sh_intc.c                         |    2 
 hw/shix.c                            |    2 
 hw/spapr.c                           |   22 
 hw/spapr.h                           |   17 
 hw/spapr_hcall.c                     |   42 
 hw/spapr_llan.c                      |   10 
 hw/spapr_pci.c                       |  195 +-
 hw/spapr_pci.h                       |    4 
 hw/spapr_rtas.c                      |    4 
 hw/spapr_vio.c                       |   14 
 hw/spapr_vty.c                       |    4 
 hw/strongarm.h                       |    2 
 hw/sun4m.c                           |   16 
 hw/sun4u.c                           |   83 
 hw/usb-audio.c                       |  714 --------
 hw/usb-bt.c                          |  557 ------
 hw/usb-bus.c                         |  594 -------
 hw/usb-ccid.c                        | 1365 ----------------
 hw/usb-desc.c                        |  587 -------
 hw/usb-desc.h                        |  117 -
 hw/usb-ehci.c                        | 2386 ----------------------------
 hw/usb-hid.c                         |  635 -------
 hw/usb-hub.c                         |  549 ------
 hw/usb-libhw.c                       |   63 
 hw/usb-msd.c                         |  677 --------
 hw/usb-musb.c                        | 1544 ------------------
 hw/usb-net.c                         | 1423 ----------------
 hw/usb-ohci.c                        | 1896 ----------------------
 hw/usb-ohci.h                        |    9 
 hw/usb-serial.c                      |  637 -------
 hw/usb-uhci.c                        | 1346 ----------------
 hw/usb-uhci.h                        |   10 
 hw/usb-wacom.c                       |  381 ----
 hw/usb-xhci.c                        | 2934 -----------------------------------
 hw/usb.c                             |  609 -------
 hw/usb.h                             |   22 
 hw/usb/bus.c                         |  584 ++++++
 hw/usb/core.c                        |  688 ++++++++
 hw/usb/desc.c                        |  601 +++++++
 hw/usb/desc.h                        |  117 +
 hw/usb/dev-audio.c                   |  714 ++++++++
 hw/usb/dev-bluetooth.c               |  557 ++++++
 hw/usb/dev-hid.c                     |  638 +++++++
 hw/usb/dev-hub.c                     |  549 ++++++
 hw/usb/dev-network.c                 | 1423 ++++++++++++++++
 hw/usb/dev-serial.c                  |  637 +++++++
 hw/usb/dev-smartcard-reader.c        | 1365 ++++++++++++++++
 hw/usb/dev-storage.c                 |  677 ++++++++
 hw/usb/dev-wacom.c                   |  381 ++++
 hw/usb/hcd-ehci.c                    | 2341 +++++++++++++++++++++++++++
 hw/usb/hcd-musb.c                    | 1544 ++++++++++++++++++
 hw/usb/hcd-ohci.c                    | 1905 ++++++++++++++++++++++
 hw/usb/hcd-uhci.c                    | 1378 ++++++++++++++++
 hw/usb/hcd-xhci.c                    | 2925 ++++++++++++++++++++++++++++++++++
 hw/usb/host-bsd.c                    |  647 +++++++
 hw/usb/host-linux.c                  | 1913 ++++++++++++++++++++++
 hw/usb/host-stub.c                   |   52 
 hw/usb/libhw.c                       |   63 
 hw/usb/redirect.c                    | 1485 +++++++++++++++++
 hw/versatilepb.c                     |    5 
 hw/vexpress.c                        |    4 
 hw/vga.c                             |    2 
 hw/vhost.c                           |   33 
 hw/virtex_ml507.c                    |   12 
 hw/vmport.c                          |   12 
 hw/xen_machine_pv.c                  |    2 
 hw/xics.c                            |  135 +
 hw/xics.h                            |    8 
 hw/xilinx_zynq.c                     |  157 +
 hw/xtensa_lx60.c                     |   10 
 hw/xtensa_pic.c                      |   16 
 hw/xtensa_sim.c                      |    4 
 hw/zynq_slcr.c                       |  535 ++++++
 include/qemu/cpu.h                   |   75 
 include/qemu/object.h                |   17 
 ioport.c                             |   43 
 ioport.h                             |    2 
 iorange.h                            |    1 
 kvm-all.c                            |  190 +-
 kvm-stub.c                           |   27 
 kvm.h                                |   61 
 libcacard/vcardt.h                   |    2 
 libcacard/vscclient.c                |   22 
 linux-user/elfload.c                 |   40 
 linux-user/m68k/syscall.h            |    2 
 linux-user/main.c                    |   46 
 linux-user/qemu.h                    |   14 
 linux-user/signal.c                  |  221 +-
 linux-user/syscall.c                 |   30 
 m68k-semi.c                          |    4 
 memory.c                             |  365 +---
 memory.h                             |   35 
 monitor.c                            |  552 +++---
 osdep.h                              |    9 
 pc-bios/README                       |    2 
 pc-bios/kvmvapic.bin                 |binary
 pc-bios/optionrom/Makefile           |    2 
 pc-bios/optionrom/kvmvapic.S         |  335 +++
 pc-bios/optionrom/optionrom.h        |    3 
 pc-bios/slof.bin                     |binary
 poison.h                             |    2 
 qapi-schema-guest.json               |  182 ++
 qapi-schema-test.json                |   10 
 qapi-schema.json                     |   98 +
 qemu-common.h                        |   17 
 qemu-config.c                        |    4 
 qemu-file.h                          |    2 
 qemu-ga.c                            |   46 
 qemu-img.c                           |    4 
 qemu-io.c                            |    2 
 qemu-options.hx                      |    9 
 qemu-tool.c                          |    2 
 qemu-user.c                          |   37 
 qga/commands-posix.c                 |  390 ++++
 qga/commands-win32.c                 |  167 +
 qga/commands.c                       |    6 
 qga/guest-agent-core.h               |    2 
 qjson.h                              |    1 
 qmp-commands.hx                      |   55 
 qom/Makefile                         |    1 
 qom/cpu.c                            |   58 
 qom/object.c                         |   51 
 roms/SLOF                            |    2 
 savevm.c                             |    2 
 scripts/qapi-types.py                |    6 
 scripts/qapi-visit.py                |   31 
 scripts/tracetool                    |   13 
 slirp/bootp.c                        |    3 
 slirp/cksum.c                        |    2 
 slirp/if.c                           |  145 -
 slirp/if.h                           |    2 
 slirp/ip_icmp.c                      |    7 
 slirp/ip_icmp.h                      |    1 
 slirp/ip_input.c                     |    7 
 slirp/mbuf.c                         |   21 
 slirp/mbuf.h                         |    6 
 slirp/slirp.c                        |   10 
 slirp/slirp.h                        |    4 
 slirp/tcp_subr.c                     |    7 
 slirp/udp.c                          |    8 
 slirp/udp.h                          |    1 
 softmmu-semi.h                       |   12 
 softmmu_defs.h                       |   60 
 softmmu_header.h                     |   60 
 softmmu_template.h                   |  126 -
 sysconfigs/target/target-x86_64.conf |   28 
 target-alpha/cpu.h                   |   27 
 target-alpha/helper.c                |   18 
 target-alpha/machine.c               |   44 
 target-alpha/op_helper.c             |    6 
 target-alpha/translate.c             |   61 
 target-arm/cpu.h                     |   12 
 target-arm/helper.c                  |  130 -
 target-arm/iwmmxt_helper.c           |   66 
 target-arm/neon_helper.c             |   88 -
 target-arm/op_helper.c               |    6 
 target-arm/translate.c               |  167 +
 target-cris/cpu.h                    |   17 
 target-cris/helper.c                 |   18 
 target-cris/mmu.c                    |   19 
 target-cris/mmu.h                    |    6 
 target-cris/op_helper.c              |    6 
 target-cris/translate.c              |   57 
 target-cris/translate_v10.c          |   26 
 target-i386/cpu.h                    |   45 
 target-i386/cpuid.c                  |    2 
 target-i386/helper.c                 |   73 
 target-i386/kvm.c                    |  106 -
 target-i386/machine.c                |  180 +-
 target-i386/op_helper.c              |   35 
 target-i386/translate.c              |   82 
 target-lm32/cpu.h                    |   36 
 target-lm32/helper.c                 |   23 
 target-lm32/machine.c                |   22 
 target-lm32/op_helper.c              |    4 
 target-lm32/translate.c              |   46 
 target-m68k/cpu.h                    |   19 
 target-m68k/helper.c                 |   87 -
 target-m68k/op_helper.c              |   20 
 target-m68k/translate.c              |   22 
 target-microblaze/cpu.h              |   40 
 target-microblaze/helper.c           |   15 
 target-microblaze/mmu.c              |   12 
 target-microblaze/mmu.h              |    6 
 target-microblaze/op_helper.c        |    8 
 target-microblaze/translate.c        |   62 
 target-mips/cpu.h                    |   42 
 target-mips/helper.c                 |   26 
 target-mips/machine.c                |    4 
 target-mips/op_helper.c              |  126 -
 target-mips/translate.c              |  367 ++--
 target-ppc/cpu.h                     |   47 
 target-ppc/helper.c                  |  100 -
 target-ppc/kvm.c                     |   50 
 target-ppc/kvm_ppc.h                 |   12 
 target-ppc/machine.c                 |    4 
 target-ppc/op_helper.c               |   12 
 target-ppc/translate.c               |  138 +
 target-ppc/translate_init.c          |   53 
 target-s390x/cpu.h                   |   51 
 target-s390x/helper.c                |   47 
 target-s390x/helper.h                |  152 +
 target-s390x/helpers.h               |  152 -
 target-s390x/kvm.c                   |   56 
 target-s390x/op_helper.c             |   72 
 target-s390x/translate.c             |   65 
 target-sh4/cpu.h                     |   12 
 target-sh4/helper.c                  |   28 
 target-sh4/op_helper.c               |    4 
 target-sh4/translate.c               |   56 
 target-sparc/cc_helper.c             |   66 
 target-sparc/cpu.h                   |   75 
 target-sparc/cpu_init.c              |    5 
 target-sparc/fop_helper.c            |   68 
 target-sparc/helper.c                |   16 
 target-sparc/helper.h                |   20 
 target-sparc/int32_helper.c          |    6 
 target-sparc/int64_helper.c          |   12 
 target-sparc/ldst_helper.c           |  443 ++---
 target-sparc/machine.c               |    4 
 target-sparc/mmu_helper.c            |   28 
 target-sparc/op_helper.c             |   74 
 target-sparc/translate.c             |  142 -
 target-sparc/win_helper.c            |   58 
 target-unicore32/cpu.h               |   34 
 target-unicore32/helper.c            |   66 
 target-unicore32/op_helper.c         |    8 
 target-unicore32/translate.c         |   60 
 target-xtensa/core-dc232b.c          |    2 
 target-xtensa/core-fsf.c             |    2 
 target-xtensa/cpu.h                  |   85 -
 target-xtensa/helper.c               |  145 +
 target-xtensa/helpers.h              |    7 
 target-xtensa/op_helper.c            |  128 +
 target-xtensa/overlay_tool.h         |   23 
 target-xtensa/translate.c            |  176 +-
 tcg/arm/tcg-target.c                 |   75 
 tcg/arm/tcg-target.h                 |    3 
 tcg/hppa/tcg-target.c                |   60 
 tcg/hppa/tcg-target.h                |    4 
 tcg/i386/tcg-target.c                |  179 +-
 tcg/i386/tcg-target.h                |    3 
 tcg/ia64/tcg-target.c                |   56 
 tcg/ia64/tcg-target.h                |    3 
 tcg/mips/tcg-target.c                |   58 
 tcg/mips/tcg-target.h                |    3 
 tcg/ppc/tcg-target.c                 |   49 
 tcg/ppc/tcg-target.h                 |    2 
 tcg/ppc64/tcg-target.c               |   48 
 tcg/s390/tcg-target.c                |   52 
 tcg/s390/tcg-target.h                |    3 
 tcg/sparc/tcg-target.c               |   71 
 tcg/sparc/tcg-target.h               |    3 
 tcg/tcg.c                            |   43 
 tcg/tcg.h                            |   15 
 tcg/tci/tcg-target.c                 |    8 
 tcg/tci/tcg-target.h                 |    5 
 tci.c                                |    6 
 test-coroutine.c                     |   27 
 test-qmp-input-visitor.c             |   18 
 test-qmp-output-visitor.c            |   38 
 tests/Makefile                       |   12 
 tests/check-block.sh                 |   21 
 tests/qemu-iotests-quick.sh          |   17 
 tests/qemu-iotests/026               |    6 
 tests/qemu-iotests/028               |    5 
 tests/qemu-iotests/028.out           |    1 
 tests/qemu-iotests/030               |  151 +
 tests/qemu-iotests/030.out           |    5 
 tests/qemu-iotests/check             |    4 
 tests/qemu-iotests/common.config     |    2 
 tests/qemu-iotests/common.filter     |    8 
 tests/qemu-iotests/group             |   25 
 tests/qemu-iotests/iotests.py        |  164 +
 tests/tcg/xtensa/Makefile            |    1 
 tests/tcg/xtensa/test_break.S        |  223 ++
 thunk.h                              |    4 
 trace-events                         |   73 
 trace/simple.c                       |    2 
 translate-all.c                      |    4 
 ui/sdl.c                             |    4 
 ui/spice-core.c                      |   47 
 ui/spice-display.c                   |   57 
 ui/spice-display.h                   |   21 
 ui/vnc-enc-hextile-template.h        |    1 
 ui/vnc-jobs-async.c                  |   48 
 ui/vnc-jobs.h                        |    1 
 ui/vnc.c                             |   20 
 ui/vnc.h                             |    2 
 usb-bsd.c                            |  647 -------
 usb-linux.c                          | 1904 ----------------------
 usb-redir.c                          | 1446 -----------------
 usb-stub.c                           |   52 
 user-exec.c                          |    4 
 vl.c                                 |   39 
 xen-all.c                            |   37 
 xtensa-semi.c                        |    2 
 459 files changed, 38929 insertions(+), 29234 deletions(-)

New commits:
commit 5bd33de6635577744b3c10dd3913bfe8c5ffaf40
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Mar 18 19:15:32 2012 +0000

    tcg: fix sparc host for AREG0 free operation
    
    e141ab52d2ea5d0bc6ad3b1ad32841127ca04adc didn't handle
    the other memory access helper case, fix.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 80f0818..491c979 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -1061,6 +1061,17 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
     /* mov */
     tcg_out_movi(s, TCG_TYPE_I32, arg2, mem_index);
 
+#ifdef CONFIG_TCG_PASS_AREG0
+    /* XXX/FIXME: suboptimal */
+    tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
+                tcg_target_call_iarg_regs[2]);
+    tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
+                tcg_target_call_iarg_regs[1]);
+    tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
+                tcg_target_call_iarg_regs[0]);
+    tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
+                TCG_AREG0);
+#endif
     /* XXX: move that code at the end of the TB */
     /* qemu_st_helper[s_bits](arg0, arg1, arg2) */
     tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_st_helpers[s_bits]
commit 0184e266cb7584feefaf4b54abbaa9fa81b62fac
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Mon Aug 1 12:19:05 2011 +0000

    Sparc: avoid AREG0 wrappers for memory access helpers
    
    Adjust generation of load and store templates so that the functions
    take a parameter for CPUState instead of relying on global env.
    
    Remove wrappers. Move remaining memory helpers to ldst_helper.c.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index d2ba029..37fb7ed 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -80,7 +80,10 @@ 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
-libobj-y += op_helper.o helper.o
+ifneq ($(TARGET_BASE_ARCH), sparc)
+libobj-y += op_helper.o
+endif
+libobj-y += helper.o
 ifeq ($(TARGET_BASE_ARCH), i386)
 libobj-y += cpuid.o
 endif
@@ -101,9 +104,12 @@ 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 code compiled with static register
+# HELPER_CFLAGS is used for all the legacy code compiled with static register
 # variables
-op_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
+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
 # cpu_signal_handler() in user-exec.c.
diff --git a/configure b/configure
index afe7395..8b4e3c1 100755
--- a/configure
+++ b/configure
@@ -3606,6 +3606,13 @@ case "$target_arch2" in
     exit 1
   ;;
 esac
+
+case "$target_arch2" in
+  sparc*)
+    echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak
+  ;;
+esac
+
 echo "TARGET_SHORT_ALIGNMENT=$target_short_alignment" >> $config_target_mak
 echo "TARGET_INT_ALIGNMENT=$target_int_alignment" >> $config_target_mak
 echo "TARGET_LONG_ALIGNMENT=$target_long_alignment" >> $config_target_mak
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index ee28daa..1025752 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -587,89 +587,6 @@ void cpu_unassigned_access(CPUSPARCState *env1, target_phys_addr_t addr,
 target_phys_addr_t cpu_get_phys_page_nofault(CPUSPARCState *env, target_ulong addr,
                                            int mmu_idx);
 #endif
-
-#define WRAP_LD(rettype, fn)                                    \
-    rettype cpu_ ## fn (CPUSPARCState *env1, target_ulong addr)
-
-WRAP_LD(uint32_t, ldub_kernel);
-WRAP_LD(uint32_t, lduw_kernel);
-WRAP_LD(uint32_t, ldl_kernel);
-WRAP_LD(uint64_t, ldq_kernel);
-
-WRAP_LD(uint32_t, ldub_user);
-WRAP_LD(uint32_t, lduw_user);
-WRAP_LD(uint32_t, ldl_user);
-WRAP_LD(uint64_t, ldq_user);
-
-WRAP_LD(uint64_t, ldfq_kernel);
-WRAP_LD(uint64_t, ldfq_user);
-
-#ifdef TARGET_SPARC64
-WRAP_LD(uint32_t, ldub_hypv);
-WRAP_LD(uint32_t, lduw_hypv);
-WRAP_LD(uint32_t, ldl_hypv);
-WRAP_LD(uint64_t, ldq_hypv);
-
-WRAP_LD(uint64_t, ldfq_hypv);
-
-WRAP_LD(uint32_t, ldub_nucleus);
-WRAP_LD(uint32_t, lduw_nucleus);
-WRAP_LD(uint32_t, ldl_nucleus);
-WRAP_LD(uint64_t, ldq_nucleus);
-
-WRAP_LD(uint32_t, ldub_kernel_secondary);
-WRAP_LD(uint32_t, lduw_kernel_secondary);
-WRAP_LD(uint32_t, ldl_kernel_secondary);
-WRAP_LD(uint64_t, ldq_kernel_secondary);
-
-WRAP_LD(uint32_t, ldub_user_secondary);
-WRAP_LD(uint32_t, lduw_user_secondary);
-WRAP_LD(uint32_t, ldl_user_secondary);
-WRAP_LD(uint64_t, ldq_user_secondary);
-#endif
-#undef WRAP_LD
-
-#define WRAP_ST(datatype, fn)                                           \
-    void cpu_ ## fn (CPUSPARCState *env1, target_ulong addr, datatype val)
-
-WRAP_ST(uint32_t, stb_kernel);
-WRAP_ST(uint32_t, stw_kernel);
-WRAP_ST(uint32_t, stl_kernel);
-WRAP_ST(uint64_t, stq_kernel);
-
-WRAP_ST(uint32_t, stb_user);
-WRAP_ST(uint32_t, stw_user);
-WRAP_ST(uint32_t, stl_user);
-WRAP_ST(uint64_t, stq_user);
-
-WRAP_ST(uint64_t, stfq_kernel);
-WRAP_ST(uint64_t, stfq_user);
-
-#ifdef TARGET_SPARC64
-WRAP_ST(uint32_t, stb_hypv);
-WRAP_ST(uint32_t, stw_hypv);
-WRAP_ST(uint32_t, stl_hypv);
-WRAP_ST(uint64_t, stq_hypv);
-
-WRAP_ST(uint64_t, stfq_hypv);
-
-WRAP_ST(uint32_t, stb_nucleus);
-WRAP_ST(uint32_t, stw_nucleus);
-WRAP_ST(uint32_t, stl_nucleus);
-WRAP_ST(uint64_t, stq_nucleus);
-
-WRAP_ST(uint32_t, stb_kernel_secondary);
-WRAP_ST(uint32_t, stw_kernel_secondary);
-WRAP_ST(uint32_t, stl_kernel_secondary);
-WRAP_ST(uint64_t, stq_kernel_secondary);
-
-WRAP_ST(uint32_t, stb_user_secondary);
-WRAP_ST(uint32_t, stw_user_secondary);
-WRAP_ST(uint32_t, stl_user_secondary);
-WRAP_ST(uint64_t, stq_user_secondary);
-#endif
-
-#undef WRAP_ST
 #endif
 int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
 
@@ -782,6 +699,8 @@ uint64_t cpu_tick_get_count(CPUTimer *timer);
 void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit);
 trap_state* cpu_tsptr(CPUSPARCState* env);
 #endif
+void do_unaligned_access(CPUSPARCState *env, target_ulong addr, int is_write,
+                         int is_user, void *retaddr);
 
 #define TB_FLAG_FPU_ENABLED (1 << 4)
 #define TB_FLAG_AM_ENABLED (1 << 5)
diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
index 8468cde..1418205 100644
--- a/target-sparc/ldst_helper.c
+++ b/target-sparc/ldst_helper.c
@@ -64,6 +64,24 @@
 #define QT0 (env->qt0)
 #define QT1 (env->qt1)
 
+#if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
+#define MMUSUFFIX _mmu
+#define ALIGNED_ONLY
+
+#define SHIFT 0
+#include "softmmu_template.h"
+
+#define SHIFT 1
+#include "softmmu_template.h"
+
+#define SHIFT 2
+#include "softmmu_template.h"
+
+#define SHIFT 3
+#include "softmmu_template.h"
+#endif
+
 #if defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
 /* Calculates TSB pointer value for fault page size 8k or 64k */
 static uint64_t ultrasparc_tsb_pointer(uint64_t tsb_register,
@@ -523,17 +541,17 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
     case 9: /* Supervisor code access */
         switch (size) {
         case 1:
-            ret = ldub_code(addr);
+            ret = cpu_ldub_code(env, addr);
             break;
         case 2:
-            ret = lduw_code(addr);
+            ret = cpu_lduw_code(env, addr);
             break;
         default:
         case 4:
-            ret = ldl_code(addr);
+            ret = cpu_ldl_code(env, addr);
             break;
         case 8:
-            ret = ldq_code(addr);
+            ret = cpu_ldq_code(env, addr);
             break;
         }
         break;
@@ -2355,3 +2373,50 @@ void cpu_unassigned_access(CPUSPARCState *env, target_phys_addr_t addr,
 }
 #endif
 #endif
+
+#if !defined(CONFIG_USER_ONLY)
+/* XXX: make it generic ? */
+static void cpu_restore_state2(CPUSPARCState *env, void *retaddr)
+{
+    TranslationBlock *tb;
+    unsigned long pc;
+
+    if (retaddr) {
+        /* now we have a real cpu fault */
+        pc = (unsigned long)retaddr;
+        tb = tb_find_pc(pc);
+        if (tb) {
+            /* the PC is inside the translated code. It means that we have
+               a virtual CPU fault */
+            cpu_restore_state(tb, env, pc);
+        }
+    }
+}
+
+void do_unaligned_access(CPUSPARCState *env, target_ulong addr, int is_write,
+                         int is_user, void *retaddr)
+{
+#ifdef DEBUG_UNALIGNED
+    printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
+           "\n", addr, env->pc);
+#endif
+    cpu_restore_state2(env, retaddr);
+    helper_raise_exception(env, TT_UNALIGNED);
+}
+
+/* try to fill the TLB and return an exception if error. If retaddr is
+   NULL, it means that the function was called in C code (i.e. not
+   from generated code or from helper.c) */
+/* XXX: fix it to restore all registers */
+void tlb_fill(CPUSPARCState *env, target_ulong addr, int is_write, int mmu_idx,
+              void *retaddr)
+{
+    int ret;
+
+    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx);
+    if (ret) {
+        cpu_restore_state2(env, retaddr);
+        cpu_loop_exit(env);
+    }
+}
+#endif
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
deleted file mode 100644
index b7171d8..0000000
--- a/target-sparc/op_helper.c
+++ /dev/null
@@ -1,174 +0,0 @@
-#include "cpu.h"
-#include "dyngen-exec.h"
-#include "helper.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
-                                void *retaddr);
-
-#define MMUSUFFIX _mmu
-#define ALIGNED_ONLY
-
-#define SHIFT 0
-#include "softmmu_template.h"
-
-#define SHIFT 1
-#include "softmmu_template.h"
-
-#define SHIFT 2
-#include "softmmu_template.h"
-
-#define SHIFT 3
-#include "softmmu_template.h"
-
-/* XXX: make it generic ? */
-static void cpu_restore_state2(void *retaddr)
-{
-    TranslationBlock *tb;
-    unsigned long pc;
-
-    if (retaddr) {
-        /* now we have a real cpu fault */
-        pc = (unsigned long)retaddr;
-        tb = tb_find_pc(pc);
-        if (tb) {
-            /* the PC is inside the translated code. It means that we have
-               a virtual CPU fault */
-            cpu_restore_state(tb, env, pc);
-        }
-    }
-}
-
-static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
-                                void *retaddr)
-{
-#ifdef DEBUG_UNALIGNED
-    printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
-           "\n", addr, env->pc);
-#endif
-    cpu_restore_state2(retaddr);
-    helper_raise_exception(env, TT_UNALIGNED);
-}
-
-/* try to fill the TLB and return an exception if error. If retaddr is
-   NULL, it means that the function was called in C code (i.e. not
-   from generated code or from helper.c) */
-/* XXX: fix it to restore all registers */
-void tlb_fill(CPUSPARCState *env1, target_ulong addr, int is_write, int mmu_idx,
-              void *retaddr)
-{
-    int ret;
-    CPUSPARCState *saved_env;
-
-    saved_env = env;
-    env = env1;
-
-    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx);
-    if (ret) {
-        cpu_restore_state2(retaddr);
-        cpu_loop_exit(env);
-    }
-    env = saved_env;
-}
-
-#define WRAP_LD(rettype, fn)                                    \
-    rettype cpu_ ## fn (CPUSPARCState *env1, target_ulong addr) \
-    {                                                           \
-        CPUSPARCState *saved_env;                               \
-        rettype ret;                                            \
-                                                                \
-        saved_env = env;                                        \
-        env = env1;                                             \
-        ret = fn(addr);                                         \
-        env = saved_env;                                        \
-        return ret;                                             \
-    }
-
-WRAP_LD(uint32_t, ldub_kernel)
-WRAP_LD(uint32_t, lduw_kernel)
-WRAP_LD(uint32_t, ldl_kernel)
-WRAP_LD(uint64_t, ldq_kernel)
-
-WRAP_LD(uint32_t, ldub_user)
-WRAP_LD(uint32_t, lduw_user)
-WRAP_LD(uint32_t, ldl_user)
-WRAP_LD(uint64_t, ldq_user)
-
-WRAP_LD(uint64_t, ldfq_kernel)
-WRAP_LD(uint64_t, ldfq_user)
-#ifdef TARGET_SPARC64
-WRAP_LD(uint32_t, ldub_hypv)
-WRAP_LD(uint32_t, lduw_hypv)
-WRAP_LD(uint32_t, ldl_hypv)
-WRAP_LD(uint64_t, ldq_hypv)
-
-WRAP_LD(uint64_t, ldfq_hypv)
-
-WRAP_LD(uint32_t, ldub_nucleus)
-WRAP_LD(uint32_t, lduw_nucleus)
-WRAP_LD(uint32_t, ldl_nucleus)
-WRAP_LD(uint64_t, ldq_nucleus)
-
-WRAP_LD(uint32_t, ldub_kernel_secondary)
-WRAP_LD(uint32_t, lduw_kernel_secondary)
-WRAP_LD(uint32_t, ldl_kernel_secondary)
-WRAP_LD(uint64_t, ldq_kernel_secondary)
-
-WRAP_LD(uint32_t, ldub_user_secondary)
-WRAP_LD(uint32_t, lduw_user_secondary)
-WRAP_LD(uint32_t, ldl_user_secondary)
-WRAP_LD(uint64_t, ldq_user_secondary)
-#endif
-#undef WRAP_LD
-
-#define WRAP_ST(datatype, fn)                                           \
-    void cpu_ ## fn (CPUSPARCState *env1, target_ulong addr, datatype val)   \
-    {                                                                   \
-        CPUSPARCState *saved_env;                                       \
-                                                                        \
-        saved_env = env;                                                \
-        env = env1;                                                     \
-        fn(addr, val);                                                  \
-        env = saved_env;                                                \
-    }
-
-WRAP_ST(uint32_t, stb_kernel)
-WRAP_ST(uint32_t, stw_kernel)
-WRAP_ST(uint32_t, stl_kernel)
-WRAP_ST(uint64_t, stq_kernel)
-
-WRAP_ST(uint32_t, stb_user)
-WRAP_ST(uint32_t, stw_user)
-WRAP_ST(uint32_t, stl_user)
-WRAP_ST(uint64_t, stq_user)
-
-WRAP_ST(uint64_t, stfq_kernel)
-WRAP_ST(uint64_t, stfq_user)
-
-#ifdef TARGET_SPARC64
-WRAP_ST(uint32_t, stb_hypv)
-WRAP_ST(uint32_t, stw_hypv)
-WRAP_ST(uint32_t, stl_hypv)
-WRAP_ST(uint64_t, stq_hypv)
-
-WRAP_ST(uint64_t, stfq_hypv)
-
-WRAP_ST(uint32_t, stb_nucleus)
-WRAP_ST(uint32_t, stw_nucleus)
-WRAP_ST(uint32_t, stl_nucleus)
-WRAP_ST(uint64_t, stq_nucleus)
-
-WRAP_ST(uint32_t, stb_kernel_secondary)
-WRAP_ST(uint32_t, stw_kernel_secondary)
-WRAP_ST(uint32_t, stl_kernel_secondary)
-WRAP_ST(uint64_t, stq_kernel_secondary)
-
-WRAP_ST(uint32_t, stb_user_secondary)
-WRAP_ST(uint32_t, stw_user_secondary)
-WRAP_ST(uint32_t, stl_user_secondary)
-WRAP_ST(uint64_t, stq_user_secondary)
-#endif
-
-#undef WRAP_ST
-#endif
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 670ea2b..4967152 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -2373,9 +2373,9 @@ static void gen_faligndata(TCGv dst, TCGv gsr, TCGv s1, TCGv s2)
         goto nfpu_insn;
 
 /* before an instruction, dc->pc must be static */
-static void disas_sparc_insn(DisasContext * dc)
+static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
 {
-    unsigned int insn, opc, rs1, rs2, rd;
+    unsigned int opc, rs1, rs2, rd;
     TCGv cpu_src1, cpu_src2, cpu_tmp1, cpu_tmp2;
     TCGv_i32 cpu_src1_32, cpu_src2_32, cpu_dst_32;
     TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64;
@@ -2383,7 +2383,7 @@ static void disas_sparc_insn(DisasContext * dc)
 
     if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
         tcg_gen_debug_insn_start(dc->pc);
-    insn = ldl_code(dc->pc);
+
     opc = GET_FIELD(insn, 0, 1);
 
     rd = GET_FIELD(insn, 2, 6);
@@ -5240,6 +5240,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
     int j, lj = -1;
     int num_insns;
     int max_insns;
+    unsigned int insn;
 
     memset(dc, 0, sizeof(DisasContext));
     dc->tb = tb;
@@ -5299,7 +5300,8 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
             gen_io_start();
         last_pc = dc->pc;
-        disas_sparc_insn(dc);
+        insn = cpu_ldl_code(env, dc->pc);
+        disas_sparc_insn(dc, insn);
         num_insns++;
 
         if (dc->is_br)
commit fe8d8f0f1c3ed0f5e84edffbbc8fcdf3b7da589b
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Mon Jul 4 20:34:28 2011 +0000

    Sparc: avoid AREG0 for memory access helpers
    
    Make memory access helpers take a parameter for CPUState instead
    of relying on global env. Introduce wrappers for load and store ops.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index eb25941..d2ba029 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -103,7 +103,7 @@ $(libobj-y): $(GENERATED_HEADERS)
 
 # HELPER_CFLAGS is used for all the code compiled with static register
 # variables
-op_helper.o ldst_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
+op_helper.o 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.
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index f638457..ee28daa 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -586,8 +586,90 @@ void cpu_unassigned_access(CPUSPARCState *env1, target_phys_addr_t addr,
 #if defined(TARGET_SPARC64)
 target_phys_addr_t cpu_get_phys_page_nofault(CPUSPARCState *env, target_ulong addr,
                                            int mmu_idx);
+#endif
+
+#define WRAP_LD(rettype, fn)                                    \
+    rettype cpu_ ## fn (CPUSPARCState *env1, target_ulong addr)
+
+WRAP_LD(uint32_t, ldub_kernel);
+WRAP_LD(uint32_t, lduw_kernel);
+WRAP_LD(uint32_t, ldl_kernel);
+WRAP_LD(uint64_t, ldq_kernel);
+
+WRAP_LD(uint32_t, ldub_user);
+WRAP_LD(uint32_t, lduw_user);
+WRAP_LD(uint32_t, ldl_user);
+WRAP_LD(uint64_t, ldq_user);
+
+WRAP_LD(uint64_t, ldfq_kernel);
+WRAP_LD(uint64_t, ldfq_user);
+
+#ifdef TARGET_SPARC64
+WRAP_LD(uint32_t, ldub_hypv);
+WRAP_LD(uint32_t, lduw_hypv);
+WRAP_LD(uint32_t, ldl_hypv);
+WRAP_LD(uint64_t, ldq_hypv);
+
+WRAP_LD(uint64_t, ldfq_hypv);
+
+WRAP_LD(uint32_t, ldub_nucleus);
+WRAP_LD(uint32_t, lduw_nucleus);
+WRAP_LD(uint32_t, ldl_nucleus);
+WRAP_LD(uint64_t, ldq_nucleus);
+
+WRAP_LD(uint32_t, ldub_kernel_secondary);
+WRAP_LD(uint32_t, lduw_kernel_secondary);
+WRAP_LD(uint32_t, ldl_kernel_secondary);
+WRAP_LD(uint64_t, ldq_kernel_secondary);
+
+WRAP_LD(uint32_t, ldub_user_secondary);
+WRAP_LD(uint32_t, lduw_user_secondary);
+WRAP_LD(uint32_t, ldl_user_secondary);
+WRAP_LD(uint64_t, ldq_user_secondary);
+#endif
+#undef WRAP_LD
+
+#define WRAP_ST(datatype, fn)                                           \
+    void cpu_ ## fn (CPUSPARCState *env1, target_ulong addr, datatype val)
+
+WRAP_ST(uint32_t, stb_kernel);
+WRAP_ST(uint32_t, stw_kernel);
+WRAP_ST(uint32_t, stl_kernel);
+WRAP_ST(uint64_t, stq_kernel);
+
+WRAP_ST(uint32_t, stb_user);
+WRAP_ST(uint32_t, stw_user);
+WRAP_ST(uint32_t, stl_user);
+WRAP_ST(uint64_t, stq_user);
 
+WRAP_ST(uint64_t, stfq_kernel);
+WRAP_ST(uint64_t, stfq_user);
+
+#ifdef TARGET_SPARC64
+WRAP_ST(uint32_t, stb_hypv);
+WRAP_ST(uint32_t, stw_hypv);
+WRAP_ST(uint32_t, stl_hypv);
+WRAP_ST(uint64_t, stq_hypv);
+
+WRAP_ST(uint64_t, stfq_hypv);
+
+WRAP_ST(uint32_t, stb_nucleus);
+WRAP_ST(uint32_t, stw_nucleus);
+WRAP_ST(uint32_t, stl_nucleus);
+WRAP_ST(uint64_t, stq_nucleus);
+
+WRAP_ST(uint32_t, stb_kernel_secondary);
+WRAP_ST(uint32_t, stw_kernel_secondary);
+WRAP_ST(uint32_t, stl_kernel_secondary);
+WRAP_ST(uint64_t, stq_kernel_secondary);
+
+WRAP_ST(uint32_t, stb_user_secondary);
+WRAP_ST(uint32_t, stw_user_secondary);
+WRAP_ST(uint32_t, stl_user_secondary);
+WRAP_ST(uint64_t, stq_user_secondary);
 #endif
+
+#undef WRAP_ST
 #endif
 int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
 
diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index 1f67b08..c4d6225 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -18,11 +18,11 @@ DEF_HELPER_1(rdcwp, tl, env)
 DEF_HELPER_2(wrcwp, void, env, tl)
 DEF_HELPER_FLAGS_2(array8, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
 DEF_HELPER_1(popc, tl, tl)
-DEF_HELPER_3(ldda_asi, void, tl, int, int)
-DEF_HELPER_4(ldf_asi, void, tl, int, int, int)
-DEF_HELPER_4(stf_asi, void, tl, int, int, int)
-DEF_HELPER_4(cas_asi, tl, tl, tl, tl, i32)
-DEF_HELPER_4(casx_asi, tl, tl, tl, tl, i32)
+DEF_HELPER_4(ldda_asi, void, env, tl, int, int)
+DEF_HELPER_5(ldf_asi, void, env, tl, int, int, int)
+DEF_HELPER_5(stf_asi, void, env, tl, int, int, int)
+DEF_HELPER_5(cas_asi, tl, env, tl, tl, tl, i32)
+DEF_HELPER_5(casx_asi, tl, env, tl, tl, tl, i32)
 DEF_HELPER_2(set_softint, void, env, i64)
 DEF_HELPER_2(clear_softint, void, env, i64)
 DEF_HELPER_2(write_softint, void, env, i64)
@@ -30,7 +30,7 @@ DEF_HELPER_2(tick_set_count, void, ptr, i64)
 DEF_HELPER_1(tick_get_count, i64, ptr)
 DEF_HELPER_2(tick_set_limit, void, ptr, i64)
 #endif
-DEF_HELPER_2(check_align, void, tl, i32)
+DEF_HELPER_3(check_align, void, env, tl, i32)
 DEF_HELPER_1(debug, void, env)
 DEF_HELPER_1(save, void, env)
 DEF_HELPER_1(restore, void, env)
@@ -38,11 +38,11 @@ DEF_HELPER_3(udiv, tl, env, tl, tl)
 DEF_HELPER_3(udiv_cc, tl, env, tl, tl)
 DEF_HELPER_3(sdiv, tl, env, tl, tl)
 DEF_HELPER_3(sdiv_cc, tl, env, tl, tl)
-DEF_HELPER_2(ldqf, void, tl, int)
-DEF_HELPER_2(stqf, void, tl, int)
+DEF_HELPER_3(ldqf, void, env, tl, int)
+DEF_HELPER_3(stqf, void, env, tl, int)
 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
-DEF_HELPER_4(ld_asi, i64, tl, int, int, int)
-DEF_HELPER_4(st_asi, void, tl, i64, int, int)
+DEF_HELPER_5(ld_asi, i64, env, tl, int, int, int)
+DEF_HELPER_5(st_asi, void, env, tl, i64, int, int)
 #endif
 DEF_HELPER_2(ldfsr, void, env, i32)
 DEF_HELPER_FLAGS_1(fabss, TCG_CALL_CONST | TCG_CALL_PURE, f32, f32)
diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
index 97afdd3..8468cde 100644
--- a/target-sparc/ldst_helper.c
+++ b/target-sparc/ldst_helper.c
@@ -18,13 +18,8 @@
  */
 
 #include "cpu.h"
-#include "dyngen-exec.h"
 #include "helper.h"
 
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#endif
-
 //#define DEBUG_MMU
 //#define DEBUG_MXCC
 //#define DEBUG_UNALIGNED
@@ -69,16 +64,6 @@
 #define QT0 (env->qt0)
 #define QT1 (env->qt1)
 
-#if !defined(CONFIG_USER_ONLY)
-static void do_unassigned_access(target_phys_addr_t addr, int is_write,
-                                 int is_exec, int is_asi, int size);
-#else
-#ifdef TARGET_SPARC64
-static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
-                                 int is_asi, int size);
-#endif
-#endif
-
 #if defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
 /* Calculates TSB pointer value for fault page size 8k or 64k */
 static uint64_t ultrasparc_tsb_pointer(uint64_t tsb_register,
@@ -300,7 +285,7 @@ static inline int is_translating_asi(int asi)
 #endif
 }
 
-static inline target_ulong asi_address_mask(CPUSPARCState *env1,
+static inline target_ulong asi_address_mask(CPUSPARCState *env,
                                             int asi, target_ulong addr)
 {
     if (is_translating_asi(asi)) {
@@ -310,7 +295,7 @@ static inline target_ulong asi_address_mask(CPUSPARCState *env1,
     }
 }
 
-void helper_check_align(target_ulong addr, uint32_t align)
+void helper_check_align(CPUSPARCState *env, target_ulong addr, uint32_t align)
 {
     if (addr & align) {
 #ifdef DEBUG_UNALIGNED
@@ -372,7 +357,8 @@ static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
 
 /* Leon3 cache control */
 
-static void leon3_cache_control_st(target_ulong addr, uint64_t val, int size)
+static void leon3_cache_control_st(CPUSPARCState *env, target_ulong addr,
+                                   uint64_t val, int size)
 {
     DPRINTF_CACHE_CONTROL("st addr:%08x, val:%" PRIx64 ", size:%d\n",
                           addr, val, size);
@@ -404,7 +390,8 @@ static void leon3_cache_control_st(target_ulong addr, uint64_t val, int size)
     };
 }
 
-static uint64_t leon3_cache_control_ld(target_ulong addr, int size)
+static uint64_t leon3_cache_control_ld(CPUSPARCState *env, target_ulong addr,
+                                       int size)
 {
     uint64_t ret = 0;
 
@@ -436,14 +423,15 @@ static uint64_t leon3_cache_control_ld(target_ulong addr, int size)
     return ret;
 }
 
-uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
+uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
+                       int sign)
 {
     uint64_t ret = 0;
 #if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
     uint32_t last_addr = addr;
 #endif
 
-    helper_check_align(addr, size - 1);
+    helper_check_align(env, addr, size - 1);
     switch (asi) {
     case 2: /* SuperSparc MXCC registers and Leon3 cache control */
         switch (addr) {
@@ -451,7 +439,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
         case 0x08:          /* Leon3 Instruction Cache config */
         case 0x0C:          /* Leon3 Date Cache config */
             if (env->def->features & CPU_FEATURE_CACHE_CTRL) {
-                ret = leon3_cache_control_ld(addr, size);
+                ret = leon3_cache_control_ld(env, addr, size);
             }
             break;
         case 0x01c00a00: /* MXCC control register */
@@ -552,34 +540,34 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
     case 0xa: /* User data access */
         switch (size) {
         case 1:
-            ret = ldub_user(addr);
+            ret = cpu_ldub_user(env, addr);
             break;
         case 2:
-            ret = lduw_user(addr);
+            ret = cpu_lduw_user(env, addr);
             break;
         default:
         case 4:
-            ret = ldl_user(addr);
+            ret = cpu_ldl_user(env, addr);
             break;
         case 8:
-            ret = ldq_user(addr);
+            ret = cpu_ldq_user(env, addr);
             break;
         }
         break;
     case 0xb: /* Supervisor data access */
         switch (size) {
         case 1:
-            ret = ldub_kernel(addr);
+            ret = cpu_ldub_kernel(env, addr);
             break;
         case 2:
-            ret = lduw_kernel(addr);
+            ret = cpu_lduw_kernel(env, addr);
             break;
         default:
         case 4:
-            ret = ldl_kernel(addr);
+            ret = cpu_ldl_kernel(env, addr);
             break;
         case 8:
-            ret = ldq_kernel(addr);
+            ret = cpu_ldq_kernel(env, addr);
             break;
         }
         break;
@@ -669,7 +657,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
         break;
     case 8: /* User code access, XXX */
     default:
-        do_unassigned_access(addr, 0, 0, asi, size);
+        cpu_unassigned_access(env, addr, 0, 0, asi, size);
         ret = 0;
         break;
     }
@@ -694,9 +682,10 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
     return ret;
 }
 
-void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
+void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
+                   int size)
 {
-    helper_check_align(addr, size - 1);
+    helper_check_align(env, addr, size - 1);
     switch (asi) {
     case 2: /* SuperSparc MXCC registers and Leon3 cache control */
         switch (addr) {
@@ -704,7 +693,7 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
         case 0x08:          /* Leon3 Instruction Cache config */
         case 0x0C:          /* Leon3 Date Cache config */
             if (env->def->features & CPU_FEATURE_CACHE_CTRL) {
-                leon3_cache_control_st(addr, val, size);
+                leon3_cache_control_st(env, addr, val, size);
             }
             break;
 
@@ -902,34 +891,34 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
     case 0xa: /* User data access */
         switch (size) {
         case 1:
-            stb_user(addr, val);
+            cpu_stb_user(env, addr, val);
             break;
         case 2:
-            stw_user(addr, val);
+            cpu_stw_user(env, addr, val);
             break;
         default:
         case 4:
-            stl_user(addr, val);
+            cpu_stl_user(env, addr, val);
             break;
         case 8:
-            stq_user(addr, val);
+            cpu_stq_user(env, addr, val);
             break;
         }
         break;
     case 0xb: /* Supervisor data access */
         switch (size) {
         case 1:
-            stb_kernel(addr, val);
+            cpu_stb_kernel(env, addr, val);
             break;
         case 2:
-            stw_kernel(addr, val);
+            cpu_stw_kernel(env, addr, val);
             break;
         default:
         case 4:
-            stl_kernel(addr, val);
+            cpu_stl_kernel(env, addr, val);
             break;
         case 8:
-            stq_kernel(addr, val);
+            cpu_stq_kernel(env, addr, val);
             break;
         }
         break;
@@ -952,8 +941,8 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
             uint32_t src = val & ~3, dst = addr & ~3, temp;
 
             for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
-                temp = ldl_kernel(src);
-                stl_kernel(dst, temp);
+                temp = cpu_ldl_kernel(env, src);
+                cpu_stl_kernel(env, dst, temp);
             }
         }
         break;
@@ -965,7 +954,7 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
             uint32_t dst = addr & 7;
 
             for (i = 0; i < 32; i += 8, dst += 8) {
-                stq_kernel(dst, val);
+                cpu_stq_kernel(env, dst, val);
             }
         }
         break;
@@ -1056,7 +1045,7 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
     case 8: /* User code access, XXX */
     case 9: /* Supervisor code access, XXX */
     default:
-        do_unassigned_access(addr, 1, 0, asi, size);
+        cpu_unassigned_access(env, addr, 1, 0, asi, size);
         break;
     }
 #ifdef DEBUG_ASI
@@ -1068,7 +1057,8 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
 #else /* TARGET_SPARC64 */
 
 #ifdef CONFIG_USER_ONLY
-uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
+uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
+                       int sign)
 {
     uint64_t ret = 0;
 #if defined(DEBUG_ASI)
@@ -1079,7 +1069,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
         helper_raise_exception(env, TT_PRIV_ACT);
     }
 
-    helper_check_align(addr, size - 1);
+    helper_check_align(env, addr, size - 1);
     addr = asi_address_mask(env, asi, addr);
 
     switch (asi) {
@@ -1174,7 +1164,8 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
     return ret;
 }
 
-void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
+void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
+                   int asi, int size)
 {
 #ifdef DEBUG_ASI
     dump_asi("write", addr, asi, size, val);
@@ -1183,7 +1174,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
         helper_raise_exception(env, TT_PRIV_ACT);
     }
 
-    helper_check_align(addr, size - 1);
+    helper_check_align(env, addr, size - 1);
     addr = asi_address_mask(env, asi, addr);
 
     /* Convert to little endian */
@@ -1238,14 +1229,15 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
     case 0x8a: /* Primary no-fault LE, RO */
     case 0x8b: /* Secondary no-fault LE, RO */
     default:
-        do_unassigned_access(addr, 1, 0, 1, size);
+        helper_raise_exception(env, TT_DATA_ACCESS);
         return;
     }
 }
 
 #else /* CONFIG_USER_ONLY */
 
-uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
+uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
+                       int sign)
 {
     uint64_t ret = 0;
 #if defined(DEBUG_ASI)
@@ -1261,7 +1253,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
         helper_raise_exception(env, TT_PRIV_ACT);
     }
 
-    helper_check_align(addr, size - 1);
+    helper_check_align(env, addr, size - 1);
     addr = asi_address_mask(env, asi, addr);
 
     /* process nonfaulting loads first */
@@ -1302,17 +1294,17 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
             if (cpu_hypervisor_mode(env)) {
                 switch (size) {
                 case 1:
-                    ret = ldub_hypv(addr);
+                    ret = cpu_ldub_hypv(env, addr);
                     break;
                 case 2:
-                    ret = lduw_hypv(addr);
+                    ret = cpu_lduw_hypv(env, addr);
                     break;
                 case 4:
-                    ret = ldl_hypv(addr);
+                    ret = cpu_ldl_hypv(env, addr);
                     break;
                 default:
                 case 8:
-                    ret = ldq_hypv(addr);
+                    ret = cpu_ldq_hypv(env, addr);
                     break;
                 }
             } else {
@@ -1320,33 +1312,33 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
                 if (asi & 1) {
                     switch (size) {
                     case 1:
-                        ret = ldub_kernel_secondary(addr);
+                        ret = cpu_ldub_kernel_secondary(env, addr);
                         break;
                     case 2:
-                        ret = lduw_kernel_secondary(addr);
+                        ret = cpu_lduw_kernel_secondary(env, addr);
                         break;
                     case 4:
-                        ret = ldl_kernel_secondary(addr);
+                        ret = cpu_ldl_kernel_secondary(env, addr);
                         break;
                     default:
                     case 8:
-                        ret = ldq_kernel_secondary(addr);
+                        ret = cpu_ldq_kernel_secondary(env, addr);
                         break;
                     }
                 } else {
                     switch (size) {
                     case 1:
-                        ret = ldub_kernel(addr);
+                        ret = cpu_ldub_kernel(env, addr);
                         break;
                     case 2:
-                        ret = lduw_kernel(addr);
+                        ret = cpu_lduw_kernel(env, addr);
                         break;
                     case 4:
-                        ret = ldl_kernel(addr);
+                        ret = cpu_ldl_kernel(env, addr);
                         break;
                     default:
                     case 8:
-                        ret = ldq_kernel(addr);
+                        ret = cpu_ldq_kernel(env, addr);
                         break;
                     }
                 }
@@ -1356,33 +1348,33 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
             if (asi & 1) {
                 switch (size) {
                 case 1:
-                    ret = ldub_user_secondary(addr);
+                    ret = cpu_ldub_user_secondary(env, addr);
                     break;
                 case 2:
-                    ret = lduw_user_secondary(addr);
+                    ret = cpu_lduw_user_secondary(env, addr);
                     break;
                 case 4:
-                    ret = ldl_user_secondary(addr);
+                    ret = cpu_ldl_user_secondary(env, addr);
                     break;
                 default:
                 case 8:
-                    ret = ldq_user_secondary(addr);
+                    ret = cpu_ldq_user_secondary(env, addr);
                     break;
                 }
             } else {
                 switch (size) {
                 case 1:
-                    ret = ldub_user(addr);
+                    ret = cpu_ldub_user(env, addr);
                     break;
                 case 2:
-                    ret = lduw_user(addr);
+                    ret = cpu_lduw_user(env, addr);
                     break;
                 case 4:
-                    ret = ldl_user(addr);
+                    ret = cpu_ldl_user(env, addr);
                     break;
                 default:
                 case 8:
-                    ret = ldq_user(addr);
+                    ret = cpu_ldq_user(env, addr);
                     break;
                 }
             }
@@ -1420,17 +1412,17 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
         {
             switch (size) {
             case 1:
-                ret = ldub_nucleus(addr);
+                ret = cpu_ldub_nucleus(env, addr);
                 break;
             case 2:
-                ret = lduw_nucleus(addr);
+                ret = cpu_lduw_nucleus(env, addr);
                 break;
             case 4:
-                ret = ldl_nucleus(addr);
+                ret = cpu_ldl_nucleus(env, addr);
                 break;
             default:
             case 8:
-                ret = ldq_nucleus(addr);
+                ret = cpu_ldq_nucleus(env, addr);
                 break;
             }
             break;
@@ -1559,7 +1551,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
     case 0x5f: /* D-MMU demap, WO */
     case 0x77: /* Interrupt vector, WO */
     default:
-        do_unassigned_access(addr, 0, 0, 1, size);
+        cpu_unassigned_access(env, addr, 0, 0, 1, size);
         ret = 0;
         break;
     }
@@ -1612,7 +1604,8 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
     return ret;
 }
 
-void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
+void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
+                   int asi, int size)
 {
 #ifdef DEBUG_ASI
     dump_asi("write", addr, asi, size, val);
@@ -1627,7 +1620,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
         helper_raise_exception(env, TT_PRIV_ACT);
     }
 
-    helper_check_align(addr, size - 1);
+    helper_check_align(env, addr, size - 1);
     addr = asi_address_mask(env, asi, addr);
 
     /* Convert to little endian */
@@ -1671,17 +1664,17 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
             if (cpu_hypervisor_mode(env)) {
                 switch (size) {
                 case 1:
-                    stb_hypv(addr, val);
+                    cpu_stb_hypv(env, addr, val);
                     break;
                 case 2:
-                    stw_hypv(addr, val);
+                    cpu_stw_hypv(env, addr, val);
                     break;
                 case 4:
-                    stl_hypv(addr, val);
+                    cpu_stl_hypv(env, addr, val);
                     break;
                 case 8:
                 default:
-                    stq_hypv(addr, val);
+                    cpu_stq_hypv(env, addr, val);
                     break;
                 }
             } else {
@@ -1689,33 +1682,33 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
                 if (asi & 1) {
                     switch (size) {
                     case 1:
-                        stb_kernel_secondary(addr, val);
+                        cpu_stb_kernel_secondary(env, addr, val);
                         break;
                     case 2:
-                        stw_kernel_secondary(addr, val);
+                        cpu_stw_kernel_secondary(env, addr, val);
                         break;
                     case 4:
-                        stl_kernel_secondary(addr, val);
+                        cpu_stl_kernel_secondary(env, addr, val);
                         break;
                     case 8:
                     default:
-                        stq_kernel_secondary(addr, val);
+                        cpu_stq_kernel_secondary(env, addr, val);
                         break;
                     }
                 } else {
                     switch (size) {
                     case 1:
-                        stb_kernel(addr, val);
+                        cpu_stb_kernel(env, addr, val);
                         break;
                     case 2:
-                        stw_kernel(addr, val);
+                        cpu_stw_kernel(env, addr, val);
                         break;
                     case 4:
-                        stl_kernel(addr, val);
+                        cpu_stl_kernel(env, addr, val);
                         break;
                     case 8:
                     default:
-                        stq_kernel(addr, val);
+                        cpu_stq_kernel(env, addr, val);
                         break;
                     }
                 }
@@ -1725,33 +1718,33 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
             if (asi & 1) {
                 switch (size) {
                 case 1:
-                    stb_user_secondary(addr, val);
+                    cpu_stb_user_secondary(env, addr, val);
                     break;
                 case 2:
-                    stw_user_secondary(addr, val);
+                    cpu_stw_user_secondary(env, addr, val);
                     break;
                 case 4:
-                    stl_user_secondary(addr, val);
+                    cpu_stl_user_secondary(env, addr, val);
                     break;
                 case 8:
                 default:
-                    stq_user_secondary(addr, val);
+                    cpu_stq_user_secondary(env, addr, val);
                     break;
                 }
             } else {
                 switch (size) {
                 case 1:
-                    stb_user(addr, val);
+                    cpu_stb_user(env, addr, val);
                     break;
                 case 2:
-                    stw_user(addr, val);
+                    cpu_stw_user(env, addr, val);
                     break;
                 case 4:
-                    stl_user(addr, val);
+                    cpu_stl_user(env, addr, val);
                     break;
                 case 8:
                 default:
-                    stq_user(addr, val);
+                    cpu_stq_user(env, addr, val);
                     break;
                 }
             }
@@ -1789,17 +1782,17 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
         {
             switch (size) {
             case 1:
-                stb_nucleus(addr, val);
+                cpu_stb_nucleus(env, addr, val);
                 break;
             case 2:
-                stw_nucleus(addr, val);
+                cpu_stw_nucleus(env, addr, val);
                 break;
             case 4:
-                stl_nucleus(addr, val);
+                cpu_stl_nucleus(env, addr, val);
                 break;
             default:
             case 8:
-                stq_nucleus(addr, val);
+                cpu_stq_nucleus(env, addr, val);
                 break;
             }
             break;
@@ -1991,13 +1984,13 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
     case 0x8a: /* Primary no-fault LE, RO */
     case 0x8b: /* Secondary no-fault LE, RO */
     default:
-        do_unassigned_access(addr, 1, 0, 1, size);
+        cpu_unassigned_access(env, addr, 1, 0, 1, size);
         return;
     }
 }
 #endif /* CONFIG_USER_ONLY */
 
-void helper_ldda_asi(target_ulong addr, int asi, int rd)
+void helper_ldda_asi(CPUSPARCState *env, target_ulong addr, int asi, int rd)
 {
     if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
         || (cpu_has_hypervisor(env)
@@ -2012,22 +2005,22 @@ void helper_ldda_asi(target_ulong addr, int asi, int rd)
 #if !defined(CONFIG_USER_ONLY)
     case 0x24: /* Nucleus quad LDD 128 bit atomic */
     case 0x2c: /* Nucleus quad LDD 128 bit atomic LE */
-        helper_check_align(addr, 0xf);
+        helper_check_align(env, addr, 0xf);
         if (rd == 0) {
-            env->gregs[1] = ldq_nucleus(addr + 8);
+            env->gregs[1] = cpu_ldq_nucleus(env, addr + 8);
             if (asi == 0x2c) {
                 bswap64s(&env->gregs[1]);
             }
         } else if (rd < 8) {
-            env->gregs[rd] = ldq_nucleus(addr);
-            env->gregs[rd + 1] = ldq_nucleus(addr + 8);
+            env->gregs[rd] = cpu_ldq_nucleus(env, addr);
+            env->gregs[rd + 1] = cpu_ldq_nucleus(env, addr + 8);
             if (asi == 0x2c) {
                 bswap64s(&env->gregs[rd]);
                 bswap64s(&env->gregs[rd + 1]);
             }
         } else {
-            env->regwptr[rd] = ldq_nucleus(addr);
-            env->regwptr[rd + 1] = ldq_nucleus(addr + 8);
+            env->regwptr[rd] = cpu_ldq_nucleus(env, addr);
+            env->regwptr[rd + 1] = cpu_ldq_nucleus(env, addr + 8);
             if (asi == 0x2c) {
                 bswap64s(&env->regwptr[rd]);
                 bswap64s(&env->regwptr[rd + 1]);
@@ -2036,26 +2029,27 @@ void helper_ldda_asi(target_ulong addr, int asi, int rd)
         break;
 #endif
     default:
-        helper_check_align(addr, 0x3);
+        helper_check_align(env, addr, 0x3);
         if (rd == 0) {
-            env->gregs[1] = helper_ld_asi(addr + 4, asi, 4, 0);
+            env->gregs[1] = helper_ld_asi(env, addr + 4, asi, 4, 0);
         } else if (rd < 8) {
-            env->gregs[rd] = helper_ld_asi(addr, asi, 4, 0);
-            env->gregs[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
+            env->gregs[rd] = helper_ld_asi(env, addr, asi, 4, 0);
+            env->gregs[rd + 1] = helper_ld_asi(env, addr + 4, asi, 4, 0);
         } else {
-            env->regwptr[rd] = helper_ld_asi(addr, asi, 4, 0);
-            env->regwptr[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
+            env->regwptr[rd] = helper_ld_asi(env, addr, asi, 4, 0);
+            env->regwptr[rd + 1] = helper_ld_asi(env, addr + 4, asi, 4, 0);
         }
         break;
     }
 }
 
-void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
+void helper_ldf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
+                    int rd)
 {
     unsigned int i;
     target_ulong val;
 
-    helper_check_align(addr, 3);
+    helper_check_align(env, addr, 3);
     addr = asi_address_mask(env, asi, addr);
 
     switch (asi) {
@@ -2067,9 +2061,9 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
             helper_raise_exception(env, TT_ILL_INSN);
             return;
         }
-        helper_check_align(addr, 0x3f);
+        helper_check_align(env, addr, 0x3f);
         for (i = 0; i < 8; i++, rd += 2, addr += 8) {
-            env->fpr[rd/2].ll = helper_ld_asi(addr, asi & 0x8f, 8, 0);
+            env->fpr[rd / 2].ll = helper_ld_asi(env, addr, asi & 0x8f, 8, 0);
         }
         return;
 
@@ -2085,9 +2079,9 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
             helper_raise_exception(env, TT_ILL_INSN);
             return;
         }
-        helper_check_align(addr, 0x3f);
+        helper_check_align(env, addr, 0x3f);
         for (i = 0; i < 8; i++, rd += 2, addr += 4) {
-            env->fpr[rd/2].ll = helper_ld_asi(addr, asi & 0x19, 8, 0);
+            env->fpr[rd / 2].ll = helper_ld_asi(env, addr, asi & 0x19, 8, 0);
         }
         return;
 
@@ -2098,29 +2092,30 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
     switch (size) {
     default:
     case 4:
-        val = helper_ld_asi(addr, asi, size, 0);
+        val = helper_ld_asi(env, addr, asi, size, 0);
         if (rd & 1) {
-            env->fpr[rd/2].l.lower = val;
+            env->fpr[rd / 2].l.lower = val;
         } else {
-            env->fpr[rd/2].l.upper = val;
+            env->fpr[rd / 2].l.upper = val;
         }
         break;
     case 8:
-        env->fpr[rd/2].ll = helper_ld_asi(addr, asi, size, 0);
+        env->fpr[rd / 2].ll = helper_ld_asi(env, addr, asi, size, 0);
         break;
     case 16:
-        env->fpr[rd/2].ll = helper_ld_asi(addr, asi, 8, 0);
-        env->fpr[rd/2 + 1].ll = helper_ld_asi(addr + 8, asi, 8, 0);
+        env->fpr[rd / 2].ll = helper_ld_asi(env, addr, asi, 8, 0);
+        env->fpr[rd / 2 + 1].ll = helper_ld_asi(env, addr + 8, asi, 8, 0);
         break;
     }
 }
 
-void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
+void helper_stf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
+                    int rd)
 {
     unsigned int i;
     target_ulong val;
 
-    helper_check_align(addr, 3);
+    helper_check_align(env, addr, 3);
     addr = asi_address_mask(env, asi, addr);
 
     switch (asi) {
@@ -2134,9 +2129,9 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
             helper_raise_exception(env, TT_ILL_INSN);
             return;
         }
-        helper_check_align(addr, 0x3f);
+        helper_check_align(env, addr, 0x3f);
         for (i = 0; i < 8; i++, rd += 2, addr += 8) {
-            helper_st_asi(addr, env->fpr[rd/2].ll, asi & 0x8f, 8);
+            helper_st_asi(env, addr, env->fpr[rd / 2].ll, asi & 0x8f, 8);
         }
 
         return;
@@ -2152,9 +2147,9 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
             helper_raise_exception(env, TT_ILL_INSN);
             return;
         }
-        helper_check_align(addr, 0x3f);
+        helper_check_align(env, addr, 0x3f);
         for (i = 0; i < 8; i++, rd += 2, addr += 8) {
-            helper_st_asi(addr, env->fpr[rd/2].ll, asi & 0x19, 8);
+            helper_st_asi(env, addr, env->fpr[rd / 2].ll, asi & 0x19, 8);
         }
 
         return;
@@ -2166,71 +2161,72 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
     default:
     case 4:
         if (rd & 1) {
-            val = env->fpr[rd/2].l.lower;
+            val = env->fpr[rd / 2].l.lower;
         } else {
-            val = env->fpr[rd/2].l.upper;
+            val = env->fpr[rd / 2].l.upper;
         }
-        helper_st_asi(addr, val, asi, size);
+        helper_st_asi(env, addr, val, asi, size);
         break;
     case 8:
-        helper_st_asi(addr, env->fpr[rd/2].ll, asi, size);
+        helper_st_asi(env, addr, env->fpr[rd / 2].ll, asi, size);
         break;
     case 16:
-        helper_st_asi(addr, env->fpr[rd/2].ll, asi, 8);
-        helper_st_asi(addr + 8, env->fpr[rd/2 + 1].ll, asi, 8);
+        helper_st_asi(env, addr, env->fpr[rd / 2].ll, asi, 8);
+        helper_st_asi(env, addr + 8, env->fpr[rd / 2 + 1].ll, asi, 8);
         break;
     }
 }
 
-target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
-                            target_ulong val2, uint32_t asi)
+target_ulong helper_cas_asi(CPUSPARCState *env, target_ulong addr,
+                            target_ulong val1, target_ulong val2, uint32_t asi)
 {
     target_ulong ret;
 
     val2 &= 0xffffffffUL;
-    ret = helper_ld_asi(addr, asi, 4, 0);
+    ret = helper_ld_asi(env, addr, asi, 4, 0);
     ret &= 0xffffffffUL;
     if (val2 == ret) {
-        helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4);
+        helper_st_asi(env, addr, val1 & 0xffffffffUL, asi, 4);
     }
     return ret;
 }
 
-target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
-                             target_ulong val2, uint32_t asi)
+target_ulong helper_casx_asi(CPUSPARCState *env, target_ulong addr,
+                             target_ulong val1, target_ulong val2,
+                             uint32_t asi)
 {
     target_ulong ret;
 
-    ret = helper_ld_asi(addr, asi, 8, 0);
+    ret = helper_ld_asi(env, addr, asi, 8, 0);
     if (val2 == ret) {
-        helper_st_asi(addr, val1, asi, 8);
+        helper_st_asi(env, addr, val1, asi, 8);
     }
     return ret;
 }
 #endif /* TARGET_SPARC64 */
 
-void helper_ldqf(target_ulong addr, int mem_idx)
+void helper_ldqf(CPUSPARCState *env, target_ulong addr, int mem_idx)
 {
     /* XXX add 128 bit load */
     CPU_QuadU u;
 
-    helper_check_align(addr, 7);
+    helper_check_align(env, addr, 7);
 #if !defined(CONFIG_USER_ONLY)
     switch (mem_idx) {
     case MMU_USER_IDX:
-        u.ll.upper = ldq_user(addr);
-        u.ll.lower = ldq_user(addr + 8);
+        u.ll.upper = cpu_ldq_user(env, addr);
+        u.ll.lower = cpu_ldq_user(env, addr + 8);
         QT0 = u.q;
         break;
     case MMU_KERNEL_IDX:
-        u.ll.upper = ldq_kernel(addr);
-        u.ll.lower = ldq_kernel(addr + 8);
+        u.ll.upper = cpu_ldq_kernel(env, addr);
+        u.ll.lower = cpu_ldq_kernel(env, addr + 8);
         QT0 = u.q;
         break;
 #ifdef TARGET_SPARC64
     case MMU_HYPV_IDX:
-        u.ll.upper = ldq_hypv(addr);
-        u.ll.lower = ldq_hypv(addr + 8);
+        u.ll.upper = cpu_ldq_hypv(env, addr);
+        u.ll.lower = cpu_ldq_hypv(env, addr + 8);
         QT0 = u.q;
         break;
 #endif
@@ -2245,29 +2241,29 @@ void helper_ldqf(target_ulong addr, int mem_idx)
 #endif
 }
 
-void helper_stqf(target_ulong addr, int mem_idx)
+void helper_stqf(CPUSPARCState *env, target_ulong addr, int mem_idx)
 {
     /* XXX add 128 bit store */
     CPU_QuadU u;
 
-    helper_check_align(addr, 7);
+    helper_check_align(env, addr, 7);
 #if !defined(CONFIG_USER_ONLY)
     switch (mem_idx) {
     case MMU_USER_IDX:
         u.q = QT0;
-        stq_user(addr, u.ll.upper);
-        stq_user(addr + 8, u.ll.lower);
+        cpu_stq_user(env, addr, u.ll.upper);
+        cpu_stq_user(env, addr + 8, u.ll.lower);
         break;
     case MMU_KERNEL_IDX:
         u.q = QT0;
-        stq_kernel(addr, u.ll.upper);
-        stq_kernel(addr + 8, u.ll.lower);
+        cpu_stq_kernel(env, addr, u.ll.upper);
+        cpu_stq_kernel(env, addr + 8, u.ll.lower);
         break;
 #ifdef TARGET_SPARC64
     case MMU_HYPV_IDX:
         u.q = QT0;
-        stq_hypv(addr, u.ll.upper);
-        stq_hypv(addr + 8, u.ll.lower);
+        cpu_stq_hypv(env, addr, u.ll.upper);
+        cpu_stq_hypv(env, addr + 8, u.ll.lower);
         break;
 #endif
     default:
@@ -2281,10 +2277,10 @@ void helper_stqf(target_ulong addr, int mem_idx)
 #endif
 }
 
-#ifndef TARGET_SPARC64
 #if !defined(CONFIG_USER_ONLY)
-static void do_unassigned_access(target_phys_addr_t addr, int is_write,
-                                 int is_exec, int is_asi, int size)
+#ifndef TARGET_SPARC64
+void cpu_unassigned_access(CPUSPARCState *env, target_phys_addr_t addr,
+                           int is_write, int is_exec, int is_asi, int size)
 {
     int fault_type;
 
@@ -2342,15 +2338,9 @@ static void do_unassigned_access(target_phys_addr_t addr, int is_write,
         tlb_flush(env, 1);
     }
 }
-#endif
-#else
-#if defined(CONFIG_USER_ONLY)
-static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
-                                 int is_asi, int size)
 #else
-static void do_unassigned_access(target_phys_addr_t addr, int is_write,
-                                 int is_exec, int is_asi, int size)
-#endif
+void cpu_unassigned_access(CPUSPARCState *env, target_phys_addr_t addr,
+                           int is_write, int is_exec, int is_asi, int size)
 {
 #ifdef DEBUG_UNASSIGNED
     printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
@@ -2364,16 +2354,4 @@ static void do_unassigned_access(target_phys_addr_t addr, int is_write,
     }
 }
 #endif
-
-#if !defined(CONFIG_USER_ONLY)
-void cpu_unassigned_access(CPUSPARCState *env1, target_phys_addr_t addr,
-                           int is_write, int is_exec, int is_asi, int size)
-{
-    CPUSPARCState *saved_env;
-
-    saved_env = env;
-    env = env1;
-    do_unassigned_access(addr, is_write, is_exec, is_asi, size);
-    env = saved_env;
-}
 #endif
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 1aff125..b7171d8 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -3,6 +3,7 @@
 #include "helper.h"
 
 #if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
 static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
                                 void *retaddr);
 
@@ -71,4 +72,103 @@ void tlb_fill(CPUSPARCState *env1, target_ulong addr, int is_write, int mmu_idx,
     env = saved_env;
 }
 
-#endif /* !CONFIG_USER_ONLY */
+#define WRAP_LD(rettype, fn)                                    \
+    rettype cpu_ ## fn (CPUSPARCState *env1, target_ulong addr) \
+    {                                                           \
+        CPUSPARCState *saved_env;                               \
+        rettype ret;                                            \
+                                                                \
+        saved_env = env;                                        \
+        env = env1;                                             \
+        ret = fn(addr);                                         \
+        env = saved_env;                                        \
+        return ret;                                             \
+    }
+
+WRAP_LD(uint32_t, ldub_kernel)
+WRAP_LD(uint32_t, lduw_kernel)
+WRAP_LD(uint32_t, ldl_kernel)
+WRAP_LD(uint64_t, ldq_kernel)
+
+WRAP_LD(uint32_t, ldub_user)
+WRAP_LD(uint32_t, lduw_user)
+WRAP_LD(uint32_t, ldl_user)
+WRAP_LD(uint64_t, ldq_user)
+
+WRAP_LD(uint64_t, ldfq_kernel)
+WRAP_LD(uint64_t, ldfq_user)
+#ifdef TARGET_SPARC64
+WRAP_LD(uint32_t, ldub_hypv)
+WRAP_LD(uint32_t, lduw_hypv)
+WRAP_LD(uint32_t, ldl_hypv)
+WRAP_LD(uint64_t, ldq_hypv)
+
+WRAP_LD(uint64_t, ldfq_hypv)
+
+WRAP_LD(uint32_t, ldub_nucleus)
+WRAP_LD(uint32_t, lduw_nucleus)
+WRAP_LD(uint32_t, ldl_nucleus)
+WRAP_LD(uint64_t, ldq_nucleus)
+
+WRAP_LD(uint32_t, ldub_kernel_secondary)
+WRAP_LD(uint32_t, lduw_kernel_secondary)
+WRAP_LD(uint32_t, ldl_kernel_secondary)
+WRAP_LD(uint64_t, ldq_kernel_secondary)
+
+WRAP_LD(uint32_t, ldub_user_secondary)
+WRAP_LD(uint32_t, lduw_user_secondary)
+WRAP_LD(uint32_t, ldl_user_secondary)
+WRAP_LD(uint64_t, ldq_user_secondary)
+#endif
+#undef WRAP_LD
+
+#define WRAP_ST(datatype, fn)                                           \
+    void cpu_ ## fn (CPUSPARCState *env1, target_ulong addr, datatype val)   \
+    {                                                                   \
+        CPUSPARCState *saved_env;                                       \
+                                                                        \
+        saved_env = env;                                                \
+        env = env1;                                                     \
+        fn(addr, val);                                                  \
+        env = saved_env;                                                \
+    }
+
+WRAP_ST(uint32_t, stb_kernel)
+WRAP_ST(uint32_t, stw_kernel)
+WRAP_ST(uint32_t, stl_kernel)
+WRAP_ST(uint64_t, stq_kernel)
+
+WRAP_ST(uint32_t, stb_user)
+WRAP_ST(uint32_t, stw_user)
+WRAP_ST(uint32_t, stl_user)
+WRAP_ST(uint64_t, stq_user)
+
+WRAP_ST(uint64_t, stfq_kernel)
+WRAP_ST(uint64_t, stfq_user)
+
+#ifdef TARGET_SPARC64
+WRAP_ST(uint32_t, stb_hypv)
+WRAP_ST(uint32_t, stw_hypv)
+WRAP_ST(uint32_t, stl_hypv)
+WRAP_ST(uint64_t, stq_hypv)
+
+WRAP_ST(uint64_t, stfq_hypv)
+
+WRAP_ST(uint32_t, stb_nucleus)
+WRAP_ST(uint32_t, stw_nucleus)
+WRAP_ST(uint32_t, stl_nucleus)
+WRAP_ST(uint64_t, stq_nucleus)
+
+WRAP_ST(uint32_t, stb_kernel_secondary)
+WRAP_ST(uint32_t, stw_kernel_secondary)
+WRAP_ST(uint32_t, stl_kernel_secondary)
+WRAP_ST(uint64_t, stq_kernel_secondary)
+
+WRAP_ST(uint32_t, stb_user_secondary)
+WRAP_ST(uint32_t, stw_user_secondary)
+WRAP_ST(uint32_t, stl_user_secondary)
+WRAP_ST(uint64_t, stq_user_secondary)
+#endif
+
+#undef WRAP_ST
+#endif
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index ef176e9..670ea2b 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1955,7 +1955,7 @@ static inline void gen_ld_asi(TCGv dst, TCGv addr, int insn, int size,
     r_asi = gen_get_asi(insn, addr);
     r_size = tcg_const_i32(size);
     r_sign = tcg_const_i32(sign);
-    gen_helper_ld_asi(dst, addr, r_asi, r_size, r_sign);
+    gen_helper_ld_asi(dst, cpu_env, addr, r_asi, r_size, r_sign);
     tcg_temp_free_i32(r_sign);
     tcg_temp_free_i32(r_size);
     tcg_temp_free_i32(r_asi);
@@ -1967,7 +1967,7 @@ static inline void gen_st_asi(TCGv src, TCGv addr, int insn, int size)
 
     r_asi = gen_get_asi(insn, addr);
     r_size = tcg_const_i32(size);
-    gen_helper_st_asi(addr, src, r_asi, r_size);
+    gen_helper_st_asi(cpu_env, addr, src, r_asi, r_size);
     tcg_temp_free_i32(r_size);
     tcg_temp_free_i32(r_asi);
 }
@@ -1979,7 +1979,7 @@ static inline void gen_ldf_asi(TCGv addr, int insn, int size, int rd)
     r_asi = gen_get_asi(insn, addr);
     r_size = tcg_const_i32(size);
     r_rd = tcg_const_i32(rd);
-    gen_helper_ldf_asi(addr, r_asi, r_size, r_rd);
+    gen_helper_ldf_asi(cpu_env, addr, r_asi, r_size, r_rd);
     tcg_temp_free_i32(r_rd);
     tcg_temp_free_i32(r_size);
     tcg_temp_free_i32(r_asi);
@@ -1992,7 +1992,7 @@ static inline void gen_stf_asi(TCGv addr, int insn, int size, int rd)
     r_asi = gen_get_asi(insn, addr);
     r_size = tcg_const_i32(size);
     r_rd = tcg_const_i32(rd);
-    gen_helper_stf_asi(addr, r_asi, r_size, r_rd);
+    gen_helper_stf_asi(cpu_env, addr, r_asi, r_size, r_rd);
     tcg_temp_free_i32(r_rd);
     tcg_temp_free_i32(r_size);
     tcg_temp_free_i32(r_asi);
@@ -2005,9 +2005,9 @@ static inline void gen_swap_asi(TCGv dst, TCGv addr, int insn)
     r_asi = gen_get_asi(insn, addr);
     r_size = tcg_const_i32(4);
     r_sign = tcg_const_i32(0);
-    gen_helper_ld_asi(cpu_tmp64, addr, r_asi, r_size, r_sign);
+    gen_helper_ld_asi(cpu_tmp64, cpu_env, addr, r_asi, r_size, r_sign);
     tcg_temp_free_i32(r_sign);
-    gen_helper_st_asi(addr, dst, r_asi, r_size);
+    gen_helper_st_asi(cpu_env, addr, dst, r_asi, r_size);
     tcg_temp_free_i32(r_size);
     tcg_temp_free_i32(r_asi);
     tcg_gen_trunc_i64_tl(dst, cpu_tmp64);
@@ -2019,7 +2019,7 @@ static inline void gen_ldda_asi(TCGv hi, TCGv addr, int insn, int rd)
 
     r_asi = gen_get_asi(insn, addr);
     r_rd = tcg_const_i32(rd);
-    gen_helper_ldda_asi(addr, r_asi, r_rd);
+    gen_helper_ldda_asi(cpu_env, addr, r_asi, r_rd);
     tcg_temp_free_i32(r_rd);
     tcg_temp_free_i32(r_asi);
 }
@@ -2032,7 +2032,7 @@ static inline void gen_stda_asi(TCGv hi, TCGv addr, int insn, int rd)
     tcg_gen_concat_tl_i64(cpu_tmp64, cpu_tmp0, hi);
     r_asi = gen_get_asi(insn, addr);
     r_size = tcg_const_i32(8);
-    gen_helper_st_asi(addr, cpu_tmp64, r_asi, r_size);
+    gen_helper_st_asi(cpu_env, addr, cpu_tmp64, r_asi, r_size);
     tcg_temp_free_i32(r_size);
     tcg_temp_free_i32(r_asi);
 }
@@ -2046,7 +2046,7 @@ static inline void gen_cas_asi(TCGv dst, TCGv addr, TCGv val2, int insn,
     r_val1 = tcg_temp_new();
     gen_movl_reg_TN(rd, r_val1);
     r_asi = gen_get_asi(insn, addr);
-    gen_helper_cas_asi(dst, addr, r_val1, val2, r_asi);
+    gen_helper_cas_asi(dst, cpu_env, addr, r_val1, val2, r_asi);
     tcg_temp_free_i32(r_asi);
     tcg_temp_free(r_val1);
 }
@@ -2058,7 +2058,7 @@ static inline void gen_casx_asi(TCGv dst, TCGv addr, TCGv val2, int insn,
 
     gen_movl_reg_TN(rd, cpu_tmp64);
     r_asi = gen_get_asi(insn, addr);
-    gen_helper_casx_asi(dst, addr, cpu_tmp64, val2, r_asi);
+    gen_helper_casx_asi(dst, cpu_env, addr, cpu_tmp64, val2, r_asi);
     tcg_temp_free_i32(r_asi);
 }
 
@@ -2072,7 +2072,7 @@ static inline void gen_ld_asi(TCGv dst, TCGv addr, int insn, int size,
     r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
     r_size = tcg_const_i32(size);
     r_sign = tcg_const_i32(sign);
-    gen_helper_ld_asi(cpu_tmp64, addr, r_asi, r_size, r_sign);
+    gen_helper_ld_asi(cpu_tmp64, cpu_env, addr, r_asi, r_size, r_sign);
     tcg_temp_free(r_sign);
     tcg_temp_free(r_size);
     tcg_temp_free(r_asi);
@@ -2086,7 +2086,7 @@ static inline void gen_st_asi(TCGv src, TCGv addr, int insn, int size)
     tcg_gen_extu_tl_i64(cpu_tmp64, src);
     r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
     r_size = tcg_const_i32(size);
-    gen_helper_st_asi(addr, cpu_tmp64, r_asi, r_size);
+    gen_helper_st_asi(cpu_env, addr, cpu_tmp64, r_asi, r_size);
     tcg_temp_free(r_size);
     tcg_temp_free(r_asi);
 }
@@ -2099,11 +2099,11 @@ static inline void gen_swap_asi(TCGv dst, TCGv addr, int insn)
     r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
     r_size = tcg_const_i32(4);
     r_sign = tcg_const_i32(0);
-    gen_helper_ld_asi(cpu_tmp64, addr, r_asi, r_size, r_sign);
+    gen_helper_ld_asi(cpu_tmp64, cpu_env, addr, r_asi, r_size, r_sign);
     tcg_temp_free(r_sign);
     r_val = tcg_temp_new_i64();
     tcg_gen_extu_tl_i64(r_val, dst);
-    gen_helper_st_asi(addr, r_val, r_asi, r_size);
+    gen_helper_st_asi(cpu_env, addr, r_val, r_asi, r_size);
     tcg_temp_free_i64(r_val);
     tcg_temp_free(r_size);
     tcg_temp_free(r_asi);
@@ -2117,7 +2117,7 @@ static inline void gen_ldda_asi(TCGv hi, TCGv addr, int insn, int rd)
     r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
     r_size = tcg_const_i32(8);
     r_sign = tcg_const_i32(0);
-    gen_helper_ld_asi(cpu_tmp64, addr, r_asi, r_size, r_sign);
+    gen_helper_ld_asi(cpu_tmp64, cpu_env, addr, r_asi, r_size, r_sign);
     tcg_temp_free(r_sign);
     tcg_temp_free(r_size);
     tcg_temp_free(r_asi);
@@ -2136,7 +2136,7 @@ static inline void gen_stda_asi(TCGv hi, TCGv addr, int insn, int rd)
     tcg_gen_concat_tl_i64(cpu_tmp64, cpu_tmp0, hi);
     r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
     r_size = tcg_const_i32(8);
-    gen_helper_st_asi(addr, cpu_tmp64, r_asi, r_size);
+    gen_helper_st_asi(cpu_env, addr, cpu_tmp64, r_asi, r_size);
     tcg_temp_free(r_size);
     tcg_temp_free(r_asi);
 }
@@ -2153,7 +2153,7 @@ static inline void gen_ldstub_asi(TCGv dst, TCGv addr, int insn)
     r_val = tcg_const_i64(0xffULL);
     r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
     r_size = tcg_const_i32(1);
-    gen_helper_st_asi(addr, r_val, r_asi, r_size);
+    gen_helper_st_asi(cpu_env, addr, r_val, r_asi, r_size);
     tcg_temp_free_i32(r_size);
     tcg_temp_free_i32(r_asi);
     tcg_temp_free_i64(r_val);
@@ -4547,7 +4547,7 @@ static void disas_sparc_insn(DisasContext * dc)
                 gen_helper_restore(cpu_env);
                 gen_mov_pc_npc(dc, cpu_cond);
                 r_const = tcg_const_i32(3);
-                gen_helper_check_align(cpu_dst, r_const);
+                gen_helper_check_align(cpu_env, cpu_dst, r_const);
                 tcg_temp_free_i32(r_const);
                 tcg_gen_mov_tl(cpu_npc, cpu_dst);
                 dc->npc = DYNAMIC_PC;
@@ -4577,7 +4577,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         tcg_temp_free(r_pc);
                         gen_mov_pc_npc(dc, cpu_cond);
                         r_const = tcg_const_i32(3);
-                        gen_helper_check_align(cpu_dst, r_const);
+                        gen_helper_check_align(cpu_env, cpu_dst, r_const);
                         tcg_temp_free_i32(r_const);
                         tcg_gen_mov_tl(cpu_npc, cpu_dst);
                         dc->npc = DYNAMIC_PC;
@@ -4592,7 +4592,7 @@ static void disas_sparc_insn(DisasContext * dc)
                             goto priv_insn;
                         gen_mov_pc_npc(dc, cpu_cond);
                         r_const = tcg_const_i32(3);
-                        gen_helper_check_align(cpu_dst, r_const);
+                        gen_helper_check_align(cpu_env, cpu_dst, r_const);
                         tcg_temp_free_i32(r_const);
                         tcg_gen_mov_tl(cpu_npc, cpu_dst);
                         dc->npc = DYNAMIC_PC;
@@ -4696,7 +4696,8 @@ static void disas_sparc_insn(DisasContext * dc)
 
                         save_state(dc, cpu_cond);
                         r_const = tcg_const_i32(7);
-                        gen_helper_check_align(cpu_addr, r_const); // XXX remove
+                        /* XXX remove alignment check */
+                        gen_helper_check_align(cpu_env, cpu_addr, r_const);
                         tcg_temp_free_i32(r_const);
                         gen_address_mask(dc, cpu_addr);
                         tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx);
@@ -4921,7 +4922,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         CHECK_FPU_FEATURE(dc, FLOAT128);
                         r_const = tcg_const_i32(dc->mem_idx);
                         gen_address_mask(dc, cpu_addr);
-                        gen_helper_ldqf(cpu_addr, r_const);
+                        gen_helper_ldqf(cpu_env, cpu_addr, r_const);
                         tcg_temp_free_i32(r_const);
                         gen_op_store_QT0_fpr(QFPREG(rd));
                         gen_update_fprs_dirty(QFPREG(rd));
@@ -4961,7 +4962,8 @@ static void disas_sparc_insn(DisasContext * dc)
                         save_state(dc, cpu_cond);
                         gen_address_mask(dc, cpu_addr);
                         r_const = tcg_const_i32(7);
-                        gen_helper_check_align(cpu_addr, r_const); // XXX remove
+                        /* XXX remove alignment check */
+                        gen_helper_check_align(cpu_env, cpu_addr, r_const);
                         tcg_temp_free_i32(r_const);
                         gen_movl_reg_TN(rd + 1, cpu_tmp0);
                         tcg_gen_concat_tl_i64(cpu_tmp64, cpu_tmp0, cpu_val);
@@ -5065,7 +5067,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         gen_op_load_fpr_QT0(QFPREG(rd));
                         r_const = tcg_const_i32(dc->mem_idx);
                         gen_address_mask(dc, cpu_addr);
-                        gen_helper_stqf(cpu_addr, r_const);
+                        gen_helper_stqf(cpu_env, cpu_addr, r_const);
                         tcg_temp_free_i32(r_const);
                     }
                     break;
@@ -5108,7 +5110,7 @@ static void disas_sparc_insn(DisasContext * dc)
                             goto jmp_insn;
                         }
                         r_const = tcg_const_i32(7);
-                        gen_helper_check_align(cpu_addr, r_const);
+                        gen_helper_check_align(cpu_env, cpu_addr, r_const);
                         tcg_temp_free_i32(r_const);
                         gen_stf_asi(cpu_addr, insn, 16, QFPREG(rd));
                     }
commit 57d585f7d14fefc8ebf2b29b2b5a955bec77b5da
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Tue Jul 12 13:14:47 2011 +0000

    TCG: add 5 arg helpers to def-helper.h
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/def-helper.h b/def-helper.h
index 5d057d6..0e70c31 100644
--- a/def-helper.h
+++ b/def-helper.h
@@ -118,6 +118,8 @@
     DEF_HELPER_FLAGS_3(name, 0, ret, t1, t2, t3)
 #define DEF_HELPER_4(name, ret, t1, t2, t3, t4) \
     DEF_HELPER_FLAGS_4(name, 0, ret, t1, t2, t3, t4)
+#define DEF_HELPER_5(name, ret, t1, t2, t3, t4, t5) \
+    DEF_HELPER_FLAGS_5(name, 0, ret, t1, t2, t3, t4, t5)
 
 #endif /* DEF_HELPER_H */
 
@@ -140,6 +142,10 @@ dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3));
 dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
                                    dh_ctype(t4));
 
+#define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \
+dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
+                            dh_ctype(t4), dh_ctype(t5));
+
 #undef GEN_HELPER
 #define GEN_HELPER -1
 
@@ -203,6 +209,22 @@ static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) dh_arg_decl(t1, 1
   tcg_gen_helperN(HELPER(name), flags, sizemask, dh_retvar(ret), 4, args); \
 }
 
+#define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \
+static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
+    dh_arg_decl(t1, 1),  dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
+    dh_arg_decl(t4, 4), dh_arg_decl(t5, 5)) \
+{ \
+  TCGArg args[5]; \
+  int sizemask = 0; \
+  dh_sizemask(ret, 0); \
+  dh_arg(t1, 1); \
+  dh_arg(t2, 2); \
+  dh_arg(t3, 3); \
+  dh_arg(t4, 4); \
+  dh_arg(t5, 5); \
+  tcg_gen_helperN(HELPER(name), flags, sizemask, dh_retvar(ret), 5, args); \
+}
+
 #undef GEN_HELPER
 #define GEN_HELPER -1
 
@@ -224,6 +246,9 @@ DEF_HELPER_FLAGS_0(name, flags, ret)
 #define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \
 DEF_HELPER_FLAGS_0(name, flags, ret)
 
+#define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \
+DEF_HELPER_FLAGS_0(name, flags, ret)
+
 #undef GEN_HELPER
 #define GEN_HELPER -1
 
@@ -235,6 +260,7 @@ DEF_HELPER_FLAGS_0(name, flags, ret)
 #undef DEF_HELPER_FLAGS_2
 #undef DEF_HELPER_FLAGS_3
 #undef DEF_HELPER_FLAGS_4
+#undef DEF_HELPER_FLAGS_5
 #undef GEN_HELPER
 
 #endif
commit e141ab52d2ea5d0bc6ad3b1ad32841127ca04adc
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Sep 18 14:55:46 2011 +0000

    softmmu templates: optionally pass CPUState to memory access functions
    
    Optionally, make memory access helpers take a parameter for CPUState
    instead of relying on global env.
    
    On most targets, perform simple moves to reorder registers. On i386,
    switch from regparm(3) calling convention to standard stack-based
    version.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpu-all.h b/cpu-all.h
index 8ad1ec7..9621c3c 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -259,12 +259,21 @@ extern unsigned long reserved_va;
 #define stfl(p, v) stfl_raw(p, v)
 #define stfq(p, v) stfq_raw(p, v)
 
+#ifndef CONFIG_TCG_PASS_AREG0
 #define ldub_code(p) ldub_raw(p)
 #define ldsb_code(p) ldsb_raw(p)
 #define lduw_code(p) lduw_raw(p)
 #define ldsw_code(p) ldsw_raw(p)
 #define ldl_code(p) ldl_raw(p)
 #define ldq_code(p) ldq_raw(p)
+#else
+#define cpu_ldub_code(env1, p) ldub_raw(p)
+#define cpu_ldsb_code(env1, p) ldsb_raw(p)
+#define cpu_lduw_code(env1, p) lduw_raw(p)
+#define cpu_ldsw_code(env1, p) ldsw_raw(p)
+#define cpu_ldl_code(env1, p) ldl_raw(p)
+#define cpu_ldq_code(env1, p) ldq_raw(p)
+#endif
 
 #define ldub_kernel(p) ldub_raw(p)
 #define ldsb_kernel(p) ldsb_raw(p)
diff --git a/exec-all.h b/exec-all.h
index 8fca67b..93a5b22 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -312,7 +312,9 @@ void tlb_fill(CPUArchState *env1, target_ulong addr, int is_write, int mmu_idx,
 
 #define ACCESS_TYPE (NB_MMU_MODES + 1)
 #define MEMSUFFIX _code
+#ifndef CONFIG_TCG_PASS_AREG0
 #define env cpu_single_env
+#endif
 
 #define DATA_SIZE 1
 #include "softmmu_header.h"
diff --git a/exec.c b/exec.c
index 8fd50a1..be392e2 100644
--- a/exec.c
+++ b/exec.c
@@ -4595,7 +4595,11 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
     mmu_idx = cpu_mmu_index(env1);
     if (unlikely(env1->tlb_table[mmu_idx][page_index].addr_code !=
                  (addr & TARGET_PAGE_MASK))) {
+#ifdef CONFIG_TCG_PASS_AREG0
+        cpu_ldub_code(env1, addr);
+#else
         ldub_code(addr);
+#endif
     }
     pd = env1->iotlb[mmu_idx][page_index] & ~TARGET_PAGE_MASK;
     mr = iotlb_to_region(pd);
diff --git a/softmmu_defs.h b/softmmu_defs.h
index d47d30d..8d59f9d 100644
--- a/softmmu_defs.h
+++ b/softmmu_defs.h
@@ -9,6 +9,7 @@
 #ifndef SOFTMMU_DEFS_H
 #define SOFTMMU_DEFS_H
 
+#ifndef CONFIG_TCG_PASS_AREG0
 uint8_t __ldb_mmu(target_ulong addr, int mmu_idx);
 void __stb_mmu(target_ulong addr, uint8_t val, int mmu_idx);
 uint16_t __ldw_mmu(target_ulong addr, int mmu_idx);
@@ -26,5 +27,32 @@ uint32_t __ldl_cmmu(target_ulong addr, int mmu_idx);
 void __stl_cmmu(target_ulong addr, uint32_t val, int mmu_idx);
 uint64_t __ldq_cmmu(target_ulong addr, int mmu_idx);
 void __stq_cmmu(target_ulong addr, uint64_t val, int mmu_idx);
+#else
+uint8_t helper_ldb_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
+void helper_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
+                    int mmu_idx);
+uint16_t helper_ldw_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
+void helper_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
+                    int mmu_idx);
+uint32_t helper_ldl_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
+void helper_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
+                    int mmu_idx);
+uint64_t helper_ldq_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
+void helper_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
+                    int mmu_idx);
+
+uint8_t helper_ldb_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
+void helper_stb_cmmu(CPUArchState *env, target_ulong addr, uint8_t val,
+int mmu_idx);
+uint16_t helper_ldw_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
+void helper_stw_cmmu(CPUArchState *env, target_ulong addr, uint16_t val,
+                     int mmu_idx);
+uint32_t helper_ldl_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
+void helper_stl_cmmu(CPUArchState *env, target_ulong addr, uint32_t val,
+                     int mmu_idx);
+uint64_t helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
+void helper_stq_cmmu(CPUArchState *env, target_ulong addr, uint64_t val,
+                     int mmu_idx);
+#endif
 
 #endif
diff --git a/softmmu_header.h b/softmmu_header.h
index 818d7b6..6b72093 100644
--- a/softmmu_header.h
+++ b/softmmu_header.h
@@ -78,9 +78,23 @@
 #define ADDR_READ addr_read
 #endif
 
+#ifndef CONFIG_TCG_PASS_AREG0
+#define ENV_PARAM
+#define ENV_VAR
+#define CPU_PREFIX
+#define HELPER_PREFIX __
+#else
+#define ENV_PARAM CPUArchState *env,
+#define ENV_VAR env,
+#define CPU_PREFIX cpu_
+#define HELPER_PREFIX helper_
+#endif
+
 /* generic load/store macros */
 
-static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
+static inline RES_TYPE
+glue(glue(glue(CPU_PREFIX, ld), USUFFIX), MEMSUFFIX)(ENV_PARAM
+                                                     target_ulong ptr)
 {
     int page_index;
     RES_TYPE res;
@@ -93,7 +107,9 @@ static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
     mmu_idx = CPU_MMU_INDEX;
     if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
                  (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
-        res = glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx);
+        res = glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_VAR
+                                                                     addr,
+                                                                     mmu_idx);
     } else {
         physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
         res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr);
@@ -102,7 +118,9 @@ static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
 }
 
 #if DATA_SIZE <= 2
-static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
+static inline int
+glue(glue(glue(CPU_PREFIX, lds), SUFFIX), MEMSUFFIX)(ENV_PARAM
+                                                     target_ulong ptr)
 {
     int res, page_index;
     target_ulong addr;
@@ -114,7 +132,8 @@ static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
     mmu_idx = CPU_MMU_INDEX;
     if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
                  (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
-        res = (DATA_STYPE)glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx);
+        res = (DATA_STYPE)glue(glue(glue(HELPER_PREFIX, ld), SUFFIX),
+                               MMUSUFFIX)(ENV_VAR addr, mmu_idx);
     } else {
         physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
         res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr);
@@ -127,7 +146,9 @@ static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
 
 /* generic store macro */
 
-static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v)
+static inline void
+glue(glue(glue(CPU_PREFIX, st), SUFFIX), MEMSUFFIX)(ENV_PARAM target_ulong ptr,
+                                                    RES_TYPE v)
 {
     int page_index;
     target_ulong addr;
@@ -139,7 +160,8 @@ static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE
     mmu_idx = CPU_MMU_INDEX;
     if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write !=
                  (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
-        glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, mmu_idx);
+        glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_VAR addr, v,
+                                                               mmu_idx);
     } else {
         physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
         glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v);
@@ -151,46 +173,52 @@ static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE
 #if ACCESS_TYPE != (NB_MMU_MODES + 1)
 
 #if DATA_SIZE == 8
-static inline float64 glue(ldfq, MEMSUFFIX)(target_ulong ptr)
+static inline float64 glue(glue(CPU_PREFIX, ldfq), MEMSUFFIX)(ENV_PARAM
+                                                              target_ulong ptr)
 {
     union {
         float64 d;
         uint64_t i;
     } u;
-    u.i = glue(ldq, MEMSUFFIX)(ptr);
+    u.i = glue(glue(CPU_PREFIX, ldq), MEMSUFFIX)(ENV_VAR ptr);
     return u.d;
 }
 
-static inline void glue(stfq, MEMSUFFIX)(target_ulong ptr, float64 v)
+static inline void glue(glue(CPU_PREFIX, stfq), MEMSUFFIX)(ENV_PARAM
+                                                           target_ulong ptr,
+                                                           float64 v)
 {
     union {
         float64 d;
         uint64_t i;
     } u;
     u.d = v;
-    glue(stq, MEMSUFFIX)(ptr, u.i);
+    glue(glue(CPU_PREFIX, stq), MEMSUFFIX)(ENV_VAR ptr, u.i);
 }
 #endif /* DATA_SIZE == 8 */
 
 #if DATA_SIZE == 4
-static inline float32 glue(ldfl, MEMSUFFIX)(target_ulong ptr)
+static inline float32 glue(glue(CPU_PREFIX, ldfl), MEMSUFFIX)(ENV_PARAM
+                                                              target_ulong ptr)
 {
     union {
         float32 f;
         uint32_t i;
     } u;
-    u.i = glue(ldl, MEMSUFFIX)(ptr);
+    u.i = glue(glue(CPU_PREFIX, ldl), MEMSUFFIX)(ENV_VAR ptr);
     return u.f;
 }
 
-static inline void glue(stfl, MEMSUFFIX)(target_ulong ptr, float32 v)
+static inline void glue(glue(CPU_PREFIX, stfl), MEMSUFFIX)(ENV_PARAM
+                                                           target_ulong ptr,
+                                                           float32 v)
 {
     union {
         float32 f;
         uint32_t i;
     } u;
     u.f = v;
-    glue(stl, MEMSUFFIX)(ptr, u.i);
+    glue(glue(CPU_PREFIX, stl), MEMSUFFIX)(ENV_VAR ptr, u.i);
 }
 #endif /* DATA_SIZE == 4 */
 
@@ -205,3 +233,7 @@ static inline void glue(stfl, MEMSUFFIX)(target_ulong ptr, float32 v)
 #undef CPU_MMU_INDEX
 #undef MMUSUFFIX
 #undef ADDR_READ
+#undef ENV_PARAM
+#undef ENV_VAR
+#undef CPU_PREFIX
+#undef HELPER_PREFIX
diff --git a/softmmu_template.h b/softmmu_template.h
index d633bb5..afcab1e 100644
--- a/softmmu_template.h
+++ b/softmmu_template.h
@@ -54,10 +54,24 @@
 #define ADDR_READ addr_read
 #endif
 
-static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
+#ifndef CONFIG_TCG_PASS_AREG0
+#define ENV_PARAM
+#define ENV_VAR
+#define CPU_PREFIX
+#define HELPER_PREFIX __
+#else
+#define ENV_PARAM CPUArchState *env,
+#define ENV_VAR env,
+#define CPU_PREFIX cpu_
+#define HELPER_PREFIX helper_
+#endif
+
+static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_PARAM
+                                                        target_ulong addr,
                                                         int mmu_idx,
                                                         void *retaddr);
-static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr,
+static inline DATA_TYPE glue(io_read, SUFFIX)(ENV_PARAM
+                                              target_phys_addr_t physaddr,
                                               target_ulong addr,
                                               void *retaddr)
 {
@@ -89,7 +103,10 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr,
 }
 
 /* handle all cases except unaligned access which span two pages */
-DATA_TYPE glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr, int mmu_idx)
+DATA_TYPE
+glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_PARAM
+                                                       target_ulong addr,
+                                                       int mmu_idx)
 {
     DATA_TYPE res;
     int index;
@@ -110,22 +127,22 @@ DATA_TYPE glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr, int mmu_idx)
                 goto do_unaligned_access;
             retaddr = GETPC();
             ioaddr = env->iotlb[mmu_idx][index];
-            res = glue(io_read, SUFFIX)(ioaddr, addr, retaddr);
+            res = glue(io_read, SUFFIX)(ENV_VAR ioaddr, addr, retaddr);
         } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
             /* slow unaligned access (it spans two pages or IO) */
         do_unaligned_access:
             retaddr = GETPC();
 #ifdef ALIGNED_ONLY
-            do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
+            do_unaligned_access(ENV_VAR addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
 #endif
-            res = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr,
+            res = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_VAR addr,
                                                          mmu_idx, retaddr);
         } else {
             /* unaligned/aligned access in the same page */
 #ifdef ALIGNED_ONLY
             if ((addr & (DATA_SIZE - 1)) != 0) {
                 retaddr = GETPC();
-                do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
+                do_unaligned_access(ENV_VAR addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
             }
 #endif
             addend = env->tlb_table[mmu_idx][index].addend;
@@ -136,7 +153,7 @@ DATA_TYPE glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr, int mmu_idx)
         retaddr = GETPC();
 #ifdef ALIGNED_ONLY
         if ((addr & (DATA_SIZE - 1)) != 0)
-            do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
+            do_unaligned_access(ENV_VAR addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
 #endif
         tlb_fill(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
         goto redo;
@@ -145,9 +162,11 @@ DATA_TYPE glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr, int mmu_idx)
 }
 
 /* handle all unaligned cases */
-static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
-                                                        int mmu_idx,
-                                                        void *retaddr)
+static DATA_TYPE
+glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_PARAM
+                                       target_ulong addr,
+                                       int mmu_idx,
+                                       void *retaddr)
 {
     DATA_TYPE res, res1, res2;
     int index, shift;
@@ -164,15 +183,15 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
             if ((addr & (DATA_SIZE - 1)) != 0)
                 goto do_unaligned_access;
             ioaddr = env->iotlb[mmu_idx][index];
-            res = glue(io_read, SUFFIX)(ioaddr, addr, retaddr);
+            res = glue(io_read, SUFFIX)(ENV_VAR ioaddr, addr, retaddr);
         } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
         do_unaligned_access:
             /* slow unaligned access (it spans two pages) */
             addr1 = addr & ~(DATA_SIZE - 1);
             addr2 = addr1 + DATA_SIZE;
-            res1 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr1,
+            res1 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_VAR addr1,
                                                           mmu_idx, retaddr);
-            res2 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr2,
+            res2 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_VAR addr2,
                                                           mmu_idx, retaddr);
             shift = (addr & (DATA_SIZE - 1)) * 8;
 #ifdef TARGET_WORDS_BIGENDIAN
@@ -196,12 +215,14 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
 
 #ifndef SOFTMMU_CODE_ACCESS
 
-static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
+static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_PARAM
+                                                   target_ulong addr,
                                                    DATA_TYPE val,
                                                    int mmu_idx,
                                                    void *retaddr);
 
-static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr,
+static inline void glue(io_write, SUFFIX)(ENV_PARAM
+                                          target_phys_addr_t physaddr,
                                           DATA_TYPE val,
                                           target_ulong addr,
                                           void *retaddr)
@@ -231,8 +252,10 @@ static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr,
 #endif /* SHIFT > 2 */
 }
 
-void glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE val,
-                                         int mmu_idx)
+void glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_PARAM
+                                                            target_ulong addr,
+                                                            DATA_TYPE val,
+                                                            int mmu_idx)
 {
     target_phys_addr_t ioaddr;
     unsigned long addend;
@@ -250,21 +273,21 @@ void glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE val,
                 goto do_unaligned_access;
             retaddr = GETPC();
             ioaddr = env->iotlb[mmu_idx][index];
-            glue(io_write, SUFFIX)(ioaddr, val, addr, retaddr);
+            glue(io_write, SUFFIX)(ENV_VAR ioaddr, val, addr, retaddr);
         } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
         do_unaligned_access:
             retaddr = GETPC();
 #ifdef ALIGNED_ONLY
-            do_unaligned_access(addr, 1, mmu_idx, retaddr);
+            do_unaligned_access(ENV_VAR addr, 1, mmu_idx, retaddr);
 #endif
-            glue(glue(slow_st, SUFFIX), MMUSUFFIX)(addr, val,
+            glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_VAR addr, val,
                                                    mmu_idx, retaddr);
         } else {
             /* aligned/unaligned access in the same page */
 #ifdef ALIGNED_ONLY
             if ((addr & (DATA_SIZE - 1)) != 0) {
                 retaddr = GETPC();
-                do_unaligned_access(addr, 1, mmu_idx, retaddr);
+                do_unaligned_access(ENV_VAR addr, 1, mmu_idx, retaddr);
             }
 #endif
             addend = env->tlb_table[mmu_idx][index].addend;
@@ -275,7 +298,7 @@ void glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE val,
         retaddr = GETPC();
 #ifdef ALIGNED_ONLY
         if ((addr & (DATA_SIZE - 1)) != 0)
-            do_unaligned_access(addr, 1, mmu_idx, retaddr);
+            do_unaligned_access(ENV_VAR addr, 1, mmu_idx, retaddr);
 #endif
         tlb_fill(env, addr, 1, mmu_idx, retaddr);
         goto redo;
@@ -283,7 +306,8 @@ void glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE val,
 }
 
 /* handles all unaligned cases */
-static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
+static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_PARAM
+                                                   target_ulong addr,
                                                    DATA_TYPE val,
                                                    int mmu_idx,
                                                    void *retaddr)
@@ -302,7 +326,7 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
             if ((addr & (DATA_SIZE - 1)) != 0)
                 goto do_unaligned_access;
             ioaddr = env->iotlb[mmu_idx][index];
-            glue(io_write, SUFFIX)(ioaddr, val, addr, retaddr);
+            glue(io_write, SUFFIX)(ENV_VAR ioaddr, val, addr, retaddr);
         } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
         do_unaligned_access:
             /* XXX: not efficient, but simple */
@@ -310,10 +334,12 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
              * previous page from the TLB cache.  */
             for(i = DATA_SIZE - 1; i >= 0; i--) {
 #ifdef TARGET_WORDS_BIGENDIAN
-                glue(slow_stb, MMUSUFFIX)(addr + i, val >> (((DATA_SIZE - 1) * 8) - (i * 8)),
+                glue(slow_stb, MMUSUFFIX)(ENV_VAR addr + i,
+                                          val >> (((DATA_SIZE - 1) * 8) - (i * 8)),
                                           mmu_idx, retaddr);
 #else
-                glue(slow_stb, MMUSUFFIX)(addr + i, val >> (i * 8),
+                glue(slow_stb, MMUSUFFIX)(ENV_VAR addr + i,
+                                          val >> (i * 8),
                                           mmu_idx, retaddr);
 #endif
             }
@@ -338,3 +364,7 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
 #undef USUFFIX
 #undef DATA_SIZE
 #undef ADDR_READ
+#undef ENV_PARAM
+#undef ENV_VAR
+#undef CPU_PREFIX
+#undef HELPER_PREFIX
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 5af21b3..4d59a63 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -929,6 +929,27 @@ static inline void tcg_out_goto_label(TCGContext *s, int cond, int label_index)
 
 #include "../../softmmu_defs.h"
 
+#ifdef CONFIG_TCG_PASS_AREG0
+/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
+   int mmu_idx) */
+static const void * const qemu_ld_helpers[4] = {
+    helper_ldb_mmu,
+    helper_ldw_mmu,
+    helper_ldl_mmu,
+    helper_ldq_mmu,
+};
+
+/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
+   uintxx_t val, int mmu_idx) */
+static const void * const qemu_st_helpers[4] = {
+    helper_stb_mmu,
+    helper_stw_mmu,
+    helper_stl_mmu,
+    helper_stq_mmu,
+};
+#else
+/* legacy helper signature: __ld_mmu(target_ulong addr, int
+   mmu_idx) */
 static void *qemu_ld_helpers[4] = {
     __ldb_mmu,
     __ldw_mmu,
@@ -936,6 +957,8 @@ static void *qemu_ld_helpers[4] = {
     __ldq_mmu,
 };
 
+/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val,
+   int mmu_idx) */
 static void *qemu_st_helpers[4] = {
     __stb_mmu,
     __stw_mmu,
@@ -943,6 +966,7 @@ static void *qemu_st_helpers[4] = {
     __stq_mmu,
 };
 #endif
+#endif
 
 #define TLB_SHIFT	(CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
 
@@ -1075,6 +1099,19 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
                     TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0));
     tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
 # endif
+#ifdef CONFIG_TCG_PASS_AREG0
+    /* XXX/FIXME: suboptimal and incorrect for 64 bit */
+    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+                    tcg_target_call_iarg_regs[2], 0,
+                    tcg_target_call_iarg_regs[1], SHIFT_IMM_LSL(0));
+    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+                    tcg_target_call_iarg_regs[1], 0,
+                    tcg_target_call_iarg_regs[0], SHIFT_IMM_LSL(0));
+
+    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+                    tcg_target_call_iarg_regs[0], 0, TCG_AREG0,
+                    SHIFT_IMM_LSL(0));
+#endif
     tcg_out_call(s, (tcg_target_long) qemu_ld_helpers[s_bits]);
 
     switch (opc) {
@@ -1341,6 +1378,22 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
     }
 # endif
 
+#ifdef CONFIG_TCG_PASS_AREG0
+    /* XXX/FIXME: suboptimal and incorrect for 64 bit */
+    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+                    tcg_target_call_iarg_regs[3], 0,
+                    tcg_target_call_iarg_regs[2], SHIFT_IMM_LSL(0));
+    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+                    tcg_target_call_iarg_regs[2], 0,
+                    tcg_target_call_iarg_regs[1], SHIFT_IMM_LSL(0));
+    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+                    tcg_target_call_iarg_regs[1], 0,
+                    tcg_target_call_iarg_regs[0], SHIFT_IMM_LSL(0));
+
+    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+                    tcg_target_call_iarg_regs[0], 0, TCG_AREG0,
+                    SHIFT_IMM_LSL(0));
+#endif
     tcg_out_call(s, (tcg_target_long) qemu_st_helpers[s_bits]);
     if (opc == 3)
         tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R13, TCG_REG_R13, 0x10);
diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index c5a3730..e579ef0 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -882,6 +882,27 @@ static void tcg_out_setcond2(TCGContext *s, int cond, TCGArg ret,
 #if defined(CONFIG_SOFTMMU)
 #include "../../softmmu_defs.h"
 
+#ifdef CONFIG_TCG_PASS_AREG0
+/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
+   int mmu_idx) */
+static const void * const qemu_ld_helpers[4] = {
+    helper_ldb_mmu,
+    helper_ldw_mmu,
+    helper_ldl_mmu,
+    helper_ldq_mmu,
+};
+
+/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
+   uintxx_t val, int mmu_idx) */
+static const void * const qemu_st_helpers[4] = {
+    helper_stb_mmu,
+    helper_stw_mmu,
+    helper_stl_mmu,
+    helper_stq_mmu,
+};
+#else
+/* legacy helper signature: __ld_mmu(target_ulong addr, int
+   mmu_idx) */
 static void *qemu_ld_helpers[4] = {
     __ldb_mmu,
     __ldw_mmu,
@@ -889,12 +910,15 @@ static void *qemu_ld_helpers[4] = {
     __ldq_mmu,
 };
 
+/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val,
+   int mmu_idx) */
 static void *qemu_st_helpers[4] = {
     __stb_mmu,
     __stw_mmu,
     __stl_mmu,
     __stq_mmu,
 };
+#endif
 
 /* Load and compare a TLB entry, and branch if TLB miss.  OFFSET is set to
    the offset of the first ADDR_READ or ADDR_WRITE member of the appropriate
@@ -1061,6 +1085,15 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
     }
     tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
 
+#ifdef CONFIG_TCG_PASS_AREG0
+    /* XXX/FIXME: suboptimal */
+    tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2],
+                tcg_target_call_iarg_regs[1]);
+    tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
+                tcg_target_call_iarg_regs[0]);
+    tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
+                TCG_AREG0);
+#endif
     tcg_out_call(s, qemu_ld_helpers[opc & 3]);
 
     switch (opc) {
@@ -1212,6 +1245,17 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
         tcg_abort();
     }
 
+#ifdef CONFIG_TCG_PASS_AREG0
+    /* XXX/FIXME: suboptimal */
+    tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
+                tcg_target_call_iarg_regs[2]);
+    tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
+                tcg_target_call_iarg_regs[1]);
+    tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
+                tcg_target_call_iarg_regs[0]);
+    tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
+                TCG_AREG0);
+#endif
     tcg_out_call(s, qemu_st_helpers[opc]);
 
     /* label2: */
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index c4e940d..43a51a1 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -178,6 +178,9 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
             tcg_regset_set32(ct->u.regs, 0, 0xffff);
             tcg_regset_reset_reg(ct->u.regs, TCG_REG_RSI);
             tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDI);
+#ifdef CONFIG_TCG_PASS_AREG0
+            tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDX);
+#endif
         } else {
             tcg_regset_set32(ct->u.regs, 0, 0xff);
             tcg_regset_reset_reg(ct->u.regs, TCG_REG_EAX);
@@ -957,6 +960,27 @@ static void tcg_out_jmp(TCGContext *s, tcg_target_long dest)
 
 #include "../../softmmu_defs.h"
 
+#ifdef CONFIG_TCG_PASS_AREG0
+/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
+   int mmu_idx) */
+static const void *qemu_ld_helpers[4] = {
+    helper_ldb_mmu,
+    helper_ldw_mmu,
+    helper_ldl_mmu,
+    helper_ldq_mmu,
+};
+
+/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
+   uintxx_t val, int mmu_idx) */
+static const void *qemu_st_helpers[4] = {
+    helper_stb_mmu,
+    helper_stw_mmu,
+    helper_stl_mmu,
+    helper_stq_mmu,
+};
+#else
+/* legacy helper signature: __ld_mmu(target_ulong addr, int
+   mmu_idx) */
 static void *qemu_ld_helpers[4] = {
     __ldb_mmu,
     __ldw_mmu,
@@ -964,12 +988,15 @@ static void *qemu_ld_helpers[4] = {
     __ldq_mmu,
 };
 
+/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val,
+   int mmu_idx) */
 static void *qemu_st_helpers[4] = {
     __stb_mmu,
     __stw_mmu,
     __stl_mmu,
     __stq_mmu,
 };
+#endif
 
 /* Perform the TLB load and compare.
 
@@ -1188,11 +1215,26 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
     }
     tcg_out_push(s, args[addrlo_idx]);
     stack_adjust += 4;
+#ifdef CONFIG_TCG_PASS_AREG0
+    tcg_out_push(s, TCG_AREG0);
+    stack_adjust += 4;
+#endif
 #else
     /* The first argument is already loaded with addrlo.  */
     arg_idx = 1;
     tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx],
                  mem_index);
+#ifdef CONFIG_TCG_PASS_AREG0
+    /* XXX/FIXME: suboptimal */
+    tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[3],
+                tcg_target_call_iarg_regs[2]);
+    tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
+                tcg_target_call_iarg_regs[1]);
+    tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[1],
+                tcg_target_call_iarg_regs[0]);
+    tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0],
+                TCG_AREG0);
+#endif
 #endif
 
     tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]);
@@ -1386,11 +1428,26 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
     }
     tcg_out_push(s, args[addrlo_idx]);
     stack_adjust += 4;
+#ifdef CONFIG_TCG_PASS_AREG0
+    tcg_out_push(s, TCG_AREG0);
+    stack_adjust += 4;
+#endif
 #else
     tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32),
                 TCG_REG_RSI, data_reg);
     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index);
     stack_adjust = 0;
+#ifdef CONFIG_TCG_PASS_AREG0
+    /* XXX/FIXME: suboptimal */
+    tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[3],
+                tcg_target_call_iarg_regs[2]);
+    tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
+                tcg_target_call_iarg_regs[1]);
+    tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[1],
+                tcg_target_call_iarg_regs[0]);
+    tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0],
+                TCG_AREG0);
+#endif
 #endif
 
     tcg_out_calli(s, (tcg_target_long)qemu_st_helpers[s_bits]);
diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c
index f90252a..e02dacc 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -1452,12 +1452,25 @@ static inline void tcg_out_qemu_tlb(TCGContext *s, TCGArg addr_reg,
                                TCG_REG_P7, TCG_REG_R3, TCG_REG_R57));
 }
 
+#ifdef CONFIG_TCG_PASS_AREG0
+/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
+   int mmu_idx) */
+static const void * const qemu_ld_helpers[4] = {
+    helper_ldb_mmu,
+    helper_ldw_mmu,
+    helper_ldl_mmu,
+    helper_ldq_mmu,
+};
+#else
+/* legacy helper signature: __ld_mmu(target_ulong addr, int
+   mmu_idx) */
 static void *qemu_ld_helpers[4] = {
     __ldb_mmu,
     __ldw_mmu,
     __ldl_mmu,
     __ldq_mmu,
 };
+#endif
 
 static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
 {
@@ -1517,6 +1530,15 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
                        tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2),
                        tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
     }
+#ifdef CONFIG_TCG_PASS_AREG0
+    /* XXX/FIXME: suboptimal */
+    tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2],
+                tcg_target_call_iarg_regs[1]);
+    tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
+                tcg_target_call_iarg_regs[0]);
+    tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
+                TCG_AREG0);
+#endif
     if (!bswap || s_bits == 0) {
         tcg_out_bundle(s, miB,
                        tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
@@ -1547,12 +1569,25 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
     }
 }
 
+#ifdef CONFIG_TCG_PASS_AREG0
+/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
+   uintxx_t val, int mmu_idx) */
+static const void * const qemu_st_helpers[4] = {
+    helper_stb_mmu,
+    helper_stw_mmu,
+    helper_stl_mmu,
+    helper_stq_mmu,
+};
+#else
+/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val,
+   int mmu_idx) */
 static void *qemu_st_helpers[4] = {
     __stb_mmu,
     __stw_mmu,
     __stl_mmu,
     __stq_mmu,
 };
+#endif
 
 static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
 {
@@ -1622,6 +1657,17 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
         data_reg = TCG_REG_R2;
     }
 
+#ifdef CONFIG_TCG_PASS_AREG0
+    /* XXX/FIXME: suboptimal */
+    tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
+                tcg_target_call_iarg_regs[2]);
+    tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
+                tcg_target_call_iarg_regs[1]);
+    tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
+                tcg_target_call_iarg_regs[0]);
+    tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
+                TCG_AREG0);
+#endif
     tcg_out_bundle(s, miB,
                    tcg_opc_m4 (TCG_REG_P6, opc_st_m4[opc],
                                data_reg, TCG_REG_R3),
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index c6aa5bc..393ba07 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -750,6 +750,27 @@ static void tcg_out_setcond2(TCGContext *s, TCGCond cond, int ret,
 
 #include "../../softmmu_defs.h"
 
+#ifdef CONFIG_TCG_PASS_AREG0
+/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
+   int mmu_idx) */
+static const void * const qemu_ld_helpers[4] = {
+    helper_ldb_mmu,
+    helper_ldw_mmu,
+    helper_ldl_mmu,
+    helper_ldq_mmu,
+};
+
+/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
+   uintxx_t val, int mmu_idx) */
+static const void * const qemu_st_helpers[4] = {
+    helper_stb_mmu,
+    helper_stw_mmu,
+    helper_stl_mmu,
+    helper_stq_mmu,
+};
+#else
+/* legacy helper signature: __ld_mmu(target_ulong addr, int
+   mmu_idx) */
 static void *qemu_ld_helpers[4] = {
     __ldb_mmu,
     __ldw_mmu,
@@ -757,6 +778,8 @@ static void *qemu_ld_helpers[4] = {
     __ldq_mmu,
 };
 
+/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val,
+   int mmu_idx) */
 static void *qemu_st_helpers[4] = {
     __stb_mmu,
     __stw_mmu,
@@ -764,6 +787,7 @@ static void *qemu_st_helpers[4] = {
     __stq_mmu,
 };
 #endif
+#endif
 
 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
                             int opc)
@@ -858,6 +882,15 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
 # endif
     tcg_out_movi(s, TCG_TYPE_I32, sp_args++, mem_index);
     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
+#ifdef CONFIG_TCG_PASS_AREG0
+    /* XXX/FIXME: suboptimal and incorrect for 64 on 32 bit */
+    tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2],
+                tcg_target_call_iarg_regs[1]);
+    tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
+                tcg_target_call_iarg_regs[0]);
+    tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
+                TCG_AREG0);
+#endif
     tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
     tcg_out_nop(s);
 
@@ -1069,6 +1102,17 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
     }
 
     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_st_helpers[s_bits]);
+#ifdef CONFIG_TCG_PASS_AREG0
+    /* XXX/FIXME: suboptimal and incorrect for 64 on 32 bit */
+    tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
+                tcg_target_call_iarg_regs[2]);
+    tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
+                tcg_target_call_iarg_regs[1]);
+    tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
+                tcg_target_call_iarg_regs[0]);
+    tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
+                TCG_AREG0);
+#endif
     tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
     tcg_out_nop(s);
 
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index 6a34cab..b0aa914 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -508,6 +508,27 @@ static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg)
 
 #include "../../softmmu_defs.h"
 
+#ifdef CONFIG_TCG_PASS_AREG0
+/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
+   int mmu_idx) */
+static const void * const qemu_ld_helpers[4] = {
+    helper_ldb_mmu,
+    helper_ldw_mmu,
+    helper_ldl_mmu,
+    helper_ldq_mmu,
+};
+
+/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
+   uintxx_t val, int mmu_idx) */
+static const void * const qemu_st_helpers[4] = {
+    helper_stb_mmu,
+    helper_stw_mmu,
+    helper_stl_mmu,
+    helper_stq_mmu,
+};
+#else
+/* legacy helper signature: __ld_mmu(target_ulong addr, int
+   mmu_idx) */
 static void *qemu_ld_helpers[4] = {
     __ldb_mmu,
     __ldw_mmu,
@@ -515,6 +536,8 @@ static void *qemu_ld_helpers[4] = {
     __ldq_mmu,
 };
 
+/* legacy helper signature: __ld_mmu(target_ulong addr, int
+   mmu_idx) */
 static void *qemu_st_helpers[4] = {
     __stb_mmu,
     __stw_mmu,
@@ -522,6 +545,7 @@ static void *qemu_st_helpers[4] = {
     __stq_mmu,
 };
 #endif
+#endif
 
 static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
 {
@@ -598,6 +622,16 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
     tcg_out_movi (s, TCG_TYPE_I32, 5, mem_index);
 #endif
 
+#ifdef CONFIG_TCG_PASS_AREG0
+    /* XXX/FIXME: suboptimal */
+    tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2],
+                tcg_target_call_iarg_regs[1]);
+    tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
+                tcg_target_call_iarg_regs[0]);
+    tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
+                TCG_AREG0);
+#endif
+
     tcg_out_call (s, (tcg_target_long) qemu_ld_helpers[s_bits], 1);
     switch (opc) {
     case 0|4:
@@ -829,6 +863,17 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
     ir++;
 
     tcg_out_movi (s, TCG_TYPE_I32, ir, mem_index);
+#ifdef CONFIG_TCG_PASS_AREG0
+    /* XXX/FIXME: suboptimal */
+    tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
+                tcg_target_call_iarg_regs[2]);
+    tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
+                tcg_target_call_iarg_regs[1]);
+    tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
+                tcg_target_call_iarg_regs[0]);
+    tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
+                TCG_AREG0);
+#endif
     tcg_out_call (s, (tcg_target_long) qemu_st_helpers[opc], 1);
     label2_ptr = s->code_ptr;
     tcg_out32 (s, B);
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 7f723b5..409a1ac 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -552,6 +552,27 @@ static void tcg_out_ldsta (TCGContext *s, int ret, int addr,
 
 #include "../../softmmu_defs.h"
 
+#ifdef CONFIG_TCG_PASS_AREG0
+/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
+   int mmu_idx) */
+static const void * const qemu_ld_helpers[4] = {
+    helper_ldb_mmu,
+    helper_ldw_mmu,
+    helper_ldl_mmu,
+    helper_ldq_mmu,
+};
+
+/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
+   uintxx_t val, int mmu_idx) */
+static const void * const qemu_st_helpers[4] = {
+    helper_stb_mmu,
+    helper_stw_mmu,
+    helper_stl_mmu,
+    helper_stq_mmu,
+};
+#else
+/* legacy helper signature: __ld_mmu(target_ulong addr, int
+   mmu_idx) */
 static void *qemu_ld_helpers[4] = {
     __ldb_mmu,
     __ldw_mmu,
@@ -559,12 +580,15 @@ static void *qemu_ld_helpers[4] = {
     __ldq_mmu,
 };
 
+/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val,
+   int mmu_idx) */
 static void *qemu_st_helpers[4] = {
     __stb_mmu,
     __stw_mmu,
     __stl_mmu,
     __stq_mmu,
 };
+#endif
 
 static void tcg_out_tlb_read (TCGContext *s, int r0, int r1, int r2,
                               int addr_reg, int s_bits, int offset)
@@ -648,6 +672,15 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
     tcg_out_mov (s, TCG_TYPE_I64, 3, addr_reg);
     tcg_out_movi (s, TCG_TYPE_I64, 4, mem_index);
 
+#ifdef CONFIG_TCG_PASS_AREG0
+    /* XXX/FIXME: suboptimal */
+    tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2],
+                tcg_target_call_iarg_regs[1]);
+    tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
+                tcg_target_call_iarg_regs[0]);
+    tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
+                TCG_AREG0);
+#endif
     tcg_out_call (s, (tcg_target_long) qemu_ld_helpers[s_bits], 1);
 
     switch (opc) {
@@ -796,6 +829,17 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
     tcg_out_rld (s, RLDICL, 4, data_reg, 0, 64 - (1 << (3 + opc)));
     tcg_out_movi (s, TCG_TYPE_I64, 5, mem_index);
 
+#ifdef CONFIG_TCG_PASS_AREG0
+    /* XXX/FIXME: suboptimal */
+    tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
+                tcg_target_call_iarg_regs[2]);
+    tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
+                tcg_target_call_iarg_regs[1]);
+    tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
+                tcg_target_call_iarg_regs[0]);
+    tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
+                TCG_AREG0);
+#endif
     tcg_out_call (s, (tcg_target_long) qemu_st_helpers[opc], 1);
 
     label2_ptr = s->code_ptr;
diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c
index 47ffcc1..04662c1 100644
--- a/tcg/s390/tcg-target.c
+++ b/tcg/s390/tcg-target.c
@@ -301,6 +301,27 @@ static const uint8_t tcg_cond_to_ltr_cond[10] = {
 
 #include "../../softmmu_defs.h"
 
+#ifdef CONFIG_TCG_PASS_AREG0
+/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
+   int mmu_idx) */
+static const void * const qemu_ld_helpers[4] = {
+    helper_ldb_mmu,
+    helper_ldw_mmu,
+    helper_ldl_mmu,
+    helper_ldq_mmu,
+};
+
+/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
+   uintxx_t val, int mmu_idx) */
+static const void * const qemu_st_helpers[4] = {
+    helper_stb_mmu,
+    helper_stw_mmu,
+    helper_stl_mmu,
+    helper_stq_mmu,
+};
+#else
+/* legacy helper signature: __ld_mmu(target_ulong addr, int
+   mmu_idx) */
 static void *qemu_ld_helpers[4] = {
     __ldb_mmu,
     __ldw_mmu,
@@ -308,6 +329,8 @@ static void *qemu_ld_helpers[4] = {
     __ldq_mmu,
 };
 
+/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val,
+   int mmu_idx) */
 static void *qemu_st_helpers[4] = {
     __stb_mmu,
     __stw_mmu,
@@ -315,6 +338,7 @@ static void *qemu_st_helpers[4] = {
     __stq_mmu,
 };
 #endif
+#endif
 
 static uint8_t *tb_ret_addr;
 
@@ -1483,9 +1507,29 @@ static void tcg_prepare_qemu_ldst(TCGContext* s, TCGReg data_reg,
             tcg_abort();
         }
         tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R4, mem_index);
+#ifdef CONFIG_TCG_PASS_AREG0
+        /* XXX/FIXME: suboptimal */
+        tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2],
+                    tcg_target_call_iarg_regs[1]);
+        tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
+                    tcg_target_call_iarg_regs[0]);
+        tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
+                    TCG_AREG0);
+#endif
         tgen_calli(s, (tcg_target_ulong)qemu_st_helpers[s_bits]);
     } else {
         tcg_out_movi(s, TCG_TYPE_I32, arg1, mem_index);
+#ifdef CONFIG_TCG_PASS_AREG0
+        /* XXX/FIXME: suboptimal */
+        tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
+                    tcg_target_call_iarg_regs[2]);
+        tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
+                    tcg_target_call_iarg_regs[1]);
+        tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
+                    tcg_target_call_iarg_regs[0]);
+        tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
+                    TCG_AREG0);
+#endif
         tgen_calli(s, (tcg_target_ulong)qemu_ld_helpers[s_bits]);
 
         /* sign extension */
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index b287122..80f0818 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -59,6 +59,12 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
 };
 #endif
 
+#ifdef CONFIG_TCG_PASS_AREG0
+#define ARG_OFFSET 1
+#else
+#define ARG_OFFSET 0
+#endif
+
 static const int tcg_target_reg_alloc_order[] = {
     TCG_REG_L0,
     TCG_REG_L1,
@@ -86,9 +92,9 @@ static const int tcg_target_call_iarg_regs[6] = {
 
 static const int tcg_target_call_oarg_regs[] = {
     TCG_REG_O0,
-#if TCG_TARGET_REG_BITS == 32
-    TCG_REG_O1
-#endif
+    TCG_REG_O1,
+    TCG_REG_O2,
+    TCG_REG_O3,
 };
 
 static inline int check_fit_tl(tcg_target_long val, unsigned int bits)
@@ -155,6 +161,9 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_O0);
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_O1);
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_O2);
+#ifdef CONFIG_TCG_PASS_AREG0
+        tcg_regset_reset_reg(ct->u.regs, TCG_REG_O3);
+#endif
         break;
     case 'I':
         ct->ct |= TCG_CT_CONST_S11;
@@ -706,6 +715,27 @@ static void tcg_target_qemu_prologue(TCGContext *s)
 
 #include "../../softmmu_defs.h"
 
+#ifdef CONFIG_TCG_PASS_AREG0
+/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
+   int mmu_idx) */
+static const void * const qemu_ld_helpers[4] = {
+    helper_ldb_mmu,
+    helper_ldw_mmu,
+    helper_ldl_mmu,
+    helper_ldq_mmu,
+};
+
+/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
+   uintxx_t val, int mmu_idx) */
+static const void * const qemu_st_helpers[4] = {
+    helper_stb_mmu,
+    helper_stw_mmu,
+    helper_stl_mmu,
+    helper_stq_mmu,
+};
+#else
+/* legacy helper signature: __ld_mmu(target_ulong addr, int
+   mmu_idx) */
 static const void * const qemu_ld_helpers[4] = {
     __ldb_mmu,
     __ldw_mmu,
@@ -713,6 +743,8 @@ static const void * const qemu_ld_helpers[4] = {
     __ldq_mmu,
 };
 
+/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val,
+   int mmu_idx) */
 static const void * const qemu_st_helpers[4] = {
     __stb_mmu,
     __stw_mmu,
@@ -720,6 +752,7 @@ static const void * const qemu_st_helpers[4] = {
     __stq_mmu,
 };
 #endif
+#endif
 
 #if TARGET_LONG_BITS == 32
 #define TARGET_LD_OP LDUW
@@ -801,6 +834,17 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
 
     /* mov */
     tcg_out_movi(s, TCG_TYPE_I32, arg1, mem_index);
+#ifdef CONFIG_TCG_PASS_AREG0
+    /* XXX/FIXME: suboptimal */
+    tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
+                tcg_target_call_iarg_regs[2]);
+    tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
+                tcg_target_call_iarg_regs[1]);
+    tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
+                tcg_target_call_iarg_regs[0]);
+    tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
+                TCG_AREG0);
+#endif
 
     /* XXX: move that code at the end of the TB */
     /* qemu_ld_helper[s_bits](arg0, arg1) */
diff --git a/tcg/tci/tcg-target.c b/tcg/tci/tcg-target.c
index bd85073..453f187 100644
--- a/tcg/tci/tcg-target.c
+++ b/tcg/tci/tcg-target.c
@@ -798,6 +798,9 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
     case INDEX_op_qemu_st8:
     case INDEX_op_qemu_st16:
     case INDEX_op_qemu_st32:
+#ifdef CONFIG_TCG_PASS_AREG0
+        tcg_out_r(s, TCG_AREG0);
+#endif
         tcg_out_r(s, *args++);
         tcg_out_r(s, *args++);
 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
@@ -808,6 +811,9 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
 #endif
         break;
     case INDEX_op_qemu_st64:
+#ifdef CONFIG_TCG_PASS_AREG0
+        tcg_out_r(s, TCG_AREG0);
+#endif
         tcg_out_r(s, *args++);
 #if TCG_TARGET_REG_BITS == 32
         tcg_out_r(s, *args++);
commit 6a18ae2d2947532d5c26439548afa0481c4529f9
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Wed Feb 15 18:02:32 2012 +0000

    i386: Remove REGPARM
    
    Use stack based calling convention (GCC default) for interfacing with
    generated code instead of register based convention (regparm(3)).
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/osdep.h b/osdep.h
index 0350383..156666e 100644
--- a/osdep.h
+++ b/osdep.h
@@ -70,12 +70,6 @@
 #define inline always_inline
 #endif
 
-#ifdef __i386__
-#define REGPARM __attribute((regparm(3)))
-#else
-#define REGPARM
-#endif
-
 #define qemu_printf printf
 
 int qemu_daemon(int nochdir, int noclose);
diff --git a/softmmu_defs.h b/softmmu_defs.h
index c5a2bcd..d47d30d 100644
--- a/softmmu_defs.h
+++ b/softmmu_defs.h
@@ -9,22 +9,22 @@
 #ifndef SOFTMMU_DEFS_H
 #define SOFTMMU_DEFS_H
 
-uint8_t REGPARM __ldb_mmu(target_ulong addr, int mmu_idx);
-void REGPARM __stb_mmu(target_ulong addr, uint8_t val, int mmu_idx);
-uint16_t REGPARM __ldw_mmu(target_ulong addr, int mmu_idx);
-void REGPARM __stw_mmu(target_ulong addr, uint16_t val, int mmu_idx);
-uint32_t REGPARM __ldl_mmu(target_ulong addr, int mmu_idx);
-void REGPARM __stl_mmu(target_ulong addr, uint32_t val, int mmu_idx);
-uint64_t REGPARM __ldq_mmu(target_ulong addr, int mmu_idx);
-void REGPARM __stq_mmu(target_ulong addr, uint64_t val, int mmu_idx);
+uint8_t __ldb_mmu(target_ulong addr, int mmu_idx);
+void __stb_mmu(target_ulong addr, uint8_t val, int mmu_idx);
+uint16_t __ldw_mmu(target_ulong addr, int mmu_idx);
+void __stw_mmu(target_ulong addr, uint16_t val, int mmu_idx);
+uint32_t __ldl_mmu(target_ulong addr, int mmu_idx);
+void __stl_mmu(target_ulong addr, uint32_t val, int mmu_idx);
+uint64_t __ldq_mmu(target_ulong addr, int mmu_idx);
+void __stq_mmu(target_ulong addr, uint64_t val, int mmu_idx);
 
-uint8_t REGPARM __ldb_cmmu(target_ulong addr, int mmu_idx);
-void REGPARM __stb_cmmu(target_ulong addr, uint8_t val, int mmu_idx);
-uint16_t REGPARM __ldw_cmmu(target_ulong addr, int mmu_idx);
-void REGPARM __stw_cmmu(target_ulong addr, uint16_t val, int mmu_idx);
-uint32_t REGPARM __ldl_cmmu(target_ulong addr, int mmu_idx);
-void REGPARM __stl_cmmu(target_ulong addr, uint32_t val, int mmu_idx);
-uint64_t REGPARM __ldq_cmmu(target_ulong addr, int mmu_idx);
-void REGPARM __stq_cmmu(target_ulong addr, uint64_t val, int mmu_idx);
+uint8_t __ldb_cmmu(target_ulong addr, int mmu_idx);
+void __stb_cmmu(target_ulong addr, uint8_t val, int mmu_idx);
+uint16_t __ldw_cmmu(target_ulong addr, int mmu_idx);
+void __stw_cmmu(target_ulong addr, uint16_t val, int mmu_idx);
+uint32_t __ldl_cmmu(target_ulong addr, int mmu_idx);
+void __stl_cmmu(target_ulong addr, uint32_t val, int mmu_idx);
+uint64_t __ldq_cmmu(target_ulong addr, int mmu_idx);
+void __stq_cmmu(target_ulong addr, uint64_t val, int mmu_idx);
 
 #endif
diff --git a/softmmu_template.h b/softmmu_template.h
index e395020..d633bb5 100644
--- a/softmmu_template.h
+++ b/softmmu_template.h
@@ -89,8 +89,7 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr,
 }
 
 /* handle all cases except unaligned access which span two pages */
-DATA_TYPE REGPARM glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
-                                                      int mmu_idx)
+DATA_TYPE glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr, int mmu_idx)
 {
     DATA_TYPE res;
     int index;
@@ -232,9 +231,8 @@ static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr,
 #endif /* SHIFT > 2 */
 }
 
-void REGPARM glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr,
-                                                 DATA_TYPE val,
-                                                 int mmu_idx)
+void glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE val,
+                                         int mmu_idx)
 {
     target_phys_addr_t ioaddr;
     unsigned long addend;
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index fafd900..c4e940d 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -116,17 +116,7 @@ static inline int tcg_target_get_call_iarg_regs_count(int flags)
         return 6;
     }
 
-    flags &= TCG_CALL_TYPE_MASK;
-    switch(flags) {
-    case TCG_CALL_TYPE_STD:
-        return 0;
-    case TCG_CALL_TYPE_REGPARM_1:
-    case TCG_CALL_TYPE_REGPARM_2:
-    case TCG_CALL_TYPE_REGPARM:
-        return flags - TCG_CALL_TYPE_REGPARM_1 + 1;
-    default:
-        tcg_abort();
-    }
+    return 0;
 }
 
 /* parse target specific constraints */
@@ -1148,7 +1138,12 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
     int data_reg, data_reg2 = 0;
     int addrlo_idx;
 #if defined(CONFIG_SOFTMMU)
-    int mem_index, s_bits, arg_idx;
+    int mem_index, s_bits;
+#if TCG_TARGET_REG_BITS == 64
+    int arg_idx;
+#else
+    int stack_adjust;
+#endif
     uint8_t *label_ptr[3];
 #endif
 
@@ -1184,16 +1179,33 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
     }
 
     /* XXX: move that code at the end of the TB */
+#if TCG_TARGET_REG_BITS == 32
+    tcg_out_pushi(s, mem_index);
+    stack_adjust = 4;
+    if (TARGET_LONG_BITS == 64) {
+        tcg_out_push(s, args[addrlo_idx + 1]);
+        stack_adjust += 4;
+    }
+    tcg_out_push(s, args[addrlo_idx]);
+    stack_adjust += 4;
+#else
     /* The first argument is already loaded with addrlo.  */
     arg_idx = 1;
-    if (TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 64) {
-        tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx++],
-                    args[addrlo_idx + 1]);
-    }
     tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx],
                  mem_index);
+#endif
+
     tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]);
 
+#if TCG_TARGET_REG_BITS == 32
+    if (stack_adjust == (TCG_TARGET_REG_BITS / 8)) {
+        /* Pop and discard.  This is 2 bytes smaller than the add.  */
+        tcg_out_pop(s, TCG_REG_ECX);
+    } else if (stack_adjust != 0) {
+        tcg_out_addi(s, TCG_REG_CALL_STACK, stack_adjust);
+    }
+#endif
+
     switch(opc) {
     case 0 | 4:
         tcg_out_ext8s(s, data_reg, TCG_REG_EAX, P_REXW);
@@ -1359,45 +1371,27 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
     }
 
     /* XXX: move that code at the end of the TB */
-    if (TCG_TARGET_REG_BITS == 64) {
-        tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32),
-                    TCG_REG_RSI, data_reg);
-        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index);
-        stack_adjust = 0;
-    } else if (TARGET_LONG_BITS == 32) {
-        tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, data_reg);
-        if (opc == 3) {
-            tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_ECX, data_reg2);
-            tcg_out_pushi(s, mem_index);
-            stack_adjust = 4;
-        } else {
-            tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
-            stack_adjust = 0;
-        }
-    } else {
-        if (opc == 3) {
-            tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, args[addrlo_idx + 1]);
-            tcg_out_pushi(s, mem_index);
-            tcg_out_push(s, data_reg2);
-            tcg_out_push(s, data_reg);
-            stack_adjust = 12;
-        } else {
-            tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, args[addrlo_idx + 1]);
-            switch(opc) {
-            case 0:
-                tcg_out_ext8u(s, TCG_REG_ECX, data_reg);
-                break;
-            case 1:
-                tcg_out_ext16u(s, TCG_REG_ECX, data_reg);
-                break;
-            case 2:
-                tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_ECX, data_reg);
-                break;
-            }
-            tcg_out_pushi(s, mem_index);
-            stack_adjust = 4;
-        }
+#if TCG_TARGET_REG_BITS == 32
+    tcg_out_pushi(s, mem_index);
+    stack_adjust = 4;
+    if (opc == 3) {
+        tcg_out_push(s, data_reg2);
+        stack_adjust += 4;
+    }
+    tcg_out_push(s, data_reg);
+    stack_adjust += 4;
+    if (TARGET_LONG_BITS == 64) {
+        tcg_out_push(s, args[addrlo_idx + 1]);
+        stack_adjust += 4;
     }
+    tcg_out_push(s, args[addrlo_idx]);
+    stack_adjust += 4;
+#else
+    tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32),
+                TCG_REG_RSI, data_reg);
+    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index);
+    stack_adjust = 0;
+#endif
 
     tcg_out_calli(s, (tcg_target_long)qemu_st_helpers[s_bits]);
 
@@ -1962,9 +1956,15 @@ static void tcg_target_qemu_prologue(TCGContext *s)
         tcg_out_push(s, tcg_target_callee_save_regs[i]);
     }
 
-    tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
-
+#if TCG_TARGET_REG_BITS == 32
+    tcg_out_ld(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_ESP,
+               (ARRAY_SIZE(tcg_target_callee_save_regs) + 1) * 4);
+    tcg_out_ld(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[1], TCG_REG_ESP,
+               (ARRAY_SIZE(tcg_target_callee_save_regs) + 2) * 4);
+#else
     tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
+#endif
+    tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
 
     /* jmp *tb.  */
     tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, tcg_target_call_iarg_regs[1]);
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
index 3f22aaa..2f37fd2 100644
--- a/tcg/ppc/tcg-target.h
+++ b/tcg/ppc/tcg-target.h
@@ -98,5 +98,5 @@ typedef enum {
 #define TCG_TARGET_HAS_GUEST_BASE
 
 #define tcg_qemu_tb_exec(env, tb_ptr) \
-    ((long REGPARM __attribute__ ((longcall)) \
+    ((long __attribute__ ((longcall)) \
       (*)(void *, void *))code_gen_prologue)(env, tb_ptr)
diff --git a/tcg/tcg.c b/tcg/tcg.c
index ad2e983..ccfcd1a 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -594,9 +594,6 @@ void tcg_register_helper(void *func, const char *name)
 void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
                    int sizemask, TCGArg ret, int nargs, TCGArg *args)
 {
-#if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64
-    int call_type;
-#endif
     int i;
     int real_args;
     int nb_rets;
@@ -621,9 +618,6 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
 
     *gen_opc_ptr++ = INDEX_op_call;
     nparam = gen_opparam_ptr++;
-#if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64
-    call_type = (flags & TCG_CALL_TYPE_MASK);
-#endif
     if (ret != TCG_CALL_DUMMY_ARG) {
 #if TCG_TARGET_REG_BITS < 64
         if (sizemask & 1) {
@@ -649,14 +643,6 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
 #if TCG_TARGET_REG_BITS < 64
         int is_64bit = sizemask & (1 << (i+1)*2);
         if (is_64bit) {
-#ifdef TCG_TARGET_I386
-            /* REGPARM case: if the third parameter is 64 bit, it is
-               allocated on the stack */
-            if (i == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
-                call_type = TCG_CALL_TYPE_REGPARM_2;
-                flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
-            }
-#endif
 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
             /* some targets want aligned 64 bit args */
             if (real_args & 1) {
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 9bc9fc9..5f6c647 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -252,11 +252,6 @@ typedef int TCGv_i64;
 #define TCGV_UNUSED_I64(x) x = MAKE_TCGV_I64(-1)
 
 /* call flags */
-#define TCG_CALL_TYPE_MASK      0x000f
-#define TCG_CALL_TYPE_STD       0x0000 /* standard C call */
-#define TCG_CALL_TYPE_REGPARM_1 0x0001 /* i386 style regparm call (1 reg) */
-#define TCG_CALL_TYPE_REGPARM_2 0x0002 /* i386 style regparm call (2 regs) */
-#define TCG_CALL_TYPE_REGPARM   0x0003 /* i386 style regparm call (3 regs) */
 /* A pure function only reads its arguments and TCG global variables
    and cannot raise exceptions. Hence a call to a pure function can be
    safely suppressed if the return value is not used. */
@@ -589,5 +584,5 @@ extern uint8_t code_gen_prologue[];
 /* TCG targets may use a different definition of tcg_qemu_tb_exec. */
 #if !defined(tcg_qemu_tb_exec)
 # define tcg_qemu_tb_exec(env, tb_ptr) \
-    ((tcg_target_ulong REGPARM (*)(void *, void *))code_gen_prologue)(env, tb_ptr)
+    ((tcg_target_ulong (*)(void *, void *))code_gen_prologue)(env, tb_ptr)
 #endif
commit 361dea401f529fc136aaeb49c82b2a5bb7faa316
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Mar 10 20:37:00 2012 +0000

    sparc64: implement PCI and ISA irqs
    
    Generate correct trap for external interrupts. Map PCI and ISA IRQs to
    RIC/UltraSPARC-IIi interrupt vectors.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index b10f31e..7e28808 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -66,6 +66,8 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
 #define RESET_WCMASK 0x98000000
 #define RESET_WMASK  0x60000000
 
+#define MAX_IVEC 0x30
+
 typedef struct APBState {
     SysBusDevice busdev;
     PCIBus      *bus;
@@ -77,7 +79,8 @@ typedef struct APBState {
     uint32_t pci_control[16];
     uint32_t pci_irq_map[8];
     uint32_t obio_irq_map[32];
-    qemu_irq pci_irqs[32];
+    qemu_irq *pbm_irqs;
+    qemu_irq *ivec_irqs;
     uint32_t reset_control;
     unsigned int nr_resets;
 } APBState;
@@ -87,7 +90,7 @@ static void apb_config_writel (void *opaque, target_phys_addr_t addr,
 {
     APBState *s = opaque;
 
-    APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %x\n", __func__, addr, val);
+    APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %" PRIx64 "\n", __func__, addr, val);
 
     switch (addr & 0xffff) {
     case 0x30 ... 0x4f: /* DMA error registers */
@@ -104,6 +107,12 @@ static void apb_config_writel (void *opaque, target_phys_addr_t addr,
             s->pci_irq_map[(addr & 0x3f) >> 3] |= val & ~PBM_PCI_IMR_MASK;
         }
         break;
+    case 0x1000 ... 0x1080: /* OBIO interrupt control */
+        if (addr & 4) {
+            s->obio_irq_map[(addr & 0xff) >> 3] &= PBM_PCI_IMR_MASK;
+            s->obio_irq_map[(addr & 0xff) >> 3] |= val & ~PBM_PCI_IMR_MASK;
+        }
+        break;
     case 0x2000 ... 0x202f: /* PCI control */
         s->pci_control[(addr & 0x3f) >> 2] = val;
         break;
@@ -154,6 +163,13 @@ static uint64_t apb_config_readl (void *opaque,
             val = 0;
         }
         break;
+    case 0x1000 ... 0x1080: /* OBIO interrupt control */
+        if (addr & 4) {
+            val = s->obio_irq_map[(addr & 0xff) >> 3];
+        } else {
+            val = 0;
+        }
+        break;
     case 0x2000 ... 0x202f: /* PCI control */
         val = s->pci_control[(addr & 0x3f) >> 2];
         break;
@@ -190,7 +206,7 @@ static void apb_pci_config_write(void *opaque, target_phys_addr_t addr,
     APBState *s = opaque;
 
     val = qemu_bswap_len(val, size);
-    APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %x\n", __func__, addr, val);
+    APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %" PRIx64 "\n", __func__, addr, val);
     pci_data_write(s->bus, addr, val, size);
 }
 
@@ -280,10 +296,19 @@ static void pci_apb_set_irq(void *opaque, int irq_num, int level)
     if (irq_num < 32) {
         if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
             APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
-            qemu_set_irq(s->pci_irqs[irq_num], level);
+            qemu_set_irq(s->ivec_irqs[irq_num], level);
+        } else {
+            APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
+            qemu_irq_lower(s->ivec_irqs[irq_num]);
+        }
+    } else {
+        /* OBIO IRQ map onto the next 16 INO.  */
+        if (s->obio_irq_map[irq_num - 32] & PBM_PCI_IMR_ENABLED) {
+            APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
+            qemu_set_irq(s->ivec_irqs[irq_num], level);
         } else {
             APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
-            qemu_irq_lower(s->pci_irqs[irq_num]);
+            qemu_irq_lower(s->ivec_irqs[irq_num]);
         }
     }
 }
@@ -316,12 +341,12 @@ static int apb_pci_bridge_initfn(PCIDevice *dev)
 
 PCIBus *pci_apb_init(target_phys_addr_t special_base,
                      target_phys_addr_t mem_base,
-                     qemu_irq *pic, PCIBus **bus2, PCIBus **bus3)
+                     qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3,
+                     qemu_irq **pbm_irqs)
 {
     DeviceState *dev;
     SysBusDevice *s;
     APBState *d;
-    unsigned int i;
     PCIDevice *pci_dev;
     PCIBridge *br;
 
@@ -346,9 +371,8 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
                               get_system_io(),
                               0, 32);
 
-    for (i = 0; i < 32; i++) {
-        sysbus_connect_irq(s, i, pic[i]);
-    }
+    *pbm_irqs = d->pbm_irqs;
+    d->ivec_irqs = ivec_irqs;
 
     pci_create_simple(d->bus, 0, "pbm-pci");
 
@@ -402,9 +426,7 @@ static int pci_pbm_init_device(SysBusDevice *dev)
     for (i = 0; i < 8; i++) {
         s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
     }
-    for (i = 0; i < 32; i++) {
-        sysbus_init_irq(dev, &s->pci_irqs[i]);
-    }
+    s->pbm_irqs = qemu_allocate_irqs(pci_apb_set_irq, s, MAX_IVEC);
 
     /* apb_config */
     memory_region_init_io(&s->apb_config, &apb_config_ops, s, "apb-config",
diff --git a/hw/apb_pci.h b/hw/apb_pci.h
index 8869f9d..55f7c4c 100644
--- a/hw/apb_pci.h
+++ b/hw/apb_pci.h
@@ -5,5 +5,6 @@
 
 PCIBus *pci_apb_init(target_phys_addr_t special_base,
                      target_phys_addr_t mem_base,
-                     qemu_irq *pic, PCIBus **bus2, PCIBus **bus3);
+                     qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3,
+                     qemu_irq **pbm_irqs);
 #endif
diff --git a/hw/sun4u.c b/hw/sun4u.c
index c32eddb..237e20c 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -81,7 +81,7 @@
 #define FW_CFG_SPARC64_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01)
 #define FW_CFG_SPARC64_DEPTH (FW_CFG_ARCH_LOCAL + 0x02)
 
-#define MAX_PILS 16
+#define IVEC_MAX             0x30
 
 #define TICK_MAX             0x7fffffffffffffffULL
 
@@ -304,18 +304,24 @@ static void cpu_kick_irq(CPUSPARCState *env)
     qemu_cpu_kick(env);
 }
 
-static void cpu_set_irq(void *opaque, int irq, int level)
+static void cpu_set_ivec_irq(void *opaque, int irq, int level)
 {
     CPUSPARCState *env = opaque;
 
     if (level) {
-        CPUIRQ_DPRINTF("Raise CPU IRQ %d\n", irq);
-        env->pil_in |= 1 << irq;
-        cpu_kick_irq(env);
-    } else {
-        CPUIRQ_DPRINTF("Lower CPU IRQ %d\n", irq);
-        env->pil_in &= ~(1 << irq);
-        cpu_check_irqs(env);
+        CPUIRQ_DPRINTF("Raise IVEC IRQ %d\n", irq);
+        env->interrupt_index = TT_IVEC;
+        env->pil_in |= 1 << 5;
+        env->ivec_status |= 0x20;
+        env->ivec_data[0] = (0x1f << 6) | irq;
+        env->ivec_data[1] = 0;
+        env->ivec_data[2] = 0;
+        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+      } else {
+        CPUIRQ_DPRINTF("Lower IVEC IRQ %d\n", irq);
+        env->pil_in &= ~(1 << 5);
+        env->ivec_status &= ~0x20;
+        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
     }
 }
 
@@ -521,13 +527,29 @@ void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit)
     }
 }
 
-static void dummy_isa_irq_handler(void *opaque, int n, int level)
+static void isa_irq_handler(void *opaque, int n, int level)
 {
+    static const int isa_irq_to_ivec[16] = {
+        [1] = 0x29, /* keyboard */
+        [4] = 0x2b, /* serial */
+        [6] = 0x27, /* floppy */
+        [7] = 0x22, /* parallel */
+        [12] = 0x2a, /* mouse */
+    };
+    qemu_irq *irqs = opaque;
+    int ivec;
+
+    assert(n < 16);
+    ivec = isa_irq_to_ivec[n];
+    EBUS_DPRINTF("Set ISA IRQ %d level %d -> ivec 0x%x\n", n, level, ivec);
+    if (ivec) {
+        qemu_set_irq(irqs[ivec], level);
+    }
 }
 
 /* EBUS (Eight bit bus) bridge */
 static ISABus *
-pci_ebus_init(PCIBus *bus, int devfn)
+pci_ebus_init(PCIBus *bus, int devfn, qemu_irq *irqs)
 {
     qemu_irq *isa_irq;
     PCIDevice *pci_dev;
@@ -536,7 +558,7 @@ pci_ebus_init(PCIBus *bus, int devfn)
     pci_dev = pci_create_simple(bus, devfn, "ebus");
     isa_bus = DO_UPCAST(ISABus, qbus,
                         qdev_get_child_bus(&pci_dev->qdev, "isa.0"));
-    isa_irq = qemu_allocate_irqs(dummy_isa_irq_handler, NULL, 16);
+    isa_irq = qemu_allocate_irqs(isa_irq_handler, irqs, 16);
     isa_bus_irqs(isa_bus, isa_irq);
     return isa_bus;
 }
@@ -761,7 +783,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
     long initrd_size, kernel_size;
     PCIBus *pci_bus, *pci_bus2, *pci_bus3;
     ISABus *isa_bus;
-    qemu_irq *irq;
+    qemu_irq *ivec_irqs, *pbm_irqs;
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     DriveInfo *fd[MAX_FD];
     void *fw_cfg;
@@ -774,14 +796,13 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
 
     prom_init(hwdef->prom_addr, bios_name);
 
-
-    irq = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS);
-    pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, irq, &pci_bus2,
-                           &pci_bus3);
+    ivec_irqs = qemu_allocate_irqs(cpu_set_ivec_irq, env, IVEC_MAX);
+    pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_irqs, &pci_bus2,
+                           &pci_bus3, &pbm_irqs);
     pci_vga_init(pci_bus);
 
     // XXX Should be pci_bus3
-    isa_bus = pci_ebus_init(pci_bus, -1);
+    isa_bus = pci_ebus_init(pci_bus, -1, pbm_irqs);
 
     i = 0;
     if (hwdef->console_serial_base) {
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 887adc3..f638457 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -493,6 +493,9 @@ struct CPUSPARCState {
     /* UA 2005 hyperprivileged registers */
     uint64_t hpstate, htstate[MAXTL_MAX], hintp, htba, hver, hstick_cmpr, ssr;
     CPUTimer *hstick; // UA 2005
+    /* Interrupt vector registers */
+    uint64_t ivec_status;
+    uint64_t ivec_data[3];
     uint32_t softint;
 #define SOFTINT_TIMER   1
 #define SOFTINT_STIMER  (1 << 16)
diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
index 48d433c..97afdd3 100644
--- a/target-sparc/ldst_helper.c
+++ b/target-sparc/ldst_helper.c
@@ -1526,6 +1526,19 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
             ret = env->dtlb[reg].tag;
             break;
         }
+    case 0x48: /* Interrupt dispatch, RO */
+        break;
+    case 0x49: /* Interrupt data receive */
+        ret = env->ivec_status;
+        break;
+    case 0x7f: /* Incoming interrupt vector, RO */
+        {
+            int reg = (addr >> 4) & 0x3;
+            if (reg < 3) {
+                ret = env->ivec_data[reg];
+            }
+            break;
+        }
     case 0x46: /* D-cache data */
     case 0x47: /* D-cache tag access */
     case 0x4b: /* E-cache error enable */
@@ -1540,11 +1553,6 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
     case 0x7e: /* E-cache tag */
         break;
     case 0x5b: /* D-MMU data pointer */
-    case 0x48: /* Interrupt dispatch, RO */
-    case 0x49: /* Interrupt data receive */
-    case 0x7f: /* Incoming interrupt vector, RO */
-        /* XXX */
-        break;
     case 0x54: /* I-MMU data in, WO */
     case 0x57: /* I-MMU demap, WO */
     case 0x5c: /* D-MMU data in, WO */
@@ -1954,7 +1962,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
         demap_tlb(env->dtlb, addr, "dmmu", env);
         return;
     case 0x49: /* Interrupt data receive */
-        /* XXX */
+        env->ivec_status = val & 0x20;
         return;
     case 0x46: /* D-cache data */
     case 0x47: /* D-cache tag access */
commit 89aaf60dedbe0e6415acfe816e02b538e5c54e68
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Mar 10 17:55:05 2012 +0000

    sparc: reset CPU state on reset
    
    Not strictly accurate for Sparc64 but avoid confusing Valgrind.
    
    Reported-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 86f9de6..887adc3 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -415,14 +415,15 @@ struct CPUSPARCState {
 #if !defined(TARGET_SPARC64)
     int      psref;    /* enable fpu */
 #endif
-    target_ulong version;
     int interrupt_index;
-    uint32_t nwindows;
     /* NOTE: we allow 8 more registers to handle wrapping */
     target_ulong regbase[MAX_NWINDOWS * 16 + 8];
 
     CPU_COMMON
 
+    target_ulong version;
+    uint32_t nwindows;
+
     /* MMU regs */
 #if defined(TARGET_SPARC64)
     uint64_t lsu;
diff --git a/target-sparc/cpu_init.c b/target-sparc/cpu_init.c
index 29132fb..5c03f0b 100644
--- a/target-sparc/cpu_init.c
+++ b/target-sparc/cpu_init.c
@@ -30,6 +30,7 @@ void cpu_state_reset(CPUSPARCState *env)
         log_cpu_state(env, 0);
     }
 
+    memset(env, 0, offsetof(CPUSPARCState, breakpoints));
     tlb_flush(env, 1);
     env->cwp = 0;
 #ifndef TARGET_SPARC64
commit b21227c499b5939891cdc1e5e6834c92eaf2dee0
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Mar 10 16:53:47 2012 +0000

    apb: use normal PCI device header for PBM device
    
    PBM has a normal PCI device header, fix.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 1d25da8..b10f31e 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -444,7 +444,6 @@ static void pbm_pci_host_class_init(ObjectClass *klass, void *data)
     k->vendor_id = PCI_VENDOR_ID_SUN;
     k->device_id = PCI_DEVICE_ID_SUN_SABRE;
     k->class_id = PCI_CLASS_BRIDGE_HOST;
-    k->is_bridge = 1;
 }
 
 static TypeInfo pbm_pci_host_info = {
commit 103f9af2a1ad6427533ae2c92d9e1e721b2ae902
Merge: 69784ea... 14dd5fa...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Mar 17 16:23:19 2012 +0000

    Merge branch 'arm-devs.for-upstream' of git://git.linaro.org/people/pmaydell/qemu-arm
    
    * 'arm-devs.for-upstream' of git://git.linaro.org/people/pmaydell/qemu-arm:
      hw/pxa2xx.c: Fix handling of pxa2xx_i2c variable offset within region
      hw/pxa2xx_lcd.c: drop target_phys_addr_t usage in device state
      hw/pxa2xx_dma.c: drop target_phys_addr_t usage in device state
      ARM: Remove unnecessary subpage workarounds
      hw/omap_i2c: Convert to qdev

commit 69784eaec335d09619639db4da6c1e4770290526
Author: Stefan Weil <sw at weilnetz.de>
Date:   Fri Mar 16 23:50:54 2012 +0100

    w64: Fix data type of next_tb and tcg_qemu_tb_exec
    
    next_tb is the numeric value of a tcg target (= QEMU host) address.
    
    Using tcg_target_ulong instead of unsigned long shows this and makes
    the code portable for hosts with an unusual size of long (w64).
    
    The type cast '(long)(next_tb & ~3)' was not needed (casting
    unsigned long to long does not change the bits, and nor does
    casting long to pointer for most (= all non w64) hosts.
    It is removed here.
    
    Macro or function tcg_qemu_tb_exec is used to set next_tb.
    The function also returns next_tb. Therefore tcg_qemu_tb_exec
    must return a tcg_target_ulong.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpu-exec.c b/cpu-exec.c
index bd5791f..0fa8325 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -55,7 +55,7 @@ void cpu_resume_from_signal(CPUArchState *env, void *puc)
 static void cpu_exec_nocache(CPUArchState *env, int max_cycles,
                              TranslationBlock *orig_tb)
 {
-    unsigned long next_tb;
+    tcg_target_ulong next_tb;
     TranslationBlock *tb;
 
     /* Should never happen.
@@ -186,7 +186,7 @@ int cpu_exec(CPUArchState *env)
     int ret, interrupt_request;
     TranslationBlock *tb;
     uint8_t *tc_ptr;
-    unsigned long next_tb;
+    tcg_target_ulong next_tb;
 
     if (env->halted) {
         if (!cpu_has_work(env)) {
@@ -565,7 +565,7 @@ int cpu_exec(CPUArchState *env)
                     if ((next_tb & 3) == 2) {
                         /* Instruction counter expired.  */
                         int insns_left;
-                        tb = (TranslationBlock *)(long)(next_tb & ~3);
+                        tb = (TranslationBlock *)(next_tb & ~3);
                         /* Restore PC.  */
                         cpu_pc_from_tb(env, tb);
                         insns_left = env->icount_decr.u32;
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 92943c1..9bc9fc9 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -589,5 +589,5 @@ extern uint8_t code_gen_prologue[];
 /* TCG targets may use a different definition of tcg_qemu_tb_exec. */
 #if !defined(tcg_qemu_tb_exec)
 # define tcg_qemu_tb_exec(env, tb_ptr) \
-    ((long REGPARM (*)(void *, void *))code_gen_prologue)(env, tb_ptr)
+    ((tcg_target_ulong REGPARM (*)(void *, void *))code_gen_prologue)(env, tb_ptr)
 #endif
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
index b61e99a..30a0f21 100644
--- a/tcg/tci/tcg-target.h
+++ b/tcg/tci/tcg-target.h
@@ -154,7 +154,7 @@ typedef enum {
 
 void tci_disas(uint8_t opc);
 
-unsigned long tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr);
+tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr);
 #define tcg_qemu_tb_exec tcg_qemu_tb_exec
 
 static inline void flush_icache_range(tcg_target_ulong start,
diff --git a/tci.c b/tci.c
index fb9ebef..70e7bfb 100644
--- a/tci.c
+++ b/tci.c
@@ -429,9 +429,9 @@ static bool tci_compare64(uint64_t u0, uint64_t u1, TCGCond condition)
 }
 
 /* Interpret pseudo code in tb. */
-unsigned long tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr)
+tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr)
 {
-    unsigned long next_tb = 0;
+    tcg_target_ulong next_tb = 0;
 
     env = cpustate;
     tci_reg[TCG_AREG0] = (tcg_target_ulong)env;
commit 3bf7e40ab9140e577a6e7e17d3f5711b28aed833
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Dec 27 17:11:20 2011 +0200

    softfloat: fix for C99
    
    C99 appears to consider compound literals as non-constants, and complains
    when they are used in static initializers.  Switch to ordinary initializer
    syntax.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Acked-by: Andreas Färber <afaerber at suse.de>
    Reported-by: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index c5e2dab..4902450 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -89,8 +89,8 @@ const float64 float64_default_nan = const_float64(LIT64( 0xFFF8000000000000 ));
 #define floatx80_default_nan_low  LIT64( 0xC000000000000000 )
 #endif
 
-const floatx80 floatx80_default_nan = make_floatx80(floatx80_default_nan_high,
-                                                    floatx80_default_nan_low);
+const floatx80 floatx80_default_nan
+    = make_floatx80_init(floatx80_default_nan_high, floatx80_default_nan_low);
 
 /*----------------------------------------------------------------------------
 | The pattern for a default generated quadruple-precision NaN.  The `high' and
@@ -104,8 +104,8 @@ const floatx80 floatx80_default_nan = make_floatx80(floatx80_default_nan_high,
 #define float128_default_nan_low  LIT64( 0x0000000000000000 )
 #endif
 
-const float128 float128_default_nan = make_float128(float128_default_nan_high,
-                                                    float128_default_nan_low);
+const float128 float128_default_nan
+    = make_float128_init(float128_default_nan_high, float128_default_nan_low);
 
 /*----------------------------------------------------------------------------
 | Raises the exceptions specified by `flags'.  Floating-point traps can be
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index 07c2929..2ce4110 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -129,6 +129,7 @@ typedef struct {
     uint16_t high;
 } floatx80;
 #define make_floatx80(exp, mant) ((floatx80) { mant, exp })
+#define make_floatx80_init(exp, mant) { .low = mant, .high = exp }
 typedef struct {
 #ifdef HOST_WORDS_BIGENDIAN
     uint64_t high, low;
@@ -137,6 +138,7 @@ typedef struct {
 #endif
 } float128;
 #define make_float128(high_, low_) ((float128) { .high = high_, .low = low_ })
+#define make_float128_init(high_, low_) { .high = high_, .low = low_ }
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE floating-point underflow tininess-detection mode.
commit 6344d922a1182d58b47566dfc0390782305d264b
Merge: 6b41fec... d9e028c...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Mar 17 12:59:41 2012 +0000

    Merge branch 'target-arm.for-upstream' of git://git.linaro.org/people/pmaydell/qemu-arm
    
    * 'target-arm.for-upstream' of git://git.linaro.org/people/pmaydell/qemu-arm:
      target-arm: Decode SETEND correctly in Thumb
      target-arm: Clear IT bits when taking exceptions in v7M
      target-arm: Fix typo in ARM946 cp15 c5 handling

commit 6b41fecf2e9e39fee54de2706b1a1727906513fd
Merge: cb76e9c... 1d7a119...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Mar 17 12:59:36 2012 +0000

    Merge branch 'malta' of git://qemu.weilnetz.de/qemu
    
    * 'malta' of git://qemu.weilnetz.de/qemu:
      malta: Fix display for LED array
      malta: Use symbolic hardware addresses
      malta: Always allocate flash memory
      malta: Clean allocation of bios region alias

commit cb76e9c7b7e9fe8786be2ef729636b264fe1d63a
Merge: 1329d18... 38ae51a...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Mar 17 12:59:23 2012 +0000

    Merge branch 'ppc-for-upstream' of git://repo.or.cz/qemu/agraf
    
    * 'ppc-for-upstream' of git://repo.or.cz/qemu/agraf:
      PPC: Fix openpic with relative memregions
      pseries: Configure PCI bridge using properties
      PPC: KVM: Synchronize regs on CPU dump
      kvm: Comparison with ioctl number macros needs to be unsigned
      ppc: Correctly define POWERPC_INSNS2_DEFAULT
      pseries: Add support for level interrupts to XICS
      PPC: Fix large page support in TCG
      PPC: Add PIR register to POWER7 CPU
      pseries: Remove PCI device from PCI host bridge code
      pseries: Remove unused constant from PCI code
      pseries: Update SLOF firmware image
      PPC64: Add support for ldbrx and stdbrx instructions
      pseries: Don't try to munmap() a malloc()ed TCE table
      ppc: Add missing 'static' to spin_rw_ops
      PPC: 405: Fix ppc405ep initialization
      Bad zero comparison for sas_ss_flags on powerpc

commit 1329d1896cc627cf71e3833525152ff59dd5113b
Author: Amos Kong <akong at redhat.com>
Date:   Tue Mar 13 14:05:36 2012 +0800

    vmstate: fix varrays with uint32_t indexes
    
    VMSTATE_VARRAY_UINT32() is used in hw/ds1225y.c, and we checked
    VMS_VARRAY_UINT32 bit of field->flags in vmstate_load_state(),
    but we don't check this bit in vmstate_save_state().
    
    Signed-off-by: Amos Kong <akong at redhat.com>
    Acked-by: Juan Quintela <quintela at redhat.com>
    Acked-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/savevm.c b/savevm.c
index 80be1ff..694eaa4 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1486,6 +1486,8 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
                 n_elems = field->num;
             } else if (field->flags & VMS_VARRAY_INT32) {
                 n_elems = *(int32_t *)(opaque+field->num_offset);
+            } else if (field->flags & VMS_VARRAY_UINT32) {
+                n_elems = *(uint32_t *)(opaque+field->num_offset);
             } else if (field->flags & VMS_VARRAY_UINT16) {
                 n_elems = *(uint16_t *)(opaque+field->num_offset);
             } else if (field->flags & VMS_VARRAY_UINT8) {
commit 4055299ef0e1c6e4a9b09ce000757b1274129991
Author: Kirill Batuzov <batuzovk at ispras.ru>
Date:   Fri Mar 2 13:22:17 2012 +0400

    Fix large memory chunks allocation with tcg_malloc.
    
    An attempt to allocate a large memory chunk after a small one resulted in
    circular links in list of pools.  It caused the same memory being
    allocated twice for different arrays.
    
    Now pools for large memory chunks are kept in separate list and are
    freed during pool reset because current allocator can not reuse them.
    
    Signed-off-by: Kirill Batuzov <batuzovk at ispras.ru>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 531db55..ad2e983 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -173,11 +173,9 @@ void *tcg_malloc_internal(TCGContext *s, int size)
         /* big malloc: insert a new pool (XXX: could optimize) */
         p = g_malloc(sizeof(TCGPool) + size);
         p->size = size;
-        if (s->pool_current)
-            s->pool_current->next = p;
-        else
-            s->pool_first = p;
-        p->next = s->pool_current;
+        p->next = s->pool_first_large;
+        s->pool_first_large = p;
+        return p->data;
     } else {
         p = s->pool_current;
         if (!p) {
@@ -208,6 +206,12 @@ void *tcg_malloc_internal(TCGContext *s, int size)
 
 void tcg_pool_reset(TCGContext *s)
 {
+    TCGPool *p, *t;
+    for (p = s->pool_first_large; p; p = t) {
+        t = p->next;
+        g_free(p);
+    }
+    s->pool_first_large = NULL;
     s->pool_cur = s->pool_end = NULL;
     s->pool_current = NULL;
 }
diff --git a/tcg/tcg.h b/tcg/tcg.h
index cc223ea..92943c1 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -337,7 +337,7 @@ typedef struct TCGContext TCGContext;
 
 struct TCGContext {
     uint8_t *pool_cur, *pool_end;
-    TCGPool *pool_first, *pool_current;
+    TCGPool *pool_first, *pool_current, *pool_first_large;
     TCGLabel *labels;
     int nb_labels;
     TCGTemp *temps; /* globals first, temps after */
commit 14dd5faa7e168d70760902c269dc68f3104b8ed6
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Mar 14 15:37:53 2012 +0000

    hw/pxa2xx.c: Fix handling of pxa2xx_i2c variable offset within region
    
    The pxa2xx I2C controller can have its registers at an arbitrary offset
    within the MemoryRegion it creates. We use this to create two controllers,
    one which covers a region of size 0x10000 with registers starting at an
    offset 0x1600 into that region, and a second one which covers a region
    of size just 0x100 with the registers starting at the base of the region.
    
    The implementation of this offsetting uses two qdev properties, "offset"
    (which sets the offset which must be subtracted from the address to
    get the offset into the actual register bank) and "size", which is the
    size of the MemoryRegion. We were actually using "offset" for two
    purposes: firstly the required one of handling the registers not being
    at the base of the MemoryRegion, and secondly as a workaround for a
    deficiency of QEMU. Until commit 5312bd8b3, if a MemoryRegion was mapped
    at a non-page boundary, the address passed into the read and write
    functions would be the offset from the start of the page, not the
    offset from the start of the MemoryRegion. So when calculating the value
    to set the "offset" qdev property we included a rounding to a page
    boundary.
    
    Following commit 5312bd8b3 MemoryRegion read/write functions are now
    correctly passed the offset from the base of the region, and our
    workaround now means we're subtracting too much from addresses, resulting
    in warnings like "pxa2xx_i2c_read: Bad register 0xffffff90".
    The fix for this is simply to remove the rounding to a page boundary;
    this allows us to slightly simplify the expression since
      base - (base & (~region_size)) == base & region_size
    
    The qdev property "offset" itself must remain because it is still
    performing its primary job of handling register banks not being at
    the base of the MemoryRegion.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index f552877..1d5c35f 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -1507,8 +1507,7 @@ PXA2xxI2CState *pxa2xx_i2c_init(target_phys_addr_t base,
 
     i2c_dev = sysbus_from_qdev(qdev_create(NULL, "pxa2xx_i2c"));
     qdev_prop_set_uint32(&i2c_dev->qdev, "size", region_size + 1);
-    qdev_prop_set_uint32(&i2c_dev->qdev, "offset",
-            base - (base & (~region_size) & TARGET_PAGE_MASK));
+    qdev_prop_set_uint32(&i2c_dev->qdev, "offset", base & region_size);
 
     qdev_init_nofail(&i2c_dev->qdev);
 
commit 27424dcc6804e630602a61229e57e42b14050869
Author: Mitsyanko Igor <i.mitsyanko at samsung.com>
Date:   Wed Mar 14 15:37:53 2012 +0000

    hw/pxa2xx_lcd.c: drop target_phys_addr_t usage in device state
    
    Pxa2xx LCD controller is intended to work with 32-bit bus and it has no knowledge
    of system's physical address size, so it should not use target_phys_addr_t in it's
    state. Convert three variables in DMAChannel state from target_phys_addr_t to uint32_t,
    use VMSTATE_UINT32 instead of VMSTATE_UINTTL for these variables.
    We can do this safely because:
    1) pxa2xx has 32-bit physical address;
    2) rest of the code in file never assumes converted variables to have any size
    different from uint32_t;
    3) we shouldn't have used VMSTATE_UINTTL in the first place because this macro
    is for target_ulong type (which can be different from target_phys_addr_t).
    
    Signed-off-by: Igor Mitsyanko <i.mitsyanko at samsung.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index fcbdfb3..ee8bf57 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -19,15 +19,15 @@
 #include "framebuffer.h"
 
 struct DMAChannel {
-    target_phys_addr_t branch;
+    uint32_t branch;
     uint8_t up;
     uint8_t palette[1024];
     uint8_t pbuffer[1024];
     void (*redraw)(PXA2xxLCDState *s, target_phys_addr_t addr,
                    int *miny, int *maxy);
 
-    target_phys_addr_t descriptor;
-    target_phys_addr_t source;
+    uint32_t descriptor;
+    uint32_t source;
     uint32_t id;
     uint32_t command;
 };
@@ -929,11 +929,11 @@ static const VMStateDescription vmstate_dma_channel = {
     .minimum_version_id = 0,
     .minimum_version_id_old = 0,
     .fields      = (VMStateField[]) {
-        VMSTATE_UINTTL(branch, struct DMAChannel),
+        VMSTATE_UINT32(branch, struct DMAChannel),
         VMSTATE_UINT8(up, struct DMAChannel),
         VMSTATE_BUFFER(pbuffer, struct DMAChannel),
-        VMSTATE_UINTTL(descriptor, struct DMAChannel),
-        VMSTATE_UINTTL(source, struct DMAChannel),
+        VMSTATE_UINT32(descriptor, struct DMAChannel),
+        VMSTATE_UINT32(source, struct DMAChannel),
         VMSTATE_UINT32(id, struct DMAChannel),
         VMSTATE_UINT32(command, struct DMAChannel),
         VMSTATE_END_OF_LIST()
commit a10394e1daff859517566b9882d4bdec0f6969ca
Author: Mitsyanko Igor <i.mitsyanko at samsung.com>
Date:   Wed Mar 14 15:37:53 2012 +0000

    hw/pxa2xx_dma.c: drop target_phys_addr_t usage in device state
    
    Pxa2xx DMA controller is a 32-bit device and it has no knowledge of system's
    physical address size, so it should not use target_phys_addr_t in it's state.
    Convert variables descr, src and dest from type target_phys_addr_t to uint32_t,
    use VMSTATE_UINT32 instead of VMSTATE_UINTTL for these variables.
    
    We can do this safely because:
    1) pxa2xx actually has 32-bit physical address size;
    2) rest of the code in file never assumes descr, src and dest variables to have
    size different from uint32_t;
    3) we shouldn't have used VMSTATE_UINTTL in the first place because this macro
    is for target_ulong type (which can be different from target_phys_addr_t).
    
    Signed-off-by: Igor Mitsyanko <i.mitsyanko at samsung.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/pxa2xx_dma.c b/hw/pxa2xx_dma.c
index 8ced0dd..0310154 100644
--- a/hw/pxa2xx_dma.c
+++ b/hw/pxa2xx_dma.c
@@ -18,9 +18,9 @@
 #define PXA2XX_DMA_NUM_REQUESTS 75
 
 typedef struct {
-    target_phys_addr_t descr;
-    target_phys_addr_t src;
-    target_phys_addr_t dest;
+    uint32_t descr;
+    uint32_t src;
+    uint32_t dest;
     uint32_t cmd;
     uint32_t state;
     int request;
@@ -512,9 +512,9 @@ static VMStateDescription vmstate_pxa2xx_dma_chan = {
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .fields = (VMStateField[]) {
-        VMSTATE_UINTTL(descr, PXA2xxDMAChannel),
-        VMSTATE_UINTTL(src, PXA2xxDMAChannel),
-        VMSTATE_UINTTL(dest, PXA2xxDMAChannel),
+        VMSTATE_UINT32(descr, PXA2xxDMAChannel),
+        VMSTATE_UINT32(src, PXA2xxDMAChannel),
+        VMSTATE_UINT32(dest, PXA2xxDMAChannel),
         VMSTATE_UINT32(cmd, PXA2xxDMAChannel),
         VMSTATE_UINT32(state, PXA2xxDMAChannel),
         VMSTATE_INT32(request, PXA2xxDMAChannel),
commit 0e4a398ab2c5e9b540a80859ec28163b65e7a891
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Mar 14 15:37:53 2012 +0000

    ARM: Remove unnecessary subpage workarounds
    
    In the ARM per-CPU peripherals (GIC, private timers, SCU, etc),
    remove workarounds for subpage memory region read/write functions
    being passed offsets from the start of the page rather than the
    start of the region. Following commit 5312bd8b3 the masking off
    of high bits of the address offset is now harmless but unnecessary.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index c67b70f..ba6a89d 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -42,7 +42,6 @@ static uint64_t mpcore_scu_read(void *opaque, target_phys_addr_t offset,
 {
     mpcore_priv_state *s = (mpcore_priv_state *)opaque;
     int id;
-    offset &= 0xff;
     /* SCU */
     switch (offset) {
     case 0x00: /* Control.  */
@@ -63,7 +62,6 @@ static void mpcore_scu_write(void *opaque, target_phys_addr_t offset,
                              uint64_t value, unsigned size)
 {
     mpcore_priv_state *s = (mpcore_priv_state *)opaque;
-    offset &= 0xff;
     /* SCU */
     switch (offset) {
     case 0: /* Control register.  */
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index d8a7a19..6b34c06 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -658,14 +658,14 @@ static uint64_t gic_thiscpu_read(void *opaque, target_phys_addr_t addr,
                                  unsigned size)
 {
     gic_state *s = (gic_state *)opaque;
-    return gic_cpu_read(s, gic_get_current_cpu(), addr & 0xff);
+    return gic_cpu_read(s, gic_get_current_cpu(), addr);
 }
 
 static void gic_thiscpu_write(void *opaque, target_phys_addr_t addr,
                               uint64_t value, unsigned size)
 {
     gic_state *s = (gic_state *)opaque;
-    gic_cpu_write(s, gic_get_current_cpu(), addr & 0xff, value);
+    gic_cpu_write(s, gic_get_current_cpu(), addr, value);
 }
 
 /* Wrappers to read/write the GIC CPU interface for a specific CPU.
@@ -677,7 +677,7 @@ static uint64_t gic_do_cpu_read(void *opaque, target_phys_addr_t addr,
     gic_state **backref = (gic_state **)opaque;
     gic_state *s = *backref;
     int id = (backref - s->backref);
-    return gic_cpu_read(s, id, addr & 0xff);
+    return gic_cpu_read(s, id, addr);
 }
 
 static void gic_do_cpu_write(void *opaque, target_phys_addr_t addr,
@@ -686,7 +686,7 @@ static void gic_do_cpu_write(void *opaque, target_phys_addr_t addr,
     gic_state **backref = (gic_state **)opaque;
     gic_state *s = *backref;
     int id = (backref - s->backref);
-    gic_cpu_write(s, id, addr & 0xff, value);
+    gic_cpu_write(s, id, addr, value);
 }
 
 static const MemoryRegionOps gic_thiscpu_ops = {
diff --git a/hw/arm_mptimer.c b/hw/arm_mptimer.c
index 361e887..df7fb4c 100644
--- a/hw/arm_mptimer.c
+++ b/hw/arm_mptimer.c
@@ -97,7 +97,6 @@ static uint64_t timerblock_read(void *opaque, target_phys_addr_t addr,
 {
     timerblock *tb = (timerblock *)opaque;
     int64_t val;
-    addr &= 0x1f;
     switch (addr) {
     case 0: /* Load */
         return tb->load;
@@ -126,7 +125,6 @@ static void timerblock_write(void *opaque, target_phys_addr_t addr,
 {
     timerblock *tb = (timerblock *)opaque;
     int64_t old;
-    addr &= 0x1f;
     switch (addr) {
     case 0: /* Load */
         tb->load = value;
commit 1d7a1197068da26813e2a4706b4573143db166f5
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Jan 28 05:18:19 2012 +0000

    malta: Fix display for LED array
    
    The 8-LED array was already implemented in the first commit to Malta,
    but this implementation was incomplete.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index d8c8c35..4752bb2 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -338,9 +338,9 @@ static void malta_fpga_write(void *opaque, target_phys_addr_t addr,
         break;
 
     /* LEDBAR Register */
-    /* XXX: implement a 8-LED array */
     case 0x00408:
         s->leds = val & 0xff;
+        malta_fpga_update_display(s);
         break;
 
     /* ASCIIWORD Register */
commit 03a1a8e1b13bb447c898eb282ee8c3fc41c866b4
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Jan 28 05:18:18 2012 +0000

    malta: Use symbolic hardware addresses
    
    The patch adds definitions of some hardware addresses and uses these
    definitions.
    
    It also replaces the type of all addresses from signed to unsigned values.
    This is only a cosmetic change because addresses are unsigned values,
    the functions called also expect unsigned values,
    and we need no sign extension here.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 734e700..d8c8c35 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -55,6 +55,13 @@
 #define ENVP_NB_ENTRIES	 	16
 #define ENVP_ENTRY_SIZE	 	256
 
+/* Hardware addresses */
+#define FLASH_ADDRESS 0x1e000000ULL
+#define FPGA_ADDRESS  0x1f000000ULL
+#define RESET_ADDRESS 0x1fc00000ULL
+
+#define FLASH_SIZE    0x400000
+
 #define MAX_IDE_BUS 2
 
 typedef struct {
@@ -777,7 +784,7 @@ void mips_malta_init (ram_addr_t ram_size,
     MemoryRegion *system_memory = get_system_memory();
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     MemoryRegion *bios, *bios_alias = g_new(MemoryRegion, 1);
-    target_long bios_size = 0x400000;
+    target_long bios_size = FLASH_SIZE;
     int64_t kernel_entry;
     PCIBus *pci_bus;
     ISABus *isa_bus;
@@ -847,7 +854,7 @@ void mips_malta_init (ram_addr_t ram_size,
     be = 0;
 #endif
     /* FPGA */
-    malta_fpga_init(system_memory, 0x1f000000LL, env->irq[2], serial_hds[2]);
+    malta_fpga_init(system_memory, FPGA_ADDRESS, env->irq[2], serial_hds[2]);
 
     /* Load firmware in flash / BIOS. */
     dinfo = drive_get(IF_PFLASH, 0, fl_idx);
@@ -855,11 +862,11 @@ void mips_malta_init (ram_addr_t ram_size,
     if (dinfo) {
         printf("Register parallel flash %d size " TARGET_FMT_lx " at "
                "addr %08llx '%s' %x\n",
-               fl_idx, bios_size, 0x1e000000LL,
+               fl_idx, bios_size, FLASH_ADDRESS,
                bdrv_get_device_name(dinfo->bdrv), fl_sectors);
     }
 #endif
-    fl = pflash_cfi01_register(0x1e000000LL, NULL, "mips_malta.bios",
+    fl = pflash_cfi01_register(FLASH_ADDRESS, NULL, "mips_malta.bios",
                                BIOS_SIZE, dinfo ? dinfo->bdrv : NULL,
                                65536, fl_sectors,
                                4, 0x0000, 0x0000, 0x0000, 0x0000, be);
@@ -882,7 +889,7 @@ void mips_malta_init (ram_addr_t ram_size,
             }
             filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
             if (filename) {
-                bios_size = load_image_targphys(filename, 0x1e000000LL,
+                bios_size = load_image_targphys(filename, FLASH_ADDRESS,
                                                 BIOS_SIZE);
                 g_free(filename);
             } else {
@@ -911,7 +918,7 @@ void mips_malta_init (ram_addr_t ram_size,
 
     /* Map the BIOS at a 2nd physical location, as on the real board. */
     memory_region_init_alias(bios_alias, "bios.1fc", bios, 0, BIOS_SIZE);
-    memory_region_add_subregion(system_memory, 0x1fc00000LL, bios_alias);
+    memory_region_add_subregion(system_memory, RESET_ADDRESS, bios_alias);
 
     /* Board ID = 0x420 (Malta Board with CoreLV)
        XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
commit bb4b335871677e0aa447484332e975d6c2ab0ba4
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Jan 28 05:18:17 2012 +0000

    malta: Always allocate flash memory
    
    There is no reason why there should not be a flash memory when the
    Malta emulation is started with a Linux kernel. When flash memory
    is always available, the code is simpler, and it can be better tested.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 2528fbe..734e700 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -777,7 +777,7 @@ void mips_malta_init (ram_addr_t ram_size,
     MemoryRegion *system_memory = get_system_memory();
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     MemoryRegion *bios, *bios_alias = g_new(MemoryRegion, 1);
-    target_long bios_size;
+    target_long bios_size = 0x400000;
     int64_t kernel_entry;
     PCIBus *pci_bus;
     ISABus *isa_bus;
@@ -791,7 +791,7 @@ void mips_malta_init (ram_addr_t ram_size,
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     DriveInfo *fd[MAX_FD];
     int fl_idx = 0;
-    int fl_sectors = 0;
+    int fl_sectors = bios_size >> 16;
     int be;
 
     DeviceState *dev = qdev_create(NULL, "mips-malta");
@@ -849,14 +849,24 @@ void mips_malta_init (ram_addr_t ram_size,
     /* FPGA */
     malta_fpga_init(system_memory, 0x1f000000LL, env->irq[2], serial_hds[2]);
 
-    /* Load firmware in flash / BIOS unless we boot directly into a kernel. */
+    /* Load firmware in flash / BIOS. */
+    dinfo = drive_get(IF_PFLASH, 0, fl_idx);
+#ifdef DEBUG_BOARD_INIT
+    if (dinfo) {
+        printf("Register parallel flash %d size " TARGET_FMT_lx " at "
+               "addr %08llx '%s' %x\n",
+               fl_idx, bios_size, 0x1e000000LL,
+               bdrv_get_device_name(dinfo->bdrv), fl_sectors);
+    }
+#endif
+    fl = pflash_cfi01_register(0x1e000000LL, NULL, "mips_malta.bios",
+                               BIOS_SIZE, dinfo ? dinfo->bdrv : NULL,
+                               65536, fl_sectors,
+                               4, 0x0000, 0x0000, 0x0000, 0x0000, be);
+    bios = pflash_cfi01_get_memory(fl);
+    fl_idx++;
     if (kernel_filename) {
         /* Write a small bootloader to the flash location. */
-        bios = g_new(MemoryRegion, 1);
-        memory_region_init_ram(bios, "mips_malta.bios", BIOS_SIZE);
-        vmstate_register_ram_global(bios);
-        memory_region_set_readonly(bios, true);
-        memory_region_add_subregion(system_memory, 0x1e000000LL, bios);
         loaderparams.ram_size = ram_size;
         loaderparams.kernel_filename = kernel_filename;
         loaderparams.kernel_cmdline = kernel_cmdline;
@@ -864,32 +874,12 @@ void mips_malta_init (ram_addr_t ram_size,
         kernel_entry = load_kernel();
         write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
     } else {
-        dinfo = drive_get(IF_PFLASH, 0, fl_idx);
-        if (dinfo) {
-            /* Load firmware from flash. */
-            bios_size = 0x400000;
-            fl_sectors = bios_size >> 16;
-#ifdef DEBUG_BOARD_INIT
-            printf("Register parallel flash %d size " TARGET_FMT_lx " at "
-                   "addr %08llx '%s' %x\n",
-                   fl_idx, bios_size, 0x1e000000LL,
-                   bdrv_get_device_name(dinfo->bdrv), fl_sectors);
-#endif
-            fl = pflash_cfi01_register(0x1e000000LL,
-                                       NULL, "mips_malta.bios", BIOS_SIZE,
-                                       dinfo->bdrv, 65536, fl_sectors,
-                                       4, 0x0000, 0x0000, 0x0000, 0x0000, be);
-            bios = pflash_cfi01_get_memory(fl);
-            fl_idx++;
-        } else {
-            bios = g_new(MemoryRegion, 1);
-            memory_region_init_ram(bios, "mips_malta.bios", BIOS_SIZE);
-            vmstate_register_ram_global(bios);
-            memory_region_set_readonly(bios, true);
-            memory_region_add_subregion(system_memory, 0x1e000000LL, bios);
+        /* Load firmware from flash. */
+        if (!dinfo) {
             /* Load a BIOS image. */
-            if (bios_name == NULL)
+            if (bios_name == NULL) {
                 bios_name = BIOS_FILENAME;
+            }
             filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
             if (filename) {
                 bios_size = load_image_targphys(filename, 0x1e000000LL,
commit 82a9807bcaa2db2825eee0d1236218ccebaaf875
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Jan 28 05:18:16 2012 +0000

    malta: Clean allocation of bios region alias
    
    It is sufficient to define the region alias once for all code branches.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 5e26775..2528fbe 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -856,10 +856,7 @@ void mips_malta_init (ram_addr_t ram_size,
         memory_region_init_ram(bios, "mips_malta.bios", BIOS_SIZE);
         vmstate_register_ram_global(bios);
         memory_region_set_readonly(bios, true);
-        memory_region_init_alias(bios_alias, "bios.1fc", bios, 0, BIOS_SIZE);
-        /* Map the bios at two physical locations, as on the real board. */
         memory_region_add_subregion(system_memory, 0x1e000000LL, bios);
-        memory_region_add_subregion(system_memory, 0x1fc00000LL, bios_alias);
         loaderparams.ram_size = ram_size;
         loaderparams.kernel_filename = kernel_filename;
         loaderparams.kernel_cmdline = kernel_cmdline;
@@ -883,29 +880,19 @@ void mips_malta_init (ram_addr_t ram_size,
                                        dinfo->bdrv, 65536, fl_sectors,
                                        4, 0x0000, 0x0000, 0x0000, 0x0000, be);
             bios = pflash_cfi01_get_memory(fl);
-            /* Map the bios at two physical locations, as on the real board. */
-            memory_region_init_alias(bios_alias, "bios.1fc",
-                                     bios, 0, BIOS_SIZE);
-            memory_region_add_subregion(system_memory, 0x1fc00000LL,
-                                        bios_alias);
-           fl_idx++;
+            fl_idx++;
         } else {
             bios = g_new(MemoryRegion, 1);
             memory_region_init_ram(bios, "mips_malta.bios", BIOS_SIZE);
             vmstate_register_ram_global(bios);
             memory_region_set_readonly(bios, true);
-            memory_region_init_alias(bios_alias, "bios.1fc",
-                                     bios, 0, BIOS_SIZE);
-            /* Map the bios at two physical locations, as on the real board. */
             memory_region_add_subregion(system_memory, 0x1e000000LL, bios);
-            memory_region_add_subregion(system_memory, 0x1fc00000LL,
-                                        bios_alias);
             /* Load a BIOS image. */
             if (bios_name == NULL)
                 bios_name = BIOS_FILENAME;
             filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
             if (filename) {
-                bios_size = load_image_targphys(filename, 0x1fc00000LL,
+                bios_size = load_image_targphys(filename, 0x1e000000LL,
                                                 BIOS_SIZE);
                 g_free(filename);
             } else {
@@ -932,6 +919,10 @@ void mips_malta_init (ram_addr_t ram_size,
 #endif
     }
 
+    /* Map the BIOS at a 2nd physical location, as on the real board. */
+    memory_region_init_alias(bios_alias, "bios.1fc", bios, 0, BIOS_SIZE);
+    memory_region_add_subregion(system_memory, 0x1fc00000LL, bios_alias);
+
     /* Board ID = 0x420 (Malta Board with CoreLV)
        XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
        map to the board ID. */
commit d9e028c1d9c2a8d2ad42f2aeb502b71086a52d4d
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Mar 14 12:26:11 2012 +0000

    target-arm: Decode SETEND correctly in Thumb
    
    Decode the SETEND instruction correctly in Thumb mode,
    rather than accidentally treating it like CPS. We don't
    support BE8 mode, but this change brings the Thumb mode
    in to line with behaviour in ARM mode: 'SETEND BE' is
    not supported and will provoke an UNDEF exception, but
    'SETEND LE' is correctly handled as a no-op.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reported-by: Daniel Forsgren <daniel.forsgren at enea.com>
    Reviewed-by: Laurent Desnogues <laurent.desnogues at gmail.com>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 2709010..81725d1 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -9704,32 +9704,49 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
             store_reg(s, rd, tmp);
             break;
 
-        case 6: /* cps */
-            ARCH(6);
-            if (IS_USER(s))
+        case 6:
+            switch ((insn >> 5) & 7) {
+            case 2:
+                /* setend */
+                ARCH(6);
+                if (insn & (1 << 3)) {
+                    /* BE8 mode not implemented.  */
+                    goto illegal_op;
+                }
                 break;
-            if (IS_M(env)) {
-                tmp = tcg_const_i32((insn & (1 << 4)) != 0);
-                /* FAULTMASK */
-                if (insn & 1) {
-                    addr = tcg_const_i32(19);
-                    gen_helper_v7m_msr(cpu_env, addr, tmp);
-                    tcg_temp_free_i32(addr);
+            case 3:
+                /* cps */
+                ARCH(6);
+                if (IS_USER(s)) {
+                    break;
                 }
-                /* PRIMASK */
-                if (insn & 2) {
-                    addr = tcg_const_i32(16);
-                    gen_helper_v7m_msr(cpu_env, addr, tmp);
-                    tcg_temp_free_i32(addr);
+                if (IS_M(env)) {
+                    tmp = tcg_const_i32((insn & (1 << 4)) != 0);
+                    /* FAULTMASK */
+                    if (insn & 1) {
+                        addr = tcg_const_i32(19);
+                        gen_helper_v7m_msr(cpu_env, addr, tmp);
+                        tcg_temp_free_i32(addr);
+                    }
+                    /* PRIMASK */
+                    if (insn & 2) {
+                        addr = tcg_const_i32(16);
+                        gen_helper_v7m_msr(cpu_env, addr, tmp);
+                        tcg_temp_free_i32(addr);
+                    }
+                    tcg_temp_free_i32(tmp);
+                    gen_lookup_tb(s);
+                } else {
+                    if (insn & (1 << 4)) {
+                        shift = CPSR_A | CPSR_I | CPSR_F;
+                    } else {
+                        shift = 0;
+                    }
+                    gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
                 }
-                tcg_temp_free_i32(tmp);
-                gen_lookup_tb(s);
-            } else {
-                if (insn & (1 << 4))
-                    shift = CPSR_A | CPSR_I | CPSR_F;
-                else
-                    shift = 0;
-                gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
+                break;
+            default:
+                goto undef;
             }
             break;
 
commit c98d174c24b915e9908785feb63eb3b5abe33818
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Mar 14 12:26:10 2012 +0000

    target-arm: Clear IT bits when taking exceptions in v7M
    
    When taking an exception for an M profile core, we must clear
    the IT bits. Since the IT bits are cached in env->condexec_bits
    we must clear them there: writing the bits in env->uncached_cpsr
    has no effect. (Reported as LP:944645.)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 4116fee..1314f23 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -877,7 +877,8 @@ static void do_interrupt_v7m(CPUARMState *env)
     v7m_push(env, env->regs[1]);
     v7m_push(env, env->regs[0]);
     switch_v7m_sp(env, 0);
-    env->uncached_cpsr &= ~CPSR_IT;
+    /* Clear IT bits */
+    env->condexec_bits = 0;
     env->regs[14] = lr;
     addr = ldl_phys(env->v7m.vecbase + env->v7m.exception * 4);
     env->regs[15] = addr & 0xfffffffe;
commit 4de47793d49e70ee048e15889d4bf139e7b36ce7
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Mar 14 12:26:10 2012 +0000

    target-arm: Fix typo in ARM946 cp15 c5 handling
    
    Fix a typo in handling of the ARM946 cp15 c5 c0 0 1 handling
    (instruction access permission bits) that meant it would
    return the data access permission bits by mistake.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 8a08db8..4116fee 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2025,7 +2025,7 @@ uint32_t HELPER(get_cp15)(CPUARMState *env, uint32_t insn)
             return env->cp15.c5_data;
         case 1:
             if (arm_feature(env, ARM_FEATURE_MPU))
-                return simple_mpu_ap_bits(env->cp15.c5_data);
+                return simple_mpu_ap_bits(env->cp15.c5_insn);
             return env->cp15.c5_insn;
         case 2:
             if (!arm_feature(env, ARM_FEATURE_MPU))
commit 54e17933bf78cdbbeb0f12b2db38f210c2a992d4
Author: Juha Riihimäki <juha.riihimaki at nokia.com>
Date:   Wed Mar 14 15:37:53 2012 +0000

    hw/omap_i2c: Convert to qdev
    
    Convert the omap_i2c device to qdev.
    
    Signed-off-by: Juha Riihimäki <juha.riihimaki at nokia.com>
    [Riku Voipio: Fixes and restructuring patchset]
    Signed-off-by: Riku Voipio <riku.voipio at iki.fi>
    [Peter Maydell: More fixes and cleanups for upstream submission]
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/nseries.c b/hw/nseries.c
index c5b3184..a5cfa8c 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -45,7 +45,6 @@ struct n800_s {
         uint32_t (*txrx)(void *opaque, uint32_t value, int len);
         uWireSlave *chip;
     } ts;
-    i2c_bus *i2c;
 
     int keymap[0x80];
     DeviceState *kbd;
@@ -194,12 +193,10 @@ 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);
-
-    /* Attach the CPU on one end of our I2C bus.  */
-    s->i2c = omap_i2c_bus(s->cpu->i2c[0]);
+    i2c_bus *i2c = omap_i2c_bus(s->cpu->i2c[0]);
 
     /* Attach a menelaus PM chip */
-    dev = i2c_create_slave(s->i2c, "twl92230", N8X0_MENELAUS_ADDR);
+    dev = i2c_create_slave(i2c, "twl92230", N8X0_MENELAUS_ADDR);
     qdev_connect_gpio_out(dev, 3,
                           qdev_get_gpio_in(s->cpu->ih[0],
                                            OMAP_INT_24XX_SYS_NIRQ));
@@ -207,7 +204,7 @@ static void n8x0_i2c_setup(struct n800_s *s)
     qemu_system_powerdown = qdev_get_gpio_in(dev, 3);
 
     /* Attach a TMP105 PM chip (A0 wired to ground) */
-    dev = i2c_create_slave(s->i2c, "tmp105", N8X0_TMP105_ADDR);
+    dev = i2c_create_slave(i2c, "tmp105", N8X0_TMP105_ADDR);
     qdev_connect_gpio_out(dev, 0, tmp_irq);
 }
 
@@ -391,7 +388,8 @@ 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(s->i2c, "lm8323", N810_LM8323_ADDR);
+    s->kbd = i2c_create_slave(omap_i2c_bus(s->cpu->i2c[0]),
+                           "lm8323", N810_LM8323_ADDR);
     qdev_connect_gpio_out(s->kbd, 0, kbd_irq);
 }
 
diff --git a/hw/omap.h b/hw/omap.h
index 63ef847..6c3d004 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -764,16 +764,7 @@ void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover);
 void omap_mmc_enable(struct omap_mmc_s *s, int enable);
 
 /* omap_i2c.c */
-struct omap_i2c_s;
-struct omap_i2c_s *omap_i2c_init(MemoryRegion *sysmem,
-                                 target_phys_addr_t base,
-                                 qemu_irq irq,
-                                 qemu_irq *dma,
-                                 omap_clk clk);
-struct omap_i2c_s *omap2_i2c_init(struct omap_target_agent_s *ta,
-                qemu_irq irq, qemu_irq *dma, omap_clk fclk, omap_clk iclk);
-void omap_i2c_reset(struct omap_i2c_s *s);
-i2c_bus *omap_i2c_bus(struct omap_i2c_s *s);
+i2c_bus *omap_i2c_bus(DeviceState *omap_i2c);
 
 # define cpu_is_omap310(cpu)		(cpu->mpu_model == omap310)
 # define cpu_is_omap1510(cpu)		(cpu->mpu_model == omap1510)
@@ -867,7 +858,7 @@ struct omap_mpu_state_s {
 
     struct omap_pwl_s *pwl;
     struct omap_pwt_s *pwt;
-    struct omap_i2c_s *i2c[2];
+    DeviceState *i2c[2];
 
     struct omap_rtc_s *rtc;
 
diff --git a/hw/omap1.c b/hw/omap1.c
index 5317b9b..2a341bf 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -3694,7 +3694,6 @@ static void omap1_mpu_reset(void *opaque)
     omap_uwire_reset(mpu->microwire);
     omap_pwl_reset(mpu->pwl);
     omap_pwt_reset(mpu->pwt);
-    omap_i2c_reset(mpu->i2c[0]);
     omap_rtc_reset(mpu->rtc);
     omap_mcbsp_reset(mpu->mcbsp1);
     omap_mcbsp_reset(mpu->mcbsp2);
@@ -3993,9 +3992,15 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
     s->pwt = omap_pwt_init(system_memory, 0xfffb6000,
                            omap_findclk(s, "armxor_ck"));
 
-    s->i2c[0] = omap_i2c_init(system_memory, 0xfffb3800,
-                              qdev_get_gpio_in(s->ih[1], OMAP_INT_I2C),
-                    &s->drq[OMAP_DMA_I2C_RX], omap_findclk(s, "mpuper_ck"));
+    s->i2c[0] = qdev_create(NULL, "omap_i2c");
+    qdev_prop_set_uint8(s->i2c[0], "revision", 0x11);
+    qdev_prop_set_ptr(s->i2c[0], "fclk", omap_findclk(s, "mpuper_ck"));
+    qdev_init_nofail(s->i2c[0]);
+    busdev = sysbus_from_qdev(s->i2c[0]);
+    sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(s->ih[1], OMAP_INT_I2C));
+    sysbus_connect_irq(busdev, 1, s->drq[OMAP_DMA_I2C_TX]);
+    sysbus_connect_irq(busdev, 2, s->drq[OMAP_DMA_I2C_RX]);
+    sysbus_mmio_map(busdev, 0, 0xfffb3800);
 
     s->rtc = omap_rtc_init(system_memory, 0xfffb4800,
                            qdev_get_gpio_in(s->ih[1], OMAP_INT_RTC_TIMER),
diff --git a/hw/omap2.c b/hw/omap2.c
index 157defb..42fce5e 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -2222,8 +2222,6 @@ static void omap2_mpu_reset(void *opaque)
     omap_mmc_reset(mpu->mmc);
     omap_mcspi_reset(mpu->mcspi[0]);
     omap_mcspi_reset(mpu->mcspi[1]);
-    omap_i2c_reset(mpu->i2c[0]);
-    omap_i2c_reset(mpu->i2c[1]);
     cpu_state_reset(mpu->env);
 }
 
@@ -2395,16 +2393,29 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
                     omap_findclk(s, "clk32-kHz"),
                     omap_findclk(s, "core_l4_iclk"));
 
-    s->i2c[0] = omap2_i2c_init(omap_l4tao(s->l4, 5),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C1_IRQ),
-                    &s->drq[OMAP24XX_DMA_I2C1_TX],
-                    omap_findclk(s, "i2c1.fclk"),
-                    omap_findclk(s, "i2c1.iclk"));
-    s->i2c[1] = omap2_i2c_init(omap_l4tao(s->l4, 6),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C2_IRQ),
-                    &s->drq[OMAP24XX_DMA_I2C2_TX],
-                    omap_findclk(s, "i2c2.fclk"),
-                    omap_findclk(s, "i2c2.iclk"));
+    s->i2c[0] = qdev_create(NULL, "omap_i2c");
+    qdev_prop_set_uint8(s->i2c[0], "revision", 0x34);
+    qdev_prop_set_ptr(s->i2c[0], "iclk", omap_findclk(s, "i2c1.iclk"));
+    qdev_prop_set_ptr(s->i2c[0], "fclk", omap_findclk(s, "i2c1.fclk"));
+    qdev_init_nofail(s->i2c[0]);
+    busdev = sysbus_from_qdev(s->i2c[0]);
+    sysbus_connect_irq(busdev, 0,
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C1_IRQ));
+    sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_I2C1_TX]);
+    sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_I2C1_RX]);
+    sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4tao(s->l4, 5), 0));
+
+    s->i2c[1] = qdev_create(NULL, "omap_i2c");
+    qdev_prop_set_uint8(s->i2c[1], "revision", 0x34);
+    qdev_prop_set_ptr(s->i2c[1], "iclk", omap_findclk(s, "i2c2.iclk"));
+    qdev_prop_set_ptr(s->i2c[1], "fclk", omap_findclk(s, "i2c2.fclk"));
+    qdev_init_nofail(s->i2c[1]);
+    busdev = sysbus_from_qdev(s->i2c[1]);
+    sysbus_connect_irq(busdev, 0,
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C2_IRQ));
+    sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_I2C2_TX]);
+    sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_I2C2_RX]);
+    sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4tao(s->l4, 6), 0));
 
     s->gpio = qdev_create(NULL, "omap2-gpio");
     qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model);
diff --git a/hw/omap_i2c.c b/hw/omap_i2c.c
index 5ec422c..20bc82e 100644
--- a/hw/omap_i2c.c
+++ b/hw/omap_i2c.c
@@ -19,14 +19,20 @@
 #include "hw.h"
 #include "i2c.h"
 #include "omap.h"
+#include "sysbus.h"
 
-struct omap_i2c_s {
+
+typedef struct OMAPI2CState {
+    SysBusDevice busdev;
     MemoryRegion iomem;
     qemu_irq irq;
     qemu_irq drq[2];
     i2c_bus *bus;
 
     uint8_t revision;
+    void *iclk;
+    void *fclk;
+
     uint8_t mask;
     uint16_t stat;
     uint16_t dma;
@@ -40,12 +46,12 @@ struct omap_i2c_s {
     uint8_t divider;
     uint8_t times[2];
     uint16_t test;
-};
+} OMAPI2CState;
 
 #define OMAP2_INTR_REV	0x34
 #define OMAP2_GC_REV	0x34
 
-static void omap_i2c_interrupts_update(struct omap_i2c_s *s)
+static void omap_i2c_interrupts_update(OMAPI2CState *s)
 {
     qemu_set_irq(s->irq, s->stat & s->mask);
     if ((s->dma >> 15) & 1)					/* RDMA_EN */
@@ -54,7 +60,7 @@ static void omap_i2c_interrupts_update(struct omap_i2c_s *s)
         qemu_set_irq(s->drq[1], (s->stat >> 4) & 1);		/* XRDY */
 }
 
-static void omap_i2c_fifo_run(struct omap_i2c_s *s)
+static void omap_i2c_fifo_run(OMAPI2CState *s)
 {
     int ack = 1;
 
@@ -122,8 +128,10 @@ static void omap_i2c_fifo_run(struct omap_i2c_s *s)
         s->control &= ~(1 << 1);				/* STP */
 }
 
-void omap_i2c_reset(struct omap_i2c_s *s)
+static void omap_i2c_reset(DeviceState *dev)
 {
+    OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState,
+                                  sysbus_from_qdev(dev));
     s->mask = 0;
     s->stat = 0;
     s->dma = 0;
@@ -143,7 +151,7 @@ void omap_i2c_reset(struct omap_i2c_s *s)
 
 static uint32_t omap_i2c_read(void *opaque, target_phys_addr_t addr)
 {
-    struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
+    OMAPI2CState *s = opaque;
     int offset = addr & OMAP_MPUI_REG_MASK;
     uint16_t ret;
 
@@ -243,7 +251,7 @@ static uint32_t omap_i2c_read(void *opaque, target_phys_addr_t addr)
 static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
-    struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
+    OMAPI2CState *s = opaque;
     int offset = addr & OMAP_MPUI_REG_MASK;
     int nack;
 
@@ -309,14 +317,14 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
         }
 
         if (value & 2)
-            omap_i2c_reset(s);
+            omap_i2c_reset(&s->busdev.qdev);
         break;
 
     case 0x24:	/* I2C_CON */
         s->control = value & 0xcf87;
         if (~value & (1 << 15)) {				/* I2C_EN */
             if (s->revision < OMAP2_INTR_REV)
-                omap_i2c_reset(s);
+                omap_i2c_reset(&s->busdev.qdev);
             break;
         }
         if ((value & (1 << 15)) && !(value & (1 << 10))) {	/* MST */
@@ -385,7 +393,7 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
 static void omap_i2c_writeb(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
-    struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
+    OMAPI2CState *s = opaque;
     int offset = addr & OMAP_MPUI_REG_MASK;
 
     switch (offset) {
@@ -426,50 +434,59 @@ static const MemoryRegionOps omap_i2c_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-struct omap_i2c_s *omap_i2c_init(MemoryRegion *sysmem,
-                                 target_phys_addr_t base,
-                                 qemu_irq irq,
-                                 qemu_irq *dma,
-                                 omap_clk clk)
+static int omap_i2c_init(SysBusDevice *dev)
 {
-    struct omap_i2c_s *s = (struct omap_i2c_s *)
-            g_malloc0(sizeof(struct omap_i2c_s));
-
-    /* TODO: set a value greater or equal to real hardware */
-    s->revision = 0x11;
-    s->irq = irq;
-    s->drq[0] = dma[0];
-    s->drq[1] = dma[1];
-    s->bus = i2c_init_bus(NULL, "i2c");
-    omap_i2c_reset(s);
+    OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState, dev);
 
-    memory_region_init_io(&s->iomem, &omap_i2c_ops, s, "omap.i2c", 0x800);
-    memory_region_add_subregion(sysmem, base, &s->iomem);
-
-    return s;
+    if (!s->fclk) {
+        hw_error("omap_i2c: fclk not connected\n");
+    }
+    if (s->revision >= OMAP2_INTR_REV && !s->iclk) {
+        /* Note that OMAP1 doesn't have a separate interface clock */
+        hw_error("omap_i2c: iclk not connected\n");
+    }
+    sysbus_init_irq(dev, &s->irq);
+    sysbus_init_irq(dev, &s->drq[0]);
+    sysbus_init_irq(dev, &s->drq[1]);
+    memory_region_init_io(&s->iomem, &omap_i2c_ops, s, "omap.i2c",
+                          (s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    s->bus = i2c_init_bus(&dev->qdev, NULL);
+    return 0;
 }
 
-struct omap_i2c_s *omap2_i2c_init(struct omap_target_agent_s *ta,
-                qemu_irq irq, qemu_irq *dma, omap_clk fclk, omap_clk iclk)
-{
-    struct omap_i2c_s *s = (struct omap_i2c_s *)
-            g_malloc0(sizeof(struct omap_i2c_s));
+static Property omap_i2c_properties[] = {
+    DEFINE_PROP_UINT8("revision", OMAPI2CState, revision, 0),
+    DEFINE_PROP_PTR("iclk", OMAPI2CState, iclk),
+    DEFINE_PROP_PTR("fclk", OMAPI2CState, fclk),
+    DEFINE_PROP_END_OF_LIST(),
+};
 
-    s->revision = 0x34;
-    s->irq = irq;
-    s->drq[0] = dma[0];
-    s->drq[1] = dma[1];
-    s->bus = i2c_init_bus(NULL, "i2c");
-    omap_i2c_reset(s);
+static void omap_i2c_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+    k->init = omap_i2c_init;
+    dc->props = omap_i2c_properties;
+    dc->reset = omap_i2c_reset;
+}
 
-    memory_region_init_io(&s->iomem, &omap_i2c_ops, s, "omap2.i2c",
-                          omap_l4_region_size(ta, 0));
-    omap_l4_attach(ta, 0, &s->iomem);
+static TypeInfo omap_i2c_info = {
+    .name = "omap_i2c",
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(OMAPI2CState),
+    .class_init = omap_i2c_class_init,
+};
 
-    return s;
+static void omap_i2c_register_types(void)
+{
+    type_register_static(&omap_i2c_info);
 }
 
-i2c_bus *omap_i2c_bus(struct omap_i2c_s *s)
+i2c_bus *omap_i2c_bus(DeviceState *omap_i2c)
 {
+    OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState, sysbus_from_qdev(omap_i2c));
     return s->bus;
 }
+
+type_init(omap_i2c_register_types)
commit 38ae51a804a6ad2baec3e45ecb1571583b312441
Author: Alexander Graf <agraf at suse.de>
Date:   Wed Mar 14 20:17:07 2012 +0100

    PPC: Fix openpic with relative memregions
    
    After commit 5312bd8b3152 we got memory region relative offsets into our mmio
    callbacks instead of page boundary based offsets.
    
    This broke the OpenPIC emulation which expected offsets to be on page boundary
    and substracted its region offset manually.
    
    This patch gets rid of that manual substraction and lets the memory api do its
    magic instead.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/openpic.c b/hw/openpic.c
index 280b7a9..58ef871 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -713,7 +713,7 @@ static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
     if (addr & 0xF)
         return;
-    addr -= 0x1100;
+    addr -= 0x10;
     addr &= 0xFFFF;
     idx = (addr & 0xFFF0) >> 6;
     addr = addr & 0x30;
@@ -746,7 +746,7 @@ static uint32_t openpic_timer_read (void *opaque, uint32_t addr)
     retval = 0xFFFFFFFF;
     if (addr & 0xF)
         return retval;
-    addr -= 0x1100;
+    addr -= 0x10;
     addr &= 0xFFFF;
     idx = (addr & 0xFFF0) >> 6;
     addr = addr & 0x30;
@@ -1361,7 +1361,6 @@ static void mpic_src_ext_write (void *opaque, target_phys_addr_t addr,
     if (addr & 0xF)
         return;
 
-    addr -= MPIC_EXT_REG_START & (OPENPIC_PAGE_SIZE - 1);
     if (addr < MPIC_EXT_REG_SIZE) {
         idx += (addr & 0xFFF0) >> 5;
         if (addr & 0x10) {
@@ -1385,7 +1384,6 @@ static uint32_t mpic_src_ext_read (void *opaque, target_phys_addr_t addr)
     if (addr & 0xF)
         return retval;
 
-    addr -= MPIC_EXT_REG_START & (OPENPIC_PAGE_SIZE - 1);
     if (addr < MPIC_EXT_REG_SIZE) {
         idx += (addr & 0xFFF0) >> 5;
         if (addr & 0x10) {
@@ -1411,7 +1409,6 @@ static void mpic_src_int_write (void *opaque, target_phys_addr_t addr,
     if (addr & 0xF)
         return;
 
-    addr -= MPIC_INT_REG_START & (OPENPIC_PAGE_SIZE - 1);
     if (addr < MPIC_INT_REG_SIZE) {
         idx += (addr & 0xFFF0) >> 5;
         if (addr & 0x10) {
@@ -1435,7 +1432,6 @@ static uint32_t mpic_src_int_read (void *opaque, target_phys_addr_t addr)
     if (addr & 0xF)
         return retval;
 
-    addr -= MPIC_INT_REG_START & (OPENPIC_PAGE_SIZE - 1);
     if (addr < MPIC_INT_REG_SIZE) {
         idx += (addr & 0xFFF0) >> 5;
         if (addr & 0x10) {
@@ -1461,7 +1457,6 @@ static void mpic_src_msg_write (void *opaque, target_phys_addr_t addr,
     if (addr & 0xF)
         return;
 
-    addr -= MPIC_MSG_REG_START & (OPENPIC_PAGE_SIZE - 1);
     if (addr < MPIC_MSG_REG_SIZE) {
         idx += (addr & 0xFFF0) >> 5;
         if (addr & 0x10) {
@@ -1485,7 +1480,6 @@ static uint32_t mpic_src_msg_read (void *opaque, target_phys_addr_t addr)
     if (addr & 0xF)
         return retval;
 
-    addr -= MPIC_MSG_REG_START & (OPENPIC_PAGE_SIZE - 1);
     if (addr < MPIC_MSG_REG_SIZE) {
         idx += (addr & 0xFFF0) >> 5;
         if (addr & 0x10) {
@@ -1511,7 +1505,6 @@ static void mpic_src_msi_write (void *opaque, target_phys_addr_t addr,
     if (addr & 0xF)
         return;
 
-    addr -= MPIC_MSI_REG_START & (OPENPIC_PAGE_SIZE - 1);
     if (addr < MPIC_MSI_REG_SIZE) {
         idx += (addr & 0xFFF0) >> 5;
         if (addr & 0x10) {
@@ -1534,7 +1527,6 @@ static uint32_t mpic_src_msi_read (void *opaque, target_phys_addr_t addr)
     if (addr & 0xF)
         return retval;
 
-    addr -= MPIC_MSI_REG_START & (OPENPIC_PAGE_SIZE - 1);
     if (addr < MPIC_MSI_REG_SIZE) {
         idx += (addr & 0xFFF0) >> 5;
         if (addr & 0x10) {
commit 298a971024534e9ab6c7b57845bbbd8188867d7a
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Mon Mar 12 17:50:24 2012 +0000

    pseries: Configure PCI bridge using properties
    
    Currently, the function spapr_create_phb() uses its parameters to
    initialize the correct memory windows for the new PCI Host Bridge
    (PHB).  This is not the way things are supposed to be done with qdevs,
    and means you can't create extra PHBs easily using -device.
    
    Since pSeries machines can and do have many PHBs with various
    configurations, this is a real limitation, not just a theoretical.
    This patch, therefore, alters the PHB initialization code to use qdev
    properties to set these parameters of the new bridge, moving most of
    the code from spapr_create_phb() to spapr_phb_init().
    
    While we're at it, we change the naming of each PCI bus and its
    associated memory regions to be less arbitrary and make it easier to
    relate the guest and qemu views of memory to each other.
    
    Signed-off-by: Alexey Kardashevskiy <aik at ozlabs.ru>
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index 233250f..e7ef551 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -180,49 +180,6 @@ static void pci_spapr_set_irq(void *opaque, int irq_num, int level)
     qemu_set_irq(phb->lsi_table[irq_num].qirq, level);
 }
 
-static int spapr_phb_init(SysBusDevice *s)
-{
-    sPAPRPHBState *phb = FROM_SYSBUS(sPAPRPHBState, s);
-    int i;
-
-    /* Initialize the LSI table */
-    for (i = 0; i < SPAPR_PCI_NUM_LSI; i++) {
-        qemu_irq qirq;
-        uint32_t num;
-
-        qirq = spapr_allocate_lsi(0, &num);
-        if (!qirq) {
-            return -1;
-        }
-
-        phb->lsi_table[i].dt_irq = num;
-        phb->lsi_table[i].qirq = qirq;
-    }
-
-    return 0;
-}
-
-static void spapr_phb_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-
-    sdc->init = spapr_phb_init;
-}
-
-static TypeInfo spapr_phb_info = {
-    .name          = "spapr-pci-host-bridge",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(sPAPRPHBState),
-    .class_init    = spapr_phb_class_init,
-};
-
-static void spapr_register_types(void)
-{
-    type_register_static(&spapr_phb_info);
-}
-
-type_init(spapr_register_types)
-
 static uint64_t spapr_io_read(void *opaque, target_phys_addr_t addr,
                               unsigned size)
 {
@@ -260,35 +217,29 @@ static const MemoryRegionOps spapr_io_ops = {
     .write = spapr_io_write
 };
 
-void spapr_create_phb(sPAPREnvironment *spapr,
-                      const char *busname, uint64_t buid,
-                      uint64_t mem_win_addr, uint64_t mem_win_size,
-                      uint64_t io_win_addr)
+/*
+ * PHB PCI device
+ */
+static int spapr_phb_init(SysBusDevice *s)
 {
-    DeviceState *dev;
-    SysBusDevice *s;
-    sPAPRPHBState *phb;
+    sPAPRPHBState *phb = FROM_SYSBUS(sPAPRPHBState, s);
+    char *namebuf;
+    int i;
     PCIBus *bus;
-    char namebuf[strlen(busname)+11];
 
-    dev = qdev_create(NULL, "spapr-pci-host-bridge");
-    qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
-    phb = FROM_SYSBUS(sPAPRPHBState, s);
+    phb->dtbusname = g_strdup_printf("pci@%" PRIx64, phb->buid);
+    namebuf = alloca(strlen(phb->dtbusname) + 32);
 
-    phb->mem_win_addr = mem_win_addr;
-
-    sprintf(namebuf, "%s-mem", busname);
+    /* Initialize memory regions */
+    sprintf(namebuf, "%s.mmio", phb->dtbusname);
     memory_region_init(&phb->memspace, namebuf, INT64_MAX);
 
-    sprintf(namebuf, "%s-memwindow", busname);
+    sprintf(namebuf, "%s.mmio-alias", phb->dtbusname);
     memory_region_init_alias(&phb->memwindow, namebuf, &phb->memspace,
-                             SPAPR_PCI_MEM_WIN_BUS_OFFSET, mem_win_size);
-    memory_region_add_subregion(get_system_memory(), mem_win_addr,
+                             SPAPR_PCI_MEM_WIN_BUS_OFFSET, phb->mem_win_size);
+    memory_region_add_subregion(get_system_memory(), phb->mem_win_addr,
                                 &phb->memwindow);
 
-    phb->io_win_addr = io_win_addr;
-
     /* On ppc, we only have MMIO no specific IO space from the CPU
      * perspective.  In theory we ought to be able to embed the PCI IO
      * memory region direction in the system memory space.  However,
@@ -297,33 +248,92 @@ void spapr_create_phb(sPAPREnvironment *spapr,
      * system io address space.  This hack to bounce things via
      * system_io works around the problem until all the users of
      * old_portion are updated */
-    sprintf(namebuf, "%s-io", busname);
+    sprintf(namebuf, "%s.io", phb->dtbusname);
     memory_region_init(&phb->iospace, namebuf, SPAPR_PCI_IO_WIN_SIZE);
     /* FIXME: fix to support multiple PHBs */
     memory_region_add_subregion(get_system_io(), 0, &phb->iospace);
 
-    sprintf(namebuf, "%s-iowindow", busname);
+    sprintf(namebuf, "%s.io-alias", phb->dtbusname);
     memory_region_init_io(&phb->iowindow, &spapr_io_ops, phb,
                           namebuf, SPAPR_PCI_IO_WIN_SIZE);
-    memory_region_add_subregion(get_system_memory(), io_win_addr,
+    memory_region_add_subregion(get_system_memory(), phb->io_win_addr,
                                 &phb->iowindow);
 
-    phb->host_state.bus = bus = pci_register_bus(&phb->busdev.qdev, busname,
-                                                 pci_spapr_set_irq,
-                                                 pci_spapr_map_irq,
-                                                 phb,
-                                                 &phb->memspace, &phb->iospace,
-                                                 PCI_DEVFN(0, 0),
-                                                 SPAPR_PCI_NUM_LSI);
+    bus = pci_register_bus(&phb->busdev.qdev,
+                           phb->busname ? phb->busname : phb->dtbusname,
+                           pci_spapr_set_irq, pci_spapr_map_irq, phb,
+                           &phb->memspace, &phb->iospace,
+                           PCI_DEVFN(0, 0), SPAPR_PCI_NUM_LSI);
+    phb->host_state.bus = bus;
+
+    QLIST_INSERT_HEAD(&spapr->phbs, phb, list);
+
+    /* Initialize the LSI table */
+    for (i = 0; i < SPAPR_PCI_NUM_LSI; i++) {
+        qemu_irq qirq;
+        uint32_t num;
+
+        qirq = spapr_allocate_lsi(0, &num);
+        if (!qirq) {
+            return -1;
+        }
+
+        phb->lsi_table[i].dt_irq = num;
+        phb->lsi_table[i].qirq = qirq;
+    }
+
+    return 0;
+}
+
+static Property spapr_phb_properties[] = {
+    DEFINE_PROP_HEX64("buid", sPAPRPHBState, buid, 0),
+    DEFINE_PROP_STRING("busname", sPAPRPHBState, busname),
+    DEFINE_PROP_HEX64("mem_win_addr", sPAPRPHBState, mem_win_addr, 0),
+    DEFINE_PROP_HEX64("mem_win_size", sPAPRPHBState, mem_win_size, 0x20000000),
+    DEFINE_PROP_HEX64("io_win_addr", sPAPRPHBState, io_win_addr, 0),
+    DEFINE_PROP_HEX64("io_win_size", sPAPRPHBState, io_win_size, 0x10000),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void spapr_phb_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    sdc->init = spapr_phb_init;
+    dc->props = spapr_phb_properties;
 
     spapr_rtas_register("read-pci-config", rtas_read_pci_config);
     spapr_rtas_register("write-pci-config", rtas_write_pci_config);
     spapr_rtas_register("ibm,read-pci-config", rtas_ibm_read_pci_config);
     spapr_rtas_register("ibm,write-pci-config", rtas_ibm_write_pci_config);
+}
 
-    QLIST_INSERT_HEAD(&spapr->phbs, phb, list);
+static TypeInfo spapr_phb_info = {
+    .name          = "spapr-pci-host-bridge",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(sPAPRPHBState),
+    .class_init    = spapr_phb_class_init,
+};
+
+void spapr_create_phb(sPAPREnvironment *spapr,
+                      const char *busname, uint64_t buid,
+                      uint64_t mem_win_addr, uint64_t mem_win_size,
+                      uint64_t io_win_addr)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, spapr_phb_info.name);
 
-    /* pci_bus_set_mem_base(bus, mem_va_start - SPAPR_PCI_MEM_BAR_START); */
+    if (busname) {
+        qdev_prop_set_string(dev, "busname", g_strdup(busname));
+    }
+    qdev_prop_set_uint64(dev, "buid", buid);
+    qdev_prop_set_uint64(dev, "mem_win_addr", mem_win_addr);
+    qdev_prop_set_uint64(dev, "mem_win_size", mem_win_size);
+    qdev_prop_set_uint64(dev, "io_win_addr", io_win_addr);
+
+    qdev_init_nofail(dev);
 }
 
 /* Macros to operate with address in OF binding to PCI */
@@ -415,3 +425,9 @@ int spapr_populate_pci_devices(sPAPRPHBState *phb,
 
     return 0;
 }
+
+static void register_types(void)
+{
+    type_register_static(&spapr_phb_info);
+}
+type_init(register_types)
diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h
index 213340c..039f85b 100644
--- a/hw/spapr_pci.h
+++ b/hw/spapr_pci.h
@@ -33,9 +33,11 @@ typedef struct sPAPRPHBState {
     PCIHostState host_state;
 
     uint64_t buid;
+    char *busname;
+    char *dtbusname;
 
     MemoryRegion memspace, iospace;
-    target_phys_addr_t mem_win_addr, io_win_addr;
+    target_phys_addr_t mem_win_addr, mem_win_size, io_win_addr, io_win_size;
     MemoryRegion memwindow, iowindow;
 
     struct {
commit 29979a8d2596d33b474c11efb376ed47ba1d44d3
Author: Alexander Graf <agraf at suse.de>
Date:   Wed Mar 14 00:13:22 2012 +0100

    PPC: KVM: Synchronize regs on CPU dump
    
    When we dump the CPU registers, there's a certain chance they haven't been
    synchronized with KVM yet, so we have to manually trigger that.
    
    This aligns the code with x86 and fixes a bug where the register state was
    bogus on invalid/unknown kvm exit reasons.
    
    Reported-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 4722a09..c9a503a 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -9319,6 +9319,8 @@ void cpu_dump_state (CPUPPCState *env, FILE *f, fprintf_function cpu_fprintf,
 
     int i;
 
+    cpu_synchronize_state(env);
+
     cpu_fprintf(f, "NIP " TARGET_FMT_lx "   LR " TARGET_FMT_lx " CTR "
                 TARGET_FMT_lx " XER " TARGET_FMT_lx "\n",
                 env->nip, env->lr, env->ctr, env->xer);
commit 92e4b519e0808948ae4bc710fb1db7d3cc2245a1
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Wed Mar 7 14:41:09 2012 +0000

    kvm: Comparison with ioctl number macros needs to be unsigned
    
    In kvm-all.c we store an ioctl cmd number in the irqchip_inject_ioctl field
    of KVMState, which has type 'int'.  This seems to make sense since the
    ioctl() man page says that the cmd parameter has type int.
    
    However, the kernel treats ioctl numbers as unsigned - sys_ioctl() takes an
    unsigned int, and the macros which generate ioctl numbers expand to
    unsigned expressions.  Furthermore, some ioctls (IOC_READ ioctls on x86
    and IOC_WRITE ioctls on powerpc) have bit 31 set, and so would be negative
    if interpreted as an int. This has the surprising and compile-breaking
    consequence that in kvm_irqchip_set_irq() where we do:
        return (s->irqchip_inject_ioctl == KVM_IRQ_LINE) ? 1 : event.status;
    We will get a "comparison is always false due to limited range of data
    type" warning from gcc if KVM_IRQ_LINE is one of the bit-31-set ioctls,
    which it is on powerpc.
    
    So, despite the fact that the man page and posix say ioctl numbers are
    signed, they're actually unsigned.  The kernel uses unsigned, the glibc
    header uses unsigned long, and FreeBSD, NetBSD and OSX also use unsigned
    long ioctl numbers in the code.
    
    Therefore, this patch changes the variable to be unsigned, fixing the
    compile.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/kvm-all.c b/kvm-all.c
index 42e5e23..ba2cee1 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -79,7 +79,10 @@ struct KVMState
     int pit_state2;
     int xsave, xcrs;
     int many_ioeventfds;
-    int irqchip_inject_ioctl;
+    /* The man page (and posix) say ioctl numbers are signed int, but
+     * they're not.  Linux, glibc and *BSD all treat ioctl numbers as
+     * unsigned, and treating them as signed here can break things */
+    unsigned irqchip_inject_ioctl;
 #ifdef KVM_CAP_IRQ_ROUTING
     struct kvm_irq_routing *irq_routes;
     int nr_allocated_irq_routes;
commit 6bbc5ed163d0eb8e3268ec81742a0d4f4f0bfc22
Author: Meador Inge <meadori at codesourcery.com>
Date:   Thu Feb 23 03:44:14 2012 +0000

    ppc: Correctly define POWERPC_INSNS2_DEFAULT
    
    'POWERPC_INSNS2_DEFAULT' was defined incorrectly which was causing the
    opcode table creation code to erroneously register 'eieio' and 'mbar'
    for the "default" processor:
    
       ** ERROR: opcode 1a already assigned in opcode table 16
       *** ERROR: unable to insert opcode [1f-16-1a]
       *** ERROR initializing PowerPC instruction 0x1f 0x16 0x1a
    
    Signed-off-by: Meador Inge <meadori at codesourcery.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 5a958b9..367eefa 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -6718,7 +6718,7 @@ static void init_proc_620 (CPUPPCState *env)
 #if defined (TARGET_PPC64) && 0 // XXX: TODO
 #define CPU_POWERPC_DEFAULT    CPU_POWERPC_PPC64
 #define POWERPC_INSNS_DEFAULT  POWERPC_INSNS_PPC64
-#define POWERPC_INSNS2_DEFAULT POWERPC_INSNS_PPC64
+#define POWERPC_INSNS2_DEFAULT POWERPC_INSNS2_PPC64
 #define POWERPC_MSRM_DEFAULT   POWERPC_MSRM_PPC64
 #define POWERPC_MMU_DEFAULT    POWERPC_MMU_PPC64
 #define POWERPC_EXCP_DEFAULT   POWERPC_EXCP_PPC64
@@ -6730,7 +6730,7 @@ static void init_proc_620 (CPUPPCState *env)
 #else
 #define CPU_POWERPC_DEFAULT    CPU_POWERPC_PPC32
 #define POWERPC_INSNS_DEFAULT  POWERPC_INSNS_PPC32
-#define POWERPC_INSNS2_DEFAULT POWERPC_INSNS_PPC32
+#define POWERPC_INSNS2_DEFAULT POWERPC_INSNS2_PPC32
 #define POWERPC_MSRM_DEFAULT   POWERPC_MSRM_PPC32
 #define POWERPC_MMU_DEFAULT    POWERPC_MMU_PPC32
 #define POWERPC_EXCP_DEFAULT   POWERPC_EXCP_PPC32
commit d07fee7e8ad9d3611404fa145270d3b885b2772a
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Wed Mar 7 15:12:21 2012 +0000

    pseries: Add support for level interrupts to XICS
    
    The pseries "xics" interrupt controller, like most interrupt
    controllers can support both message (i.e. edge sensitive) interrupts
    and level sensitive interrupts, but it needs to know which are which.
    
    When I implemented the xics emulation for qemu, the only devices we
    supported were the PAPR virtual IO devices.  These devices only use
    message interrupts, so they were the only ones I implemented in xics.
    
    Since then, however, we have added support for PCI devices, which use
    level sensitive interrupts.  It turns out the message interrupt logic
    still actually works most of the time for these, but there are
    circumstances where we can lost interrupts due to the incorrect
    interrupt logic.
    
    This patch, therefore, implements the correct xics level-sensitive
    interrupt logic.  The type of the interrupt is set when a device
    allocates a new xics interrupt.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/spapr.c b/hw/spapr.c
index 3719e0e..bfaf260 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -83,7 +83,8 @@
 
 sPAPREnvironment *spapr;
 
-qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num)
+qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num,
+                            enum xics_irq_type type)
 {
     uint32_t irq;
     qemu_irq qirq;
@@ -95,7 +96,7 @@ qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num)
         irq = spapr->next_irq++;
     }
 
-    qirq = xics_find_qirq(spapr->icp, irq);
+    qirq = xics_assign_irq(spapr->icp, irq, type);
     if (!qirq) {
         return NULL;
     }
diff --git a/hw/spapr.h b/hw/spapr.h
index a41641f..11160b0 100644
--- a/hw/spapr.h
+++ b/hw/spapr.h
@@ -286,7 +286,18 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn);
 target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode,
                              target_ulong *args);
 
-qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num);
+qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num,
+                            enum xics_irq_type type);
+
+static inline qemu_irq spapr_allocate_msi(uint32_t hint, uint32_t *irq_num)
+{
+    return spapr_allocate_irq(hint, irq_num, XICS_MSI);
+}
+
+static inline qemu_irq spapr_allocate_lsi(uint32_t hint, uint32_t *irq_num)
+{
+    return spapr_allocate_irq(hint, irq_num, XICS_LSI);
+}
 
 static inline uint32_t rtas_ld(target_ulong phys, int n)
 {
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index c06afac..233250f 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -190,7 +190,7 @@ static int spapr_phb_init(SysBusDevice *s)
         qemu_irq qirq;
         uint32_t num;
 
-        qirq = spapr_allocate_irq(0, &num);
+        qirq = spapr_allocate_lsi(0, &num);
         if (!qirq) {
             return -1;
         }
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index 2fb3cee..dbf5a90 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -670,7 +670,7 @@ static int spapr_vio_busdev_init(DeviceState *qdev)
         dev->qdev.id = id;
     }
 
-    dev->qirq = spapr_allocate_irq(dev->vio_irq_num, &dev->vio_irq_num);
+    dev->qirq = spapr_allocate_msi(dev->vio_irq_num, &dev->vio_irq_num);
     if (!dev->qirq) {
         return -1;
     }
diff --git a/hw/xics.c b/hw/xics.c
index f7963f3..668a0d6 100644
--- a/hw/xics.c
+++ b/hw/xics.c
@@ -132,9 +132,9 @@ static void icp_eoi(struct icp_state *icp, int server, uint32_t xirr)
 {
     struct icp_server_state *ss = icp->ss + server;
 
-    ics_eoi(icp->ics, xirr & XISR_MASK);
     /* Send EOI -> ICS */
     ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
+    ics_eoi(icp->ics, xirr & XISR_MASK);
     if (!XISR(ss)) {
         icp_resend(icp, server);
     }
@@ -165,8 +165,9 @@ struct ics_irq_state {
     int server;
     uint8_t priority;
     uint8_t saved_priority;
-    /* int pending:1; */
-    /* int presented:1; */
+    enum xics_irq_type type;
+    int asserted:1;
+    int sent:1;
     int rejected:1;
     int masked_pending:1;
 };
@@ -185,9 +186,32 @@ static int ics_valid_irq(struct ics_state *ics, uint32_t nr)
         && (nr < (ics->offset + ics->nr_irqs));
 }
 
-static void ics_set_irq_msi(void *opaque, int srcno, int val)
+static void resend_msi(struct ics_state *ics, int srcno)
+{
+    struct ics_irq_state *irq = ics->irqs + srcno;
+
+    /* FIXME: filter by server#? */
+    if (irq->rejected) {
+        irq->rejected = 0;
+        if (irq->priority != 0xff) {
+            icp_irq(ics->icp, irq->server, srcno + ics->offset,
+                    irq->priority);
+        }
+    }
+}
+
+static void resend_lsi(struct ics_state *ics, int srcno)
+{
+    struct ics_irq_state *irq = ics->irqs + srcno;
+
+    if ((irq->priority != 0xff) && irq->asserted && !irq->sent) {
+        irq->sent = 1;
+        icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
+    }
+}
+
+static void set_irq_msi(struct ics_state *ics, int srcno, int val)
 {
-    struct ics_state *ics = (struct ics_state *)opaque;
     struct ics_irq_state *irq = ics->irqs + srcno;
 
     if (val) {
@@ -200,71 +224,108 @@ static void ics_set_irq_msi(void *opaque, int srcno, int val)
     }
 }
 
-static void ics_reject_msi(struct ics_state *ics, int nr)
+static void set_irq_lsi(struct ics_state *ics, int srcno, int val)
 {
-    struct ics_irq_state *irq = ics->irqs + nr - ics->offset;
+    struct ics_irq_state *irq = ics->irqs + srcno;
 
-    irq->rejected = 1;
+    irq->asserted = val;
+    resend_lsi(ics, srcno);
 }
 
-static void ics_resend_msi(struct ics_state *ics)
+static void ics_set_irq(void *opaque, int srcno, int val)
 {
-    int i;
+    struct ics_state *ics = (struct ics_state *)opaque;
+    struct ics_irq_state *irq = ics->irqs + srcno;
 
-    for (i = 0; i < ics->nr_irqs; i++) {
-        struct ics_irq_state *irq = ics->irqs + i;
+    if (irq->type == XICS_LSI) {
+        set_irq_lsi(ics, srcno, val);
+    } else {
+        set_irq_msi(ics, srcno, val);
+    }
+}
 
-        /* FIXME: filter by server#? */
-        if (irq->rejected) {
-            irq->rejected = 0;
-            if (irq->priority != 0xff) {
-                icp_irq(ics->icp, irq->server, i + ics->offset, irq->priority);
-            }
-        }
+static void write_xive_msi(struct ics_state *ics, int srcno)
+{
+    struct ics_irq_state *irq = ics->irqs + srcno;
+
+    if (!irq->masked_pending || (irq->priority == 0xff)) {
+        return;
     }
+
+    irq->masked_pending = 0;
+    icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
 }
 
-static void ics_write_xive_msi(struct ics_state *ics, int nr, int server,
-                               uint8_t priority)
+static void write_xive_lsi(struct ics_state *ics, int srcno)
 {
-    struct ics_irq_state *irq = ics->irqs + nr - ics->offset;
+    resend_lsi(ics, srcno);
+}
+
+static void ics_write_xive(struct ics_state *ics, int nr, int server,
+                           uint8_t priority)
+{
+    int srcno = nr - ics->offset;
+    struct ics_irq_state *irq = ics->irqs + srcno;
 
     irq->server = server;
     irq->priority = priority;
 
-    if (!irq->masked_pending || (priority == 0xff)) {
-        return;
+    if (irq->type == XICS_LSI) {
+        write_xive_lsi(ics, srcno);
+    } else {
+        write_xive_msi(ics, srcno);
     }
-
-    irq->masked_pending = 0;
-    icp_irq(ics->icp, server, nr, priority);
 }
 
 static void ics_reject(struct ics_state *ics, int nr)
 {
-    ics_reject_msi(ics, nr);
+    struct ics_irq_state *irq = ics->irqs + nr - ics->offset;
+
+    irq->rejected = 1; /* Irrelevant but harmless for LSI */
+    irq->sent = 0; /* Irrelevant but harmless for MSI */
 }
 
 static void ics_resend(struct ics_state *ics)
 {
-    ics_resend_msi(ics);
+    int i;
+
+    for (i = 0; i < ics->nr_irqs; i++) {
+        struct ics_irq_state *irq = ics->irqs + i;
+
+        /* FIXME: filter by server#? */
+        if (irq->type == XICS_LSI) {
+            resend_lsi(ics, i);
+        } else {
+            resend_msi(ics, i);
+        }
+    }
 }
 
 static void ics_eoi(struct ics_state *ics, int nr)
 {
+    int srcno = nr - ics->offset;
+    struct ics_irq_state *irq = ics->irqs + srcno;
+
+    if (irq->type == XICS_LSI) {
+        irq->sent = 0;
+    }
 }
 
 /*
  * Exported functions
  */
 
-qemu_irq xics_find_qirq(struct icp_state *icp, int irq)
+qemu_irq xics_assign_irq(struct icp_state *icp, int irq,
+                         enum xics_irq_type type)
 {
     if ((irq < icp->ics->offset)
         || (irq >= (icp->ics->offset + icp->ics->nr_irqs))) {
         return NULL;
     }
 
+    assert((type == XICS_MSI) || (type == XICS_LSI));
+
+    icp->ics->irqs[irq - icp->ics->offset].type = type;
     return icp->ics->qirqs[irq - icp->ics->offset];
 }
 
@@ -332,7 +393,7 @@ static void rtas_set_xive(sPAPREnvironment *spapr, uint32_t token,
         return;
     }
 
-    ics_write_xive_msi(ics, nr, server, priority);
+    ics_write_xive(ics, nr, server, priority);
 
     rtas_st(rets, 0, 0); /* Success */
 }
@@ -477,7 +538,7 @@ struct icp_state *xics_system_init(int nr_irqs)
         ics->irqs[i].saved_priority = 0xff;
     }
 
-    ics->qirqs = qemu_allocate_irqs(ics_set_irq_msi, ics, nr_irqs);
+    ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, nr_irqs);
 
     spapr_register_hypercall(H_CPPR, h_cppr);
     spapr_register_hypercall(H_IPI, h_ipi);
diff --git a/hw/xics.h b/hw/xics.h
index 83c1182..2080159 100644
--- a/hw/xics.h
+++ b/hw/xics.h
@@ -31,7 +31,13 @@
 
 struct icp_state;
 
-qemu_irq xics_find_qirq(struct icp_state *icp, int irq);
+enum xics_irq_type {
+    XICS_MSI,        /* Message-signalled (edge) interrupt */
+    XICS_LSI,        /* Level-signalled interrupt */
+};
+
+qemu_irq xics_assign_irq(struct icp_state *icp, int irq,
+                         enum xics_irq_type type);
 
 struct icp_state *xics_system_init(int nr_irqs);
 
commit eb6ea4b22e89d4c6ed510c7cfcd33d15be92733b
Author: Nathan Whitehorn <nwhitehorn at freebsd.org>
Date:   Fri Mar 9 04:30:41 2012 +0000

    PPC: Fix large page support in TCG
    
    Fix large page support in TCG. The old code would overwrite the large page
    table entry with the fake 4 KB one generated here whenever the ref/change bits
    were updated, causing it to point to the wrong area of memory.
    
    Signed-off-by: Nathan Whitehorn <nwhitehorn at freebsd.org>
    Acked-by: David Gibson <david at gibson.drobpear.id.au>
    [agraf: fix whitespace, braces]
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index bd711b6..39dcc27 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -591,12 +591,6 @@ static inline int _find_pte(CPUPPCState *env, mmu_ctx_t *ctx, int is_64b, int h,
                 pte1 = ldq_phys(env->htab_base + pteg_off + (i * 16) + 8);
             }
 
-            /* We have a TLB that saves 4K pages, so let's
-             * split a huge page to 4k chunks */
-            if (target_page_bits != TARGET_PAGE_BITS)
-                pte1 |= (ctx->eaddr & (( 1 << target_page_bits ) - 1))
-                        & TARGET_PAGE_MASK;
-
             r = pte64_check(ctx, pte0, pte1, h, rw, type);
             LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
                     TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
@@ -672,6 +666,12 @@ static inline int _find_pte(CPUPPCState *env, mmu_ctx_t *ctx, int is_64b, int h,
         }
     }
 
+    /* We have a TLB that saves 4K pages, so let's
+     * split a huge page to 4k chunks */
+    if (target_page_bits != TARGET_PAGE_BITS) {
+        ctx->raddr |= (ctx->eaddr & ((1 << target_page_bits) - 1))
+                      & TARGET_PAGE_MASK;
+    }
     return ret;
 }
 
commit 2e06214f22e080be4a8a17b0fae3b4c03b0aa3ea
Author: Nathan Whitehorn <nwhitehorn at freebsd.org>
Date:   Sat Mar 3 06:36:36 2012 +0000

    PPC: Add PIR register to POWER7 CPU
    
    The POWER7 emulation is missing the Processor Identification Register,
    mandatory in recent POWER CPUs, that is required for SMP on at least
    some operating systems (e.g. FreeBSD) to function properly. This patch
    copies the existing PIR code from the other CPUs that implement it.
    
    Signed-off-by: Nathan Whitehorn <nwhitehorn at freebsd.org>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index c707959..5a958b9 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -6588,6 +6588,11 @@ static void init_proc_POWER7 (CPUPPCState *env)
     gen_spr_7xx(env);
     /* Time base */
     gen_tbl(env);
+    /* Processor identification */
+    spr_register(env, SPR_PIR, "PIR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_pir,
+                 0x00000000);
 #if !defined(CONFIG_USER_ONLY)
     /* PURR & SPURR: Hack - treat these as aliases for the TB for now */
     spr_register(env, SPR_PURR,   "PURR",
commit 76ab9583cea5c742f32743cc65abc326719bd646
Author: Alexey Kardashevskiy <aik at ozlabs.ru>
Date:   Mon Feb 27 17:18:12 2012 +0000

    pseries: Remove PCI device from PCI host bridge code
    
    The sPAPR PCI code defines a PCI device "spapr-pci-host-bridge-pci" which
    is never used.  This came over from the earlier bridge driver we used as
    a template.  Some other bridges appear on their own PCI bus as a device,
    but that is not true of pSeries bridges, which are pure host to PCI with
    no visible presence on the PCI side.
    
    Signed-off-by: Alexey Kardashevskiy <aik at ozlabs.ru>
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index 3d5e50a..c06afac 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -202,25 +202,6 @@ static int spapr_phb_init(SysBusDevice *s)
     return 0;
 }
 
-static int spapr_main_pci_host_init(PCIDevice *d)
-{
-    return 0;
-}
-
-static void spapr_main_pci_host_class_init(ObjectClass *klass, void *data)
-{
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = spapr_main_pci_host_init;
-}
-
-static TypeInfo spapr_main_pci_host_info = {
-    .name          = "spapr-pci-host-bridge-pci",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PCIDevice),
-    .class_init    = spapr_main_pci_host_class_init,
-};
-
 static void spapr_phb_class_init(ObjectClass *klass, void *data)
 {
     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
@@ -238,7 +219,6 @@ static TypeInfo spapr_phb_info = {
 static void spapr_register_types(void)
 {
     type_register_static(&spapr_phb_info);
-    type_register_static(&spapr_main_pci_host_info);
 }
 
 type_init(spapr_register_types)
commit 323abebf9997f30fb357602e169ea6333ac20bc3
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Mon Feb 27 17:18:11 2012 +0000

    pseries: Remove unused constant from PCI code
    
    The 'bars' constant array was used in experimental device allocation code
    which is no longer necessary now that we always run the SLOF firmware.
    This patch removes the now redundant variable.
    
    Signed-off-by: Alexey Kardashevskiy <aik at ozlabs.ru>
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index 374dcf8..3d5e50a 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -32,13 +32,6 @@
 
 #include "hw/pci_internals.h"
 
-static const uint32_t bars[] = {
-    PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1,
-    PCI_BASE_ADDRESS_2, PCI_BASE_ADDRESS_3,
-    PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5
-    /*, PCI_ROM_ADDRESS*/
-};
-
 static PCIDevice *find_dev(sPAPREnvironment *spapr,
                            uint64_t buid, uint32_t config_addr)
 {
commit 53f649e863dd08b6ff212093556add42f456d14d
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Mon Feb 27 17:18:10 2012 +0000

    pseries: Update SLOF firmware image
    
    This patch updates the SLOF firmware image used on the pseries
    machine.  The new version adds support for Cirrus VGA and virtfs, as
    well as including a number of bugfixes.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/pc-bios/README b/pc-bios/README
index 5dce355..71f4871 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -17,7 +17,7 @@
 - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
   implementation for certain IBM POWER hardware.  The sources are at
   https://github.com/dgibson/SLOF, and the image currently in qemu is
-  built from git tag qemu-slof-20120111.1.
+  built from git tag qemu-slof-20120217.
 
 - sgabios (the Serial Graphics Adapter option ROM) provides a means for
   legacy x86 software to communicate with an attached serial console as
diff --git a/pc-bios/slof.bin b/pc-bios/slof.bin
index 8554f54..449a7bb 100644
Binary files a/pc-bios/slof.bin and b/pc-bios/slof.bin differ
diff --git a/roms/SLOF b/roms/SLOF
index ab062ff..d153364 160000
--- a/roms/SLOF
+++ b/roms/SLOF
@@ -1 +1 @@
-Subproject commit ab062ff3b37c39649f2b0d94ed607adc6f6b3c7d
+Subproject commit d153364253548d6cd91403711f84996e6a7dab31
commit cd6e9320142fea0d9e82c8ca7f3a4c2f20fecf39
Author: Thomas Huth <thuth at linux.vnet.ibm.com>
Date:   Mon Feb 27 17:18:08 2012 +0000

    PPC64: Add support for ldbrx and stdbrx instructions
    
    These instructions for loading and storing byte-swapped 64-bit values have
    been introduced in PowerISA 2.06.
    
    Signed-off-by: Thomas Huth <thuth at linux.vnet.ibm.com>
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index ad09cbe..ca6f1cb 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1918,8 +1918,10 @@ enum {
     PPC2_DFP           = 0x0000000000000004ULL,
     /* Embedded.Processor Control                                            */
     PPC2_PRCNTL        = 0x0000000000000008ULL,
+    /* Byte-reversed, indexed, double-word load and store                    */
+    PPC2_DBRX          = 0x0000000000000010ULL,
 
-#define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_PRCNTL)
+#define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_PRCNTL | PPC2_DBRX)
 };
 
 /*****************************************************************************/
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 3ec59a7..4722a09 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -2650,7 +2650,7 @@ static void glue(gen_, name##ux)(DisasContext *ctx)
     tcg_temp_free(EA);                                                        \
 }
 
-#define GEN_LDX(name, ldop, opc2, opc3, type)                                 \
+#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2)                        \
 static void glue(gen_, name##x)(DisasContext *ctx)                            \
 {                                                                             \
     TCGv EA;                                                                  \
@@ -2660,6 +2660,8 @@ static void glue(gen_, name##x)(DisasContext *ctx)                            \
     gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
     tcg_temp_free(EA);                                                        \
 }
+#define GEN_LDX(name, ldop, opc2, opc3, type)                                 \
+    GEN_LDX_E(name, ldop, opc2, opc3, type, PPC_NONE)
 
 #define GEN_LDS(name, ldop, op, type)                                         \
 GEN_LD(name, ldop, op | 0x20, type);                                          \
@@ -2793,8 +2795,8 @@ static void glue(gen_, name##ux)(DisasContext *ctx)
     tcg_temp_free(EA);                                                        \
 }
 
-#define GEN_STX(name, stop, opc2, opc3, type)                                 \
-static void glue(gen_, name##x)(DisasContext *ctx)                                    \
+#define GEN_STX_E(name, stop, opc2, opc3, type, type2)                        \
+static void glue(gen_, name##x)(DisasContext *ctx)                            \
 {                                                                             \
     TCGv EA;                                                                  \
     gen_set_access_type(ctx, ACCESS_INT);                                     \
@@ -2803,6 +2805,8 @@ static void glue(gen_, name##x)(DisasContext *ctx)
     gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
     tcg_temp_free(EA);                                                        \
 }
+#define GEN_STX(name, stop, opc2, opc3, type)                                 \
+    GEN_STX_E(name, stop, opc2, opc3, type, PPC_NONE)
 
 #define GEN_STS(name, stop, op, type)                                         \
 GEN_ST(name, stop, op | 0x20, type);                                          \
@@ -2891,6 +2895,18 @@ static inline void gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
 }
 GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
 
+#if defined(TARGET_PPC64)
+/* ldbrx */
+static inline void gen_qemu_ld64ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
+{
+    tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
+    if (likely(!ctx->le_mode)) {
+        tcg_gen_bswap64_tl(arg1, arg1);
+    }
+}
+GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX);
+#endif  /* TARGET_PPC64 */
+
 /* sthbrx */
 static inline void gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
 {
@@ -2921,6 +2937,22 @@ static inline void gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
 }
 GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
 
+#if defined(TARGET_PPC64)
+/* stdbrx */
+static inline void gen_qemu_st64r(DisasContext *ctx, TCGv arg1, TCGv arg2)
+{
+    if (likely(!ctx->le_mode)) {
+        TCGv t0 = tcg_temp_new();
+        tcg_gen_bswap64_tl(t0, arg1);
+        tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
+        tcg_temp_free(t0);
+    } else {
+        tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
+    }
+}
+GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX);
+#endif  /* TARGET_PPC64 */
+
 /***                    Integer load and store multiple                    ***/
 
 /* lmw */
@@ -8818,7 +8850,7 @@ GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT),
 #undef GEN_LD
 #undef GEN_LDU
 #undef GEN_LDUX
-#undef GEN_LDX
+#undef GEN_LDX_E
 #undef GEN_LDS
 #define GEN_LD(name, ldop, opc, type)                                         \
 GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
@@ -8826,8 +8858,8 @@ GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
 GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
 #define GEN_LDUX(name, ldop, opc2, opc3, type)                                \
 GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
-#define GEN_LDX(name, ldop, opc2, opc3, type)                                 \
-GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
+#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2)                        \
+GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
 #define GEN_LDS(name, ldop, op, type)                                         \
 GEN_LD(name, ldop, op | 0x20, type)                                           \
 GEN_LDU(name, ldop, op | 0x21, type)                                          \
@@ -8843,6 +8875,7 @@ GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B)
 GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B)
 GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B)
 GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B)
+GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX)
 #endif
 GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER)
 GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER)
@@ -8850,7 +8883,7 @@ GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER)
 #undef GEN_ST
 #undef GEN_STU
 #undef GEN_STUX
-#undef GEN_STX
+#undef GEN_STX_E
 #undef GEN_STS
 #define GEN_ST(name, stop, opc, type)                                         \
 GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
@@ -8858,8 +8891,8 @@ GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
 GEN_HANDLER(stop##u, opc, 0xFF, 0xFF, 0x00000000, type),
 #define GEN_STUX(name, stop, opc2, opc3, type)                                \
 GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
-#define GEN_STX(name, stop, opc2, opc3, type)                                 \
-GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
+#define GEN_STX_E(name, stop, opc2, opc3, type, type2)                        \
+GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
 #define GEN_STS(name, stop, op, type)                                         \
 GEN_ST(name, stop, op | 0x20, type)                                           \
 GEN_STU(name, stop, op | 0x21, type)                                          \
@@ -8872,6 +8905,7 @@ GEN_STS(stw, st32, 0x04, PPC_INTEGER)
 #if defined(TARGET_PPC64)
 GEN_STUX(std, st64, 0x15, 0x05, PPC_64B)
 GEN_STX(std, st64, 0x15, 0x04, PPC_64B)
+GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX)
 #endif
 GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER)
 GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER)
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 1ec6f42..c707959 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -6571,7 +6571,7 @@ static void init_proc_970MP (CPUPPCState *env)
                               PPC_64B | PPC_ALTIVEC |                         \
                               PPC_SEGMENT_64B | PPC_SLBI |                    \
                               PPC_POPCNTB | PPC_POPCNTWD)
-#define POWERPC_INSNS2_POWER7 (PPC2_VSX | PPC2_DFP)
+#define POWERPC_INSNS2_POWER7 (PPC2_VSX | PPC2_DFP | PPC2_DBRX)
 #define POWERPC_MSRM_POWER7   (0x800000000204FF36ULL)
 #define POWERPC_MMU_POWER7    (POWERPC_MMU_2_06)
 #define POWERPC_EXCP_POWER7   (POWERPC_EXCP_POWER7)
commit b5aec39672dc6084b43fa3f77764a6f549255a53
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Mon Feb 27 17:18:07 2012 +0000

    pseries: Don't try to munmap() a malloc()ed TCE table
    
    For the pseries machine, TCE (IOMMU) tables can either be directly
    malloc()ed in qemu or, when running on a KVM which supports it, mmap()ed
    from a KVM ioctl.  The latter option is used when available, because it
    allows the (frequent bottlenext) H_PUT_TCE hypercall to be KVM accelerated.
    However, even when KVM is persent, TCE acceleration is not always possible.
    Only KVM HV supports this ioctl(), not KVM PR, or the kernel could run out
    of contiguous memory to allocate the new table.  In this case we need to
    fall back on the malloc()ed table.
    
    When a device is removed, and we need to remove the TCE table, we need to
    either munmap() or free() the table as appropriate for how it was
    allocated.  The code is supposed to do that, but we buggily fail to
    initialize the tcet->fd variable in the malloc() case, which is used as a
    flag to determine which is the right choice.
    
    This patch fixes the bug, and cleans up error messages relating to this
    path while we're at it.
    
    Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index aeb3de9..724f4c7 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -843,12 +843,18 @@ void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd)
     int fd;
     void *table;
 
+    /* Must set fd to -1 so we don't try to munmap when called for
+     * destroying the table, which the upper layers -will- do
+     */
+    *pfd = -1;
     if (!cap_spapr_tce) {
         return NULL;
     }
 
     fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_SPAPR_TCE, &args);
     if (fd < 0) {
+        fprintf(stderr, "KVM: Failed to create TCE table for liobn 0x%x\n",
+                liobn);
         return NULL;
     }
 
@@ -857,6 +863,8 @@ void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd)
 
     table = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
     if (table == MAP_FAILED) {
+        fprintf(stderr, "KVM: Failed to map TCE table for liobn 0x%x\n",
+                liobn);
         close(fd);
         return NULL;
     }
@@ -876,8 +884,8 @@ int kvmppc_remove_spapr_tce(void *table, int fd, uint32_t window_size)
     len = (window_size / SPAPR_VIO_TCE_PAGE_SIZE)*sizeof(VIOsPAPR_RTCE);
     if ((munmap(table, len) < 0) ||
         (close(fd) < 0)) {
-        fprintf(stderr, "KVM: Unexpected error removing KVM SPAPR TCE "
-                "table: %s", strerror(errno));
+        fprintf(stderr, "KVM: Unexpected error removing TCE table: %s",
+                strerror(errno));
         /* Leak the table */
     }
 
commit b7c28f02a12c98a4710b5c150b0753d39454101e
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Feb 25 02:37:12 2012 +0000

    ppc: Add missing 'static' to spin_rw_ops
    
    spin_rw_ops is only used in hw/ppce500_spin.c.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Acked-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c
index 268f5fd..960b7b0 100644
--- a/hw/ppce500_spin.c
+++ b/hw/ppce500_spin.c
@@ -182,7 +182,7 @@ static uint64_t spin_read(void *opaque, target_phys_addr_t addr, unsigned len)
     }
 }
 
-const MemoryRegionOps spin_rw_ops = {
+static const MemoryRegionOps spin_rw_ops = {
     .read = spin_read,
     .write = spin_write,
     .endianness = DEVICE_BIG_ENDIAN,
commit d715ea961254512c6989e17edbfaf959aa7805b0
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Feb 21 19:01:11 2012 +0100

    PPC: 405: Fix ppc405ep initialization
    
    When trying to run a ppc405 guest, it segfaults quite quickly, trying to
    access timers that weren't initialized. Initialize them properly instead.
    
    Reported-by: Andreas Faerber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
index 6f8342e..89e5013 100644
--- a/hw/ppc405_uc.c
+++ b/hw/ppc405_uc.c
@@ -2471,6 +2471,8 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
     ppc4xx_pob_init(env);
     /* OBP arbitrer */
     ppc4xx_opba_init(0xef600600);
+    /* Initialize timers */
+    ppc_booke_timers_init(env, sysclk, 0);
     /* Universal interrupt controller */
     irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
     irqs[PPCUIC_OUTPUT_INT] =
commit 32a2003af9cb0cb11b3992fd3248cb89752c53e9
Author: Alex Barcelo <abarcelo at ac.upc.edu>
Date:   Thu Feb 9 23:55:46 2012 +0000

    Bad zero comparison for sas_ss_flags on powerpc
    
    All architectures work the same way, and all check for sas_ss_flags ==
    0. The powerpc lines are wrong, and do the check the other way round
    (it's a qemu internal check, which is done wrong only for this
    architecture, it's more a typo than a bug). It's NOT ppc specific,
    it's POSIX standard (sigaltstack) and qemu internal.
    
    I have a test source that I will send in a follow-up (it's longer than
    I would have wished, I'm sure that a better test case can be written
    if needed)
    
    Signed-off-by: Alex Barcelo <abarcelo at ac.upc.edu>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/linux-user/signal.c b/linux-user/signal.c
index fca51e2..b1e139d 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -4118,7 +4118,7 @@ static target_ulong get_sigframe(struct target_sigaction *ka,
     oldsp = env->gpr[1];
 
     if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
-        (sas_ss_flags(oldsp))) {
+        (sas_ss_flags(oldsp) == 0)) {
         oldsp = (target_sigaltstack_used.ss_sp
                  + target_sigaltstack_used.ss_size);
     }
commit ae7d54d489540b49b7c13a7df7ddc220588a2ced
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu Mar 15 01:19:42 2012 +0100

    target-lm32/microblaze: Drop second CPU{LM32, MB}State typedef
    
    Commit 9b9a970a23625de4ae6b7461906a9a0d98d3ca95
    (target-lm32/microblaze: Typedef struct CPU{MB,LM32}State)
    introduced necessary typedefs for cpu_mmu_index() and mmu.h
    respectively.
    
    On some GCC versions this leads to "error: redefinition of typedef".
    
    Drop the original typedef to hopefully fix the build.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index 0902a24..a7d9546 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -149,7 +149,7 @@ enum {
     LM32_FLAG_IGNORE_MSB = 1,
 };
 
-typedef struct CPULM32State {
+struct CPULM32State {
     /* general registers */
     uint32_t regs[32];
 
@@ -182,7 +182,7 @@ typedef struct CPULM32State {
     uint8_t num_bps;
     uint8_t num_wps;
 
-} CPULM32State;
+};
 
 
 CPULM32State *cpu_lm32_init(const char *cpu_model);
diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index 3b52421..33b23c2 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -230,7 +230,7 @@ typedef struct CPUMBState CPUMBState;
 #define STREAM_CONTROL   (1 << 3)
 #define STREAM_NONBLOCK  (1 << 4)
 
-typedef struct CPUMBState {
+struct CPUMBState {
     uint32_t debug;
     uint32_t btaken;
     uint32_t btarget;
@@ -264,7 +264,7 @@ typedef struct CPUMBState {
 #endif
 
     CPU_COMMON
-} CPUMBState;
+};
 
 CPUMBState *cpu_mb_init(const char *cpu_model);
 int cpu_mb_exec(CPUMBState *s);
commit aea6ff7fa07b046fb9f43d6262d6e34b77e8437e
Merge: 9e4dd56... dd83b06...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Mar 14 16:47:49 2012 -0500

    Merge remote-tracking branch 'afaerber/qom-cpu.v5' into staging
    
    * afaerber/qom-cpu.v5: (43 commits)
      qom: Introduce CPU class
      Rename CPUState -> CPUArchState
      xtensa hw/: Don't use CPUState
      sparc hw/: Don't use CPUState
      sh4 hw/: Don't use CPUState
      s390x hw/: Don't use CPUState
      ppc hw/: Don't use CPUState
      mips hw/: Don't use CPUState
      microblaze hw/: Don't use CPUState
      m68k hw/: Don't use CPUState
      lm32 hw/: Don't use CPUState
      i386 hw/: Don't use CPUState
      cris hw/: Don't use CPUState
      arm hw/: Don't use CPUState
      alpha hw/: Don't use CPUState
      xtensa-semi: Don't use CPUState
      m68k-semi: Don't use CPUState
      arm-semi: Don't use CPUState
      target-xtensa: Don't overuse CPUState
      target-unicore32: Don't overuse CPUState
      ...

commit 9e4dd565b46749d5e6d5cf87bfd84f1917c68319
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Wed Mar 14 07:58:48 2012 +0100

    vnc: Limit r/w access to size of allocated memory
    
    This fixes memory reads and writes which exceeded the upper limit
    of allocated memory vd->guest.ds->data and vd->server->data.
    
    Cc: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc.c b/ui/vnc.c
index aef6d3a..deb9ecd 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2562,6 +2562,9 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
      * Update server dirty map.
      */
     cmp_bytes = 16 * ds_get_bytes_per_pixel(vd->ds);
+    if (cmp_bytes > vd->ds->surface->linesize) {
+        cmp_bytes = vd->ds->surface->linesize;
+    }
     guest_row  = vd->guest.ds->data;
     server_row = vd->server->data;
     for (y = 0; y < vd->guest.ds->height; y++) {
commit 175b2a6e4be06422da59d3a82c28d9a0e738e282
Author: Corentin Chary <corentin.chary at gmail.com>
Date:   Wed Mar 14 07:58:47 2012 +0100

    vnc: don't mess up with iohandlers in the vnc thread
    
    The threaded VNC servers messed up with QEMU fd handlers without
    any kind of locking, and that can cause some nasty race conditions.
    
    Using qemu_mutex_lock_iothread() won't work because vnc_dpy_cpy(),
    which will wait for the current job queue to finish, can be called with
    the iothread lock held.
    
    Instead, we now store the data in a temporary buffer, and use a bottom
    half to notify the main thread that new data is available.
    
    vnc_[un]lock_ouput() is still needed to access VncState members like
    abort, csock or jobs_buffer.
    
    Signed-off-by: Corentin Chary <corentin.chary at gmail.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc-jobs-async.c b/ui/vnc-jobs-async.c
index 9b3016c..087b84d 100644
--- a/ui/vnc-jobs-async.c
+++ b/ui/vnc-jobs-async.c
@@ -28,6 +28,7 @@
 
 #include "vnc.h"
 #include "vnc-jobs.h"
+#include "qemu_socket.h"
 
 /*
  * Locking:
@@ -155,6 +156,24 @@ void vnc_jobs_join(VncState *vs)
         qemu_cond_wait(&queue->cond, &queue->mutex);
     }
     vnc_unlock_queue(queue);
+    vnc_jobs_consume_buffer(vs);
+}
+
+void vnc_jobs_consume_buffer(VncState *vs)
+{
+    bool flush;
+
+    vnc_lock_output(vs);
+    if (vs->jobs_buffer.offset) {
+        vnc_write(vs, vs->jobs_buffer.buffer, vs->jobs_buffer.offset);
+        buffer_reset(&vs->jobs_buffer);
+    }
+    flush = vs->csock != -1 && vs->abort != true;
+    vnc_unlock_output(vs);
+
+    if (flush) {
+      vnc_flush(vs);
+    }
 }
 
 /*
@@ -197,7 +216,6 @@ static int vnc_worker_thread_loop(VncJobQueue *queue)
     VncState vs;
     int n_rectangles;
     int saved_offset;
-    bool flush;
 
     vnc_lock_queue(queue);
     while (QTAILQ_EMPTY(&queue->jobs) && !queue->exit) {
@@ -213,6 +231,7 @@ static int vnc_worker_thread_loop(VncJobQueue *queue)
 
     vnc_lock_output(job->vs);
     if (job->vs->csock == -1 || job->vs->abort == true) {
+        vnc_unlock_output(job->vs);
         goto disconnected;
     }
     vnc_unlock_output(job->vs);
@@ -233,10 +252,6 @@ static int vnc_worker_thread_loop(VncJobQueue *queue)
 
         if (job->vs->csock == -1) {
             vnc_unlock_display(job->vs->vd);
-            /* output mutex must be locked before going to
-             * disconnected:
-             */
-            vnc_lock_output(job->vs);
             goto disconnected;
         }
 
@@ -254,24 +269,19 @@ static int vnc_worker_thread_loop(VncJobQueue *queue)
     vs.output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF;
     vs.output.buffer[saved_offset + 1] = n_rectangles & 0xFF;
 
-    /* Switch back buffers */
     vnc_lock_output(job->vs);
-    if (job->vs->csock == -1) {
-        goto disconnected;
+    if (job->vs->csock != -1) {
+        buffer_reserve(&job->vs->jobs_buffer, vs.output.offset);
+        buffer_append(&job->vs->jobs_buffer, vs.output.buffer,
+                      vs.output.offset);
+        /* Copy persistent encoding data */
+        vnc_async_encoding_end(job->vs, &vs);
+
+	qemu_bh_schedule(job->vs->bh);
     }
-
-    vnc_write(job->vs, vs.output.buffer, vs.output.offset);
-
-disconnected:
-    /* Copy persistent encoding data */
-    vnc_async_encoding_end(job->vs, &vs);
-    flush = (job->vs->csock != -1 && job->vs->abort != true);
     vnc_unlock_output(job->vs);
 
-    if (flush) {
-        vnc_flush(job->vs);
-    }
-
+disconnected:
     vnc_lock_queue(queue);
     QTAILQ_REMOVE(&queue->jobs, job, next);
     vnc_unlock_queue(queue);
diff --git a/ui/vnc-jobs.h b/ui/vnc-jobs.h
index b8dab81..4c661f9 100644
--- a/ui/vnc-jobs.h
+++ b/ui/vnc-jobs.h
@@ -40,6 +40,7 @@ void vnc_jobs_join(VncState *vs);
 
 #ifdef CONFIG_VNC_THREAD
 
+void vnc_jobs_consume_buffer(VncState *vs);
 void vnc_start_worker_thread(void);
 bool vnc_worker_thread_running(void);
 void vnc_stop_worker_thread(void);
diff --git a/ui/vnc.c b/ui/vnc.c
index bdec33a..aef6d3a 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1068,7 +1068,10 @@ static void vnc_disconnect_finish(VncState *vs)
 
 #ifdef CONFIG_VNC_THREAD
     qemu_mutex_destroy(&vs->output_mutex);
+    qemu_bh_delete(vs->bh);
+    buffer_free(&vs->jobs_buffer);
 #endif
+
     for (i = 0; i < VNC_STAT_ROWS; ++i) {
         g_free(vs->lossy_rect[i]);
     }
@@ -1283,6 +1286,14 @@ static long vnc_client_read_plain(VncState *vs)
     return ret;
 }
 
+#ifdef CONFIG_VNC_THREAD
+static void vnc_jobs_bh(void *opaque)
+{
+    VncState *vs = opaque;
+
+    vnc_jobs_consume_buffer(vs);
+}
+#endif
 
 /*
  * First function called whenever there is more data to be read from
@@ -2687,6 +2698,7 @@ static void vnc_connect(VncDisplay *vd, int csock, int skipauth)
 
 #ifdef CONFIG_VNC_THREAD
     qemu_mutex_init(&vs->output_mutex);
+    vs->bh = qemu_bh_new(vnc_jobs_bh, vs);
 #endif
 
     QTAILQ_INSERT_HEAD(&vd->clients, vs, next);
diff --git a/ui/vnc.h b/ui/vnc.h
index 0bd1fc6..a851ebd 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -304,6 +304,8 @@ struct VncState
     VncJob job;
 #else
     QemuMutex output_mutex;
+    QEMUBH *bh;
+    Buffer jobs_buffer;
 #endif
 
     /* Encoding specific, if you add something here, don't forget to
commit dd83b06ae61cfa2dc4381ab49f365bd0995fc930
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Jan 28 16:39:52 2012 +0100

    qom: Introduce CPU class
    
    Reintroduce CPUState as QOM object: It's abstract and derived directly
    from TYPE_OBJECT for compatibility with the user emulators.
    The identifier CPUState avoids conflicts between CPU() and the struct.
    
    Introduce $(qom-twice-y) to build it separately for system and for user
    emulators.
    
    Prepare a virtual reset method, (re)introduce cpu_reset() as wrapper.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile.objs b/Makefile.objs
index f71ea17..226b01d 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -14,6 +14,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))
 
 universal-obj-y += $(qom-obj-y)
 
@@ -93,6 +94,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-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX))
 common-obj-y += readline.o console.o cursor.o
 common-obj-y += $(oslib-obj-y)
@@ -200,6 +202,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)
 
 ######################################################################
 # libhw
diff --git a/configure b/configure
index fe4fc4f..afe7395 100755
--- a/configure
+++ b/configure
@@ -3921,6 +3921,7 @@ fi
 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/include/qemu/cpu.h b/include/qemu/cpu.h
new file mode 100644
index 0000000..4291279
--- /dev/null
+++ b/include/qemu/cpu.h
@@ -0,0 +1,75 @@
+/*
+ * QEMU CPU model
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
+ */
+#ifndef QEMU_CPU_H
+#define QEMU_CPU_H
+
+#include "qemu/object.h"
+
+/**
+ * SECTION:cpu
+ * @section_id: QEMU-cpu
+ * @title: CPU Class
+ * @short_description: Base class for all CPUs
+ */
+
+#define TYPE_CPU "cpu"
+
+#define CPU(obj) OBJECT_CHECK(CPUState, (obj), TYPE_CPU)
+#define CPU_CLASS(class) OBJECT_CLASS_CHECK(CPUClass, (class), TYPE_CPU)
+#define CPU_GET_CLASS(obj) OBJECT_GET_CLASS(CPUClass, (obj), TYPE_CPU)
+
+typedef struct CPUState CPUState;
+
+/**
+ * CPUClass:
+ * @reset: Callback to reset the #CPU to its initial state.
+ *
+ * Represents a CPU family or model.
+ */
+typedef struct CPUClass {
+    /*< private >*/
+    ObjectClass parent_class;
+    /*< public >*/
+
+    void (*reset)(CPUState *cpu);
+} CPUClass;
+
+/**
+ * CPUState:
+ *
+ * State of one CPU core or thread.
+ */
+struct CPUState {
+    /*< private >*/
+    Object parent_obj;
+    /*< public >*/
+
+    /* TODO Move common fields from CPUState here. */
+};
+
+
+/**
+ * cpu_reset:
+ * @cpu: The CPU whose state is to be reset.
+ */
+void cpu_reset(CPUState *cpu);
+
+
+#endif
diff --git a/qom/Makefile b/qom/Makefile
index 885a263..34c6de5 100644
--- a/qom/Makefile
+++ b/qom/Makefile
@@ -1 +1,2 @@
 qom-y = object.o container.o qom-qobject.o
+qom-twice-y = cpu.o
diff --git a/qom/cpu.c b/qom/cpu.c
new file mode 100644
index 0000000..5b36046
--- /dev/null
+++ b/qom/cpu.c
@@ -0,0 +1,58 @@
+/*
+ * QEMU CPU model
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
+ */
+
+#include "qemu/cpu.h"
+#include "qemu-common.h"
+
+void cpu_reset(CPUState *cpu)
+{
+    CPUClass *klass = CPU_GET_CLASS(cpu);
+
+    if (klass->reset != NULL) {
+        (*klass->reset)(cpu);
+    }
+}
+
+static void cpu_common_reset(CPUState *cpu)
+{
+}
+
+static void cpu_class_init(ObjectClass *klass, void *data)
+{
+    CPUClass *k = CPU_CLASS(klass);
+
+    k->reset = cpu_common_reset;
+}
+
+static TypeInfo cpu_type_info = {
+    .name = TYPE_CPU,
+    .parent = TYPE_OBJECT,
+    .instance_size = sizeof(CPUState),
+    .abstract = true,
+    .class_size = sizeof(CPUClass),
+    .class_init = cpu_class_init,
+};
+
+static void cpu_register_types(void)
+{
+    type_register_static(&cpu_type_info);
+}
+
+type_init(cpu_register_types)
commit 9349b4f9fda360f3d9adc4cf4443a1a9b429c17e
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:32 2012 +0100

    Rename CPUState -> CPUArchState
    
    Scripted conversion:
      for file in *.[hc] hw/*.[hc] hw/kvm/*.[hc] linux-user/*.[hc] linux-user/m68k/*.[hc] bsd-user/*.[hc] darwin-user/*.[hc] tcg/*/*.[hc] target-*/cpu.h; do
        sed -i "s/CPUState/CPUArchState/g" $file
      done
    
    All occurrences of CPUArchState are expected to be replaced by QOM CPUState,
    once all targets are QOM'ified and common fields have been extracted.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/bsd-user/main.c b/bsd-user/main.c
index 78533d5..48cb715 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -70,11 +70,11 @@ int cpu_get_pic_interrupt(CPUX86State *env)
 #endif
 
 /* These are no-ops because we are not threadsafe.  */
-static inline void cpu_exec_start(CPUState *env)
+static inline void cpu_exec_start(CPUArchState *env)
 {
 }
 
-static inline void cpu_exec_end(CPUState *env)
+static inline void cpu_exec_end(CPUArchState *env)
 {
 }
 
@@ -713,7 +713,7 @@ static void usage(void)
     exit(1);
 }
 
-THREAD CPUState *thread_env;
+THREAD CPUArchState *thread_env;
 
 /* Assumes contents are already zeroed.  */
 void init_task_state(TaskState *ts)
@@ -737,7 +737,7 @@ int main(int argc, char **argv)
     struct target_pt_regs regs1, *regs = &regs1;
     struct image_info info1, *info = &info1;
     TaskState ts1, *ts = &ts1;
-    CPUState *env;
+    CPUArchState *env;
     int optind;
     const char *r;
     int gdbstub_port = 0;
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index 1ba2d08..8a5ee3d 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -139,8 +139,8 @@ abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
                             abi_long arg2, abi_long arg3, abi_long arg4,
                             abi_long arg5, abi_long arg6);
 void gemu_log(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
-extern THREAD CPUState *thread_env;
-void cpu_loop(CPUState *env);
+extern THREAD CPUArchState *thread_env;
+void cpu_loop(CPUArchState *env);
 char *target_strerror(int err);
 int get_osversion(void);
 void fork_start(void);
@@ -167,13 +167,13 @@ void print_openbsd_syscall_ret(int num, abi_long ret);
 extern int do_strace;
 
 /* signal.c */
-void process_pending_signals(CPUState *cpu_env);
+void process_pending_signals(CPUArchState *cpu_env);
 void signal_init(void);
-//int queue_signal(CPUState *env, int sig, target_siginfo_t *info);
+//int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info);
 //void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
 //void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
-long do_sigreturn(CPUState *env);
-long do_rt_sigreturn(CPUState *env);
+long do_sigreturn(CPUArchState *env);
+long do_rt_sigreturn(CPUArchState *env);
 abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
 
 /* mmap.c */
diff --git a/bsd-user/signal.c b/bsd-user/signal.c
index 40313c8..445f69e 100644
--- a/bsd-user/signal.c
+++ b/bsd-user/signal.c
@@ -33,6 +33,6 @@ void signal_init(void)
 {
 }
 
-void process_pending_signals(CPUState *cpu_env)
+void process_pending_signals(CPUArchState *cpu_env)
 {
 }
diff --git a/cpu-all.h b/cpu-all.h
index e831ae0..8ad1ec7 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -322,20 +322,20 @@ void page_set_flags(target_ulong start, target_ulong end, int flags);
 int page_check_range(target_ulong start, target_ulong len, int flags);
 #endif
 
-CPUState *cpu_copy(CPUState *env);
-CPUState *qemu_get_cpu(int cpu);
+CPUArchState *cpu_copy(CPUArchState *env);
+CPUArchState *qemu_get_cpu(int cpu);
 
 #define CPU_DUMP_CODE 0x00010000
 
-void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
+void cpu_dump_state(CPUArchState *env, FILE *f, fprintf_function cpu_fprintf,
                     int flags);
-void cpu_dump_statistics(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
+void cpu_dump_statistics(CPUArchState *env, FILE *f, fprintf_function cpu_fprintf,
                          int flags);
 
-void QEMU_NORETURN cpu_abort(CPUState *env, const char *fmt, ...)
+void QEMU_NORETURN cpu_abort(CPUArchState *env, const char *fmt, ...)
     GCC_FMT_ATTR(2, 3);
-extern CPUState *first_cpu;
-DECLARE_TLS(CPUState *,cpu_single_env);
+extern CPUArchState *first_cpu;
+DECLARE_TLS(CPUArchState *,cpu_single_env);
 #define cpu_single_env tls_var(cpu_single_env)
 
 /* Flags for use in ENV->INTERRUPT_PENDING.
@@ -389,23 +389,23 @@ DECLARE_TLS(CPUState *,cpu_single_env);
      | CPU_INTERRUPT_TGT_EXT_4)
 
 #ifndef CONFIG_USER_ONLY
-typedef void (*CPUInterruptHandler)(CPUState *, int);
+typedef void (*CPUInterruptHandler)(CPUArchState *, int);
 
 extern CPUInterruptHandler cpu_interrupt_handler;
 
-static inline void cpu_interrupt(CPUState *s, int mask)
+static inline void cpu_interrupt(CPUArchState *s, int mask)
 {
     cpu_interrupt_handler(s, mask);
 }
 #else /* USER_ONLY */
-void cpu_interrupt(CPUState *env, int mask);
+void cpu_interrupt(CPUArchState *env, int mask);
 #endif /* USER_ONLY */
 
-void cpu_reset_interrupt(CPUState *env, int mask);
+void cpu_reset_interrupt(CPUArchState *env, int mask);
 
-void cpu_exit(CPUState *s);
+void cpu_exit(CPUArchState *s);
 
-bool qemu_cpu_has_work(CPUState *env);
+bool qemu_cpu_has_work(CPUArchState *env);
 
 /* Breakpoint/watchpoint flags */
 #define BP_MEM_READ           0x01
@@ -416,26 +416,26 @@ bool qemu_cpu_has_work(CPUState *env);
 #define BP_GDB                0x10
 #define BP_CPU                0x20
 
-int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags,
+int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
                           CPUBreakpoint **breakpoint);
-int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags);
-void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint);
-void cpu_breakpoint_remove_all(CPUState *env, int mask);
-int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len,
+int cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags);
+void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint);
+void cpu_breakpoint_remove_all(CPUArchState *env, int mask);
+int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
                           int flags, CPUWatchpoint **watchpoint);
-int cpu_watchpoint_remove(CPUState *env, target_ulong addr,
+int cpu_watchpoint_remove(CPUArchState *env, target_ulong addr,
                           target_ulong len, int flags);
-void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint);
-void cpu_watchpoint_remove_all(CPUState *env, int mask);
+void cpu_watchpoint_remove_by_ref(CPUArchState *env, CPUWatchpoint *watchpoint);
+void cpu_watchpoint_remove_all(CPUArchState *env, int mask);
 
 #define SSTEP_ENABLE  0x1  /* Enable simulated HW single stepping */
 #define SSTEP_NOIRQ   0x2  /* Do not use IRQ while single stepping */
 #define SSTEP_NOTIMER 0x4  /* Do not Timers while single stepping */
 
-void cpu_single_step(CPUState *env, int enabled);
-void cpu_state_reset(CPUState *s);
-int cpu_is_stopped(CPUState *env);
-void run_on_cpu(CPUState *env, void (*func)(void *data), void *data);
+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);
 
 #define CPU_LOG_TB_OUT_ASM (1 << 0)
 #define CPU_LOG_TB_IN_ASM  (1 << 1)
@@ -466,7 +466,7 @@ int cpu_str_to_log_mask(const char *str);
 /* Return the physical page corresponding to a virtual one. Use it
    only for debugging because no protection checks are done. Return -1
    if no page found. */
-target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr);
+target_phys_addr_t cpu_get_phys_page_debug(CPUArchState *env, target_ulong addr);
 
 /* memory API */
 
@@ -508,12 +508,12 @@ extern int mem_prealloc;
 /* Set if TLB entry is an IO callback.  */
 #define TLB_MMIO        (1 << 5)
 
-void cpu_tlb_update_dirty(CPUState *env);
+void cpu_tlb_update_dirty(CPUArchState *env);
 
 void dump_exec_info(FILE *f, fprintf_function cpu_fprintf);
 #endif /* !CONFIG_USER_ONLY */
 
-int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
+int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr,
                         uint8_t *buf, int len, int is_write);
 
 #endif /* CPU_ALL_H */
diff --git a/cpu-defs.h b/cpu-defs.h
index 4527cbf..3268968 100644
--- a/cpu-defs.h
+++ b/cpu-defs.h
@@ -202,7 +202,7 @@ typedef struct CPUWatchpoint {
     jmp_buf jmp_env;                                                    \
     int exception_index;                                                \
                                                                         \
-    CPUState *next_cpu; /* next CPU sharing TB cache */                 \
+    CPUArchState *next_cpu; /* next CPU sharing TB cache */                 \
     int cpu_index; /* CPU index (informative) */                        \
     uint32_t host_tid; /* host thread ID */                             \
     int numa_node; /* NUMA node this cpu is belonging to  */            \
diff --git a/cpu-exec.c b/cpu-exec.c
index 2bf1735..bd5791f 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -26,12 +26,12 @@ int tb_invalidated_flag;
 
 //#define CONFIG_DEBUG_EXEC
 
-bool qemu_cpu_has_work(CPUState *env)
+bool qemu_cpu_has_work(CPUArchState *env)
 {
     return cpu_has_work(env);
 }
 
-void cpu_loop_exit(CPUState *env)
+void cpu_loop_exit(CPUArchState *env)
 {
     env->current_tb = NULL;
     longjmp(env->jmp_env, 1);
@@ -41,7 +41,7 @@ void cpu_loop_exit(CPUState *env)
    restored in a state compatible with the CPU emulator
  */
 #if defined(CONFIG_SOFTMMU)
-void cpu_resume_from_signal(CPUState *env, void *puc)
+void cpu_resume_from_signal(CPUArchState *env, void *puc)
 {
     /* XXX: restore cpu registers saved in host registers */
 
@@ -52,7 +52,7 @@ void cpu_resume_from_signal(CPUState *env, void *puc)
 
 /* Execute the code without caching the generated code. An interpreter
    could be used if available. */
-static void cpu_exec_nocache(CPUState *env, int max_cycles,
+static void cpu_exec_nocache(CPUArchState *env, int max_cycles,
                              TranslationBlock *orig_tb)
 {
     unsigned long next_tb;
@@ -79,7 +79,7 @@ static void cpu_exec_nocache(CPUState *env, int max_cycles,
     tb_free(tb);
 }
 
-static TranslationBlock *tb_find_slow(CPUState *env,
+static TranslationBlock *tb_find_slow(CPUArchState *env,
                                       target_ulong pc,
                                       target_ulong cs_base,
                                       uint64_t flags)
@@ -135,7 +135,7 @@ static TranslationBlock *tb_find_slow(CPUState *env,
     return tb;
 }
 
-static inline TranslationBlock *tb_find_fast(CPUState *env)
+static inline TranslationBlock *tb_find_fast(CPUArchState *env)
 {
     TranslationBlock *tb;
     target_ulong cs_base, pc;
@@ -163,7 +163,7 @@ CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
     return old_handler;
 }
 
-static void cpu_handle_debug_exception(CPUState *env)
+static void cpu_handle_debug_exception(CPUArchState *env)
 {
     CPUWatchpoint *wp;
 
@@ -181,7 +181,7 @@ static void cpu_handle_debug_exception(CPUState *env)
 
 volatile sig_atomic_t exit_request;
 
-int cpu_exec(CPUState *env)
+int cpu_exec(CPUArchState *env)
 {
     int ret, interrupt_request;
     TranslationBlock *tb;
diff --git a/cpus.c b/cpus.c
index 17b055f..25ba621 100644
--- a/cpus.c
+++ b/cpus.c
@@ -58,7 +58,7 @@
 
 #endif /* CONFIG_LINUX */
 
-static CPUState *next_cpu;
+static CPUArchState *next_cpu;
 
 /***********************************************************/
 /* guest cycle counter */
@@ -89,7 +89,7 @@ TimersState timers_state;
 int64_t cpu_get_icount(void)
 {
     int64_t icount;
-    CPUState *env = cpu_single_env;
+    CPUArchState *env = cpu_single_env;
 
     icount = qemu_icount;
     if (env) {
@@ -339,7 +339,7 @@ void configure_icount(const char *option)
 void hw_error(const char *fmt, ...)
 {
     va_list ap;
-    CPUState *env;
+    CPUArchState *env;
 
     va_start(ap, fmt);
     fprintf(stderr, "qemu: hardware error: ");
@@ -359,7 +359,7 @@ void hw_error(const char *fmt, ...)
 
 void cpu_synchronize_all_states(void)
 {
-    CPUState *cpu;
+    CPUArchState *cpu;
 
     for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) {
         cpu_synchronize_state(cpu);
@@ -368,7 +368,7 @@ void cpu_synchronize_all_states(void)
 
 void cpu_synchronize_all_post_reset(void)
 {
-    CPUState *cpu;
+    CPUArchState *cpu;
 
     for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) {
         cpu_synchronize_post_reset(cpu);
@@ -377,14 +377,14 @@ void cpu_synchronize_all_post_reset(void)
 
 void cpu_synchronize_all_post_init(void)
 {
-    CPUState *cpu;
+    CPUArchState *cpu;
 
     for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) {
         cpu_synchronize_post_init(cpu);
     }
 }
 
-int cpu_is_stopped(CPUState *env)
+int cpu_is_stopped(CPUArchState *env)
 {
     return !runstate_is_running() || env->stopped;
 }
@@ -402,7 +402,7 @@ static void do_vm_stop(RunState state)
     }
 }
 
-static int cpu_can_run(CPUState *env)
+static int cpu_can_run(CPUArchState *env)
 {
     if (env->stop) {
         return 0;
@@ -413,7 +413,7 @@ static int cpu_can_run(CPUState *env)
     return 1;
 }
 
-static bool cpu_thread_is_idle(CPUState *env)
+static bool cpu_thread_is_idle(CPUArchState *env)
 {
     if (env->stop || env->queued_work_first) {
         return false;
@@ -430,7 +430,7 @@ static bool cpu_thread_is_idle(CPUState *env)
 
 bool all_cpu_threads_idle(void)
 {
-    CPUState *env;
+    CPUArchState *env;
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
         if (!cpu_thread_is_idle(env)) {
@@ -440,7 +440,7 @@ bool all_cpu_threads_idle(void)
     return true;
 }
 
-static void cpu_handle_guest_debug(CPUState *env)
+static void cpu_handle_guest_debug(CPUArchState *env)
 {
     gdb_set_stop_cpu(env);
     qemu_system_debug_request();
@@ -494,7 +494,7 @@ static void qemu_init_sigbus(void)
     prctl(PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_EARLY, 0, 0);
 }
 
-static void qemu_kvm_eat_signals(CPUState *env)
+static void qemu_kvm_eat_signals(CPUArchState *env)
 {
     struct timespec ts = { 0, 0 };
     siginfo_t siginfo;
@@ -537,7 +537,7 @@ static void qemu_init_sigbus(void)
 {
 }
 
-static void qemu_kvm_eat_signals(CPUState *env)
+static void qemu_kvm_eat_signals(CPUArchState *env)
 {
 }
 #endif /* !CONFIG_LINUX */
@@ -547,7 +547,7 @@ static void dummy_signal(int sig)
 {
 }
 
-static void qemu_kvm_init_cpu_signals(CPUState *env)
+static void qemu_kvm_init_cpu_signals(CPUArchState *env)
 {
     int r;
     sigset_t set;
@@ -582,7 +582,7 @@ static void qemu_tcg_init_cpu_signals(void)
 }
 
 #else /* _WIN32 */
-static void qemu_kvm_init_cpu_signals(CPUState *env)
+static void qemu_kvm_init_cpu_signals(CPUArchState *env)
 {
     abort();
 }
@@ -619,7 +619,7 @@ void qemu_init_cpu_loop(void)
     qemu_thread_get_self(&io_thread);
 }
 
-void run_on_cpu(CPUState *env, void (*func)(void *data), void *data)
+void run_on_cpu(CPUArchState *env, void (*func)(void *data), void *data)
 {
     struct qemu_work_item wi;
 
@@ -641,14 +641,14 @@ void run_on_cpu(CPUState *env, void (*func)(void *data), void *data)
 
     qemu_cpu_kick(env);
     while (!wi.done) {
-        CPUState *self_env = cpu_single_env;
+        CPUArchState *self_env = cpu_single_env;
 
         qemu_cond_wait(&qemu_work_cond, &qemu_global_mutex);
         cpu_single_env = self_env;
     }
 }
 
-static void flush_queued_work(CPUState *env)
+static void flush_queued_work(CPUArchState *env)
 {
     struct qemu_work_item *wi;
 
@@ -665,7 +665,7 @@ static void flush_queued_work(CPUState *env)
     qemu_cond_broadcast(&qemu_work_cond);
 }
 
-static void qemu_wait_io_event_common(CPUState *env)
+static void qemu_wait_io_event_common(CPUArchState *env)
 {
     if (env->stop) {
         env->stop = 0;
@@ -678,7 +678,7 @@ static void qemu_wait_io_event_common(CPUState *env)
 
 static void qemu_tcg_wait_io_event(void)
 {
-    CPUState *env;
+    CPUArchState *env;
 
     while (all_cpu_threads_idle()) {
        /* Start accounting real time to the virtual clock if the CPUs
@@ -696,7 +696,7 @@ static void qemu_tcg_wait_io_event(void)
     }
 }
 
-static void qemu_kvm_wait_io_event(CPUState *env)
+static void qemu_kvm_wait_io_event(CPUArchState *env)
 {
     while (cpu_thread_is_idle(env)) {
         qemu_cond_wait(env->halt_cond, &qemu_global_mutex);
@@ -708,7 +708,7 @@ static void qemu_kvm_wait_io_event(CPUState *env)
 
 static void *qemu_kvm_cpu_thread_fn(void *arg)
 {
-    CPUState *env = arg;
+    CPUArchState *env = arg;
     int r;
 
     qemu_mutex_lock(&qemu_global_mutex);
@@ -745,7 +745,7 @@ static void tcg_exec_all(void);
 
 static void *qemu_tcg_cpu_thread_fn(void *arg)
 {
-    CPUState *env = arg;
+    CPUArchState *env = arg;
 
     qemu_tcg_init_cpu_signals();
     qemu_thread_get_self(env->thread);
@@ -779,7 +779,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
     return NULL;
 }
 
-static void qemu_cpu_kick_thread(CPUState *env)
+static void qemu_cpu_kick_thread(CPUArchState *env)
 {
 #ifndef _WIN32
     int err;
@@ -800,7 +800,7 @@ static void qemu_cpu_kick_thread(CPUState *env)
 
 void qemu_cpu_kick(void *_env)
 {
-    CPUState *env = _env;
+    CPUArchState *env = _env;
 
     qemu_cond_broadcast(env->halt_cond);
     if (kvm_enabled() && !env->thread_kicked) {
@@ -825,7 +825,7 @@ void qemu_cpu_kick_self(void)
 
 int qemu_cpu_is_self(void *_env)
 {
-    CPUState *env = _env;
+    CPUArchState *env = _env;
 
     return qemu_thread_is_self(env->thread);
 }
@@ -852,7 +852,7 @@ void qemu_mutex_unlock_iothread(void)
 
 static int all_vcpus_paused(void)
 {
-    CPUState *penv = first_cpu;
+    CPUArchState *penv = first_cpu;
 
     while (penv) {
         if (!penv->stopped) {
@@ -866,7 +866,7 @@ static int all_vcpus_paused(void)
 
 void pause_all_vcpus(void)
 {
-    CPUState *penv = first_cpu;
+    CPUArchState *penv = first_cpu;
 
     qemu_clock_enable(vm_clock, false);
     while (penv) {
@@ -899,7 +899,7 @@ void pause_all_vcpus(void)
 
 void resume_all_vcpus(void)
 {
-    CPUState *penv = first_cpu;
+    CPUArchState *penv = first_cpu;
 
     qemu_clock_enable(vm_clock, true);
     while (penv) {
@@ -912,7 +912,7 @@ void resume_all_vcpus(void)
 
 static void qemu_tcg_init_vcpu(void *_env)
 {
-    CPUState *env = _env;
+    CPUArchState *env = _env;
 
     /* share a single thread for all cpus with TCG */
     if (!tcg_cpu_thread) {
@@ -935,7 +935,7 @@ static void qemu_tcg_init_vcpu(void *_env)
     }
 }
 
-static void qemu_kvm_start_vcpu(CPUState *env)
+static void qemu_kvm_start_vcpu(CPUArchState *env)
 {
     env->thread = g_malloc0(sizeof(QemuThread));
     env->halt_cond = g_malloc0(sizeof(QemuCond));
@@ -949,7 +949,7 @@ static void qemu_kvm_start_vcpu(CPUState *env)
 
 void qemu_init_vcpu(void *_env)
 {
-    CPUState *env = _env;
+    CPUArchState *env = _env;
 
     env->nr_cores = smp_cores;
     env->nr_threads = smp_threads;
@@ -996,7 +996,7 @@ void vm_stop_force_state(RunState state)
     }
 }
 
-static int tcg_cpu_exec(CPUState *env)
+static int tcg_cpu_exec(CPUArchState *env)
 {
     int ret;
 #ifdef CONFIG_PROFILER
@@ -1045,7 +1045,7 @@ static void tcg_exec_all(void)
         next_cpu = first_cpu;
     }
     for (; next_cpu != NULL && !exit_request; next_cpu = next_cpu->next_cpu) {
-        CPUState *env = next_cpu;
+        CPUArchState *env = next_cpu;
 
         qemu_clock_enable(vm_clock,
                           (env->singlestep_enabled & SSTEP_NOTIMER) == 0);
@@ -1065,7 +1065,7 @@ static void tcg_exec_all(void)
 
 void set_numa_modes(void)
 {
-    CPUState *env;
+    CPUArchState *env;
     int i;
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
@@ -1111,7 +1111,7 @@ void list_cpus(FILE *f, fprintf_function cpu_fprintf, const char *optarg)
 CpuInfoList *qmp_query_cpus(Error **errp)
 {
     CpuInfoList *head = NULL, *cur_item = NULL;
-    CPUState *env;
+    CPUArchState *env;
 
     for(env = first_cpu; env != NULL; env = env->next_cpu) {
         CpuInfoList *info;
@@ -1157,7 +1157,7 @@ void qmp_memsave(int64_t addr, int64_t size, const char *filename,
 {
     FILE *f;
     uint32_t l;
-    CPUState *env;
+    CPUArchState *env;
     uint8_t buf[1024];
 
     if (!has_cpu) {
@@ -1232,7 +1232,7 @@ exit:
 void qmp_inject_nmi(Error **errp)
 {
 #if defined(TARGET_I386)
-    CPUState *env;
+    CPUArchState *env;
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
         if (!env->apic_state) {
diff --git a/darwin-user/main.c b/darwin-user/main.c
index f5cadc7..544e219 100644
--- a/darwin-user/main.c
+++ b/darwin-user/main.c
@@ -71,7 +71,7 @@ void gemu_log(const char *fmt, ...)
     va_end(ap);
 }
 
-int cpu_get_pic_interrupt(CPUState *env)
+int cpu_get_pic_interrupt(CPUArchState *env)
 {
     return -1;
 }
@@ -729,7 +729,7 @@ static void usage(void)
 }
 
 /* XXX: currently only used for async signals (see signal.c) */
-CPUState *global_env;
+CPUArchState *global_env;
 
 /* used to free thread contexts */
 TaskState *first_task_state;
@@ -741,7 +741,7 @@ int main(int argc, char **argv)
     const char *log_mask = NULL;
     struct target_pt_regs regs1, *regs = &regs1;
     TaskState ts1, *ts = &ts1;
-    CPUState *env;
+    CPUArchState *env;
     int optind;
     short use_gdbstub = 0;
     const char *r;
diff --git a/darwin-user/qemu.h b/darwin-user/qemu.h
index b6d3e6c..9e16c8e 100644
--- a/darwin-user/qemu.h
+++ b/darwin-user/qemu.h
@@ -104,8 +104,8 @@ void qerror(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
 
 void write_dt(void *ptr, unsigned long addr, unsigned long limit, int flags);
 
-extern CPUState *global_env;
-void cpu_loop(CPUState *env);
+extern CPUArchState *global_env;
+void cpu_loop(CPUArchState *env);
 void init_paths(const char *prefix);
 const char *path(const char *pathname);
 
@@ -122,7 +122,7 @@ void signal_init(void);
 int queue_signal(int sig, target_siginfo_t *info);
 void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
 void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
-long do_sigreturn(CPUState *env, int num);
+long do_sigreturn(CPUArchState *env, int num);
 
 /* machload.c */
 int mach_exec(const char * filename, char ** argv, char ** envp,
diff --git a/darwin-user/signal.c b/darwin-user/signal.c
index 8f9705d..489cb64 100644
--- a/darwin-user/signal.c
+++ b/darwin-user/signal.c
@@ -377,12 +377,12 @@ long do_sigreturn(CPUX86State *env, int num)
 #else
 
 static void setup_frame(int sig, struct emulated_sigaction *ka,
-			void *set, CPUState *env)
+			void *set, CPUArchState *env)
 {
     fprintf(stderr, "setup_frame: not implemented\n");
 }
 
-long do_sigreturn(CPUState *env, int num)
+long do_sigreturn(CPUArchState *env, int num)
 {
     int i = 0;
     struct target_sigcontext *scp = get_int_arg(&i, env);
diff --git a/def-helper.h b/def-helper.h
index 8a822c7..5d057d6 100644
--- a/def-helper.h
+++ b/def-helper.h
@@ -52,7 +52,7 @@
 #define dh_ctype_tl target_ulong
 #define dh_ctype_ptr void *
 #define dh_ctype_void void
-#define dh_ctype_env CPUState *
+#define dh_ctype_env CPUArchState *
 #define dh_ctype(t) dh_ctype_##t
 
 /* We can't use glue() here because it falls foul of C preprocessor
diff --git a/disas.c b/disas.c
index 3b1fd97..4945c44 100644
--- a/disas.c
+++ b/disas.c
@@ -339,7 +339,7 @@ const char *lookup_symbol(target_ulong orig_addr)
 #include "monitor.h"
 
 static int monitor_disas_is_physical;
-static CPUState *monitor_disas_env;
+static CPUArchState *monitor_disas_env;
 
 static int
 monitor_read_memory (bfd_vma memaddr, bfd_byte *myaddr, int length,
@@ -363,7 +363,7 @@ monitor_fprintf(FILE *stream, const char *fmt, ...)
     return 0;
 }
 
-void monitor_disas(Monitor *mon, CPUState *env,
+void monitor_disas(Monitor *mon, CPUArchState *env,
                    target_ulong pc, int nb_insn, int is_physical, int flags)
 {
     int count, i;
diff --git a/disas.h b/disas.h
index f9287f7..3ab42af 100644
--- a/disas.h
+++ b/disas.h
@@ -8,7 +8,7 @@
 void disas(FILE *out, void *code, unsigned long size);
 void target_disas(FILE *out, target_ulong code, target_ulong size, int flags);
 
-void monitor_disas(Monitor *mon, CPUState *env,
+void monitor_disas(Monitor *mon, CPUArchState *env,
                    target_ulong pc, int nb_insn, int is_physical, int flags);
 
 /* Look up symbol for debugging purpose.  Returns "" if unknown. */
diff --git a/dyngen-exec.h b/dyngen-exec.h
index 09be9ea..083e20b 100644
--- a/dyngen-exec.h
+++ b/dyngen-exec.h
@@ -61,10 +61,10 @@
 #endif
 
 #if defined(AREG0)
-register CPUState *env asm(AREG0);
+register CPUArchState *env asm(AREG0);
 #else
 /* TODO: Try env = cpu_single_env. */
-extern CPUState *env;
+extern CPUArchState *env;
 #endif
 
 #endif /* !defined(__DYNGEN_EXEC_H__) */
diff --git a/exec-all.h b/exec-all.h
index 3ec60a2..8fca67b 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -76,30 +76,30 @@ extern uint16_t gen_opc_icount[OPC_BUF_SIZE];
 
 #include "qemu-log.h"
 
-void gen_intermediate_code(CPUState *env, struct TranslationBlock *tb);
-void gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb);
-void restore_state_to_opc(CPUState *env, struct TranslationBlock *tb,
+void gen_intermediate_code(CPUArchState *env, struct TranslationBlock *tb);
+void gen_intermediate_code_pc(CPUArchState *env, struct TranslationBlock *tb);
+void restore_state_to_opc(CPUArchState *env, struct TranslationBlock *tb,
                           int pc_pos);
 
 void cpu_gen_init(void);
-int cpu_gen_code(CPUState *env, struct TranslationBlock *tb,
+int cpu_gen_code(CPUArchState *env, struct TranslationBlock *tb,
                  int *gen_code_size_ptr);
 int cpu_restore_state(struct TranslationBlock *tb,
-                      CPUState *env, unsigned long searched_pc);
-void cpu_resume_from_signal(CPUState *env1, void *puc);
-void cpu_io_recompile(CPUState *env, void *retaddr);
-TranslationBlock *tb_gen_code(CPUState *env, 
+                      CPUArchState *env, unsigned long searched_pc);
+void cpu_resume_from_signal(CPUArchState *env1, void *puc);
+void cpu_io_recompile(CPUArchState *env, void *retaddr);
+TranslationBlock *tb_gen_code(CPUArchState *env, 
                               target_ulong pc, target_ulong cs_base, int flags,
                               int cflags);
-void cpu_exec_init(CPUState *env);
-void QEMU_NORETURN cpu_loop_exit(CPUState *env1);
+void cpu_exec_init(CPUArchState *env);
+void QEMU_NORETURN cpu_loop_exit(CPUArchState *env1);
 int page_unprotect(target_ulong address, unsigned long pc, void *puc);
 void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
                                    int is_cpu_write_access);
-void tlb_flush_page(CPUState *env, target_ulong addr);
-void tlb_flush(CPUState *env, int flush_global);
+void tlb_flush_page(CPUArchState *env, target_ulong addr);
+void tlb_flush(CPUArchState *env, int flush_global);
 #if !defined(CONFIG_USER_ONLY)
-void tlb_set_page(CPUState *env, target_ulong vaddr,
+void tlb_set_page(CPUArchState *env, target_ulong vaddr,
                   target_phys_addr_t paddr, int prot,
                   int mmu_idx, target_ulong size);
 #endif
@@ -182,7 +182,7 @@ static inline unsigned int tb_phys_hash_func(tb_page_addr_t pc)
 }
 
 void tb_free(TranslationBlock *tb);
-void tb_flush(CPUState *env);
+void tb_flush(CPUArchState *env);
 void tb_link_page(TranslationBlock *tb,
                   tb_page_addr_t phys_pc, tb_page_addr_t phys_page2);
 void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr);
@@ -305,7 +305,7 @@ uint64_t io_mem_read(struct MemoryRegion *mr, target_phys_addr_t addr,
 void io_mem_write(struct MemoryRegion *mr, target_phys_addr_t addr,
                   uint64_t value, unsigned size);
 
-void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
+void tlb_fill(CPUArchState *env1, target_ulong addr, int is_write, int mmu_idx,
               void *retaddr);
 
 #include "softmmu_defs.h"
@@ -333,15 +333,15 @@ void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
 #endif
 
 #if defined(CONFIG_USER_ONLY)
-static inline tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong addr)
+static inline tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
 {
     return addr;
 }
 #else
-tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong addr);
+tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr);
 #endif
 
-typedef void (CPUDebugExcpHandler)(CPUState *env);
+typedef void (CPUDebugExcpHandler)(CPUArchState *env);
 
 CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler);
 
@@ -353,7 +353,7 @@ extern volatile sig_atomic_t exit_request;
 
 /* Deterministic execution requires that IO only be performed on the last
    instruction of a TB so that interrupts take effect immediately.  */
-static inline int can_do_io(CPUState *env)
+static inline int can_do_io(CPUArchState *env)
 {
     if (!use_icount) {
         return 1;
diff --git a/exec.c b/exec.c
index 0c86bce..8fd50a1 100644
--- a/exec.c
+++ b/exec.c
@@ -123,10 +123,10 @@ static MemoryRegion io_mem_subpage_ram;
 
 #endif
 
-CPUState *first_cpu;
+CPUArchState *first_cpu;
 /* current CPU in the current thread. It is only valid inside
    cpu_exec() */
-DEFINE_TLS(CPUState *,cpu_single_env);
+DEFINE_TLS(CPUArchState *,cpu_single_env);
 /* 0 = Do not count executed instructions.
    1 = Precise instruction counting.
    2 = Adaptive rate instruction counting.  */
@@ -509,7 +509,7 @@ static target_phys_addr_t section_addr(MemoryRegionSection *section,
 }
 
 static void tlb_protect_code(ram_addr_t ram_addr);
-static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
+static void tlb_unprotect_code_phys(CPUArchState *env, ram_addr_t ram_addr,
                                     target_ulong vaddr);
 #define mmap_lock() do { } while(0)
 #define mmap_unlock() do { } while(0)
@@ -661,7 +661,7 @@ void cpu_exec_init_all(void)
 
 static int cpu_common_post_load(void *opaque, int version_id)
 {
-    CPUState *env = opaque;
+    CPUArchState *env = opaque;
 
     /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
        version_id is increased. */
@@ -678,16 +678,16 @@ static const VMStateDescription vmstate_cpu_common = {
     .minimum_version_id_old = 1,
     .post_load = cpu_common_post_load,
     .fields      = (VMStateField []) {
-        VMSTATE_UINT32(halted, CPUState),
-        VMSTATE_UINT32(interrupt_request, CPUState),
+        VMSTATE_UINT32(halted, CPUArchState),
+        VMSTATE_UINT32(interrupt_request, CPUArchState),
         VMSTATE_END_OF_LIST()
     }
 };
 #endif
 
-CPUState *qemu_get_cpu(int cpu)
+CPUArchState *qemu_get_cpu(int cpu)
 {
-    CPUState *env = first_cpu;
+    CPUArchState *env = first_cpu;
 
     while (env) {
         if (env->cpu_index == cpu)
@@ -698,9 +698,9 @@ CPUState *qemu_get_cpu(int cpu)
     return env;
 }
 
-void cpu_exec_init(CPUState *env)
+void cpu_exec_init(CPUArchState *env)
 {
-    CPUState **penv;
+    CPUArchState **penv;
     int cpu_index;
 
 #if defined(CONFIG_USER_ONLY)
@@ -799,9 +799,9 @@ static void page_flush_tb(void)
 
 /* flush all the translation blocks */
 /* XXX: tb_flush is currently not thread safe */
-void tb_flush(CPUState *env1)
+void tb_flush(CPUArchState *env1)
 {
-    CPUState *env;
+    CPUArchState *env;
 #if defined(DEBUG_FLUSH)
     printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
            (unsigned long)(code_gen_ptr - code_gen_buffer),
@@ -934,7 +934,7 @@ static inline void tb_reset_jump(TranslationBlock *tb, int n)
 
 void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
 {
-    CPUState *env;
+    CPUArchState *env;
     PageDesc *p;
     unsigned int h, n1;
     tb_page_addr_t phys_pc;
@@ -1043,7 +1043,7 @@ static void build_page_bitmap(PageDesc *p)
     }
 }
 
-TranslationBlock *tb_gen_code(CPUState *env,
+TranslationBlock *tb_gen_code(CPUArchState *env,
                               target_ulong pc, target_ulong cs_base,
                               int flags, int cflags)
 {
@@ -1090,7 +1090,7 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
                                    int is_cpu_write_access)
 {
     TranslationBlock *tb, *tb_next, *saved_tb;
-    CPUState *env = cpu_single_env;
+    CPUArchState *env = cpu_single_env;
     tb_page_addr_t tb_start, tb_end;
     PageDesc *p;
     int n;
@@ -1227,7 +1227,7 @@ static void tb_invalidate_phys_page(tb_page_addr_t addr,
     int n;
 #ifdef TARGET_HAS_PRECISE_SMC
     TranslationBlock *current_tb = NULL;
-    CPUState *env = cpu_single_env;
+    CPUArchState *env = cpu_single_env;
     int current_tb_modified = 0;
     target_ulong current_pc = 0;
     target_ulong current_cs_base = 0;
@@ -1457,12 +1457,12 @@ static void tb_reset_jump_recursive(TranslationBlock *tb)
 
 #if defined(TARGET_HAS_ICE)
 #if defined(CONFIG_USER_ONLY)
-static void breakpoint_invalidate(CPUState *env, target_ulong pc)
+static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
 {
     tb_invalidate_phys_page_range(pc, pc + 1, 0);
 }
 #else
-static void breakpoint_invalidate(CPUState *env, target_ulong pc)
+static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
 {
     target_phys_addr_t addr;
     ram_addr_t ram_addr;
@@ -1482,19 +1482,19 @@ static void breakpoint_invalidate(CPUState *env, target_ulong pc)
 #endif /* TARGET_HAS_ICE */
 
 #if defined(CONFIG_USER_ONLY)
-void cpu_watchpoint_remove_all(CPUState *env, int mask)
+void cpu_watchpoint_remove_all(CPUArchState *env, int mask)
 
 {
 }
 
-int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len,
+int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
                           int flags, CPUWatchpoint **watchpoint)
 {
     return -ENOSYS;
 }
 #else
 /* Add a watchpoint.  */
-int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len,
+int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
                           int flags, CPUWatchpoint **watchpoint)
 {
     target_ulong len_mask = ~(len - 1);
@@ -1527,7 +1527,7 @@ int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len,
 }
 
 /* Remove a specific watchpoint.  */
-int cpu_watchpoint_remove(CPUState *env, target_ulong addr, target_ulong len,
+int cpu_watchpoint_remove(CPUArchState *env, target_ulong addr, target_ulong len,
                           int flags)
 {
     target_ulong len_mask = ~(len - 1);
@@ -1544,7 +1544,7 @@ int cpu_watchpoint_remove(CPUState *env, target_ulong addr, target_ulong len,
 }
 
 /* Remove a specific watchpoint by reference.  */
-void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint)
+void cpu_watchpoint_remove_by_ref(CPUArchState *env, CPUWatchpoint *watchpoint)
 {
     QTAILQ_REMOVE(&env->watchpoints, watchpoint, entry);
 
@@ -1554,7 +1554,7 @@ void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint)
 }
 
 /* Remove all matching watchpoints.  */
-void cpu_watchpoint_remove_all(CPUState *env, int mask)
+void cpu_watchpoint_remove_all(CPUArchState *env, int mask)
 {
     CPUWatchpoint *wp, *next;
 
@@ -1566,7 +1566,7 @@ void cpu_watchpoint_remove_all(CPUState *env, int mask)
 #endif
 
 /* Add a breakpoint.  */
-int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags,
+int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
                           CPUBreakpoint **breakpoint)
 {
 #if defined(TARGET_HAS_ICE)
@@ -1594,7 +1594,7 @@ int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags,
 }
 
 /* Remove a specific breakpoint.  */
-int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags)
+int cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags)
 {
 #if defined(TARGET_HAS_ICE)
     CPUBreakpoint *bp;
@@ -1612,7 +1612,7 @@ int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags)
 }
 
 /* Remove a specific breakpoint by reference.  */
-void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint)
+void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint)
 {
 #if defined(TARGET_HAS_ICE)
     QTAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
@@ -1624,7 +1624,7 @@ void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint)
 }
 
 /* Remove all matching breakpoints. */
-void cpu_breakpoint_remove_all(CPUState *env, int mask)
+void cpu_breakpoint_remove_all(CPUArchState *env, int mask)
 {
 #if defined(TARGET_HAS_ICE)
     CPUBreakpoint *bp, *next;
@@ -1638,7 +1638,7 @@ void cpu_breakpoint_remove_all(CPUState *env, int mask)
 
 /* enable or disable single step mode. EXCP_DEBUG is returned by the
    CPU loop after each instruction */
-void cpu_single_step(CPUState *env, int enabled)
+void cpu_single_step(CPUArchState *env, int enabled)
 {
 #if defined(TARGET_HAS_ICE)
     if (env->singlestep_enabled != enabled) {
@@ -1694,7 +1694,7 @@ void cpu_set_log_filename(const char *filename)
     cpu_set_log(loglevel);
 }
 
-static void cpu_unlink_tb(CPUState *env)
+static void cpu_unlink_tb(CPUArchState *env)
 {
     /* FIXME: TB unchaining isn't SMP safe.  For now just ignore the
        problem and hope the cpu will stop of its own accord.  For userspace
@@ -1716,7 +1716,7 @@ static void cpu_unlink_tb(CPUState *env)
 
 #ifndef CONFIG_USER_ONLY
 /* mask must never be zero, except for A20 change call */
-static void tcg_handle_interrupt(CPUState *env, int mask)
+static void tcg_handle_interrupt(CPUArchState *env, int mask)
 {
     int old_mask;
 
@@ -1747,19 +1747,19 @@ CPUInterruptHandler cpu_interrupt_handler = tcg_handle_interrupt;
 
 #else /* CONFIG_USER_ONLY */
 
-void cpu_interrupt(CPUState *env, int mask)
+void cpu_interrupt(CPUArchState *env, int mask)
 {
     env->interrupt_request |= mask;
     cpu_unlink_tb(env);
 }
 #endif /* CONFIG_USER_ONLY */
 
-void cpu_reset_interrupt(CPUState *env, int mask)
+void cpu_reset_interrupt(CPUArchState *env, int mask)
 {
     env->interrupt_request &= ~mask;
 }
 
-void cpu_exit(CPUState *env)
+void cpu_exit(CPUArchState *env)
 {
     env->exit_request = 1;
     cpu_unlink_tb(env);
@@ -1837,7 +1837,7 @@ int cpu_str_to_log_mask(const char *str)
     return mask;
 }
 
-void cpu_abort(CPUState *env, const char *fmt, ...)
+void cpu_abort(CPUArchState *env, const char *fmt, ...)
 {
     va_list ap;
     va_list ap2;
@@ -1877,17 +1877,17 @@ void cpu_abort(CPUState *env, const char *fmt, ...)
     abort();
 }
 
-CPUState *cpu_copy(CPUState *env)
+CPUArchState *cpu_copy(CPUArchState *env)
 {
-    CPUState *new_env = cpu_init(env->cpu_model_str);
-    CPUState *next_cpu = new_env->next_cpu;
+    CPUArchState *new_env = cpu_init(env->cpu_model_str);
+    CPUArchState *next_cpu = new_env->next_cpu;
     int cpu_index = new_env->cpu_index;
 #if defined(TARGET_HAS_ICE)
     CPUBreakpoint *bp;
     CPUWatchpoint *wp;
 #endif
 
-    memcpy(new_env, env, sizeof(CPUState));
+    memcpy(new_env, env, sizeof(CPUArchState));
 
     /* Preserve chaining and index. */
     new_env->next_cpu = next_cpu;
@@ -1913,7 +1913,7 @@ CPUState *cpu_copy(CPUState *env)
 
 #if !defined(CONFIG_USER_ONLY)
 
-static inline void tlb_flush_jmp_cache(CPUState *env, target_ulong addr)
+static inline void tlb_flush_jmp_cache(CPUArchState *env, target_ulong addr)
 {
     unsigned int i;
 
@@ -1947,7 +1947,7 @@ static CPUTLBEntry s_cputlb_empty_entry = {
  * entries from the TLB at any time, so flushing more entries than
  * required is only an efficiency issue, not a correctness issue.
  */
-void tlb_flush(CPUState *env, int flush_global)
+void tlb_flush(CPUArchState *env, int flush_global)
 {
     int i;
 
@@ -1984,7 +1984,7 @@ static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
     }
 }
 
-void tlb_flush_page(CPUState *env, target_ulong addr)
+void tlb_flush_page(CPUArchState *env, target_ulong addr)
 {
     int i;
     int mmu_idx;
@@ -2025,7 +2025,7 @@ static void tlb_protect_code(ram_addr_t ram_addr)
 
 /* update the TLB so that writes in physical page 'phys_addr' are no longer
    tested for self modifying code */
-static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
+static void tlb_unprotect_code_phys(CPUArchState *env, ram_addr_t ram_addr,
                                     target_ulong vaddr)
 {
     cpu_physical_memory_set_dirty_flags(ram_addr, CODE_DIRTY_FLAG);
@@ -2047,7 +2047,7 @@ static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
 void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
                                      int dirty_flags)
 {
-    CPUState *env;
+    CPUArchState *env;
     unsigned long length, start1;
     int i;
 
@@ -2102,7 +2102,7 @@ static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
 }
 
 /* update the TLB according to the current state of the dirty bits */
-void cpu_tlb_update_dirty(CPUState *env)
+void cpu_tlb_update_dirty(CPUArchState *env)
 {
     int i;
     int mmu_idx;
@@ -2120,7 +2120,7 @@ static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, target_ulong vaddr)
 
 /* update the TLB corresponding to virtual page vaddr
    so that it is no longer dirty */
-static inline void tlb_set_dirty(CPUState *env, target_ulong vaddr)
+static inline void tlb_set_dirty(CPUArchState *env, target_ulong vaddr)
 {
     int i;
     int mmu_idx;
@@ -2133,7 +2133,7 @@ static inline void tlb_set_dirty(CPUState *env, target_ulong vaddr)
 
 /* Our TLB does not support large pages, so remember the area covered by
    large pages and trigger a full TLB flush if these are invalidated.  */
-static void tlb_add_large_page(CPUState *env, target_ulong vaddr,
+static void tlb_add_large_page(CPUArchState *env, target_ulong vaddr,
                                target_ulong size)
 {
     target_ulong mask = ~(size - 1);
@@ -2174,7 +2174,7 @@ static bool is_ram_rom_romd(MemoryRegionSection *s)
 /* Add a new TLB entry. At most one entry for a given virtual address
    is permitted. Only a single TARGET_PAGE_SIZE region is mapped, the
    supplied size is only used by tlb_flush_page.  */
-void tlb_set_page(CPUState *env, target_ulong vaddr,
+void tlb_set_page(CPUArchState *env, target_ulong vaddr,
                   target_phys_addr_t paddr, int prot,
                   int mmu_idx, target_ulong size)
 {
@@ -2277,11 +2277,11 @@ void tlb_set_page(CPUState *env, target_ulong vaddr,
 
 #else
 
-void tlb_flush(CPUState *env, int flush_global)
+void tlb_flush(CPUArchState *env, int flush_global)
 {
 }
 
-void tlb_flush_page(CPUState *env, target_ulong addr)
+void tlb_flush_page(CPUArchState *env, target_ulong addr)
 {
 }
 
@@ -2542,7 +2542,7 @@ int page_unprotect(target_ulong address, unsigned long pc, void *puc)
     return 0;
 }
 
-static inline void tlb_set_dirty(CPUState *env,
+static inline void tlb_set_dirty(CPUArchState *env,
                                  unsigned long addr, target_ulong vaddr)
 {
 }
@@ -3299,7 +3299,7 @@ static const MemoryRegionOps notdirty_mem_ops = {
 /* Generate a debug exception if a watchpoint has been hit.  */
 static void check_watchpoint(int offset, int len_mask, int flags)
 {
-    CPUState *env = cpu_single_env;
+    CPUArchState *env = cpu_single_env;
     target_ulong pc, cs_base;
     TranslationBlock *tb;
     target_ulong vaddr;
@@ -3544,7 +3544,7 @@ static void core_begin(MemoryListener *listener)
 
 static void core_commit(MemoryListener *listener)
 {
-    CPUState *env;
+    CPUArchState *env;
 
     /* since each CPU stores ram addresses in its TLB cache, we must
        reset the modified entries */
@@ -3734,7 +3734,7 @@ MemoryRegion *get_system_io(void)
 
 /* physical memory access (slow version, mainly for debug) */
 #if defined(CONFIG_USER_ONLY)
-int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
+int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr,
                         uint8_t *buf, int len, int is_write)
 {
     int l, flags;
@@ -4440,7 +4440,7 @@ void stq_be_phys(target_phys_addr_t addr, uint64_t val)
 }
 
 /* virtual memory access for debug (includes writing to ROM) */
-int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
+int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr,
                         uint8_t *buf, int len, int is_write)
 {
     int l;
@@ -4471,7 +4471,7 @@ int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
 
 /* in deterministic execution mode, instructions doing device I/Os
    must be at the end of the TB */
-void cpu_io_recompile(CPUState *env, void *retaddr)
+void cpu_io_recompile(CPUArchState *env, void *retaddr)
 {
     TranslationBlock *tb;
     uint32_t n, cflags;
@@ -4585,7 +4585,7 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
 /* NOTE: this function can trigger an exception */
 /* NOTE2: the returned address is not exactly the physical address: it
    is the offset relative to phys_ram_base */
-tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong addr)
+tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
 {
     int mmu_idx, page_index, pd;
     void *p;
diff --git a/gdbstub.c b/gdbstub.c
index b5ec362..f4e97f7 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -42,7 +42,7 @@
 #include "kvm.h"
 
 #ifndef TARGET_CPU_MEMORY_RW_DEBUG
-static inline int target_memory_rw_debug(CPUState *env, target_ulong addr,
+static inline int target_memory_rw_debug(CPUArchState *env, target_ulong addr,
                                          uint8_t *buf, int len, int is_write)
 {
     return cpu_memory_rw_debug(env, addr, buf, len, is_write);
@@ -287,9 +287,9 @@ enum RSState {
     RS_SYSCALL,
 };
 typedef struct GDBState {
-    CPUState *c_cpu; /* current CPU for step/continue ops */
-    CPUState *g_cpu; /* current CPU for other ops */
-    CPUState *query_cpu; /* for q{f|s}ThreadInfo */
+    CPUArchState *c_cpu; /* current CPU for step/continue ops */
+    CPUArchState *g_cpu; /* current CPU for other ops */
+    CPUArchState *query_cpu; /* for q{f|s}ThreadInfo */
     enum RSState state; /* parsing state */
     char line_buf[MAX_PACKET_LENGTH];
     int line_buf_index;
@@ -1655,12 +1655,12 @@ static int cpu_gdb_write_register(CPUXtensaState *env, uint8_t *mem_buf, int n)
 
 #define NUM_CORE_REGS 0
 
-static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_read_register(CPUArchState *env, uint8_t *mem_buf, int n)
 {
     return 0;
 }
 
-static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_write_register(CPUArchState *env, uint8_t *mem_buf, int n)
 {
     return 0;
 }
@@ -1736,7 +1736,7 @@ static const char *get_feature_xml(const char *p, const char **newp)
 }
 #endif
 
-static int gdb_read_register(CPUState *env, uint8_t *mem_buf, int reg)
+static int gdb_read_register(CPUArchState *env, uint8_t *mem_buf, int reg)
 {
     GDBRegisterState *r;
 
@@ -1751,7 +1751,7 @@ static int gdb_read_register(CPUState *env, uint8_t *mem_buf, int reg)
     return 0;
 }
 
-static int gdb_write_register(CPUState *env, uint8_t *mem_buf, int reg)
+static int gdb_write_register(CPUArchState *env, uint8_t *mem_buf, int reg)
 {
     GDBRegisterState *r;
 
@@ -1773,7 +1773,7 @@ static int gdb_write_register(CPUState *env, uint8_t *mem_buf, int reg)
    gdb reading a CPU register, and set_reg is gdb modifying a CPU register.
  */
 
-void gdb_register_coprocessor(CPUState * env,
+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)
 {
@@ -1820,7 +1820,7 @@ static const int xlat_gdb_type[] = {
 
 static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
 {
-    CPUState *env;
+    CPUArchState *env;
     int err = 0;
 
     if (kvm_enabled())
@@ -1854,7 +1854,7 @@ static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
 
 static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type)
 {
-    CPUState *env;
+    CPUArchState *env;
     int err = 0;
 
     if (kvm_enabled())
@@ -1887,7 +1887,7 @@ static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type)
 
 static void gdb_breakpoint_remove_all(void)
 {
-    CPUState *env;
+    CPUArchState *env;
 
     if (kvm_enabled()) {
         kvm_remove_all_breakpoints(gdbserver_state->c_cpu);
@@ -1939,7 +1939,7 @@ static void gdb_set_cpu_pc(GDBState *s, target_ulong pc)
 #endif
 }
 
-static inline int gdb_id(CPUState *env)
+static inline int gdb_id(CPUArchState *env)
 {
 #if defined(CONFIG_USER_ONLY) && defined(CONFIG_USE_NPTL)
     return env->host_tid;
@@ -1948,9 +1948,9 @@ static inline int gdb_id(CPUState *env)
 #endif
 }
 
-static CPUState *find_cpu(uint32_t thread_id)
+static CPUArchState *find_cpu(uint32_t thread_id)
 {
-    CPUState *env;
+    CPUArchState *env;
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
         if (gdb_id(env) == thread_id) {
@@ -1963,7 +1963,7 @@ static CPUState *find_cpu(uint32_t thread_id)
 
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
-    CPUState *env;
+    CPUArchState *env;
     const char *p;
     uint32_t thread;
     int ch, reg_size, type, res;
@@ -2383,7 +2383,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
     return RS_IDLE;
 }
 
-void gdb_set_stop_cpu(CPUState *env)
+void gdb_set_stop_cpu(CPUArchState *env)
 {
     gdbserver_state->c_cpu = env;
     gdbserver_state->g_cpu = env;
@@ -2393,7 +2393,7 @@ void gdb_set_stop_cpu(CPUState *env)
 static void gdb_vm_state_change(void *opaque, int running, RunState state)
 {
     GDBState *s = gdbserver_state;
-    CPUState *env = s->c_cpu;
+    CPUArchState *env = s->c_cpu;
     char buf[256];
     const char *type;
     int ret;
@@ -2602,7 +2602,7 @@ static void gdb_read_byte(GDBState *s, int ch)
 }
 
 /* Tell the remote gdb that the process has exited.  */
-void gdb_exit(CPUState *env, int code)
+void gdb_exit(CPUArchState *env, int code)
 {
   GDBState *s;
   char buf[4];
@@ -2642,7 +2642,7 @@ gdb_queuesig (void)
 }
 
 int
-gdb_handlesig (CPUState *env, int sig)
+gdb_handlesig (CPUArchState *env, int sig)
 {
   GDBState *s;
   char buf[256];
@@ -2691,7 +2691,7 @@ gdb_handlesig (CPUState *env, int sig)
 }
 
 /* Tell the remote gdb that the process has exited due to SIG.  */
-void gdb_signalled(CPUState *env, int sig)
+void gdb_signalled(CPUArchState *env, int sig)
 {
   GDBState *s;
   char buf[4];
@@ -2787,7 +2787,7 @@ int gdbserver_start(int port)
 }
 
 /* Disable gdb stub for child processes.  */
-void gdbserver_fork(CPUState *env)
+void gdbserver_fork(CPUArchState *env)
 {
     GDBState *s = gdbserver_state;
     if (gdbserver_fd < 0 || s->fd < 0)
diff --git a/gdbstub.h b/gdbstub.h
index d82334f..b44e275 100644
--- a/gdbstub.h
+++ b/gdbstub.h
@@ -11,22 +11,22 @@
 #define GDB_WATCHPOINT_ACCESS    4
 
 #ifdef NEED_CPU_H
-typedef void (*gdb_syscall_complete_cb)(CPUState *env,
+typedef void (*gdb_syscall_complete_cb)(CPUArchState *env,
                                         target_ulong ret, target_ulong err);
 
 void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...);
 int use_gdb_syscalls(void);
-void gdb_set_stop_cpu(CPUState *env);
-void gdb_exit(CPUState *, int);
+void gdb_set_stop_cpu(CPUArchState *env);
+void gdb_exit(CPUArchState *, int);
 #ifdef CONFIG_USER_ONLY
 int gdb_queuesig (void);
-int gdb_handlesig (CPUState *, int);
-void gdb_signalled(CPUState *, int);
-void gdbserver_fork(CPUState *);
+int gdb_handlesig (CPUArchState *, int);
+void gdb_signalled(CPUArchState *, int);
+void gdbserver_fork(CPUArchState *);
 #endif
 /* Get or set a register.  Returns the size of the register.  */
-typedef int (*gdb_reg_cb)(CPUState *env, uint8_t *buf, int reg);
-void gdb_register_coprocessor(CPUState *env,
+typedef int (*gdb_reg_cb)(CPUArchState *env, uint8_t *buf, int reg);
+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);
 
diff --git a/gen-icount.h b/gen-icount.h
index 5fb3829..430cb44 100644
--- a/gen-icount.h
+++ b/gen-icount.h
@@ -14,13 +14,13 @@ static inline void gen_icount_start(void)
 
     icount_label = gen_new_label();
     count = tcg_temp_local_new_i32();
-    tcg_gen_ld_i32(count, cpu_env, offsetof(CPUState, icount_decr.u32));
+    tcg_gen_ld_i32(count, cpu_env, offsetof(CPUArchState, icount_decr.u32));
     /* This is a horrid hack to allow fixing up the value later.  */
     icount_arg = gen_opparam_ptr + 1;
     tcg_gen_subi_i32(count, count, 0xdeadbeef);
 
     tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, icount_label);
-    tcg_gen_st16_i32(count, cpu_env, offsetof(CPUState, icount_decr.u16.low));
+    tcg_gen_st16_i32(count, cpu_env, offsetof(CPUArchState, icount_decr.u16.low));
     tcg_temp_free_i32(count);
 }
 
@@ -36,13 +36,13 @@ static void gen_icount_end(TranslationBlock *tb, int num_insns)
 static inline void gen_io_start(void)
 {
     TCGv_i32 tmp = tcg_const_i32(1);
-    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, can_do_io));
+    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUArchState, can_do_io));
     tcg_temp_free_i32(tmp);
 }
 
 static inline void gen_io_end(void)
 {
     TCGv_i32 tmp = tcg_const_i32(0);
-    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, can_do_io));
+    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUArchState, can_do_io));
     tcg_temp_free_i32(tmp);
 }
diff --git a/kvm-all.c b/kvm-all.c
index 3c6b4f0..42e5e23 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -190,7 +190,7 @@ static int kvm_set_user_memory_region(KVMState *s, KVMSlot *slot)
 
 static void kvm_reset_vcpu(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUArchState *env = opaque;
 
     kvm_arch_reset_vcpu(env);
 }
@@ -200,7 +200,7 @@ int kvm_pit_in_kernel(void)
     return kvm_state->pit_in_kernel;
 }
 
-int kvm_init_vcpu(CPUState *env)
+int kvm_init_vcpu(CPUArchState *env)
 {
     KVMState *s = kvm_state;
     long mmap_size;
@@ -830,7 +830,7 @@ static MemoryListener kvm_memory_listener = {
     .priority = 10,
 };
 
-static void kvm_handle_interrupt(CPUState *env, int mask)
+static void kvm_handle_interrupt(CPUArchState *env, int mask)
 {
     env->interrupt_request |= mask;
 
@@ -1135,7 +1135,7 @@ static void kvm_handle_io(uint16_t port, void *data, int direction, int size,
     }
 }
 
-static int kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
+static int kvm_handle_internal_error(CPUArchState *env, struct kvm_run *run)
 {
     fprintf(stderr, "KVM internal error.");
     if (kvm_check_extension(kvm_state, KVM_CAP_INTERNAL_ERROR_DATA)) {
@@ -1190,7 +1190,7 @@ void kvm_flush_coalesced_mmio_buffer(void)
 
 static void do_kvm_cpu_synchronize_state(void *_env)
 {
-    CPUState *env = _env;
+    CPUArchState *env = _env;
 
     if (!env->kvm_vcpu_dirty) {
         kvm_arch_get_registers(env);
@@ -1198,26 +1198,26 @@ static void do_kvm_cpu_synchronize_state(void *_env)
     }
 }
 
-void kvm_cpu_synchronize_state(CPUState *env)
+void kvm_cpu_synchronize_state(CPUArchState *env)
 {
     if (!env->kvm_vcpu_dirty) {
         run_on_cpu(env, do_kvm_cpu_synchronize_state, env);
     }
 }
 
-void kvm_cpu_synchronize_post_reset(CPUState *env)
+void kvm_cpu_synchronize_post_reset(CPUArchState *env)
 {
     kvm_arch_put_registers(env, KVM_PUT_RESET_STATE);
     env->kvm_vcpu_dirty = 0;
 }
 
-void kvm_cpu_synchronize_post_init(CPUState *env)
+void kvm_cpu_synchronize_post_init(CPUArchState *env)
 {
     kvm_arch_put_registers(env, KVM_PUT_FULL_STATE);
     env->kvm_vcpu_dirty = 0;
 }
 
-int kvm_cpu_exec(CPUState *env)
+int kvm_cpu_exec(CPUArchState *env)
 {
     struct kvm_run *run = env->kvm_run;
     int ret, run_ret;
@@ -1350,7 +1350,7 @@ int kvm_vm_ioctl(KVMState *s, int type, ...)
     return ret;
 }
 
-int kvm_vcpu_ioctl(CPUState *env, int type, ...)
+int kvm_vcpu_ioctl(CPUArchState *env, int type, ...)
 {
     int ret;
     void *arg;
@@ -1439,7 +1439,7 @@ void kvm_setup_guest_memory(void *start, size_t size)
 }
 
 #ifdef KVM_CAP_SET_GUEST_DEBUG
-struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env,
+struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUArchState *env,
                                                  target_ulong pc)
 {
     struct kvm_sw_breakpoint *bp;
@@ -1452,26 +1452,26 @@ struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env,
     return NULL;
 }
 
-int kvm_sw_breakpoints_active(CPUState *env)
+int kvm_sw_breakpoints_active(CPUArchState *env)
 {
     return !QTAILQ_EMPTY(&env->kvm_state->kvm_sw_breakpoints);
 }
 
 struct kvm_set_guest_debug_data {
     struct kvm_guest_debug dbg;
-    CPUState *env;
+    CPUArchState *env;
     int err;
 };
 
 static void kvm_invoke_set_guest_debug(void *data)
 {
     struct kvm_set_guest_debug_data *dbg_data = data;
-    CPUState *env = dbg_data->env;
+    CPUArchState *env = dbg_data->env;
 
     dbg_data->err = kvm_vcpu_ioctl(env, KVM_SET_GUEST_DEBUG, &dbg_data->dbg);
 }
 
-int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
+int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap)
 {
     struct kvm_set_guest_debug_data data;
 
@@ -1487,11 +1487,11 @@ int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
     return data.err;
 }
 
-int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
+int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr,
                           target_ulong len, int type)
 {
     struct kvm_sw_breakpoint *bp;
-    CPUState *env;
+    CPUArchState *env;
     int err;
 
     if (type == GDB_BREAKPOINT_SW) {
@@ -1532,11 +1532,11 @@ int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
     return 0;
 }
 
-int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
+int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr,
                           target_ulong len, int type)
 {
     struct kvm_sw_breakpoint *bp;
-    CPUState *env;
+    CPUArchState *env;
     int err;
 
     if (type == GDB_BREAKPOINT_SW) {
@@ -1573,11 +1573,11 @@ int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
     return 0;
 }
 
-void kvm_remove_all_breakpoints(CPUState *current_env)
+void kvm_remove_all_breakpoints(CPUArchState *current_env)
 {
     struct kvm_sw_breakpoint *bp, *next;
     KVMState *s = current_env->kvm_state;
-    CPUState *env;
+    CPUArchState *env;
 
     QTAILQ_FOREACH_SAFE(bp, &s->kvm_sw_breakpoints, entry, next) {
         if (kvm_arch_remove_sw_breakpoint(current_env, bp) != 0) {
@@ -1598,29 +1598,29 @@ void kvm_remove_all_breakpoints(CPUState *current_env)
 
 #else /* !KVM_CAP_SET_GUEST_DEBUG */
 
-int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
+int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap)
 {
     return -EINVAL;
 }
 
-int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
+int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr,
                           target_ulong len, int type)
 {
     return -EINVAL;
 }
 
-int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
+int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr,
                           target_ulong len, int type)
 {
     return -EINVAL;
 }
 
-void kvm_remove_all_breakpoints(CPUState *current_env)
+void kvm_remove_all_breakpoints(CPUArchState *current_env)
 {
 }
 #endif /* !KVM_CAP_SET_GUEST_DEBUG */
 
-int kvm_set_signal_mask(CPUState *env, const sigset_t *sigset)
+int kvm_set_signal_mask(CPUArchState *env, const sigset_t *sigset)
 {
     struct kvm_signal_mask *sigmask;
     int r;
@@ -1690,7 +1690,7 @@ int kvm_set_ioeventfd_pio_word(int fd, uint16_t addr, uint16_t val, bool assign)
     return 0;
 }
 
-int kvm_on_sigbus_vcpu(CPUState *env, int code, void *addr)
+int kvm_on_sigbus_vcpu(CPUArchState *env, int code, void *addr)
 {
     return kvm_arch_on_sigbus_vcpu(env, code, addr);
 }
diff --git a/kvm-stub.c b/kvm-stub.c
index 1f1c686..69a1228 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -22,7 +22,7 @@ int kvm_pit_in_kernel(void)
 }
 
 
-int kvm_init_vcpu(CPUState *env)
+int kvm_init_vcpu(CPUArchState *env)
 {
     return -ENOSYS;
 }
@@ -46,19 +46,19 @@ void kvm_flush_coalesced_mmio_buffer(void)
 {
 }
 
-void kvm_cpu_synchronize_state(CPUState *env)
+void kvm_cpu_synchronize_state(CPUArchState *env)
 {
 }
 
-void kvm_cpu_synchronize_post_reset(CPUState *env)
+void kvm_cpu_synchronize_post_reset(CPUArchState *env)
 {
 }
 
-void kvm_cpu_synchronize_post_init(CPUState *env)
+void kvm_cpu_synchronize_post_init(CPUArchState *env)
 {
 }
 
-int kvm_cpu_exec(CPUState *env)
+int kvm_cpu_exec(CPUArchState *env)
 {
     abort ();
 }
@@ -87,29 +87,29 @@ void kvm_setup_guest_memory(void *start, size_t size)
 {
 }
 
-int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
+int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap)
 {
     return -ENOSYS;
 }
 
-int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
+int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr,
                           target_ulong len, int type)
 {
     return -EINVAL;
 }
 
-int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
+int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr,
                           target_ulong len, int type)
 {
     return -EINVAL;
 }
 
-void kvm_remove_all_breakpoints(CPUState *current_env)
+void kvm_remove_all_breakpoints(CPUArchState *current_env)
 {
 }
 
 #ifndef _WIN32
-int kvm_set_signal_mask(CPUState *env, const sigset_t *sigset)
+int kvm_set_signal_mask(CPUArchState *env, const sigset_t *sigset)
 {
     abort();
 }
@@ -125,7 +125,7 @@ int kvm_set_ioeventfd_mmio_long(int fd, uint32_t adr, uint32_t val, bool assign)
     return -ENOSYS;
 }
 
-int kvm_on_sigbus_vcpu(CPUState *env, int code, void *addr)
+int kvm_on_sigbus_vcpu(CPUArchState *env, int code, void *addr)
 {
     return 1;
 }
diff --git a/kvm.h b/kvm.h
index 8ef4476..330f17b 100644
--- a/kvm.h
+++ b/kvm.h
@@ -61,9 +61,9 @@ int kvm_has_gsi_routing(void);
 int kvm_allows_irq0_override(void);
 
 #ifdef NEED_CPU_H
-int kvm_init_vcpu(CPUState *env);
+int kvm_init_vcpu(CPUArchState *env);
 
-int kvm_cpu_exec(CPUState *env);
+int kvm_cpu_exec(CPUArchState *env);
 
 #if !defined(CONFIG_USER_ONLY)
 void kvm_setup_guest_memory(void *start, size_t size);
@@ -73,19 +73,19 @@ int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size);
 void kvm_flush_coalesced_mmio_buffer(void);
 #endif
 
-int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
+int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr,
                           target_ulong len, int type);
-int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
+int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr,
                           target_ulong len, int type);
-void kvm_remove_all_breakpoints(CPUState *current_env);
-int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap);
+void kvm_remove_all_breakpoints(CPUArchState *current_env);
+int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap);
 #ifndef _WIN32
-int kvm_set_signal_mask(CPUState *env, const sigset_t *sigset);
+int kvm_set_signal_mask(CPUArchState *env, const sigset_t *sigset);
 #endif
 
 int kvm_pit_in_kernel(void);
 
-int kvm_on_sigbus_vcpu(CPUState *env, int code, void *addr);
+int kvm_on_sigbus_vcpu(CPUArchState *env, int code, void *addr);
 int kvm_on_sigbus(int code, void *addr);
 
 /* internal API */
@@ -98,20 +98,20 @@ int kvm_ioctl(KVMState *s, int type, ...);
 
 int kvm_vm_ioctl(KVMState *s, int type, ...);
 
-int kvm_vcpu_ioctl(CPUState *env, int type, ...);
+int kvm_vcpu_ioctl(CPUArchState *env, int type, ...);
 
 /* Arch specific hooks */
 
 extern const KVMCapabilityInfo kvm_arch_required_capabilities[];
 
-void kvm_arch_pre_run(CPUState *env, struct kvm_run *run);
-void kvm_arch_post_run(CPUState *env, struct kvm_run *run);
+void kvm_arch_pre_run(CPUArchState *env, struct kvm_run *run);
+void kvm_arch_post_run(CPUArchState *env, struct kvm_run *run);
 
-int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run);
+int kvm_arch_handle_exit(CPUArchState *env, struct kvm_run *run);
 
-int kvm_arch_process_async_events(CPUState *env);
+int kvm_arch_process_async_events(CPUArchState *env);
 
-int kvm_arch_get_registers(CPUState *env);
+int kvm_arch_get_registers(CPUArchState *env);
 
 /* state subset only touched by the VCPU itself during runtime */
 #define KVM_PUT_RUNTIME_STATE   1
@@ -120,15 +120,15 @@ int kvm_arch_get_registers(CPUState *env);
 /* full state set, modified during initialization or on vmload */
 #define KVM_PUT_FULL_STATE      3
 
-int kvm_arch_put_registers(CPUState *env, int level);
+int kvm_arch_put_registers(CPUArchState *env, int level);
 
 int kvm_arch_init(KVMState *s);
 
-int kvm_arch_init_vcpu(CPUState *env);
+int kvm_arch_init_vcpu(CPUArchState *env);
 
-void kvm_arch_reset_vcpu(CPUState *env);
+void kvm_arch_reset_vcpu(CPUArchState *env);
 
-int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr);
+int kvm_arch_on_sigbus_vcpu(CPUArchState *env, int code, void *addr);
 int kvm_arch_on_sigbus(int code, void *addr);
 
 void kvm_arch_init_irq_routing(KVMState *s);
@@ -153,14 +153,14 @@ struct kvm_sw_breakpoint {
 
 QTAILQ_HEAD(kvm_sw_breakpoint_head, kvm_sw_breakpoint);
 
-struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env,
+struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUArchState *env,
                                                  target_ulong pc);
 
-int kvm_sw_breakpoints_active(CPUState *env);
+int kvm_sw_breakpoints_active(CPUArchState *env);
 
-int kvm_arch_insert_sw_breakpoint(CPUState *current_env,
+int kvm_arch_insert_sw_breakpoint(CPUArchState *current_env,
                                   struct kvm_sw_breakpoint *bp);
-int kvm_arch_remove_sw_breakpoint(CPUState *current_env,
+int kvm_arch_remove_sw_breakpoint(CPUArchState *current_env,
                                   struct kvm_sw_breakpoint *bp);
 int kvm_arch_insert_hw_breakpoint(target_ulong addr,
                                   target_ulong len, int type);
@@ -168,35 +168,35 @@ int kvm_arch_remove_hw_breakpoint(target_ulong addr,
                                   target_ulong len, int type);
 void kvm_arch_remove_all_hw_breakpoints(void);
 
-void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg);
+void kvm_arch_update_guest_debug(CPUArchState *env, struct kvm_guest_debug *dbg);
 
-bool kvm_arch_stop_on_emulation_error(CPUState *env);
+bool kvm_arch_stop_on_emulation_error(CPUArchState *env);
 
 int kvm_check_extension(KVMState *s, unsigned int extension);
 
 uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function,
                                       uint32_t index, int reg);
-void kvm_cpu_synchronize_state(CPUState *env);
-void kvm_cpu_synchronize_post_reset(CPUState *env);
-void kvm_cpu_synchronize_post_init(CPUState *env);
+void kvm_cpu_synchronize_state(CPUArchState *env);
+void kvm_cpu_synchronize_post_reset(CPUArchState *env);
+void kvm_cpu_synchronize_post_init(CPUArchState *env);
 
 /* generic hooks - to be moved/refactored once there are more users */
 
-static inline void cpu_synchronize_state(CPUState *env)
+static inline void cpu_synchronize_state(CPUArchState *env)
 {
     if (kvm_enabled()) {
         kvm_cpu_synchronize_state(env);
     }
 }
 
-static inline void cpu_synchronize_post_reset(CPUState *env)
+static inline void cpu_synchronize_post_reset(CPUArchState *env)
 {
     if (kvm_enabled()) {
         kvm_cpu_synchronize_post_reset(env);
     }
 }
 
-static inline void cpu_synchronize_post_init(CPUState *env)
+static inline void cpu_synchronize_post_init(CPUArchState *env)
 {
     if (kvm_enabled()) {
         kvm_cpu_synchronize_post_init(env);
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 48e3232..e502b39 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1044,7 +1044,7 @@ static inline void bswap_sym(struct elf_sym *sym) { }
 #endif
 
 #ifdef USE_ELF_CORE_DUMP
-static int elf_core_dump(int, const CPUState *);
+static int elf_core_dump(int, const CPUArchState *);
 #endif /* USE_ELF_CORE_DUMP */
 static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias);
 
@@ -1930,7 +1930,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
  * from given cpu into just specified register set.  Prototype is:
  *
  * static void elf_core_copy_regs(taret_elf_gregset_t *regs,
- *                                const CPUState *env);
+ *                                const CPUArchState *env);
  *
  * Parameters:
  *     regs - copy register values into here (allocated and zeroed by caller)
@@ -2054,8 +2054,8 @@ static void fill_auxv_note(struct memelfnote *, const TaskState *);
 static void fill_elf_note_phdr(struct elf_phdr *, int, off_t);
 static size_t note_size(const struct memelfnote *);
 static void free_note_info(struct elf_note_info *);
-static int fill_note_info(struct elf_note_info *, long, const CPUState *);
-static void fill_thread_info(struct elf_note_info *, const CPUState *);
+static int fill_note_info(struct elf_note_info *, long, const CPUArchState *);
+static void fill_thread_info(struct elf_note_info *, const CPUArchState *);
 static int core_dump_filename(const TaskState *, char *, size_t);
 
 static int dump_write(int, const void *, size_t);
@@ -2448,7 +2448,7 @@ static int write_note(struct memelfnote *men, int fd)
     return (0);
 }
 
-static void fill_thread_info(struct elf_note_info *info, const CPUState *env)
+static void fill_thread_info(struct elf_note_info *info, const CPUArchState *env)
 {
     TaskState *ts = (TaskState *)env->opaque;
     struct elf_thread_status *ets;
@@ -2466,10 +2466,10 @@ static void fill_thread_info(struct elf_note_info *info, const CPUState *env)
 }
 
 static int fill_note_info(struct elf_note_info *info,
-                          long signr, const CPUState *env)
+                          long signr, const CPUArchState *env)
 {
 #define NUMNOTES 3
-    CPUState *cpu = NULL;
+    CPUArchState *cpu = NULL;
     TaskState *ts = (TaskState *)env->opaque;
     int i;
 
@@ -2595,7 +2595,7 @@ static int write_note_info(struct elf_note_info *info, int fd)
  * handler (provided that target process haven't registered
  * handler for that) that does the dump when signal is received.
  */
-static int elf_core_dump(int signr, const CPUState *env)
+static int elf_core_dump(int signr, const CPUArchState *env)
 {
     const TaskState *ts = (const TaskState *)env->opaque;
     struct vm_area_struct *vma = NULL;
diff --git a/linux-user/main.c b/linux-user/main.c
index 3b48882..962677e 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -146,7 +146,7 @@ static inline void exclusive_idle(void)
    Must only be called from outside cpu_arm_exec.   */
 static inline void start_exclusive(void)
 {
-    CPUState *other;
+    CPUArchState *other;
     pthread_mutex_lock(&exclusive_lock);
     exclusive_idle();
 
@@ -172,7 +172,7 @@ static inline void end_exclusive(void)
 }
 
 /* Wait for exclusive ops to finish, and begin cpu execution.  */
-static inline void cpu_exec_start(CPUState *env)
+static inline void cpu_exec_start(CPUArchState *env)
 {
     pthread_mutex_lock(&exclusive_lock);
     exclusive_idle();
@@ -181,7 +181,7 @@ static inline void cpu_exec_start(CPUState *env)
 }
 
 /* Mark cpu as not executing, and release pending exclusive ops.  */
-static inline void cpu_exec_end(CPUState *env)
+static inline void cpu_exec_end(CPUArchState *env)
 {
     pthread_mutex_lock(&exclusive_lock);
     env->running = 0;
@@ -206,11 +206,11 @@ void cpu_list_unlock(void)
 }
 #else /* if !CONFIG_USE_NPTL */
 /* These are no-ops because we are not threadsafe.  */
-static inline void cpu_exec_start(CPUState *env)
+static inline void cpu_exec_start(CPUArchState *env)
 {
 }
 
-static inline void cpu_exec_end(CPUState *env)
+static inline void cpu_exec_end(CPUArchState *env)
 {
 }
 
@@ -2888,7 +2888,7 @@ void cpu_loop(CPUS390XState *env)
 
 #endif /* TARGET_S390X */
 
-THREAD CPUState *thread_env;
+THREAD CPUArchState *thread_env;
 
 void task_settid(TaskState *ts)
 {
@@ -3277,7 +3277,7 @@ int main(int argc, char **argv, char **envp)
     struct image_info info1, *info = &info1;
     struct linux_binprm bprm;
     TaskState *ts;
-    CPUState *env;
+    CPUArchState *env;
     int optind;
     char **target_environ, **wrk;
     char **target_argv;
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 308dbc0..6889567 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -171,7 +171,7 @@ struct linux_binprm {
         char **argv;
         char **envp;
         char * filename;        /* Name of binary */
-        int (*core_dump)(int, const CPUState *); /* coredump routine */
+        int (*core_dump)(int, const CPUArchState *); /* coredump routine */
 };
 
 void do_init_thread(struct target_pt_regs *regs, struct image_info *infop);
@@ -196,8 +196,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                     abi_long arg5, abi_long arg6, abi_long arg7,
                     abi_long arg8);
 void gemu_log(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
-extern THREAD CPUState *thread_env;
-void cpu_loop(CPUState *env);
+extern THREAD CPUArchState *thread_env;
+void cpu_loop(CPUArchState *env);
 char *target_strerror(int err);
 int get_osversion(void);
 void fork_start(void);
@@ -219,15 +219,15 @@ void print_syscall_ret(int num, abi_long arg1);
 extern int do_strace;
 
 /* signal.c */
-void process_pending_signals(CPUState *cpu_env);
+void process_pending_signals(CPUArchState *cpu_env);
 void signal_init(void);
-int queue_signal(CPUState *env, int sig, target_siginfo_t *info);
+int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info);
 void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
 void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
 int target_to_host_signal(int sig);
 int host_to_target_signal(int sig);
-long do_sigreturn(CPUState *env);
-long do_rt_sigreturn(CPUState *env);
+long do_sigreturn(CPUArchState *env);
+long do_rt_sigreturn(CPUArchState *env);
 abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
 
 #ifdef TARGET_I386
diff --git a/linux-user/signal.c b/linux-user/signal.c
index f44f78e..fca51e2 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -347,7 +347,7 @@ void signal_init(void)
 
 /* signal queue handling */
 
-static inline struct sigqueue *alloc_sigqueue(CPUState *env)
+static inline struct sigqueue *alloc_sigqueue(CPUArchState *env)
 {
     TaskState *ts = env->opaque;
     struct sigqueue *q = ts->first_free;
@@ -357,7 +357,7 @@ static inline struct sigqueue *alloc_sigqueue(CPUState *env)
     return q;
 }
 
-static inline void free_sigqueue(CPUState *env, struct sigqueue *q)
+static inline void free_sigqueue(CPUArchState *env, struct sigqueue *q)
 {
     TaskState *ts = env->opaque;
     q->next = ts->first_free;
@@ -415,7 +415,7 @@ static void QEMU_NORETURN force_sig(int target_sig)
 
 /* queue a signal so that it will be send to the virtual CPU as soon
    as possible */
-int queue_signal(CPUState *env, int sig, target_siginfo_t *info)
+int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
 {
     TaskState *ts = env->opaque;
     struct emulated_sigtable *k;
@@ -5214,25 +5214,25 @@ long do_rt_sigreturn(CPUAlphaState *env)
 #else
 
 static void setup_frame(int sig, struct target_sigaction *ka,
-			target_sigset_t *set, CPUState *env)
+			target_sigset_t *set, CPUArchState *env)
 {
     fprintf(stderr, "setup_frame: not implemented\n");
 }
 
 static void setup_rt_frame(int sig, struct target_sigaction *ka,
                            target_siginfo_t *info,
-			   target_sigset_t *set, CPUState *env)
+			   target_sigset_t *set, CPUArchState *env)
 {
     fprintf(stderr, "setup_rt_frame: not implemented\n");
 }
 
-long do_sigreturn(CPUState *env)
+long do_sigreturn(CPUArchState *env)
 {
     fprintf(stderr, "do_sigreturn: not implemented\n");
     return -TARGET_ENOSYS;
 }
 
-long do_rt_sigreturn(CPUState *env)
+long do_rt_sigreturn(CPUArchState *env)
 {
     fprintf(stderr, "do_rt_sigreturn: not implemented\n");
     return -TARGET_ENOSYS;
@@ -5240,7 +5240,7 @@ long do_rt_sigreturn(CPUState *env)
 
 #endif
 
-void process_pending_signals(CPUState *cpu_env)
+void process_pending_signals(CPUArchState *cpu_env)
 {
     int sig;
     abi_ulong handler;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 29888bd..9f5e53a 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -3955,7 +3955,7 @@ static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
 
 static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
 typedef struct {
-    CPUState *env;
+    CPUArchState *env;
     pthread_mutex_t mutex;
     pthread_cond_t cond;
     pthread_t thread;
@@ -3968,7 +3968,7 @@ typedef struct {
 static void *clone_func(void *arg)
 {
     new_thread_info *info = arg;
-    CPUState *env;
+    CPUArchState *env;
     TaskState *ts;
 
     env = info->env;
@@ -3998,7 +3998,7 @@ static void *clone_func(void *arg)
 
 static int clone_func(void *arg)
 {
-    CPUState *env = arg;
+    CPUArchState *env = arg;
     cpu_loop(env);
     /* never exits */
     return 0;
@@ -4007,13 +4007,13 @@ static int clone_func(void *arg)
 
 /* do_fork() Must return host values and target errnos (unlike most
    do_*() functions). */
-static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
+static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
                    abi_ulong parent_tidptr, target_ulong newtls,
                    abi_ulong child_tidptr)
 {
     int ret;
     TaskState *ts;
-    CPUState *new_env;
+    CPUArchState *new_env;
 #if defined(CONFIG_USE_NPTL)
     unsigned int nptl_flags;
     sigset_t sigmask;
@@ -4640,7 +4640,7 @@ int get_osversion(void)
 
 static int open_self_maps(void *cpu_env, int fd)
 {
-    TaskState *ts = ((CPUState *)cpu_env)->opaque;
+    TaskState *ts = ((CPUArchState *)cpu_env)->opaque;
 
     dprintf(fd, "%08llx-%08llx rw-p %08llx 00:00 0          [stack]\n",
                 (unsigned long long)ts->info->stack_limit,
@@ -4653,7 +4653,7 @@ static int open_self_maps(void *cpu_env, int fd)
 
 static int open_self_stat(void *cpu_env, int fd)
 {
-    TaskState *ts = ((CPUState *)cpu_env)->opaque;
+    TaskState *ts = ((CPUArchState *)cpu_env)->opaque;
     abi_ulong start_stack = ts->info->start_stack;
     int i;
 
@@ -4678,7 +4678,7 @@ static int open_self_stat(void *cpu_env, int fd)
 
 static int open_self_auxv(void *cpu_env, int fd)
 {
-    TaskState *ts = ((CPUState *)cpu_env)->opaque;
+    TaskState *ts = ((CPUArchState *)cpu_env)->opaque;
     abi_ulong auxv = ts->info->saved_auxv;
     abi_ulong len = ts->info->auxv_len;
     char *ptr;
@@ -4784,13 +4784,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
          be disabling signals.  */
       if (first_cpu->next_cpu) {
           TaskState *ts;
-          CPUState **lastp;
-          CPUState *p;
+          CPUArchState **lastp;
+          CPUArchState *p;
 
           cpu_list_lock();
           lastp = &first_cpu;
           p = first_cpu;
-          while (p && p != (CPUState *)cpu_env) {
+          while (p && p != (CPUArchState *)cpu_env) {
               lastp = &p->next_cpu;
               p = p->next_cpu;
           }
@@ -4801,7 +4801,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
           /* Remove the CPU from the list.  */
           *lastp = p->next_cpu;
           cpu_list_unlock();
-          ts = ((CPUState *)cpu_env)->opaque;
+          ts = ((CPUArchState *)cpu_env)->opaque;
           if (ts->child_tidptr) {
               put_user_u32(0, ts->child_tidptr);
               sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
@@ -6091,7 +6091,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
     case TARGET_NR_mprotect:
         {
-            TaskState *ts = ((CPUState *)cpu_env)->opaque;
+            TaskState *ts = ((CPUArchState *)cpu_env)->opaque;
             /* Special hack to detect libc making the stack executable.  */
             if ((arg3 & PROT_GROWSDOWN)
                 && arg1 >= ts->info->stack_limit
@@ -7076,7 +7076,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
     defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA) || \
     defined(TARGET_M68K) || defined(TARGET_S390X)
-        ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
+        ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUArchState *)cpu_env));
         break;
 #else
         goto unimplemented;
diff --git a/monitor.c b/monitor.c
index e3b72ff..d57e7bf 100644
--- a/monitor.c
+++ b/monitor.c
@@ -156,7 +156,7 @@ struct Monitor {
     int outbuf_index;
     ReadLineState *rs;
     MonitorControl *mc;
-    CPUState *mon_cpu;
+    CPUArchState *mon_cpu;
     BlockDriverCompletionFunc *password_completion_cb;
     void *password_opaque;
 #ifdef CONFIG_DEBUG_MONITOR
@@ -742,7 +742,7 @@ CommandInfoList *qmp_query_commands(Error **errp)
 /* set the current CPU defined by the user */
 int monitor_set_cpu(int cpu_index)
 {
-    CPUState *env;
+    CPUArchState *env;
 
     for(env = first_cpu; env != NULL; env = env->next_cpu) {
         if (env->cpu_index == cpu_index) {
@@ -753,7 +753,7 @@ int monitor_set_cpu(int cpu_index)
     return -1;
 }
 
-static CPUState *mon_get_cpu(void)
+static CPUArchState *mon_get_cpu(void)
 {
     if (!cur_mon->mon_cpu) {
         monitor_set_cpu(0);
@@ -769,7 +769,7 @@ int monitor_get_cpu_index(void)
 
 static void do_info_registers(Monitor *mon)
 {
-    CPUState *env;
+    CPUArchState *env;
     env = mon_get_cpu();
 #ifdef TARGET_I386
     cpu_dump_state(env, (FILE *)mon, monitor_fprintf,
@@ -806,7 +806,7 @@ static void do_info_history(Monitor *mon)
 /* XXX: not implemented in other targets */
 static void do_info_cpu_stats(Monitor *mon)
 {
-    CPUState *env;
+    CPUArchState *env;
 
     env = mon_get_cpu();
     cpu_dump_statistics(env, (FILE *)mon, &monitor_fprintf, 0);
@@ -987,7 +987,7 @@ static void monitor_printc(Monitor *mon, int c)
 static void memory_dump(Monitor *mon, int count, int format, int wsize,
                         target_phys_addr_t addr, int is_physical)
 {
-    CPUState *env;
+    CPUArchState *env;
     int l, line_size, i, max_digits, len;
     uint8_t buf[16];
     uint64_t v;
@@ -1547,7 +1547,7 @@ static void print_pte(Monitor *mon, target_phys_addr_t addr,
                    pte & PG_RW_MASK ? 'W' : '-');
 }
 
-static void tlb_info_32(Monitor *mon, CPUState *env)
+static void tlb_info_32(Monitor *mon, CPUArchState *env)
 {
     unsigned int l1, l2;
     uint32_t pgd, pde, pte;
@@ -1575,7 +1575,7 @@ static void tlb_info_32(Monitor *mon, CPUState *env)
     }
 }
 
-static void tlb_info_pae32(Monitor *mon, CPUState *env)
+static void tlb_info_pae32(Monitor *mon, CPUArchState *env)
 {
     unsigned int l1, l2, l3;
     uint64_t pdpe, pde, pte;
@@ -1615,7 +1615,7 @@ static void tlb_info_pae32(Monitor *mon, CPUState *env)
 }
 
 #ifdef TARGET_X86_64
-static void tlb_info_64(Monitor *mon, CPUState *env)
+static void tlb_info_64(Monitor *mon, CPUArchState *env)
 {
     uint64_t l1, l2, l3, l4;
     uint64_t pml4e, pdpe, pde, pte;
@@ -1674,7 +1674,7 @@ static void tlb_info_64(Monitor *mon, CPUState *env)
 
 static void tlb_info(Monitor *mon)
 {
-    CPUState *env;
+    CPUArchState *env;
 
     env = mon_get_cpu();
 
@@ -1719,7 +1719,7 @@ static void mem_print(Monitor *mon, target_phys_addr_t *pstart,
     }
 }
 
-static void mem_info_32(Monitor *mon, CPUState *env)
+static void mem_info_32(Monitor *mon, CPUArchState *env)
 {
     unsigned int l1, l2;
     int prot, last_prot;
@@ -1760,7 +1760,7 @@ static void mem_info_32(Monitor *mon, CPUState *env)
     mem_print(mon, &start, &last_prot, (target_phys_addr_t)1 << 32, 0);
 }
 
-static void mem_info_pae32(Monitor *mon, CPUState *env)
+static void mem_info_pae32(Monitor *mon, CPUArchState *env)
 {
     unsigned int l1, l2, l3;
     int prot, last_prot;
@@ -1817,7 +1817,7 @@ static void mem_info_pae32(Monitor *mon, CPUState *env)
 
 
 #ifdef TARGET_X86_64
-static void mem_info_64(Monitor *mon, CPUState *env)
+static void mem_info_64(Monitor *mon, CPUArchState *env)
 {
     int prot, last_prot;
     uint64_t l1, l2, l3, l4;
@@ -1897,7 +1897,7 @@ static void mem_info_64(Monitor *mon, CPUState *env)
 
 static void mem_info(Monitor *mon)
 {
-    CPUState *env;
+    CPUArchState *env;
 
     env = mon_get_cpu();
 
@@ -1936,7 +1936,7 @@ static void print_tlb(Monitor *mon, int idx, tlb_t *tlb)
 
 static void tlb_info(Monitor *mon)
 {
-    CPUState *env = mon_get_cpu();
+    CPUArchState *env = mon_get_cpu();
     int i;
 
     monitor_printf (mon, "ITLB:\n");
@@ -1952,7 +1952,7 @@ static void tlb_info(Monitor *mon)
 #if defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_XTENSA)
 static void tlb_info(Monitor *mon)
 {
-    CPUState *env1 = mon_get_cpu();
+    CPUArchState *env1 = mon_get_cpu();
 
     dump_mmu((FILE*)mon, (fprintf_function)monitor_printf, env1);
 }
@@ -1966,7 +1966,7 @@ static void do_info_mtree(Monitor *mon)
 static void do_info_numa(Monitor *mon)
 {
     int i;
-    CPUState *env;
+    CPUArchState *env;
 
     monitor_printf(mon, "%d nodes\n", nb_numa_nodes);
     for (i = 0; i < nb_numa_nodes; i++) {
@@ -2173,7 +2173,7 @@ static void do_acl_remove(Monitor *mon, const QDict *qdict)
 #if defined(TARGET_I386)
 static void do_inject_mce(Monitor *mon, const QDict *qdict)
 {
-    CPUState *cenv;
+    CPUArchState *cenv;
     int cpu_index = qdict_get_int(qdict, "cpu_index");
     int bank = qdict_get_int(qdict, "bank");
     uint64_t status = qdict_get_int(qdict, "status");
@@ -2625,7 +2625,7 @@ typedef struct MonitorDef {
 #if defined(TARGET_I386)
 static target_long monitor_get_pc (const struct MonitorDef *md, int val)
 {
-    CPUState *env = mon_get_cpu();
+    CPUArchState *env = mon_get_cpu();
     return env->eip + env->segs[R_CS].base;
 }
 #endif
@@ -2633,7 +2633,7 @@ static target_long monitor_get_pc (const struct MonitorDef *md, int val)
 #if defined(TARGET_PPC)
 static target_long monitor_get_ccr (const struct MonitorDef *md, int val)
 {
-    CPUState *env = mon_get_cpu();
+    CPUArchState *env = mon_get_cpu();
     unsigned int u;
     int i;
 
@@ -2646,31 +2646,31 @@ static target_long monitor_get_ccr (const struct MonitorDef *md, int val)
 
 static target_long monitor_get_msr (const struct MonitorDef *md, int val)
 {
-    CPUState *env = mon_get_cpu();
+    CPUArchState *env = mon_get_cpu();
     return env->msr;
 }
 
 static target_long monitor_get_xer (const struct MonitorDef *md, int val)
 {
-    CPUState *env = mon_get_cpu();
+    CPUArchState *env = mon_get_cpu();
     return env->xer;
 }
 
 static target_long monitor_get_decr (const struct MonitorDef *md, int val)
 {
-    CPUState *env = mon_get_cpu();
+    CPUArchState *env = mon_get_cpu();
     return cpu_ppc_load_decr(env);
 }
 
 static target_long monitor_get_tbu (const struct MonitorDef *md, int val)
 {
-    CPUState *env = mon_get_cpu();
+    CPUArchState *env = mon_get_cpu();
     return cpu_ppc_load_tbu(env);
 }
 
 static target_long monitor_get_tbl (const struct MonitorDef *md, int val)
 {
-    CPUState *env = mon_get_cpu();
+    CPUArchState *env = mon_get_cpu();
     return cpu_ppc_load_tbl(env);
 }
 #endif
@@ -2679,7 +2679,7 @@ static target_long monitor_get_tbl (const struct MonitorDef *md, int val)
 #ifndef TARGET_SPARC64
 static target_long monitor_get_psr (const struct MonitorDef *md, int val)
 {
-    CPUState *env = mon_get_cpu();
+    CPUArchState *env = mon_get_cpu();
 
     return cpu_get_psr(env);
 }
@@ -2687,7 +2687,7 @@ static target_long monitor_get_psr (const struct MonitorDef *md, int val)
 
 static target_long monitor_get_reg(const struct MonitorDef *md, int val)
 {
-    CPUState *env = mon_get_cpu();
+    CPUArchState *env = mon_get_cpu();
     return env->regwptr[val];
 }
 #endif
@@ -3019,7 +3019,7 @@ static int get_monitor_def(target_long *pval, const char *name)
             if (md->get_value) {
                 *pval = md->get_value(md, md->offset);
             } else {
-                CPUState *env = mon_get_cpu();
+                CPUArchState *env = mon_get_cpu();
                 ptr = (uint8_t *)env + md->offset;
                 switch(md->type) {
                 case MD_I32:
diff --git a/poison.h b/poison.h
index 5354e77..d396f20 100644
--- a/poison.h
+++ b/poison.h
@@ -34,7 +34,7 @@
 #pragma GCC poison TARGET_PAGE_BITS
 #pragma GCC poison TARGET_PAGE_ALIGN
 
-#pragma GCC poison CPUState
+#pragma GCC poison CPUArchState
 #pragma GCC poison env
 
 #pragma GCC poison lduw_phys
diff --git a/softmmu-semi.h b/softmmu-semi.h
index 86a9f8a..648cb95 100644
--- a/softmmu-semi.h
+++ b/softmmu-semi.h
@@ -7,14 +7,14 @@
  * This code is licensed under the GPL
  */
 
-static inline uint32_t softmmu_tget32(CPUState *env, uint32_t addr)
+static inline uint32_t softmmu_tget32(CPUArchState *env, uint32_t addr)
 {
     uint32_t val;
 
     cpu_memory_rw_debug(env, addr, (uint8_t *)&val, 4, 0);
     return tswap32(val);
 }
-static inline uint32_t softmmu_tget8(CPUState *env, uint32_t addr)
+static inline uint32_t softmmu_tget8(CPUArchState *env, uint32_t addr)
 {
     uint8_t val;
 
@@ -26,7 +26,7 @@ static inline uint32_t softmmu_tget8(CPUState *env, uint32_t addr)
 #define get_user_u8(arg, p) ({ arg = softmmu_tget8(env, p) ; 0; })
 #define get_user_ual(arg, p) get_user_u32(arg, p)
 
-static inline void softmmu_tput32(CPUState *env, uint32_t addr, uint32_t val)
+static inline void softmmu_tput32(CPUArchState *env, uint32_t addr, uint32_t val)
 {
     val = tswap32(val);
     cpu_memory_rw_debug(env, addr, (uint8_t *)&val, 4, 1);
@@ -34,7 +34,7 @@ static inline void softmmu_tput32(CPUState *env, uint32_t addr, uint32_t val)
 #define put_user_u32(arg, p) ({ softmmu_tput32(env, p, arg) ; 0; })
 #define put_user_ual(arg, p) put_user_u32(arg, p)
 
-static void *softmmu_lock_user(CPUState *env, uint32_t addr, uint32_t len,
+static void *softmmu_lock_user(CPUArchState *env, uint32_t addr, uint32_t len,
                                int copy)
 {
     uint8_t *p;
@@ -45,7 +45,7 @@ static void *softmmu_lock_user(CPUState *env, uint32_t addr, uint32_t len,
     return p;
 }
 #define lock_user(type, p, len, copy) softmmu_lock_user(env, p, len, copy)
-static char *softmmu_lock_user_string(CPUState *env, uint32_t addr)
+static char *softmmu_lock_user_string(CPUArchState *env, uint32_t addr)
 {
     char *p;
     char *s;
@@ -60,7 +60,7 @@ static char *softmmu_lock_user_string(CPUState *env, uint32_t addr)
     return s;
 }
 #define lock_user_string(p) softmmu_lock_user_string(env, p)
-static void softmmu_unlock_user(CPUState *env, void *p, target_ulong addr,
+static void softmmu_unlock_user(CPUArchState *env, void *p, target_ulong addr,
                                 target_ulong len)
 {
     if (len)
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index ecc2a35..48c0fdc 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -25,7 +25,7 @@
 
 #define TARGET_LONG_BITS 64
 
-#define CPUState struct CPUAlphaState
+#define CPUArchState struct CPUAlphaState
 
 #include "cpu-defs.h"
 
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 2bbb5d1..26c114b 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -23,7 +23,7 @@
 
 #define ELF_MACHINE	EM_ARM
 
-#define CPUState struct CPUARMState
+#define CPUArchState struct CPUARMState
 
 #include "config.h"
 #include "qemu-common.h"
diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index f38393a..31899c2 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -25,7 +25,7 @@
 
 #define TARGET_LONG_BITS 32
 
-#define CPUState struct CPUCRISState
+#define CPUArchState struct CPUCRISState
 
 #include "cpu-defs.h"
 
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 6e26d21..a1ed3e7 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -42,7 +42,7 @@
 #define ELF_MACHINE	EM_386
 #endif
 
-#define CPUState struct CPUX86State
+#define CPUArchState struct CPUX86State
 
 #include "cpu-defs.h"
 
diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index 684b2fa..0902a24 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -22,7 +22,7 @@
 
 #define TARGET_LONG_BITS 32
 
-#define CPUState struct CPULM32State
+#define CPUArchState struct CPULM32State
 
 #include "config.h"
 #include "qemu-common.h"
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index 2c83b89..6696e30 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -22,7 +22,7 @@
 
 #define TARGET_LONG_BITS 32
 
-#define CPUState struct CPUM68KState
+#define CPUArchState struct CPUM68KState
 
 #include "config.h"
 #include "qemu-common.h"
diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index 6ae5649..3b52421 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -24,7 +24,7 @@
 
 #define TARGET_LONG_BITS 32
 
-#define CPUState struct CPUMBState
+#define CPUArchState struct CPUMBState
 
 #include "cpu-defs.h"
 #include "softfloat.h"
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 94381ec..7430aa5 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -7,7 +7,7 @@
 
 #define ELF_MACHINE	EM_MIPS
 
-#define CPUState struct CPUMIPSState
+#define CPUArchState struct CPUMIPSState
 
 #include "config.h"
 #include "qemu-common.h"
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 3508d8a..ad09cbe 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -71,7 +71,7 @@
 
 #endif /* defined (TARGET_PPC64) */
 
-#define CPUState struct CPUPPCState
+#define CPUArchState struct CPUPPCState
 
 #include "cpu-defs.h"
 
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index af6cc4e..ea849fc 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -26,7 +26,7 @@
 
 #define ELF_MACHINE	EM_S390
 
-#define CPUState struct CPUS390XState
+#define CPUArchState struct CPUS390XState
 
 #include "cpu-defs.h"
 #define TARGET_PAGE_BITS 12
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index b45e54f..965536d 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -37,7 +37,7 @@
 #define SH_CPU_SH7750_ALL (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7750R)
 #define SH_CPU_SH7751_ALL (SH_CPU_SH7751 | SH_CPU_SH7751R)
 
-#define CPUState struct CPUSH4State
+#define CPUArchState struct CPUSH4State
 
 #include "cpu-defs.h"
 
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 2c2cea7..86f9de6 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -23,7 +23,7 @@
 # endif
 #endif
 
-#define CPUState struct CPUSPARCState
+#define CPUArchState struct CPUSPARCState
 
 #include "cpu-defs.h"
 
diff --git a/target-unicore32/cpu.h b/target-unicore32/cpu.h
index 171f0a9..a3f8589 100644
--- a/target-unicore32/cpu.h
+++ b/target-unicore32/cpu.h
@@ -18,7 +18,7 @@
 
 #define ELF_MACHINE             EM_UNICORE32
 
-#define CPUState                struct CPUUniCore32State
+#define CPUArchState                struct CPUUniCore32State
 
 #include "config.h"
 #include "qemu-common.h"
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index b7723ca..a7bcf52 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -31,7 +31,7 @@
 #define TARGET_LONG_BITS 32
 #define ELF_MACHINE EM_XTENSA
 
-#define CPUState struct CPUXtensaState
+#define CPUArchState struct CPUXtensaState
 
 #include "config.h"
 #include "qemu-common.h"
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 5b233f5..5af21b3 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -990,10 +990,10 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
     tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_AREG0,
                     TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
     /* In the
-     *  ldr r1 [r0, #(offsetof(CPUState, tlb_table[mem_index][0].addr_read))]
+     *  ldr r1 [r0, #(offsetof(CPUArchState, tlb_table[mem_index][0].addr_read))]
      * below, the offset is likely to exceed 12 bits if mem_index != 0 and
      * not exceed otherwise, so use an
-     *  add r0, r0, #(mem_index * sizeof *CPUState.tlb_table)
+     *  add r0, r0, #(mem_index * sizeof *CPUArchState.tlb_table)
      * before.
      */
     if (mem_index)
@@ -1001,7 +1001,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
                         (mem_index << (TLB_SHIFT & 1)) |
                         ((16 - (TLB_SHIFT >> 1)) << 8));
     tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R0,
-                    offsetof(CPUState, tlb_table[0][0].addr_read));
+                    offsetof(CPUArchState, tlb_table[0][0].addr_read));
     tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, TCG_REG_R1,
                     TCG_REG_R8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
     /* Check alignment.  */
@@ -1012,12 +1012,12 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
     /* XXX: possibly we could use a block data load or writeback in
      * the first access.  */
     tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
-                    offsetof(CPUState, tlb_table[0][0].addr_read) + 4);
+                    offsetof(CPUArchState, tlb_table[0][0].addr_read) + 4);
     tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
                     TCG_REG_R1, addr_reg2, SHIFT_IMM_LSL(0));
 #  endif
     tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
-                    offsetof(CPUState, tlb_table[0][0].addend));
+                    offsetof(CPUArchState, tlb_table[0][0].addend));
 
     switch (opc) {
     case 0:
@@ -1210,10 +1210,10 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
     tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R0,
                     TCG_AREG0, TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
     /* In the
-     *  ldr r1 [r0, #(offsetof(CPUState, tlb_table[mem_index][0].addr_write))]
+     *  ldr r1 [r0, #(offsetof(CPUArchState, tlb_table[mem_index][0].addr_write))]
      * below, the offset is likely to exceed 12 bits if mem_index != 0 and
      * not exceed otherwise, so use an
-     *  add r0, r0, #(mem_index * sizeof *CPUState.tlb_table)
+     *  add r0, r0, #(mem_index * sizeof *CPUArchState.tlb_table)
      * before.
      */
     if (mem_index)
@@ -1221,7 +1221,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
                         (mem_index << (TLB_SHIFT & 1)) |
                         ((16 - (TLB_SHIFT >> 1)) << 8));
     tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R0,
-                    offsetof(CPUState, tlb_table[0][0].addr_write));
+                    offsetof(CPUArchState, tlb_table[0][0].addr_write));
     tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, TCG_REG_R1,
                     TCG_REG_R8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
     /* Check alignment.  */
@@ -1232,12 +1232,12 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
     /* XXX: possibly we could use a block data load or writeback in
      * the first access.  */
     tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
-                    offsetof(CPUState, tlb_table[0][0].addr_write) + 4);
+                    offsetof(CPUArchState, tlb_table[0][0].addr_write) + 4);
     tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
                     TCG_REG_R1, addr_reg2, SHIFT_IMM_LSL(0));
 #  endif
     tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
-                    offsetof(CPUState, tlb_table[0][0].addend));
+                    offsetof(CPUArchState, tlb_table[0][0].addend));
 
     switch (opc) {
     case 0:
@@ -1797,7 +1797,7 @@ static void tcg_target_init(TCGContext *s)
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_PC);
 
     tcg_add_target_add_op_defs(arm_op_defs);
-    tcg_set_frame(s, TCG_AREG0, offsetof(CPUState, temp_buf),
+    tcg_set_frame(s, TCG_AREG0, offsetof(CPUArchState, temp_buf),
                   CPU_TEMP_BUF_NLONGS * sizeof(long));
 }
 
diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index 71f4a8a..c5a3730 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -1040,13 +1040,13 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
     lab1 = gen_new_label();
     lab2 = gen_new_label();
 
-    offset = offsetof(CPUState, tlb_table[mem_index][0].addr_read);
+    offset = offsetof(CPUArchState, tlb_table[mem_index][0].addr_read);
     offset = tcg_out_tlb_read(s, TCG_REG_R26, TCG_REG_R25, addrlo_reg, addrhi_reg,
                               opc & 3, lab1, offset);
 
     /* TLB Hit.  */
     tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20, (offset ? TCG_REG_R1 : TCG_REG_R25),
-               offsetof(CPUState, tlb_table[mem_index][0].addend) - offset);
+               offsetof(CPUArchState, tlb_table[mem_index][0].addend) - offset);
     tcg_out_qemu_ld_direct(s, datalo_reg, datahi_reg, addrlo_reg, TCG_REG_R20, opc);
     tcg_out_branch(s, lab2, 1);
 
@@ -1155,13 +1155,13 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
     lab1 = gen_new_label();
     lab2 = gen_new_label();
 
-    offset = offsetof(CPUState, tlb_table[mem_index][0].addr_write);
+    offset = offsetof(CPUArchState, tlb_table[mem_index][0].addr_write);
     offset = tcg_out_tlb_read(s, TCG_REG_R26, TCG_REG_R25, addrlo_reg, addrhi_reg,
                               opc, lab1, offset);
 
     /* TLB Hit.  */
     tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20, (offset ? TCG_REG_R1 : TCG_REG_R25),
-               offsetof(CPUState, tlb_table[mem_index][0].addend) - offset);
+               offsetof(CPUArchState, tlb_table[mem_index][0].addend) - offset);
 
     /* There are no indexed stores, so we must do this addition explitly.
        Careful to avoid R20, which is used for the bswaps to follow.  */
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 1dbe240..fafd900 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -1031,7 +1031,7 @@ static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
                 (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
 
     tcg_out_modrm_sib_offset(s, OPC_LEA + P_REXW, r1, TCG_AREG0, r1, 0,
-                             offsetof(CPUState, tlb_table[mem_index][0])
+                             offsetof(CPUArchState, tlb_table[mem_index][0])
                              + which);
 
     /* cmp 0(r1), r0 */
diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c
index e3de79f..f90252a 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -1479,8 +1479,8 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
 
     /* Read the TLB entry */
     tcg_out_qemu_tlb(s, addr_reg, s_bits,
-                     offsetof(CPUState, tlb_table[mem_index][0].addr_read),
-                     offsetof(CPUState, tlb_table[mem_index][0].addend));
+                     offsetof(CPUArchState, tlb_table[mem_index][0].addr_read),
+                     offsetof(CPUArchState, tlb_table[mem_index][0].addend));
 
     /* P6 is the fast path, and P7 the slow path */
     tcg_out_bundle(s, mLX,
@@ -1570,8 +1570,8 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
 #endif
 
     tcg_out_qemu_tlb(s, addr_reg, opc,
-                     offsetof(CPUState, tlb_table[mem_index][0].addr_write),
-                     offsetof(CPUState, tlb_table[mem_index][0].addend));
+                     offsetof(CPUArchState, tlb_table[mem_index][0].addr_write),
+                     offsetof(CPUArchState, tlb_table[mem_index][0].addend));
 
     /* P6 is the fast path, and P7 the slow path */
     tcg_out_bundle(s, mLX,
@@ -2368,6 +2368,6 @@ static void tcg_target_init(TCGContext *s)
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R6);
 
     tcg_add_target_add_op_defs(ia64_op_defs);
-    tcg_set_frame(s, TCG_AREG0, offsetof(CPUState, temp_buf),
+    tcg_set_frame(s, TCG_AREG0, offsetof(CPUArchState, temp_buf),
                   CPU_TEMP_BUF_NLONGS * sizeof(long));
 }
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index c5c3282..c6aa5bc 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -827,7 +827,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
     tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
     tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
     tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
-                    offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_meml);
+                    offsetof(CPUArchState, tlb_table[mem_index][0].addr_read) + addr_meml);
     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
     tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
 
@@ -837,7 +837,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
     tcg_out_nop(s);
 
     tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
-                    offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_memh);
+                    offsetof(CPUArchState, tlb_table[mem_index][0].addr_read) + addr_memh);
 
     label1_ptr = s->code_ptr;
     tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
@@ -893,7 +893,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
     reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
 
     tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
-                    offsetof(CPUState, tlb_table[mem_index][0].addend));
+                    offsetof(CPUArchState, tlb_table[mem_index][0].addend));
     tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_A0, addr_regl);
 #else
     if (GUEST_BASE == (int16_t)GUEST_BASE) {
@@ -1013,7 +1013,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
     tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
     tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
     tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
-                    offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_meml);
+                    offsetof(CPUArchState, tlb_table[mem_index][0].addr_write) + addr_meml);
     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
     tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
 
@@ -1023,7 +1023,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
     tcg_out_nop(s);
 
     tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
-                    offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_memh);
+                    offsetof(CPUArchState, tlb_table[mem_index][0].addr_write) + addr_memh);
 
     label1_ptr = s->code_ptr;
     tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
@@ -1080,7 +1080,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
     reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
 
     tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
-                    offsetof(CPUState, tlb_table[mem_index][0].addend));
+                    offsetof(CPUArchState, tlb_table[mem_index][0].addend));
     tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
 #else
     if (GUEST_BASE == (int16_t)GUEST_BASE) {
@@ -1529,6 +1529,6 @@ static void tcg_target_init(TCGContext *s)
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);   /* stack pointer */
 
     tcg_add_target_add_op_defs(mips_op_defs);
-    tcg_set_frame(s, TCG_AREG0, offsetof(CPUState, temp_buf),
+    tcg_set_frame(s, TCG_AREG0, offsetof(CPUArchState, temp_buf),
                   CPU_TEMP_BUF_NLONGS * sizeof(long));
 }
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index f5d9bf3..6a34cab 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -564,7 +564,7 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
     tcg_out32 (s, (LWZU
                    | RT (r1)
                    | RA (r0)
-                   | offsetof (CPUState, tlb_table[mem_index][0].addr_read)
+                   | offsetof (CPUArchState, tlb_table[mem_index][0].addr_read)
                    )
         );
     tcg_out32 (s, (RLWINM
@@ -760,7 +760,7 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
     tcg_out32 (s, (LWZU
                    | RT (r1)
                    | RA (r0)
-                   | offsetof (CPUState, tlb_table[mem_index][0].addr_write)
+                   | offsetof (CPUArchState, tlb_table[mem_index][0].addr_write)
                    )
         );
     tcg_out32 (s, (RLWINM
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 4419378..7f723b5 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -635,7 +635,7 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
     rbase = 0;
 
     tcg_out_tlb_read (s, r0, r1, r2, addr_reg, s_bits,
-                      offsetof (CPUState, tlb_table[mem_index][0].addr_read));
+                      offsetof (CPUArchState, tlb_table[mem_index][0].addr_read));
 
     tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1) | CMP_L);
 
@@ -782,7 +782,7 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
     rbase = 0;
 
     tcg_out_tlb_read (s, r0, r1, r2, addr_reg, opc,
-                      offsetof (CPUState, tlb_table[mem_index][0].addr_write));
+                      offsetof (CPUArchState, tlb_table[mem_index][0].addr_write));
 
     tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1) | CMP_L);
 
diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c
index 9317fe8..47ffcc1 100644
--- a/tcg/s390/tcg-target.c
+++ b/tcg/s390/tcg-target.c
@@ -1439,9 +1439,9 @@ static void tcg_prepare_qemu_ldst(TCGContext* s, TCGReg data_reg,
     tgen64_andi_tmp(s, arg1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
 
     if (is_store) {
-        ofs = offsetof(CPUState, tlb_table[mem_index][0].addr_write);
+        ofs = offsetof(CPUArchState, tlb_table[mem_index][0].addr_write);
     } else {
-        ofs = offsetof(CPUState, tlb_table[mem_index][0].addr_read);
+        ofs = offsetof(CPUArchState, tlb_table[mem_index][0].addr_read);
     }
     assert(ofs < 0x80000);
 
@@ -1515,7 +1515,7 @@ static void tcg_prepare_qemu_ldst(TCGContext* s, TCGReg data_reg,
     *(label1_ptr + 1) = ((unsigned long)s->code_ptr -
                          (unsigned long)label1_ptr) >> 1;
 
-    ofs = offsetof(CPUState, tlb_table[mem_index][0].addend);
+    ofs = offsetof(CPUArchState, tlb_table[mem_index][0].addend);
     assert(ofs < 0x80000);
 
     tcg_out_mem(s, 0, RXY_AG, arg0, arg1, TCG_AREG0, ofs);
@@ -2293,7 +2293,7 @@ static void tcg_target_init(TCGContext *s)
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
 
     tcg_add_target_add_op_defs(s390_op_defs);
-    tcg_set_frame(s, TCG_AREG0, offsetof(CPUState, temp_buf),
+    tcg_set_frame(s, TCG_AREG0, offsetof(CPUArchState, temp_buf),
                   CPU_TEMP_BUF_NLONGS * sizeof(long));
 }
 
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 4461fb4..b287122 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -776,7 +776,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
     tcg_out_andi(s, arg1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
 
     /* add arg1, x, arg1 */
-    tcg_out_addi(s, arg1, offsetof(CPUState,
+    tcg_out_addi(s, arg1, offsetof(CPUArchState,
                                    tlb_table[mem_index][0].addr_read));
 
     /* add env, arg1, arg1 */
@@ -988,7 +988,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
     tcg_out_andi(s, arg1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
 
     /* add arg1, x, arg1 */
-    tcg_out_addi(s, arg1, offsetof(CPUState,
+    tcg_out_addi(s, arg1, offsetof(CPUArchState,
                                    tlb_table[mem_index][0].addr_write));
 
     /* add env, arg1, arg1 */
diff --git a/tcg/tci/tcg-target.c b/tcg/tci/tcg-target.c
index fc0880c..bd85073 100644
--- a/tcg/tci/tcg-target.c
+++ b/tcg/tci/tcg-target.c
@@ -891,7 +891,7 @@ static void tcg_target_init(TCGContext *s)
     tcg_regset_clear(s->reserved_regs);
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
     tcg_add_target_add_op_defs(tcg_target_op_defs);
-    tcg_set_frame(s, TCG_AREG0, offsetof(CPUState, temp_buf),
+    tcg_set_frame(s, TCG_AREG0, offsetof(CPUArchState, temp_buf),
                   CPU_TEMP_BUF_NLONGS * sizeof(long));
 }
 
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
index 81fcc0f..b61e99a 100644
--- a/tcg/tci/tcg-target.h
+++ b/tcg/tci/tcg-target.h
@@ -154,7 +154,7 @@ typedef enum {
 
 void tci_disas(uint8_t opc);
 
-unsigned long tcg_qemu_tb_exec(CPUState *env, uint8_t *tb_ptr);
+unsigned long tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr);
 #define tcg_qemu_tb_exec tcg_qemu_tb_exec
 
 static inline void flush_icache_range(tcg_target_ulong start,
diff --git a/tci.c b/tci.c
index a20a714..fb9ebef 100644
--- a/tci.c
+++ b/tci.c
@@ -52,7 +52,7 @@ typedef uint64_t (*helper_function)(tcg_target_ulong, tcg_target_ulong,
 
 /* TCI can optionally use a global register variable for env. */
 #if !defined(AREG0)
-CPUState *env;
+CPUArchState *env;
 #endif
 
 /* Targets which don't use GETPC also don't need tci_tb_ptr
@@ -429,7 +429,7 @@ static bool tci_compare64(uint64_t u0, uint64_t u1, TCGCond condition)
 }
 
 /* Interpret pseudo code in tb. */
-unsigned long tcg_qemu_tb_exec(CPUState *cpustate, uint8_t *tb_ptr)
+unsigned long tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr)
 {
     unsigned long next_tb = 0;
 
diff --git a/translate-all.c b/translate-all.c
index 041c108..8c7d303 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -51,7 +51,7 @@ void cpu_gen_init(void)
    '*gen_code_size_ptr' contains the size of the generated code (host
    code).
 */
-int cpu_gen_code(CPUState *env, TranslationBlock *tb, int *gen_code_size_ptr)
+int cpu_gen_code(CPUArchState *env, TranslationBlock *tb, int *gen_code_size_ptr)
 {
     TCGContext *s = &tcg_ctx;
     uint8_t *gen_code_buf;
@@ -109,7 +109,7 @@ int cpu_gen_code(CPUState *env, TranslationBlock *tb, int *gen_code_size_ptr)
 /* The cpu state corresponding to 'searched_pc' is restored.
  */
 int cpu_restore_state(TranslationBlock *tb,
-                      CPUState *env, unsigned long searched_pc)
+                      CPUArchState *env, unsigned long searched_pc)
 {
     TCGContext *s = &tcg_ctx;
     int j;
diff --git a/user-exec.c b/user-exec.c
index abf6885..cd905ff 100644
--- a/user-exec.c
+++ b/user-exec.c
@@ -38,7 +38,7 @@
 
 //#define DEBUG_SIGNAL
 
-static void exception_action(CPUState *env1)
+static void exception_action(CPUArchState *env1)
 {
 #if defined(TARGET_I386)
     raise_exception_err_env(env1, env1->exception_index, env1->error_code);
@@ -50,7 +50,7 @@ static void exception_action(CPUState *env1)
 /* exit the current TB from a signal handler. The host registers are
    restored in a state compatible with the CPU emulator
  */
-void cpu_resume_from_signal(CPUState *env1, void *puc)
+void cpu_resume_from_signal(CPUArchState *env1, void *puc)
 {
 #ifdef __linux__
     struct ucontext *uc = puc;
diff --git a/xen-all.c b/xen-all.c
index 6cef506..493112b 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -530,14 +530,14 @@ static MemoryListener xen_memory_listener = {
 
 static void xen_reset_vcpu(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUArchState *env = opaque;
 
     env->halted = 1;
 }
 
 void xen_vcpu_init(void)
 {
-    CPUState *first_cpu;
+    CPUArchState *first_cpu;
 
     if ((first_cpu = qemu_get_cpu(0))) {
         qemu_register_reset(xen_reset_vcpu, first_cpu);
commit 5bfcb36ec49192cb22f45f4b7ae805c530a1fd9e
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:24 2012 +0100

    xtensa hw/: Don't use CPUState
    
    Scripted conversion:
      for file in hw/xtensa_*.[hc]; do
        sed -i "s/CPUState/CPUXtensaState/g" $file
      done
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c
index 80ba4d7..afdef49 100644
--- a/hw/xtensa_lx60.c
+++ b/hw/xtensa_lx60.c
@@ -148,7 +148,7 @@ static uint64_t translate_phys_addr(void *env, uint64_t addr)
 
 static void lx60_reset(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUXtensaState *env = opaque;
 
     cpu_state_reset(env);
 }
@@ -164,7 +164,7 @@ static void lx_init(const LxBoardDesc *board,
     int be = 0;
 #endif
     MemoryRegion *system_memory = get_system_memory();
-    CPUState *env = NULL;
+    CPUXtensaState *env = NULL;
     MemoryRegion *ram, *rom, *system_io;
     DriveInfo *dinfo;
     pflash_t *flash = NULL;
diff --git a/hw/xtensa_pic.c b/hw/xtensa_pic.c
index 71d5fc8..653ded6 100644
--- a/hw/xtensa_pic.c
+++ b/hw/xtensa_pic.c
@@ -29,7 +29,7 @@
 #include "qemu-log.h"
 #include "qemu-timer.h"
 
-void xtensa_advance_ccount(CPUState *env, uint32_t d)
+void xtensa_advance_ccount(CPUXtensaState *env, uint32_t d)
 {
     uint32_t old_ccount = env->sregs[CCOUNT];
 
@@ -45,7 +45,7 @@ void xtensa_advance_ccount(CPUState *env, uint32_t d)
     }
 }
 
-void check_interrupts(CPUState *env)
+void check_interrupts(CPUXtensaState *env)
 {
     int minlevel = xtensa_get_cintlevel(env);
     uint32_t int_set_enabled = env->sregs[INTSET] & env->sregs[INTENABLE];
@@ -84,7 +84,7 @@ void check_interrupts(CPUState *env)
 
 static void xtensa_set_irq(void *opaque, int irq, int active)
 {
-    CPUState *env = opaque;
+    CPUXtensaState *env = opaque;
 
     if (irq >= env->config->ninterrupt) {
         qemu_log("%s: bad IRQ %d\n", __func__, irq);
@@ -101,12 +101,12 @@ static void xtensa_set_irq(void *opaque, int irq, int active)
     }
 }
 
-void xtensa_timer_irq(CPUState *env, uint32_t id, uint32_t active)
+void xtensa_timer_irq(CPUXtensaState *env, uint32_t id, uint32_t active)
 {
     qemu_set_irq(env->irq_inputs[env->config->timerint[id]], active);
 }
 
-void xtensa_rearm_ccompare_timer(CPUState *env)
+void xtensa_rearm_ccompare_timer(CPUXtensaState *env)
 {
     int i;
     uint32_t wake_ccount = env->sregs[CCOUNT] - 1;
@@ -125,7 +125,7 @@ void xtensa_rearm_ccompare_timer(CPUState *env)
 
 static void xtensa_ccompare_cb(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUXtensaState *env = opaque;
 
     if (env->halted) {
         env->halt_clock = qemu_get_clock_ns(vm_clock);
@@ -137,7 +137,7 @@ static void xtensa_ccompare_cb(void *opaque)
     }
 }
 
-void xtensa_irq_init(CPUState *env)
+void xtensa_irq_init(CPUXtensaState *env)
 {
     env->irq_inputs = (void **)qemu_allocate_irqs(
             xtensa_set_irq, env, env->config->ninterrupt);
@@ -148,7 +148,7 @@ void xtensa_irq_init(CPUState *env)
     }
 }
 
-void *xtensa_get_extint(CPUState *env, unsigned extint)
+void *xtensa_get_extint(CPUXtensaState *env, unsigned extint)
 {
     if (extint < env->config->nextint) {
         unsigned irq = env->config->extint[extint];
diff --git a/hw/xtensa_sim.c b/hw/xtensa_sim.c
index 445cfde..c7e05dc 100644
--- a/hw/xtensa_sim.c
+++ b/hw/xtensa_sim.c
@@ -47,7 +47,7 @@ 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)
 {
-    CPUState *env = NULL;
+    CPUXtensaState *env = NULL;
     MemoryRegion *ram, *rom;
     int n;
 
commit 98cec4a2e6d8bf72a2798036397049b5e906e49c
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:24 2012 +0100

    sparc hw/: Don't use CPUState
    
    Scripted conversion:
      for file in hw/sun4m.c hw/sun4u.c hw/grlib.h hw/leon3.c; do
        sed -i "s/CPUState/CPUSPARCState/g" $file
      done
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/grlib.h b/hw/grlib.h
index fdf4b11..e1c4137 100644
--- a/hw/grlib.h
+++ b/hw/grlib.h
@@ -42,7 +42,7 @@ void grlib_irqmp_ack(DeviceState *dev, int intno);
 
 static inline
 DeviceState *grlib_irqmp_create(target_phys_addr_t   base,
-                                CPUState            *env,
+                                CPUSPARCState            *env,
                                 qemu_irq           **cpu_irqs,
                                 uint32_t             nr_irqs,
                                 set_pil_in_fn        set_pil_in)
diff --git a/hw/leon3.c b/hw/leon3.c
index 1dc5a02..0a5ff16 100644
--- a/hw/leon3.c
+++ b/hw/leon3.c
@@ -42,14 +42,14 @@
 #define MAX_PILS 16
 
 typedef struct ResetData {
-    CPUState *env;
+    CPUSPARCState *env;
     uint32_t  entry;            /* save kernel entry in case of reset */
 } ResetData;
 
 static void main_cpu_reset(void *opaque)
 {
     ResetData *s   = (ResetData *)opaque;
-    CPUState  *env = s->env;
+    CPUSPARCState  *env = s->env;
 
     cpu_state_reset(env);
 
@@ -65,7 +65,7 @@ void leon3_irq_ack(void *irq_manager, int intno)
 
 static void leon3_set_pil_in(void *opaque, uint32_t pil_in)
 {
-    CPUState *env = (CPUState *)opaque;
+    CPUSPARCState *env = (CPUSPARCState *)opaque;
 
     assert(env != NULL);
 
@@ -101,7 +101,7 @@ static void leon3_generic_hw_init(ram_addr_t  ram_size,
                                   const char *initrd_filename,
                                   const char *cpu_model)
 {
-    CPUState   *env;
+    CPUSPARCState   *env;
     MemoryRegion *address_space_mem = get_system_memory();
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     MemoryRegion *prom = g_new(MemoryRegion, 1);
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 4045740..7bcbf37 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -228,7 +228,7 @@ void sun4m_irq_info(Monitor *mon)
         slavio_irq_info(mon, slavio_intctl);
 }
 
-void cpu_check_irqs(CPUState *env)
+void cpu_check_irqs(CPUSPARCState *env)
 {
     if (env->pil_in && (env->interrupt_index == 0 ||
                         (env->interrupt_index & ~15) == TT_EXTINT)) {
@@ -253,7 +253,7 @@ void cpu_check_irqs(CPUState *env)
     }
 }
 
-static void cpu_kick_irq(CPUState *env)
+static void cpu_kick_irq(CPUSPARCState *env)
 {
     env->halted = 0;
     cpu_check_irqs(env);
@@ -262,7 +262,7 @@ static void cpu_kick_irq(CPUState *env)
 
 static void cpu_set_irq(void *opaque, int irq, int level)
 {
-    CPUState *env = opaque;
+    CPUSPARCState *env = opaque;
 
     if (level) {
         trace_sun4m_cpu_set_irq_raise(irq);
@@ -281,7 +281,7 @@ static void dummy_cpu_set_irq(void *opaque, int irq, int level)
 
 static void main_cpu_reset(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUSPARCState *env = opaque;
 
     cpu_state_reset(env);
     env->halted = 0;
@@ -289,7 +289,7 @@ static void main_cpu_reset(void *opaque)
 
 static void secondary_cpu_reset(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUSPARCState *env = opaque;
 
     cpu_state_reset(env);
     env->halted = 1;
@@ -809,7 +809,7 @@ static TypeInfo ram_info = {
 static void cpu_devinit(const char *cpu_model, unsigned int id,
                         uint64_t prom_addr, qemu_irq **cpu_irqs)
 {
-    CPUState *env;
+    CPUSPARCState *env;
 
     env = cpu_init(cpu_model);
     if (!env) {
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 8b043f2..c32eddb 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -243,7 +243,7 @@ static unsigned long sun4u_load_kernel(const char *kernel_filename,
     return kernel_size;
 }
 
-void cpu_check_irqs(CPUState *env)
+void cpu_check_irqs(CPUSPARCState *env)
 {
     uint32_t pil = env->pil_in |
                   (env->softint & ~(SOFTINT_TIMER | SOFTINT_STIMER));
@@ -297,7 +297,7 @@ void cpu_check_irqs(CPUState *env)
     }
 }
 
-static void cpu_kick_irq(CPUState *env)
+static void cpu_kick_irq(CPUSPARCState *env)
 {
     env->halted = 0;
     cpu_check_irqs(env);
@@ -306,7 +306,7 @@ static void cpu_kick_irq(CPUState *env)
 
 static void cpu_set_irq(void *opaque, int irq, int level)
 {
-    CPUState *env = opaque;
+    CPUSPARCState *env = opaque;
 
     if (level) {
         CPUIRQ_DPRINTF("Raise CPU IRQ %d\n", irq);
@@ -320,7 +320,7 @@ static void cpu_set_irq(void *opaque, int irq, int level)
 }
 
 typedef struct ResetData {
-    CPUState *env;
+    CPUSPARCState *env;
     uint64_t prom_addr;
 } ResetData;
 
@@ -344,7 +344,7 @@ void cpu_get_timer(QEMUFile *f, CPUTimer *s)
     qemu_get_timer(f, s->qtimer);
 }
 
-static CPUTimer* cpu_timer_create(const char* name, CPUState *env,
+static CPUTimer* cpu_timer_create(const char* name, CPUSPARCState *env,
                                   QEMUBHFunc *cb, uint32_t frequency,
                                   uint64_t disabled_mask)
 {
@@ -373,7 +373,7 @@ static void cpu_timer_reset(CPUTimer *timer)
 static void main_cpu_reset(void *opaque)
 {
     ResetData *s = (ResetData *)opaque;
-    CPUState *env = s->env;
+    CPUSPARCState *env = s->env;
     static unsigned int nr_resets;
 
     cpu_state_reset(env);
@@ -396,7 +396,7 @@ static void main_cpu_reset(void *opaque)
 
 static void tick_irq(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUSPARCState *env = opaque;
 
     CPUTimer* timer = env->tick;
 
@@ -413,7 +413,7 @@ static void tick_irq(void *opaque)
 
 static void stick_irq(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUSPARCState *env = opaque;
 
     CPUTimer* timer = env->stick;
 
@@ -430,7 +430,7 @@ static void stick_irq(void *opaque)
 
 static void hstick_irq(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUSPARCState *env = opaque;
 
     CPUTimer* timer = env->hstick;
 
@@ -714,9 +714,9 @@ static TypeInfo ram_info = {
     .class_init    = ram_class_init,
 };
 
-static CPUState *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef)
+static CPUSPARCState *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef)
 {
-    CPUState *env;
+    CPUSPARCState *env;
     ResetData *reset_info;
 
     uint32_t   tick_frequency = 100*1000000;
@@ -755,7 +755,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
                         const char *initrd_filename, const char *cpu_model,
                         const struct hwdef *hwdef)
 {
-    CPUState *env;
+    CPUSPARCState *env;
     M48t59State *nvram;
     unsigned int i;
     long initrd_size, kernel_size;
commit 0b7ade1d3e02aa7c5b2e8f4aa7de6d836759b39d
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:23 2012 +0100

    sh4 hw/: Don't use CPUState
    
    Scripted conversion:
      for file in hw/sh.h hw/shix.c hw/r2d.c; do
        sed -i "s/CPUState/CPUSH4State/g" $file
      done
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/r2d.c b/hw/r2d.c
index ae327a7..c55de01 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -192,14 +192,14 @@ static qemu_irq *r2d_fpga_init(MemoryRegion *sysmem,
 }
 
 typedef struct ResetData {
-    CPUState *env;
+    CPUSH4State *env;
     uint32_t vector;
 } ResetData;
 
 static void main_cpu_reset(void *opaque)
 {
     ResetData *s = (ResetData *)opaque;
-    CPUState *env = s->env;
+    CPUSH4State *env = s->env;
 
     cpu_state_reset(env);
     env->pc = s->vector;
@@ -224,7 +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)
 {
-    CPUState *env;
+    CPUSH4State *env;
     ResetData *reset_info;
     struct SH7750State *s;
     MemoryRegion *sdram = g_new(MemoryRegion, 1);
diff --git a/hw/sh.h b/hw/sh.h
index 6488db2..40df18c 100644
--- a/hw/sh.h
+++ b/hw/sh.h
@@ -11,7 +11,7 @@
 struct SH7750State;
 struct MemoryRegion;
 
-struct SH7750State *sh7750_init(CPUState * cpu, struct MemoryRegion *sysmem);
+struct SH7750State *sh7750_init(CPUSH4State * cpu, struct MemoryRegion *sysmem);
 
 typedef struct {
     /* The callback will be triggered if any of the designated lines change */
diff --git a/hw/shix.c b/hw/shix.c
index e259c17..dd9ce17 100644
--- a/hw/shix.c
+++ b/hw/shix.c
@@ -43,7 +43,7 @@ static void shix_init(ram_addr_t ram_size,
 	       const char *initrd_filename, const char *cpu_model)
 {
     int ret;
-    CPUState *env;
+    CPUSH4State *env;
     struct SH7750State *s;
     MemoryRegion *sysmem = get_system_memory();
     MemoryRegion *rom = g_new(MemoryRegion, 1);
commit 0e4213a7ef630e1de4c7fc0bd6ff9ecc6e07daea
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:23 2012 +0100

    s390x hw/: Don't use CPUState
    
    Scripted conversion:
      for file in hw/s390-*.[hc]; do
        sed -i "s/CPUState/CPUS390XState/g" $file
      done
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index c450e4b..be1f5f1 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -85,7 +85,7 @@ VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size)
     return bus;
 }
 
-static void s390_virtio_irq(CPUState *env, int config_change, uint64_t token)
+static void s390_virtio_irq(CPUS390XState *env, int config_change, uint64_t token)
 {
     if (kvm_enabled()) {
         kvm_s390_virtio_irq(env, config_change, token);
@@ -116,7 +116,7 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
     s390_virtio_device_sync(dev);
 
     if (dev->qdev.hotplugged) {
-        CPUState *env = s390_cpu_addr2state(0);
+        CPUS390XState *env = s390_cpu_addr2state(0);
         s390_virtio_irq(env, VIRTIO_PARAM_DEV_ADD, dev->dev_offs);
     }
 
@@ -331,7 +331,7 @@ static void virtio_s390_notify(void *opaque, uint16_t vector)
 {
     VirtIOS390Device *dev = (VirtIOS390Device*)opaque;
     uint64_t token = s390_virtio_device_vq_token(dev, vector);
-    CPUState *env = s390_cpu_addr2state(0);
+    CPUS390XState *env = s390_cpu_addr2state(0);
 
     s390_virtio_irq(env, 0, token);
 }
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index 15e3ef3..1ebe70d 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 CPUState **ipi_states;
+static CPUS390XState **ipi_states;
 
-CPUState *s390_cpu_addr2state(uint16_t cpu_addr)
+CPUS390XState *s390_cpu_addr2state(uint16_t cpu_addr)
 {
     if (cpu_addr >= smp_cpus) {
         return NULL;
@@ -72,7 +72,7 @@ CPUState *s390_cpu_addr2state(uint16_t cpu_addr)
     return ipi_states[cpu_addr];
 }
 
-int s390_virtio_hypercall(CPUState *env, uint64_t mem, uint64_t hypercall)
+int s390_virtio_hypercall(CPUS390XState *env, uint64_t mem, uint64_t hypercall)
 {
     int r = 0, i;
 
@@ -129,7 +129,7 @@ int s390_virtio_hypercall(CPUState *env, uint64_t mem, uint64_t hypercall)
  */
 static unsigned s390_running_cpus;
 
-void s390_add_running_cpu(CPUState *env)
+void s390_add_running_cpu(CPUS390XState *env)
 {
     if (env->halted) {
         s390_running_cpus++;
@@ -138,7 +138,7 @@ void s390_add_running_cpu(CPUState *env)
     }
 }
 
-unsigned s390_del_running_cpu(CPUState *env)
+unsigned s390_del_running_cpu(CPUS390XState *env)
 {
     if (env->halted == 0) {
         assert(s390_running_cpus >= 1);
@@ -157,7 +157,7 @@ static void s390_init(ram_addr_t my_ram_size,
                       const char *initrd_filename,
                       const char *cpu_model)
 {
-    CPUState *env = NULL;
+    CPUS390XState *env = NULL;
     MemoryRegion *sysmem = get_system_memory();
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     ram_addr_t kernel_size = 0;
@@ -205,10 +205,10 @@ static void s390_init(ram_addr_t my_ram_size,
         cpu_model = "host";
     }
 
-    ipi_states = g_malloc(sizeof(CPUState *) * smp_cpus);
+    ipi_states = g_malloc(sizeof(CPUS390XState *) * smp_cpus);
 
     for (i = 0; i < smp_cpus; i++) {
-        CPUState *tmp_env;
+        CPUS390XState *tmp_env;
 
         tmp_env = cpu_init(cpu_model);
         if (!env) {
commit e2684c0b581f2742aa52edc8cd9be255032f9247
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:23 2012 +0100

    ppc hw/: Don't use CPUState
    
    Scripted conversion:
      for file in hw/ppc*.[hc] hw/mpc8544_guts.c hw/spapr*.[hc] hw/virtex_ml507.c hw/xics.c; do
        sed -i "s/CPUState/CPUPPCState/g" $file
      done
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/mpc8544_guts.c b/hw/mpc8544_guts.c
index aeb2de7..13b0ddd 100644
--- a/hw/mpc8544_guts.c
+++ b/hw/mpc8544_guts.c
@@ -62,7 +62,7 @@ static uint64_t mpc8544_guts_read(void *opaque, target_phys_addr_t addr,
                                   unsigned size)
 {
     uint32_t value = 0;
-    CPUState *env = cpu_single_env;
+    CPUPPCState *env = cpu_single_env;
 
     addr &= MPC8544_GUTS_MMIO_SIZE - 1;
     switch (addr) {
diff --git a/hw/ppc.c b/hw/ppc.c
index a9516f1..98546de 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -47,10 +47,10 @@
 #  define LOG_TB(...) do { } while (0)
 #endif
 
-static void cpu_ppc_tb_stop (CPUState *env);
-static void cpu_ppc_tb_start (CPUState *env);
+static void cpu_ppc_tb_stop (CPUPPCState *env);
+static void cpu_ppc_tb_start (CPUPPCState *env);
 
-void ppc_set_irq(CPUState *env, int n_IRQ, int level)
+void ppc_set_irq(CPUPPCState *env, int n_IRQ, int level)
 {
     unsigned int old_pending = env->pending_interrupts;
 
@@ -77,7 +77,7 @@ void ppc_set_irq(CPUState *env, int n_IRQ, int level)
 /* PowerPC 6xx / 7xx internal IRQ controller */
 static void ppc6xx_set_irq (void *opaque, int pin, int level)
 {
-    CPUState *env = opaque;
+    CPUPPCState *env = opaque;
     int cur_level;
 
     LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
@@ -151,7 +151,7 @@ static void ppc6xx_set_irq (void *opaque, int pin, int level)
     }
 }
 
-void ppc6xx_irq_init (CPUState *env)
+void ppc6xx_irq_init (CPUPPCState *env)
 {
     env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env,
                                                   PPC6xx_INPUT_NB);
@@ -161,7 +161,7 @@ void ppc6xx_irq_init (CPUState *env)
 /* PowerPC 970 internal IRQ controller */
 static void ppc970_set_irq (void *opaque, int pin, int level)
 {
-    CPUState *env = opaque;
+    CPUPPCState *env = opaque;
     int cur_level;
 
     LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
@@ -233,7 +233,7 @@ static void ppc970_set_irq (void *opaque, int pin, int level)
     }
 }
 
-void ppc970_irq_init (CPUState *env)
+void ppc970_irq_init (CPUPPCState *env)
 {
     env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env,
                                                   PPC970_INPUT_NB);
@@ -242,7 +242,7 @@ void ppc970_irq_init (CPUState *env)
 /* POWER7 internal IRQ controller */
 static void power7_set_irq (void *opaque, int pin, int level)
 {
-    CPUState *env = opaque;
+    CPUPPCState *env = opaque;
 
     LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
                 env, pin, level);
@@ -266,7 +266,7 @@ static void power7_set_irq (void *opaque, int pin, int level)
     }
 }
 
-void ppcPOWER7_irq_init (CPUState *env)
+void ppcPOWER7_irq_init (CPUPPCState *env)
 {
     env->irq_inputs = (void **)qemu_allocate_irqs(&power7_set_irq, env,
                                                   POWER7_INPUT_NB);
@@ -276,7 +276,7 @@ void ppcPOWER7_irq_init (CPUState *env)
 /* PowerPC 40x internal IRQ controller */
 static void ppc40x_set_irq (void *opaque, int pin, int level)
 {
-    CPUState *env = opaque;
+    CPUPPCState *env = opaque;
     int cur_level;
 
     LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
@@ -346,7 +346,7 @@ static void ppc40x_set_irq (void *opaque, int pin, int level)
     }
 }
 
-void ppc40x_irq_init (CPUState *env)
+void ppc40x_irq_init (CPUPPCState *env)
 {
     env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq,
                                                   env, PPC40x_INPUT_NB);
@@ -355,7 +355,7 @@ void ppc40x_irq_init (CPUState *env)
 /* PowerPC E500 internal IRQ controller */
 static void ppce500_set_irq (void *opaque, int pin, int level)
 {
-    CPUState *env = opaque;
+    CPUPPCState *env = opaque;
     int cur_level;
 
     LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
@@ -407,7 +407,7 @@ static void ppce500_set_irq (void *opaque, int pin, int level)
     }
 }
 
-void ppce500_irq_init (CPUState *env)
+void ppce500_irq_init (CPUPPCState *env)
 {
     env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq,
                                         env, PPCE500_INPUT_NB);
@@ -421,7 +421,7 @@ uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk, int64_t tb_offset)
     return muldiv64(vmclk, tb_env->tb_freq, get_ticks_per_sec()) + tb_offset;
 }
 
-uint64_t cpu_ppc_load_tbl (CPUState *env)
+uint64_t cpu_ppc_load_tbl (CPUPPCState *env)
 {
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t tb;
@@ -436,7 +436,7 @@ uint64_t cpu_ppc_load_tbl (CPUState *env)
     return tb;
 }
 
-static inline uint32_t _cpu_ppc_load_tbu(CPUState *env)
+static inline uint32_t _cpu_ppc_load_tbu(CPUPPCState *env)
 {
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t tb;
@@ -447,7 +447,7 @@ static inline uint32_t _cpu_ppc_load_tbu(CPUState *env)
     return tb >> 32;
 }
 
-uint32_t cpu_ppc_load_tbu (CPUState *env)
+uint32_t cpu_ppc_load_tbu (CPUPPCState *env)
 {
     if (kvm_enabled()) {
         return env->spr[SPR_TBU];
@@ -464,7 +464,7 @@ static inline void cpu_ppc_store_tb(ppc_tb_t *tb_env, uint64_t vmclk,
                 __func__, value, *tb_offsetp);
 }
 
-void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
+void cpu_ppc_store_tbl (CPUPPCState *env, uint32_t value)
 {
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t tb;
@@ -475,7 +475,7 @@ void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
                      &tb_env->tb_offset, tb | (uint64_t)value);
 }
 
-static inline void _cpu_ppc_store_tbu(CPUState *env, uint32_t value)
+static inline void _cpu_ppc_store_tbu(CPUPPCState *env, uint32_t value)
 {
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t tb;
@@ -486,12 +486,12 @@ static inline void _cpu_ppc_store_tbu(CPUState *env, uint32_t value)
                      &tb_env->tb_offset, ((uint64_t)value << 32) | tb);
 }
 
-void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
+void cpu_ppc_store_tbu (CPUPPCState *env, uint32_t value)
 {
     _cpu_ppc_store_tbu(env, value);
 }
 
-uint64_t cpu_ppc_load_atbl (CPUState *env)
+uint64_t cpu_ppc_load_atbl (CPUPPCState *env)
 {
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t tb;
@@ -502,7 +502,7 @@ uint64_t cpu_ppc_load_atbl (CPUState *env)
     return tb;
 }
 
-uint32_t cpu_ppc_load_atbu (CPUState *env)
+uint32_t cpu_ppc_load_atbu (CPUPPCState *env)
 {
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t tb;
@@ -513,7 +513,7 @@ uint32_t cpu_ppc_load_atbu (CPUState *env)
     return tb >> 32;
 }
 
-void cpu_ppc_store_atbl (CPUState *env, uint32_t value)
+void cpu_ppc_store_atbl (CPUPPCState *env, uint32_t value)
 {
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t tb;
@@ -524,7 +524,7 @@ void cpu_ppc_store_atbl (CPUState *env, uint32_t value)
                      &tb_env->atb_offset, tb | (uint64_t)value);
 }
 
-void cpu_ppc_store_atbu (CPUState *env, uint32_t value)
+void cpu_ppc_store_atbu (CPUPPCState *env, uint32_t value)
 {
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t tb;
@@ -535,7 +535,7 @@ void cpu_ppc_store_atbu (CPUState *env, uint32_t value)
                      &tb_env->atb_offset, ((uint64_t)value << 32) | tb);
 }
 
-static void cpu_ppc_tb_stop (CPUState *env)
+static void cpu_ppc_tb_stop (CPUPPCState *env)
 {
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t tb, atb, vmclk;
@@ -557,7 +557,7 @@ static void cpu_ppc_tb_stop (CPUState *env)
     }
 }
 
-static void cpu_ppc_tb_start (CPUState *env)
+static void cpu_ppc_tb_start (CPUPPCState *env)
 {
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t tb, atb, vmclk;
@@ -578,7 +578,7 @@ static void cpu_ppc_tb_start (CPUState *env)
     }
 }
 
-static inline uint32_t _cpu_ppc_load_decr(CPUState *env, uint64_t next)
+static inline uint32_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next)
 {
     ppc_tb_t *tb_env = env->tb_env;
     uint32_t decr;
@@ -597,7 +597,7 @@ static inline uint32_t _cpu_ppc_load_decr(CPUState *env, uint64_t next)
     return decr;
 }
 
-uint32_t cpu_ppc_load_decr (CPUState *env)
+uint32_t cpu_ppc_load_decr (CPUPPCState *env)
 {
     ppc_tb_t *tb_env = env->tb_env;
 
@@ -608,14 +608,14 @@ uint32_t cpu_ppc_load_decr (CPUState *env)
     return _cpu_ppc_load_decr(env, tb_env->decr_next);
 }
 
-uint32_t cpu_ppc_load_hdecr (CPUState *env)
+uint32_t cpu_ppc_load_hdecr (CPUPPCState *env)
 {
     ppc_tb_t *tb_env = env->tb_env;
 
     return _cpu_ppc_load_decr(env, tb_env->hdecr_next);
 }
 
-uint64_t cpu_ppc_load_purr (CPUState *env)
+uint64_t cpu_ppc_load_purr (CPUPPCState *env)
 {
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t diff;
@@ -628,23 +628,23 @@ uint64_t cpu_ppc_load_purr (CPUState *env)
 /* When decrementer expires,
  * all we need to do is generate or queue a CPU exception
  */
-static inline void cpu_ppc_decr_excp(CPUState *env)
+static inline void cpu_ppc_decr_excp(CPUPPCState *env)
 {
     /* Raise it */
     LOG_TB("raise decrementer exception\n");
     ppc_set_irq(env, PPC_INTERRUPT_DECR, 1);
 }
 
-static inline void cpu_ppc_hdecr_excp(CPUState *env)
+static inline void cpu_ppc_hdecr_excp(CPUPPCState *env)
 {
     /* Raise it */
     LOG_TB("raise decrementer exception\n");
     ppc_set_irq(env, PPC_INTERRUPT_HDECR, 1);
 }
 
-static void __cpu_ppc_store_decr (CPUState *env, uint64_t *nextp,
+static void __cpu_ppc_store_decr (CPUPPCState *env, uint64_t *nextp,
                                   struct QEMUTimer *timer,
-                                  void (*raise_excp)(CPUState *),
+                                  void (*raise_excp)(CPUPPCState *),
                                   uint32_t decr, uint32_t value,
                                   int is_excp)
 {
@@ -681,7 +681,7 @@ static void __cpu_ppc_store_decr (CPUState *env, uint64_t *nextp,
     }
 }
 
-static inline void _cpu_ppc_store_decr(CPUState *env, uint32_t decr,
+static inline void _cpu_ppc_store_decr(CPUPPCState *env, uint32_t decr,
                                        uint32_t value, int is_excp)
 {
     ppc_tb_t *tb_env = env->tb_env;
@@ -690,7 +690,7 @@ static inline void _cpu_ppc_store_decr(CPUState *env, uint32_t decr,
                          &cpu_ppc_decr_excp, decr, value, is_excp);
 }
 
-void cpu_ppc_store_decr (CPUState *env, uint32_t value)
+void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value)
 {
     _cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0);
 }
@@ -700,7 +700,7 @@ static void cpu_ppc_decr_cb (void *opaque)
     _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
 }
 
-static inline void _cpu_ppc_store_hdecr(CPUState *env, uint32_t hdecr,
+static inline void _cpu_ppc_store_hdecr(CPUPPCState *env, uint32_t hdecr,
                                         uint32_t value, int is_excp)
 {
     ppc_tb_t *tb_env = env->tb_env;
@@ -711,7 +711,7 @@ static inline void _cpu_ppc_store_hdecr(CPUState *env, uint32_t hdecr,
     }
 }
 
-void cpu_ppc_store_hdecr (CPUState *env, uint32_t value)
+void cpu_ppc_store_hdecr (CPUPPCState *env, uint32_t value)
 {
     _cpu_ppc_store_hdecr(env, cpu_ppc_load_hdecr(env), value, 0);
 }
@@ -721,7 +721,7 @@ static void cpu_ppc_hdecr_cb (void *opaque)
     _cpu_ppc_store_hdecr(opaque, 0x00000000, 0xFFFFFFFF, 1);
 }
 
-void cpu_ppc_store_purr (CPUState *env, uint64_t value)
+void cpu_ppc_store_purr (CPUPPCState *env, uint64_t value)
 {
     ppc_tb_t *tb_env = env->tb_env;
 
@@ -731,7 +731,7 @@ void cpu_ppc_store_purr (CPUState *env, uint64_t value)
 
 static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
 {
-    CPUState *env = opaque;
+    CPUPPCState *env = opaque;
     ppc_tb_t *tb_env = env->tb_env;
 
     tb_env->tb_freq = freq;
@@ -746,7 +746,7 @@ static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
 }
 
 /* Set up (once) timebase frequency (in Hz) */
-clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq)
+clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq)
 {
     ppc_tb_t *tb_env;
 
@@ -769,28 +769,28 @@ clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq)
 
 /* Specific helpers for POWER & PowerPC 601 RTC */
 #if 0
-static clk_setup_cb cpu_ppc601_rtc_init (CPUState *env)
+static clk_setup_cb cpu_ppc601_rtc_init (CPUPPCState *env)
 {
     return cpu_ppc_tb_init(env, 7812500);
 }
 #endif
 
-void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
+void cpu_ppc601_store_rtcu (CPUPPCState *env, uint32_t value)
 {
     _cpu_ppc_store_tbu(env, value);
 }
 
-uint32_t cpu_ppc601_load_rtcu (CPUState *env)
+uint32_t cpu_ppc601_load_rtcu (CPUPPCState *env)
 {
     return _cpu_ppc_load_tbu(env);
 }
 
-void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value)
+void cpu_ppc601_store_rtcl (CPUPPCState *env, uint32_t value)
 {
     cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
 }
 
-uint32_t cpu_ppc601_load_rtcl (CPUState *env)
+uint32_t cpu_ppc601_load_rtcl (CPUPPCState *env)
 {
     return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
 }
@@ -814,7 +814,7 @@ struct ppc40x_timer_t {
 /* Fixed interval timer */
 static void cpu_4xx_fit_cb (void *opaque)
 {
-    CPUState *env;
+    CPUPPCState *env;
     ppc_tb_t *tb_env;
     ppc40x_timer_t *ppc40x_timer;
     uint64_t now, next;
@@ -853,7 +853,7 @@ static void cpu_4xx_fit_cb (void *opaque)
 }
 
 /* Programmable interval timer */
-static void start_stop_pit (CPUState *env, ppc_tb_t *tb_env, int is_excp)
+static void start_stop_pit (CPUPPCState *env, ppc_tb_t *tb_env, int is_excp)
 {
     ppc40x_timer_t *ppc40x_timer;
     uint64_t now, next;
@@ -882,7 +882,7 @@ static void start_stop_pit (CPUState *env, ppc_tb_t *tb_env, int is_excp)
 
 static void cpu_4xx_pit_cb (void *opaque)
 {
-    CPUState *env;
+    CPUPPCState *env;
     ppc_tb_t *tb_env;
     ppc40x_timer_t *ppc40x_timer;
 
@@ -904,7 +904,7 @@ static void cpu_4xx_pit_cb (void *opaque)
 /* Watchdog timer */
 static void cpu_4xx_wdt_cb (void *opaque)
 {
-    CPUState *env;
+    CPUPPCState *env;
     ppc_tb_t *tb_env;
     ppc40x_timer_t *ppc40x_timer;
     uint64_t now, next;
@@ -969,7 +969,7 @@ static void cpu_4xx_wdt_cb (void *opaque)
     }
 }
 
-void store_40x_pit (CPUState *env, target_ulong val)
+void store_40x_pit (CPUPPCState *env, target_ulong val)
 {
     ppc_tb_t *tb_env;
     ppc40x_timer_t *ppc40x_timer;
@@ -981,14 +981,14 @@ void store_40x_pit (CPUState *env, target_ulong val)
     start_stop_pit(env, tb_env, 0);
 }
 
-target_ulong load_40x_pit (CPUState *env)
+target_ulong load_40x_pit (CPUPPCState *env)
 {
     return cpu_ppc_load_decr(env);
 }
 
 static void ppc_40x_set_tb_clk (void *opaque, uint32_t freq)
 {
-    CPUState *env = opaque;
+    CPUPPCState *env = opaque;
     ppc_tb_t *tb_env = env->tb_env;
 
     LOG_TB("%s set new frequency to %" PRIu32 "\n", __func__,
@@ -998,7 +998,7 @@ static void ppc_40x_set_tb_clk (void *opaque, uint32_t freq)
     /* XXX: we should also update all timers */
 }
 
-clk_setup_cb ppc_40x_timers_init (CPUState *env, uint32_t freq,
+clk_setup_cb ppc_40x_timers_init (CPUPPCState *env, uint32_t freq,
                                   unsigned int decr_excp)
 {
     ppc_tb_t *tb_env;
@@ -1084,7 +1084,7 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
     return -1;
 }
 
-int ppc_dcr_register (CPUState *env, int dcrn, void *opaque,
+int ppc_dcr_register (CPUPPCState *env, int dcrn, void *opaque,
                       dcr_read_cb dcr_read, dcr_write_cb dcr_write)
 {
     ppc_dcr_t *dcr_env;
@@ -1107,7 +1107,7 @@ int ppc_dcr_register (CPUState *env, int dcrn, void *opaque,
     return 0;
 }
 
-int ppc_dcr_init (CPUState *env, int (*read_error)(int dcrn),
+int ppc_dcr_init (CPUPPCState *env, int (*read_error)(int dcrn),
                   int (*write_error)(int dcrn))
 {
     ppc_dcr_t *dcr_env;
diff --git a/hw/ppc.h b/hw/ppc.h
index 9f91170..2f3ea27 100644
--- a/hw/ppc.h
+++ b/hw/ppc.h
@@ -1,4 +1,4 @@
-void ppc_set_irq (CPUState *env, int n_IRQ, int level);
+void ppc_set_irq (CPUPPCState *env, int n_IRQ, int level);
 
 /* PowerPC hardware exceptions management helpers */
 typedef void (*clk_setup_cb)(void *opaque, uint32_t freq);
@@ -43,32 +43,32 @@ struct ppc_tb_t {
                                                */
 
 uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk, int64_t tb_offset);
-clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq);
+clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq);
 /* Embedded PowerPC DCR management */
 typedef uint32_t (*dcr_read_cb)(void *opaque, int dcrn);
 typedef void (*dcr_write_cb)(void *opaque, int dcrn, uint32_t val);
-int ppc_dcr_init (CPUState *env, int (*dcr_read_error)(int dcrn),
+int ppc_dcr_init (CPUPPCState *env, int (*dcr_read_error)(int dcrn),
                   int (*dcr_write_error)(int dcrn));
-int ppc_dcr_register (CPUState *env, int dcrn, void *opaque,
+int ppc_dcr_register (CPUPPCState *env, int dcrn, void *opaque,
                       dcr_read_cb drc_read, dcr_write_cb dcr_write);
-clk_setup_cb ppc_40x_timers_init (CPUState *env, uint32_t freq,
+clk_setup_cb ppc_40x_timers_init (CPUPPCState *env, uint32_t freq,
                                   unsigned int decr_excp);
 
 /* Embedded PowerPC reset */
-void ppc40x_core_reset (CPUState *env);
-void ppc40x_chip_reset (CPUState *env);
-void ppc40x_system_reset (CPUState *env);
+void ppc40x_core_reset (CPUPPCState *env);
+void ppc40x_chip_reset (CPUPPCState *env);
+void ppc40x_system_reset (CPUPPCState *env);
 void PREP_debug_write (void *opaque, uint32_t addr, uint32_t val);
 
 extern CPUWriteMemoryFunc * const PPC_io_write[];
 extern CPUReadMemoryFunc * const PPC_io_read[];
 void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val);
 
-void ppc40x_irq_init (CPUState *env);
-void ppce500_irq_init (CPUState *env);
-void ppc6xx_irq_init (CPUState *env);
-void ppc970_irq_init (CPUState *env);
-void ppcPOWER7_irq_init (CPUState *env);
+void ppc40x_irq_init (CPUPPCState *env);
+void ppce500_irq_init (CPUPPCState *env);
+void ppc6xx_irq_init (CPUPPCState *env);
+void ppc970_irq_init (CPUPPCState *env);
+void ppcPOWER7_irq_init (CPUPPCState *env);
 
 /* PPC machines for OpenBIOS */
 enum {
@@ -89,4 +89,4 @@ enum {
 #define PPC_SERIAL_MM_BAUDBASE 399193
 
 /* ppc_booke.c */
-void ppc_booke_timers_init(CPUState *env, uint32_t freq, uint32_t flags);
+void ppc_booke_timers_init(CPUPPCState *env, uint32_t freq, uint32_t flags);
diff --git a/hw/ppc405.h b/hw/ppc405.h
index d8fdf09..1f5dc5f 100644
--- a/hw/ppc405.h
+++ b/hw/ppc405.h
@@ -56,23 +56,23 @@ struct ppc4xx_bd_info_t {
 };
 
 /* PowerPC 405 core */
-ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd,
+ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
                                 uint32_t flags);
 
-CPUState *ppc405cr_init(MemoryRegion *address_space_mem,
+CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
                         MemoryRegion ram_memories[4],
                         target_phys_addr_t ram_bases[4],
                         target_phys_addr_t ram_sizes[4],
                         uint32_t sysclk, qemu_irq **picp,
                         int do_init);
-CPUState *ppc405ep_init(MemoryRegion *address_space_mem,
+CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
                         MemoryRegion ram_memories[2],
                         target_phys_addr_t ram_bases[2],
                         target_phys_addr_t ram_sizes[2],
                         uint32_t sysclk, qemu_irq **picp,
                         int do_init);
 /* IBM STBxxx microcontrollers */
-CPUState *ppc_stb025_init (MemoryRegion ram_memories[2],
+CPUPPCState *ppc_stb025_init (MemoryRegion ram_memories[2],
                            target_phys_addr_t ram_bases[2],
                            target_phys_addr_t ram_sizes[2],
                            uint32_t sysclk, qemu_irq **picp,
diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
index 951b389..6f8342e 100644
--- a/hw/ppc405_uc.c
+++ b/hw/ppc405_uc.c
@@ -41,7 +41,7 @@
 #define DEBUG_CLOCKS
 //#define DEBUG_CLOCKS_LL
 
-ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd,
+ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
                                 uint32_t flags)
 {
     ram_addr_t bdloc;
@@ -169,7 +169,7 @@ static void ppc4xx_plb_reset (void *opaque)
     plb->besr = 0x00000000;
 }
 
-static void ppc4xx_plb_init(CPUState *env)
+static void ppc4xx_plb_init(CPUPPCState *env)
 {
     ppc4xx_plb_t *plb;
 
@@ -245,7 +245,7 @@ static void ppc4xx_pob_reset (void *opaque)
     pob->besr[1] = 0x0000000;
 }
 
-static void ppc4xx_pob_init(CPUState *env)
+static void ppc4xx_pob_init(CPUPPCState *env)
 {
     ppc4xx_pob_t *pob;
 
@@ -574,7 +574,7 @@ static void ebc_reset (void *opaque)
     ebc->cfg = 0x80400000;
 }
 
-static void ppc405_ebc_init(CPUState *env)
+static void ppc405_ebc_init(CPUPPCState *env)
 {
     ppc4xx_ebc_t *ebc;
 
@@ -657,7 +657,7 @@ static void ppc405_dma_reset (void *opaque)
     dma->pol = 0x00000000;
 }
 
-static void ppc405_dma_init(CPUState *env, qemu_irq irqs[4])
+static void ppc405_dma_init(CPUPPCState *env, qemu_irq irqs[4])
 {
     ppc405_dma_t *dma;
 
@@ -960,7 +960,7 @@ static void ocm_reset (void *opaque)
     ocm->dsacntl = dsacntl;
 }
 
-static void ppc405_ocm_init(CPUState *env)
+static void ppc405_ocm_init(CPUPPCState *env)
 {
     ppc405_ocm_t *ocm;
 
@@ -1713,7 +1713,7 @@ static void ppc40x_mal_reset (void *opaque)
     mal->txeobisr = 0x00000000;
 }
 
-static void ppc405_mal_init(CPUState *env, qemu_irq irqs[4])
+static void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4])
 {
     ppc40x_mal_t *mal;
     int i;
@@ -1764,7 +1764,7 @@ static void ppc405_mal_init(CPUState *env, qemu_irq irqs[4])
 
 /*****************************************************************************/
 /* SPR */
-void ppc40x_core_reset (CPUState *env)
+void ppc40x_core_reset (CPUPPCState *env)
 {
     target_ulong dbsr;
 
@@ -1776,7 +1776,7 @@ void ppc40x_core_reset (CPUState *env)
     env->spr[SPR_40x_DBSR] = dbsr;
 }
 
-void ppc40x_chip_reset (CPUState *env)
+void ppc40x_chip_reset (CPUPPCState *env)
 {
     target_ulong dbsr;
 
@@ -1789,13 +1789,13 @@ void ppc40x_chip_reset (CPUState *env)
     env->spr[SPR_40x_DBSR] = dbsr;
 }
 
-void ppc40x_system_reset (CPUState *env)
+void ppc40x_system_reset (CPUPPCState *env)
 {
     printf("Reset PowerPC system\n");
     qemu_system_reset_request();
 }
 
-void store_40x_dbcr0 (CPUState *env, uint32_t val)
+void store_40x_dbcr0 (CPUPPCState *env, uint32_t val)
 {
     switch ((val >> 28) & 0x3) {
     case 0x0:
@@ -2066,7 +2066,7 @@ static void ppc405cr_clk_init (ppc405cr_cpc_t *cpc)
     cpc->psr |= D << 17;
 }
 
-static void ppc405cr_cpc_init (CPUState *env, clk_setup_t clk_setup[7],
+static void ppc405cr_cpc_init (CPUPPCState *env, clk_setup_t clk_setup[7],
                                uint32_t sysclk)
 {
     ppc405cr_cpc_t *cpc;
@@ -2096,7 +2096,7 @@ static void ppc405cr_cpc_init (CPUState *env, clk_setup_t clk_setup[7],
     qemu_register_reset(ppc405cr_cpc_reset, cpc);
 }
 
-CPUState *ppc405cr_init(MemoryRegion *address_space_mem,
+CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
                         MemoryRegion ram_memories[4],
                         target_phys_addr_t ram_bases[4],
                         target_phys_addr_t ram_sizes[4],
@@ -2105,7 +2105,7 @@ CPUState *ppc405cr_init(MemoryRegion *address_space_mem,
 {
     clk_setup_t clk_setup[PPC405CR_CLK_NB];
     qemu_irq dma_irqs[4];
-    CPUState *env;
+    CPUPPCState *env;
     qemu_irq *pic, *irqs;
 
     memset(clk_setup, 0, sizeof(clk_setup));
@@ -2408,7 +2408,7 @@ static void ppc405ep_cpc_reset (void *opaque)
 }
 
 /* XXX: sysclk should be between 25 and 100 MHz */
-static void ppc405ep_cpc_init (CPUState *env, clk_setup_t clk_setup[8],
+static void ppc405ep_cpc_init (CPUPPCState *env, clk_setup_t clk_setup[8],
                                uint32_t sysclk)
 {
     ppc405ep_cpc_t *cpc;
@@ -2445,7 +2445,7 @@ static void ppc405ep_cpc_init (CPUState *env, clk_setup_t clk_setup[8],
 #endif
 }
 
-CPUState *ppc405ep_init(MemoryRegion *address_space_mem,
+CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
                         MemoryRegion ram_memories[2],
                         target_phys_addr_t ram_bases[2],
                         target_phys_addr_t ram_sizes[2],
@@ -2454,7 +2454,7 @@ CPUState *ppc405ep_init(MemoryRegion *address_space_mem,
 {
     clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup;
     qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4];
-    CPUState *env;
+    CPUPPCState *env;
     qemu_irq *pic, *irqs;
 
     memset(clk_setup, 0, sizeof(clk_setup));
diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
index 835e36d..220c81d 100644
--- a/hw/ppc440_bamboo.c
+++ b/hw/ppc440_bamboo.c
@@ -121,7 +121,7 @@ out:
 }
 
 /* Create reset TLB entries for BookE, spanning the 32bit addr space.  */
-static void mmubooke_create_initial_mapping(CPUState *env,
+static void mmubooke_create_initial_mapping(CPUPPCState *env,
                                      target_ulong va,
                                      target_phys_addr_t pa)
 {
@@ -145,7 +145,7 @@ static void mmubooke_create_initial_mapping(CPUState *env,
 
 static void main_cpu_reset(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUPPCState *env = opaque;
 
     cpu_state_reset(env);
     env->gpr[1] = (16<<20) - 8;
@@ -172,7 +172,7 @@ static void bamboo_init(ram_addr_t ram_size,
     qemu_irq *pic;
     qemu_irq *irqs;
     PCIBus *pcibus;
-    CPUState *env;
+    CPUPPCState *env;
     uint64_t elf_entry;
     uint64_t elf_lowaddr;
     target_phys_addr_t loadaddr = 0;
diff --git a/hw/ppc4xx.h b/hw/ppc4xx.h
index f969e44..b511020 100644
--- a/hw/ppc4xx.h
+++ b/hw/ppc4xx.h
@@ -28,7 +28,7 @@
 #include "pci.h"
 
 /* PowerPC 4xx core initialization */
-CPUState *ppc4xx_init (const char *cpu_model,
+CPUPPCState *ppc4xx_init (const char *cpu_model,
                        clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
                        uint32_t sysclk);
 
@@ -38,7 +38,7 @@ enum {
     PPCUIC_OUTPUT_CINT = 1,
     PPCUIC_OUTPUT_NB,
 };
-qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
+qemu_irq *ppcuic_init (CPUPPCState *env, qemu_irq *irqs,
                        uint32_t dcr_base, int has_ssr, int has_vr);
 
 ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
@@ -47,13 +47,13 @@ ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
                                target_phys_addr_t ram_sizes[],
                                const unsigned int sdram_bank_sizes[]);
 
-void ppc4xx_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
+void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks,
                         MemoryRegion ram_memories[],
                         target_phys_addr_t *ram_bases,
                         target_phys_addr_t *ram_sizes,
                         int do_init);
 
-PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
+PCIBus *ppc4xx_pci_init(CPUPPCState *env, qemu_irq pci_irqs[4],
                         target_phys_addr_t config_space,
                         target_phys_addr_t int_ack,
                         target_phys_addr_t special_cycle,
diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
index 2311162..00e36f4 100644
--- a/hw/ppc4xx_devs.c
+++ b/hw/ppc4xx_devs.c
@@ -40,18 +40,18 @@
 
 static void ppc4xx_reset(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUPPCState *env = opaque;
 
     cpu_state_reset(env);
 }
 
 /*****************************************************************************/
 /* Generic PowerPC 4xx processor instantiation */
-CPUState *ppc4xx_init (const char *cpu_model,
+CPUPPCState *ppc4xx_init (const char *cpu_model,
                        clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
                        uint32_t sysclk)
 {
-    CPUState *env;
+    CPUPPCState *env;
 
     /* init CPUs */
     env = cpu_init(cpu_model);
@@ -295,7 +295,7 @@ static void ppcuic_reset (void *opaque)
     }
 }
 
-qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
+qemu_irq *ppcuic_init (CPUPPCState *env, qemu_irq *irqs,
                        uint32_t dcr_base, int has_ssr, int has_vr)
 {
     ppcuic_t *uic;
@@ -641,7 +641,7 @@ static void sdram_reset (void *opaque)
     sdram->cfg = 0x00800000;
 }
 
-void ppc4xx_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
+void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks,
                         MemoryRegion *ram_memories,
                         target_phys_addr_t *ram_bases,
                         target_phys_addr_t *ram_sizes,
diff --git a/hw/ppc_booke.c b/hw/ppc_booke.c
index 8871945..d51e7fa 100644
--- a/hw/ppc_booke.c
+++ b/hw/ppc_booke.c
@@ -71,7 +71,7 @@ struct booke_timer_t {
     uint32_t flags;
 };
 
-static void booke_update_irq(CPUState *env)
+static void booke_update_irq(CPUPPCState *env)
 {
     ppc_set_irq(env, PPC_INTERRUPT_DECR,
                 (env->spr[SPR_BOOKE_TSR] & TSR_DIS
@@ -88,7 +88,7 @@ static void booke_update_irq(CPUState *env)
 
 /* Return the location of the bit of time base at which the FIT will raise an
    interrupt */
-static uint8_t booke_get_fit_target(CPUState *env, ppc_tb_t *tb_env)
+static uint8_t booke_get_fit_target(CPUPPCState *env, ppc_tb_t *tb_env)
 {
     uint8_t fp = (env->spr[SPR_BOOKE_TCR] & TCR_FP_MASK) >> TCR_FP_SHIFT;
 
@@ -106,7 +106,7 @@ static uint8_t booke_get_fit_target(CPUState *env, ppc_tb_t *tb_env)
 
 /* Return the location of the bit of time base at which the WDT will raise an
    interrupt */
-static uint8_t booke_get_wdt_target(CPUState *env, ppc_tb_t *tb_env)
+static uint8_t booke_get_wdt_target(CPUPPCState *env, ppc_tb_t *tb_env)
 {
     uint8_t wp = (env->spr[SPR_BOOKE_TCR] & TCR_WP_MASK) >> TCR_WP_SHIFT;
 
@@ -122,7 +122,7 @@ static uint8_t booke_get_wdt_target(CPUState *env, ppc_tb_t *tb_env)
     return wp;
 }
 
-static void booke_update_fixed_timer(CPUState         *env,
+static void booke_update_fixed_timer(CPUPPCState         *env,
                                      uint8_t           target_bit,
                                      uint64_t          *next,
                                      struct QEMUTimer *timer)
@@ -153,7 +153,7 @@ static void booke_update_fixed_timer(CPUState         *env,
 
 static void booke_decr_cb(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUPPCState *env = opaque;
 
     env->spr[SPR_BOOKE_TSR] |= TSR_DIS;
     booke_update_irq(env);
@@ -166,7 +166,7 @@ static void booke_decr_cb(void *opaque)
 
 static void booke_fit_cb(void *opaque)
 {
-    CPUState *env;
+    CPUPPCState *env;
     ppc_tb_t *tb_env;
     booke_timer_t *booke_timer;
 
@@ -185,7 +185,7 @@ static void booke_fit_cb(void *opaque)
 
 static void booke_wdt_cb(void *opaque)
 {
-    CPUState *env;
+    CPUPPCState *env;
     ppc_tb_t *tb_env;
     booke_timer_t *booke_timer;
 
@@ -203,13 +203,13 @@ static void booke_wdt_cb(void *opaque)
                              booke_timer->wdt_timer);
 }
 
-void store_booke_tsr(CPUState *env, target_ulong val)
+void store_booke_tsr(CPUPPCState *env, target_ulong val)
 {
     env->spr[SPR_BOOKE_TSR] &= ~val;
     booke_update_irq(env);
 }
 
-void store_booke_tcr(CPUState *env, target_ulong val)
+void store_booke_tcr(CPUPPCState *env, target_ulong val)
 {
     ppc_tb_t *tb_env = env->tb_env;
     booke_timer_t *booke_timer = tb_env->opaque;
@@ -231,7 +231,7 @@ void store_booke_tcr(CPUState *env, target_ulong val)
 
 }
 
-void ppc_booke_timers_init(CPUState *env, uint32_t freq, uint32_t flags)
+void ppc_booke_timers_init(CPUPPCState *env, uint32_t freq, uint32_t flags)
 {
     ppc_tb_t *tb_env;
     booke_timer_t *booke_timer;
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index ee50652..8796510 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -123,7 +123,7 @@ static target_phys_addr_t round_page(target_phys_addr_t addr)
 
 static void ppc_core99_reset(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUPPCState *env = opaque;
 
     cpu_state_reset(env);
 }
@@ -136,7 +136,7 @@ static void ppc_core99_init (ram_addr_t ram_size,
                              const char *initrd_filename,
                              const char *cpu_model)
 {
-    CPUState *env = NULL;
+    CPUPPCState *env = NULL;
     char *filename;
     qemu_irq *pic, **openpic_irqs;
     MemoryRegion *unin_memory = g_new(MemoryRegion, 1);
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index be70124..7e73d37 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -67,7 +67,7 @@ static target_phys_addr_t round_page(target_phys_addr_t addr)
 
 static void ppc_heathrow_reset(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUPPCState *env = opaque;
 
     cpu_state_reset(env);
 }
@@ -80,7 +80,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
                                const char *cpu_model)
 {
     MemoryRegion *sysmem = get_system_memory();
-    CPUState *env = NULL;
+    CPUPPCState *env = NULL;
     char *filename;
     qemu_irq *pic, **heathrow_irqs;
     int linux_boot, i;
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 6ccd6fa..06d589d 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -463,7 +463,7 @@ static const MemoryRegionOps PPC_prep_io_ops = {
 
 static void cpu_request_exit(void *opaque, int irq, int level)
 {
-    CPUState *env = cpu_single_env;
+    CPUPPCState *env = cpu_single_env;
 
     if (env && level) {
         cpu_exit(env);
@@ -472,7 +472,7 @@ static void cpu_request_exit(void *opaque, int irq, int level)
 
 static void ppc_prep_reset(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUPPCState *env = opaque;
 
     cpu_state_reset(env);
 }
@@ -486,7 +486,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
                            const char *cpu_model)
 {
     MemoryRegion *sysmem = get_system_memory();
-    CPUState *env = NULL;
+    CPUPPCState *env = NULL;
     char *filename;
     nvram_t nvram;
     M48t59State *m48t59;
diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index 752aed9..5ee8cb3 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -58,7 +58,7 @@ struct boot_info
     uint32_t entry;
 };
 
-static int mpc8544_load_device_tree(CPUState *env,
+static int mpc8544_load_device_tree(CPUPPCState *env,
                                     target_phys_addr_t addr,
                                     uint32_t ramsize,
                                     target_phys_addr_t initrd_base,
@@ -178,7 +178,7 @@ static inline target_phys_addr_t booke206_page_size_to_tlb(uint64_t size)
     return ffs(size >> 10) - 1;
 }
 
-static void mmubooke_create_initial_mapping(CPUState *env,
+static void mmubooke_create_initial_mapping(CPUPPCState *env,
                                      target_ulong va,
                                      target_phys_addr_t pa)
 {
@@ -196,7 +196,7 @@ static void mmubooke_create_initial_mapping(CPUState *env,
 
 static void mpc8544ds_cpu_reset_sec(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUPPCState *env = opaque;
 
     cpu_state_reset(env);
 
@@ -208,7 +208,7 @@ static void mpc8544ds_cpu_reset_sec(void *opaque)
 
 static void mpc8544ds_cpu_reset(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUPPCState *env = opaque;
     struct boot_info *bi = env->load_info;
 
     cpu_state_reset(env);
@@ -231,7 +231,7 @@ static void mpc8544ds_init(ram_addr_t ram_size,
     MemoryRegion *address_space_mem = get_system_memory();
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     PCIBus *pci_bus;
-    CPUState *env = NULL;
+    CPUPPCState *env = NULL;
     uint64_t elf_entry;
     uint64_t elf_lowaddr;
     target_phys_addr_t entry=0;
@@ -244,7 +244,7 @@ static void mpc8544ds_init(ram_addr_t ram_size,
     unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};
     qemu_irq **irqs, *mpic;
     DeviceState *dev;
-    CPUState *firstenv = NULL;
+    CPUPPCState *firstenv = NULL;
 
     /* Setup CPUs */
     if (cpu_model == NULL) {
diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c
index 6b8a189..268f5fd 100644
--- a/hw/ppce500_spin.c
+++ b/hw/ppce500_spin.c
@@ -49,7 +49,7 @@ typedef struct spin_state {
 } SpinState;
 
 typedef struct spin_kick {
-    CPUState *env;
+    CPUPPCState *env;
     SpinInfo *spin;
 } SpinKick;
 
@@ -73,7 +73,7 @@ static inline target_phys_addr_t booke206_page_size_to_tlb(uint64_t size)
     return (ffs(size >> 10) - 1) >> 1;
 }
 
-static void mmubooke_create_initial_mapping(CPUState *env,
+static void mmubooke_create_initial_mapping(CPUPPCState *env,
                                      target_ulong va,
                                      target_phys_addr_t pa,
                                      target_phys_addr_t len)
@@ -91,7 +91,7 @@ static void mmubooke_create_initial_mapping(CPUState *env,
 static void spin_kick(void *data)
 {
     SpinKick *kick = data;
-    CPUState *env = kick->env;
+    CPUPPCState *env = kick->env;
     SpinInfo *curspin = kick->spin;
     target_phys_addr_t map_size = 64 * 1024 * 1024;
     target_phys_addr_t map_start;
@@ -121,7 +121,7 @@ static void spin_write(void *opaque, target_phys_addr_t addr, uint64_t value,
 {
     SpinState *s = opaque;
     int env_idx = addr / sizeof(SpinInfo);
-    CPUState *env;
+    CPUPPCState *env;
     SpinInfo *curspin = &s->spin[env_idx];
     uint8_t *curspin_p = (uint8_t*)curspin;
 
diff --git a/hw/spapr.c b/hw/spapr.c
index 3f9d87c..3719e0e 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -110,7 +110,7 @@ qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num)
 static int spapr_set_associativity(void *fdt, sPAPREnvironment *spapr)
 {
     int ret = 0, offset;
-    CPUState *env;
+    CPUPPCState *env;
     char cpu_model[32];
     int smt = kvmppc_smt_threads();
 
@@ -155,7 +155,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
                                    long hash_shift)
 {
     void *fdt;
-    CPUState *env;
+    CPUPPCState *env;
     uint64_t mem_reg_property[2];
     uint32_t start_prop = cpu_to_be32(initrd_base);
     uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
@@ -476,7 +476,7 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
     return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
 }
 
-static void emulate_spapr_hypercall(CPUState *env)
+static void emulate_spapr_hypercall(CPUPPCState *env)
 {
     env->gpr[3] = spapr_hypercall(env, env->gpr[3], &env->gpr[4]);
 }
@@ -504,7 +504,7 @@ static void spapr_reset(void *opaque)
 
 static void spapr_cpu_reset(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUPPCState *env = opaque;
 
     cpu_state_reset(env);
 }
@@ -517,7 +517,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
                            const char *initrd_filename,
                            const char *cpu_model)
 {
-    CPUState *env;
+    CPUPPCState *env;
     int i;
     MemoryRegion *sysmem = get_system_memory();
     MemoryRegion *ram = g_new(MemoryRegion, 1);
diff --git a/hw/spapr.h b/hw/spapr.h
index e946a34..a41641f 100644
--- a/hw/spapr.h
+++ b/hw/spapr.h
@@ -278,12 +278,12 @@ extern sPAPREnvironment *spapr;
     do { } while (0)
 #endif
 
-typedef target_ulong (*spapr_hcall_fn)(CPUState *env, sPAPREnvironment *spapr,
+typedef target_ulong (*spapr_hcall_fn)(CPUPPCState *env, sPAPREnvironment *spapr,
                                        target_ulong opcode,
                                        target_ulong *args);
 
 void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn);
-target_ulong spapr_hypercall(CPUState *env, target_ulong opcode,
+target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode,
                              target_ulong *args);
 
 qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num);
diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c
index 6ac7384..634763e 100644
--- a/hw/spapr_hcall.c
+++ b/hw/spapr_hcall.c
@@ -92,7 +92,7 @@ static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r,
     return rb;
 }
 
-static target_ulong h_enter(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_enter(CPUPPCState *env, sPAPREnvironment *spapr,
                             target_ulong opcode, target_ulong *args)
 {
     target_ulong flags = args[0];
@@ -181,7 +181,7 @@ enum {
     REMOVE_HW = 3,
 };
 
-static target_ulong remove_hpte(CPUState *env, target_ulong ptex,
+static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex,
                                 target_ulong avpn,
                                 target_ulong flags,
                                 target_ulong *vp, target_ulong *rp)
@@ -219,7 +219,7 @@ static target_ulong remove_hpte(CPUState *env, target_ulong ptex,
     return REMOVE_SUCCESS;
 }
 
-static target_ulong h_remove(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_remove(CPUPPCState *env, sPAPREnvironment *spapr,
                              target_ulong opcode, target_ulong *args)
 {
     target_ulong flags = args[0];
@@ -265,7 +265,7 @@ static target_ulong h_remove(CPUState *env, sPAPREnvironment *spapr,
 
 #define H_BULK_REMOVE_MAX_BATCH        4
 
-static target_ulong h_bulk_remove(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_bulk_remove(CPUPPCState *env, sPAPREnvironment *spapr,
                                   target_ulong opcode, target_ulong *args)
 {
     int i;
@@ -311,7 +311,7 @@ static target_ulong h_bulk_remove(CPUState *env, sPAPREnvironment *spapr,
     return H_SUCCESS;
 }
 
-static target_ulong h_protect(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_protect(CPUPPCState *env, sPAPREnvironment *spapr,
                               target_ulong opcode, target_ulong *args)
 {
     target_ulong flags = args[0];
@@ -356,7 +356,7 @@ static target_ulong h_protect(CPUState *env, sPAPREnvironment *spapr,
     return H_SUCCESS;
 }
 
-static target_ulong h_set_dabr(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_set_dabr(CPUPPCState *env, sPAPREnvironment *spapr,
                                target_ulong opcode, target_ulong *args)
 {
     /* FIXME: actually implement this */
@@ -375,7 +375,7 @@ static target_ulong h_set_dabr(CPUState *env, sPAPREnvironment *spapr,
 #define VPA_SHARED_PROC_OFFSET 0x9
 #define VPA_SHARED_PROC_VAL    0x2
 
-static target_ulong register_vpa(CPUState *env, target_ulong vpa)
+static target_ulong register_vpa(CPUPPCState *env, target_ulong vpa)
 {
     uint16_t size;
     uint8_t tmp;
@@ -410,7 +410,7 @@ static target_ulong register_vpa(CPUState *env, target_ulong vpa)
     return H_SUCCESS;
 }
 
-static target_ulong deregister_vpa(CPUState *env, target_ulong vpa)
+static target_ulong deregister_vpa(CPUPPCState *env, target_ulong vpa)
 {
     if (env->slb_shadow) {
         return H_RESOURCE;
@@ -424,7 +424,7 @@ static target_ulong deregister_vpa(CPUState *env, target_ulong vpa)
     return H_SUCCESS;
 }
 
-static target_ulong register_slb_shadow(CPUState *env, target_ulong addr)
+static target_ulong register_slb_shadow(CPUPPCState *env, target_ulong addr)
 {
     uint32_t size;
 
@@ -451,13 +451,13 @@ static target_ulong register_slb_shadow(CPUState *env, target_ulong addr)
     return H_SUCCESS;
 }
 
-static target_ulong deregister_slb_shadow(CPUState *env, target_ulong addr)
+static target_ulong deregister_slb_shadow(CPUPPCState *env, target_ulong addr)
 {
     env->slb_shadow = 0;
     return H_SUCCESS;
 }
 
-static target_ulong register_dtl(CPUState *env, target_ulong addr)
+static target_ulong register_dtl(CPUPPCState *env, target_ulong addr)
 {
     uint32_t size;
 
@@ -482,7 +482,7 @@ static target_ulong register_dtl(CPUState *env, target_ulong addr)
     return H_SUCCESS;
 }
 
-static target_ulong deregister_dtl(CPUState *emv, target_ulong addr)
+static target_ulong deregister_dtl(CPUPPCState *emv, target_ulong addr)
 {
     env->dispatch_trace_log = 0;
     env->dtl_size = 0;
@@ -490,14 +490,14 @@ static target_ulong deregister_dtl(CPUState *emv, target_ulong addr)
     return H_SUCCESS;
 }
 
-static target_ulong h_register_vpa(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_register_vpa(CPUPPCState *env, sPAPREnvironment *spapr,
                                    target_ulong opcode, target_ulong *args)
 {
     target_ulong flags = args[0];
     target_ulong procno = args[1];
     target_ulong vpa = args[2];
     target_ulong ret = H_PARAMETER;
-    CPUState *tenv;
+    CPUPPCState *tenv;
 
     for (tenv = first_cpu; tenv; tenv = tenv->next_cpu) {
         if (tenv->cpu_index == procno) {
@@ -538,7 +538,7 @@ static target_ulong h_register_vpa(CPUState *env, sPAPREnvironment *spapr,
     return ret;
 }
 
-static target_ulong h_cede(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_cede(CPUPPCState *env, sPAPREnvironment *spapr,
                            target_ulong opcode, target_ulong *args)
 {
     env->msr |= (1ULL << MSR_EE);
@@ -549,7 +549,7 @@ static target_ulong h_cede(CPUState *env, sPAPREnvironment *spapr,
     return H_SUCCESS;
 }
 
-static target_ulong h_rtas(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_rtas(CPUPPCState *env, sPAPREnvironment *spapr,
                            target_ulong opcode, target_ulong *args)
 {
     target_ulong rtas_r3 = args[0];
@@ -561,7 +561,7 @@ static target_ulong h_rtas(CPUState *env, sPAPREnvironment *spapr,
                            nret, rtas_r3 + 12 + 4*nargs);
 }
 
-static target_ulong h_logical_load(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_logical_load(CPUPPCState *env, sPAPREnvironment *spapr,
                                    target_ulong opcode, target_ulong *args)
 {
     target_ulong size = args[0];
@@ -584,7 +584,7 @@ static target_ulong h_logical_load(CPUState *env, sPAPREnvironment *spapr,
     return H_PARAMETER;
 }
 
-static target_ulong h_logical_store(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_logical_store(CPUPPCState *env, sPAPREnvironment *spapr,
                                     target_ulong opcode, target_ulong *args)
 {
     target_ulong size = args[0];
@@ -608,14 +608,14 @@ static target_ulong h_logical_store(CPUState *env, sPAPREnvironment *spapr,
     return H_PARAMETER;
 }
 
-static target_ulong h_logical_icbi(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_logical_icbi(CPUPPCState *env, sPAPREnvironment *spapr,
                                    target_ulong opcode, target_ulong *args)
 {
     /* Nothing to do on emulation, KVM will trap this in the kernel */
     return H_SUCCESS;
 }
 
-static target_ulong h_logical_dcbf(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_logical_dcbf(CPUPPCState *env, sPAPREnvironment *spapr,
                                    target_ulong opcode, target_ulong *args)
 {
     /* Nothing to do on emulation, KVM will trap this in the kernel */
@@ -644,7 +644,7 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn)
     *slot = fn;
 }
 
-target_ulong spapr_hypercall(CPUState *env, target_ulong opcode,
+target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode,
                              target_ulong *args)
 {
     if (msr_pr) {
diff --git a/hw/spapr_llan.c b/hw/spapr_llan.c
index 77d4047..cfc7778 100644
--- a/hw/spapr_llan.c
+++ b/hw/spapr_llan.c
@@ -254,7 +254,7 @@ static int check_bd(VIOsPAPRVLANDevice *dev, vlan_bd_t bd,
     return 0;
 }
 
-static target_ulong h_register_logical_lan(CPUState *env,
+static target_ulong h_register_logical_lan(CPUPPCState *env,
                                            sPAPREnvironment *spapr,
                                            target_ulong opcode,
                                            target_ulong *args)
@@ -320,7 +320,7 @@ static target_ulong h_register_logical_lan(CPUState *env,
 }
 
 
-static target_ulong h_free_logical_lan(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_free_logical_lan(CPUPPCState *env, sPAPREnvironment *spapr,
                                        target_ulong opcode, target_ulong *args)
 {
     target_ulong reg = args[0];
@@ -343,7 +343,7 @@ static target_ulong h_free_logical_lan(CPUState *env, sPAPREnvironment *spapr,
     return H_SUCCESS;
 }
 
-static target_ulong h_add_logical_lan_buffer(CPUState *env,
+static target_ulong h_add_logical_lan_buffer(CPUPPCState *env,
                                              sPAPREnvironment *spapr,
                                              target_ulong opcode,
                                              target_ulong *args)
@@ -392,7 +392,7 @@ static target_ulong h_add_logical_lan_buffer(CPUState *env,
     return H_SUCCESS;
 }
 
-static target_ulong h_send_logical_lan(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_send_logical_lan(CPUPPCState *env, sPAPREnvironment *spapr,
                                        target_ulong opcode, target_ulong *args)
 {
     target_ulong reg = args[0];
@@ -461,7 +461,7 @@ static target_ulong h_send_logical_lan(CPUState *env, sPAPREnvironment *spapr,
     return H_SUCCESS;
 }
 
-static target_ulong h_multicast_ctrl(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_multicast_ctrl(CPUPPCState *env, sPAPREnvironment *spapr,
                                      target_ulong opcode, target_ulong *args)
 {
     target_ulong reg = args[0];
diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c
index c0723b3..0946585 100644
--- a/hw/spapr_rtas.c
+++ b/hw/spapr_rtas.c
@@ -118,7 +118,7 @@ static void rtas_query_cpu_stopped_state(sPAPREnvironment *spapr,
                                          uint32_t nret, target_ulong rets)
 {
     target_ulong id;
-    CPUState *env;
+    CPUPPCState *env;
 
     if (nargs != 1 || nret != 2) {
         rtas_st(rets, 0, -3);
@@ -151,7 +151,7 @@ static void rtas_start_cpu(sPAPREnvironment *spapr,
                            uint32_t nret, target_ulong rets)
 {
     target_ulong id, start, r3;
-    CPUState *env;
+    CPUPPCState *env;
 
     if (nargs != 3 || nret != 1) {
         rtas_st(rets, 0, -3);
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index ea317ef..2fb3cee 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -194,7 +194,7 @@ static void rtce_init(VIOsPAPRDevice *dev)
     }
 }
 
-static target_ulong h_put_tce(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_put_tce(CPUPPCState *env, sPAPREnvironment *spapr,
                               target_ulong opcode, target_ulong *args)
 {
     target_ulong liobn = args[0];
@@ -405,7 +405,7 @@ uint64_t ldq_tce(VIOsPAPRDevice *dev, uint64_t taddr)
 /*
  * CRQ handling
  */
-static target_ulong h_reg_crq(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_reg_crq(CPUPPCState *env, sPAPREnvironment *spapr,
                               target_ulong opcode, target_ulong *args)
 {
     target_ulong reg = args[0];
@@ -453,7 +453,7 @@ static target_ulong h_reg_crq(CPUState *env, sPAPREnvironment *spapr,
     return H_SUCCESS;
 }
 
-static target_ulong h_free_crq(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_free_crq(CPUPPCState *env, sPAPREnvironment *spapr,
                                target_ulong opcode, target_ulong *args)
 {
     target_ulong reg = args[0];
@@ -474,7 +474,7 @@ static target_ulong h_free_crq(CPUState *env, sPAPREnvironment *spapr,
     return H_SUCCESS;
 }
 
-static target_ulong h_send_crq(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_send_crq(CPUPPCState *env, sPAPREnvironment *spapr,
                                target_ulong opcode, target_ulong *args)
 {
     target_ulong reg = args[0];
@@ -498,7 +498,7 @@ static target_ulong h_send_crq(CPUState *env, sPAPREnvironment *spapr,
     return H_HARDWARE;
 }
 
-static target_ulong h_enable_crq(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_enable_crq(CPUPPCState *env, sPAPREnvironment *spapr,
                                  target_ulong opcode, target_ulong *args)
 {
     target_ulong reg = args[0];
@@ -680,7 +680,7 @@ static int spapr_vio_busdev_init(DeviceState *qdev)
     return pc->init(dev);
 }
 
-static target_ulong h_vio_signal(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_vio_signal(CPUPPCState *env, sPAPREnvironment *spapr,
                                  target_ulong opcode,
                                  target_ulong *args)
 {
diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c
index 3efe242..60e22b1 100644
--- a/hw/spapr_vty.c
+++ b/hw/spapr_vty.c
@@ -72,7 +72,7 @@ static int spapr_vty_init(VIOsPAPRDevice *sdev)
 /* Forward declaration */
 static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg);
 
-static target_ulong h_put_term_char(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_put_term_char(CPUPPCState *env, sPAPREnvironment *spapr,
                                     target_ulong opcode, target_ulong *args)
 {
     target_ulong reg = args[0];
@@ -99,7 +99,7 @@ static target_ulong h_put_term_char(CPUState *env, sPAPREnvironment *spapr,
     return H_SUCCESS;
 }
 
-static target_ulong h_get_term_char(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_get_term_char(CPUPPCState *env, sPAPREnvironment *spapr,
                                     target_ulong opcode, target_ulong *args)
 {
     target_ulong reg = args[0];
diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c
index e672490..4a133b5 100644
--- a/hw/virtex_ml507.c
+++ b/hw/virtex_ml507.c
@@ -56,7 +56,7 @@ static struct boot_info
 } boot_info;
 
 /* Create reset TLB entries for BookE, spanning the 32bit addr space.  */
-static void mmubooke_create_initial_mapping(CPUState *env,
+static void mmubooke_create_initial_mapping(CPUPPCState *env,
                                      target_ulong va,
                                      target_phys_addr_t pa)
 {
@@ -78,12 +78,12 @@ static void mmubooke_create_initial_mapping(CPUState *env,
     tlb->PID = 0;
 }
 
-static CPUState *ppc440_init_xilinx(ram_addr_t *ram_size,
+static CPUPPCState *ppc440_init_xilinx(ram_addr_t *ram_size,
                                     int do_init,
                                     const char *cpu_model,
                                     uint32_t sysclk)
 {
-    CPUState *env;
+    CPUPPCState *env;
     qemu_irq *irqs;
 
     env = cpu_init(cpu_model);
@@ -106,7 +106,7 @@ static CPUState *ppc440_init_xilinx(ram_addr_t *ram_size,
 
 static void main_cpu_reset(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUPPCState *env = opaque;
     struct boot_info *bi = env->load_info;
 
     cpu_state_reset(env);
@@ -188,7 +188,7 @@ static void virtex_init(ram_addr_t ram_size,
 {
     MemoryRegion *address_space_mem = get_system_memory();
     DeviceState *dev;
-    CPUState *env;
+    CPUPPCState *env;
     target_phys_addr_t ram_base = 0;
     DriveInfo *dinfo;
     MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
diff --git a/hw/xics.c b/hw/xics.c
index 1c5eaa4..f7963f3 100644
--- a/hw/xics.c
+++ b/hw/xics.c
@@ -268,7 +268,7 @@ qemu_irq xics_find_qirq(struct icp_state *icp, int irq)
     return icp->ics->qirqs[irq - icp->ics->offset];
 }
 
-static target_ulong h_cppr(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_cppr(CPUPPCState *env, sPAPREnvironment *spapr,
                            target_ulong opcode, target_ulong *args)
 {
     target_ulong cppr = args[0];
@@ -277,7 +277,7 @@ static target_ulong h_cppr(CPUState *env, sPAPREnvironment *spapr,
     return H_SUCCESS;
 }
 
-static target_ulong h_ipi(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_ipi(CPUPPCState *env, sPAPREnvironment *spapr,
                           target_ulong opcode, target_ulong *args)
 {
     target_ulong server = args[0];
@@ -292,7 +292,7 @@ static target_ulong h_ipi(CPUState *env, sPAPREnvironment *spapr,
 
 }
 
-static target_ulong h_xirr(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_xirr(CPUPPCState *env, sPAPREnvironment *spapr,
                            target_ulong opcode, target_ulong *args)
 {
     uint32_t xirr = icp_accept(spapr->icp->ss + env->cpu_index);
@@ -301,7 +301,7 @@ static target_ulong h_xirr(CPUState *env, sPAPREnvironment *spapr,
     return H_SUCCESS;
 }
 
-static target_ulong h_eoi(CPUState *env, sPAPREnvironment *spapr,
+static target_ulong h_eoi(CPUPPCState *env, sPAPREnvironment *spapr,
                           target_ulong opcode, target_ulong *args)
 {
     target_ulong xirr = args[0];
@@ -424,7 +424,7 @@ static void rtas_int_on(sPAPREnvironment *spapr, uint32_t token,
 
 struct icp_state *xics_system_init(int nr_irqs)
 {
-    CPUState *env;
+    CPUPPCState *env;
     int max_server_num;
     int i;
     struct icp_state *icp;
commit 61c56c8c862b8be9cb71faf74fcd990b3624aa41
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:23 2012 +0100

    mips hw/: Don't use CPUState
    
    Scripted conversion:
      for file in hw/mips_*.[hc]; do
        sed -i "s/CPUState/CPUMIPSState/g" $file
      done
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/mips_cpudevs.h b/hw/mips_cpudevs.h
index db82b41..6bea24b 100644
--- a/hw/mips_cpudevs.h
+++ b/hw/mips_cpudevs.h
@@ -7,9 +7,9 @@ uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr);
 uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr);
 
 /* mips_int.c */
-void cpu_mips_irq_init_cpu(CPUState *env);
+void cpu_mips_irq_init_cpu(CPUMIPSState *env);
 
 /* mips_timer.c */
-void cpu_mips_clock_init(CPUState *);
+void cpu_mips_clock_init(CPUMIPSState *);
 
 #endif
diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c
index dae488a..37dc711 100644
--- a/hw/mips_fulong2e.c
+++ b/hw/mips_fulong2e.c
@@ -102,7 +102,7 @@ static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t* prom_buf, int index,
     va_end(ap);
 }
 
-static int64_t load_kernel (CPUState *env)
+static int64_t load_kernel (CPUMIPSState *env)
 {
     int64_t kernel_entry, kernel_low, kernel_high;
     int index = 0;
@@ -168,7 +168,7 @@ static int64_t load_kernel (CPUState *env)
     return kernel_entry;
 }
 
-static void write_bootloader (CPUState *env, uint8_t *base, int64_t kernel_addr)
+static void write_bootloader (CPUMIPSState *env, uint8_t *base, int64_t kernel_addr)
 {
     uint32_t *p;
 
@@ -198,7 +198,7 @@ static void write_bootloader (CPUState *env, uint8_t *base, int64_t kernel_addr)
 
 static void main_cpu_reset(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUMIPSState *env = opaque;
 
     cpu_state_reset(env);
     /* TODO: 2E reset stuff */
@@ -248,7 +248,7 @@ static void network_init (void)
 
 static void cpu_request_exit(void *opaque, int irq, int level)
 {
-    CPUState *env = cpu_single_env;
+    CPUMIPSState *env = cpu_single_env;
 
     if (env && level) {
         cpu_exit(env);
@@ -272,7 +272,7 @@ 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];
-    CPUState *env;
+    CPUMIPSState *env;
 
     /* init CPUs */
     if (cpu_model == NULL) {
diff --git a/hw/mips_int.c b/hw/mips_int.c
index 477f6ab..6423fd0 100644
--- a/hw/mips_int.c
+++ b/hw/mips_int.c
@@ -26,7 +26,7 @@
 
 static void cpu_mips_irq_request(void *opaque, int irq, int level)
 {
-    CPUState *env = (CPUState *)opaque;
+    CPUMIPSState *env = (CPUMIPSState *)opaque;
 
     if (irq < 0 || irq > 7)
         return;
@@ -44,7 +44,7 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level)
     }
 }
 
-void cpu_mips_irq_init_cpu(CPUState *env)
+void cpu_mips_irq_init_cpu(CPUMIPSState *env)
 {
     qemu_irq *qi;
     int i;
@@ -55,7 +55,7 @@ void cpu_mips_irq_init_cpu(CPUState *env)
     }
 }
 
-void cpu_mips_soft_irq(CPUState *env, int irq, int level)
+void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level)
 {
     if (irq < 0 || irq > 2) {
         return;
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index d5f1b34..a6bc7ba 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -50,7 +50,7 @@ enum jazz_model_e
 
 static void main_cpu_reset(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUMIPSState *env = opaque;
     cpu_state_reset(env);
 }
 
@@ -97,7 +97,7 @@ static const MemoryRegionOps dma_dummy_ops = {
 
 static void cpu_request_exit(void *opaque, int irq, int level)
 {
-    CPUState *env = cpu_single_env;
+    CPUMIPSState *env = cpu_single_env;
 
     if (env && level) {
         cpu_exit(env);
@@ -112,7 +112,7 @@ static void mips_jazz_init(MemoryRegion *address_space,
 {
     char *filename;
     int bios_size, n;
-    CPUState *env;
+    CPUMIPSState *env;
     qemu_irq *rc4030, *i8259;
     rc4030_dma *dmas;
     void* rc4030_opaque;
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 3335e11..5e26775 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -500,7 +500,7 @@ static void network_init(void)
      a3 - RAM size in bytes
 */
 
-static void write_bootloader (CPUState *env, uint8_t *base,
+static void write_bootloader (CPUMIPSState *env, uint8_t *base,
                               int64_t kernel_entry)
 {
     uint32_t *p;
@@ -736,7 +736,7 @@ static int64_t load_kernel (void)
     return kernel_entry;
 }
 
-static void malta_mips_config(CPUState *env)
+static void malta_mips_config(CPUMIPSState *env)
 {
     env->mvp->CP0_MVPConf0 |= ((smp_cpus - 1) << CP0MVPC0_PVPE) |
                          ((smp_cpus * env->nr_threads - 1) << CP0MVPC0_PTC);
@@ -744,7 +744,7 @@ static void malta_mips_config(CPUState *env)
 
 static void main_cpu_reset(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUMIPSState *env = opaque;
     cpu_state_reset(env);
 
     /* The bootloader does not need to be rewritten as it is located in a
@@ -759,7 +759,7 @@ static void main_cpu_reset(void *opaque)
 
 static void cpu_request_exit(void *opaque, int irq, int level)
 {
-    CPUState *env = cpu_single_env;
+    CPUMIPSState *env = cpu_single_env;
 
     if (env && level) {
         cpu_exit(env);
@@ -781,7 +781,7 @@ void mips_malta_init (ram_addr_t ram_size,
     int64_t kernel_entry;
     PCIBus *pci_bus;
     ISABus *isa_bus;
-    CPUState *env;
+    CPUMIPSState *env;
     qemu_irq *isa_irq;
     qemu_irq *cpu_exit_irq;
     int piix4_devfn;
diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
index 1fe4ac5..1ea7b58 100644
--- a/hw/mips_mipssim.c
+++ b/hw/mips_mipssim.c
@@ -46,7 +46,7 @@ static struct _loaderparams {
 } loaderparams;
 
 typedef struct ResetData {
-    CPUState *env;
+    CPUMIPSState *env;
     uint64_t vector;
 } ResetData;
 
@@ -105,7 +105,7 @@ static int64_t load_kernel(void)
 static void main_cpu_reset(void *opaque)
 {
     ResetData *s = (ResetData *)opaque;
-    CPUState *env = s->env;
+    CPUMIPSState *env = s->env;
 
     cpu_state_reset(env);
     env->active_tc.PC = s->vector & ~(target_ulong)1;
@@ -140,7 +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);
-    CPUState *env;
+    CPUMIPSState *env;
     ResetData *reset_info;
     int bios_size;
 
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index 96ad808..e2da49c 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -65,7 +65,7 @@ static const MemoryRegionOps mips_qemu_ops = {
 };
 
 typedef struct ResetData {
-    CPUState *env;
+    CPUMIPSState *env;
     uint64_t vector;
 } ResetData;
 
@@ -143,7 +143,7 @@ static int64_t load_kernel(void)
 static void main_cpu_reset(void *opaque)
 {
     ResetData *s = (ResetData *)opaque;
-    CPUState *env = s->env;
+    CPUMIPSState *env = s->env;
 
     cpu_state_reset(env);
     env->active_tc.PC = s->vector;
@@ -162,7 +162,7 @@ void mips_r4k_init (ram_addr_t ram_size,
     MemoryRegion *bios;
     MemoryRegion *iomem = g_new(MemoryRegion, 1);
     int bios_size;
-    CPUState *env;
+    CPUMIPSState *env;
     ResetData *reset_info;
     int i;
     qemu_irq *i8259;
diff --git a/hw/mips_timer.c b/hw/mips_timer.c
index cf6ac69..7aa9004 100644
--- a/hw/mips_timer.c
+++ b/hw/mips_timer.c
@@ -27,7 +27,7 @@
 #define TIMER_FREQ	100 * 1000 * 1000
 
 /* XXX: do not use a global */
-uint32_t cpu_mips_get_random (CPUState *env)
+uint32_t cpu_mips_get_random (CPUMIPSState *env)
 {
     static uint32_t lfsr = 1;
     static uint32_t prev_idx = 0;
@@ -42,7 +42,7 @@ uint32_t cpu_mips_get_random (CPUState *env)
 }
 
 /* MIPS R4K timer */
-static void cpu_mips_timer_update(CPUState *env)
+static void cpu_mips_timer_update(CPUMIPSState *env)
 {
     uint64_t now, next;
     uint32_t wait;
@@ -55,7 +55,7 @@ static void cpu_mips_timer_update(CPUState *env)
 }
 
 /* Expire the timer.  */
-static void cpu_mips_timer_expire(CPUState *env)
+static void cpu_mips_timer_expire(CPUMIPSState *env)
 {
     cpu_mips_timer_update(env);
     if (env->insn_flags & ISA_MIPS32R2) {
@@ -64,7 +64,7 @@ static void cpu_mips_timer_expire(CPUState *env)
     qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
 }
 
-uint32_t cpu_mips_get_count (CPUState *env)
+uint32_t cpu_mips_get_count (CPUMIPSState *env)
 {
     if (env->CP0_Cause & (1 << CP0Ca_DC)) {
         return env->CP0_Count;
@@ -83,7 +83,7 @@ uint32_t cpu_mips_get_count (CPUState *env)
     }
 }
 
-void cpu_mips_store_count (CPUState *env, uint32_t count)
+void cpu_mips_store_count (CPUMIPSState *env, uint32_t count)
 {
     if (env->CP0_Cause & (1 << CP0Ca_DC))
         env->CP0_Count = count;
@@ -97,7 +97,7 @@ void cpu_mips_store_count (CPUState *env, uint32_t count)
     }
 }
 
-void cpu_mips_store_compare (CPUState *env, uint32_t value)
+void cpu_mips_store_compare (CPUMIPSState *env, uint32_t value)
 {
     env->CP0_Compare = value;
     if (!(env->CP0_Cause & (1 << CP0Ca_DC)))
@@ -107,12 +107,12 @@ void cpu_mips_store_compare (CPUState *env, uint32_t value)
     qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
 }
 
-void cpu_mips_start_count(CPUState *env)
+void cpu_mips_start_count(CPUMIPSState *env)
 {
     cpu_mips_store_count(env, env->CP0_Count);
 }
 
-void cpu_mips_stop_count(CPUState *env)
+void cpu_mips_stop_count(CPUMIPSState *env)
 {
     /* Store the current value */
     env->CP0_Count += (uint32_t)muldiv64(qemu_get_clock_ns(vm_clock),
@@ -121,7 +121,7 @@ void cpu_mips_stop_count(CPUState *env)
 
 static void mips_timer_cb (void *opaque)
 {
-    CPUState *env;
+    CPUMIPSState *env;
 
     env = opaque;
 #if 0
@@ -139,7 +139,7 @@ static void mips_timer_cb (void *opaque)
     env->CP0_Count--;
 }
 
-void cpu_mips_clock_init (CPUState *env)
+void cpu_mips_clock_init (CPUMIPSState *env)
 {
     env->timer = qemu_new_timer_ns(vm_clock, &mips_timer_cb, env);
     env->CP0_Compare = 0;
commit ee118507324a597cacef3972fd69ac387c28744e
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:23 2012 +0100

    microblaze hw/: Don't use CPUState
    
    Scripted conversion:
      for file in hw/microblaze_*.[hc] hw/petalogix_ml605_mmu.c hw/petalogix_s3adsp1800_mmu.c; do
        sed -i "s/CPUState/CPUMBState/g" $file
      done
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/microblaze_boot.c b/hw/microblaze_boot.c
index 7ce04dc..b4fbb10 100644
--- a/hw/microblaze_boot.c
+++ b/hw/microblaze_boot.c
@@ -35,7 +35,7 @@
 
 static struct
 {
-    void (*machine_cpu_reset)(CPUState *);
+    void (*machine_cpu_reset)(CPUMBState *);
     uint32_t bootstrap_pc;
     uint32_t cmdline;
     uint32_t fdt;
@@ -43,7 +43,7 @@ static struct
 
 static void main_cpu_reset(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUMBState *env = opaque;
 
     cpu_state_reset(env);
     env->regs[5] = boot_info.cmdline;
@@ -99,9 +99,9 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
     return addr - 0x30000000LL;
 }
 
-void microblaze_load_kernel(CPUState *env, target_phys_addr_t ddr_base,
+void microblaze_load_kernel(CPUMBState *env, target_phys_addr_t ddr_base,
                             uint32_t ramsize, const char *dtb_filename,
-                                  void (*machine_cpu_reset)(CPUState *))
+                                  void (*machine_cpu_reset)(CPUMBState *))
 {
 
     QemuOpts *machine_opts;
diff --git a/hw/microblaze_boot.h b/hw/microblaze_boot.h
index 69d4ac6..bf9d136 100644
--- a/hw/microblaze_boot.h
+++ b/hw/microblaze_boot.h
@@ -3,8 +3,8 @@
 
 #include "hw.h"
 
-void microblaze_load_kernel(CPUState *env, target_phys_addr_t ddr_base,
+void microblaze_load_kernel(CPUMBState *env, target_phys_addr_t ddr_base,
                             uint32_t ramsize, const char *dtb_filename,
-                                  void (*machine_cpu_reset)(CPUState *));
+                                  void (*machine_cpu_reset)(CPUMBState *));
 
 #endif /* __MICROBLAZE_BOOT __ */
diff --git a/hw/microblaze_pic_cpu.c b/hw/microblaze_pic_cpu.c
index 8b5623c..ff36a52 100644
--- a/hw/microblaze_pic_cpu.c
+++ b/hw/microblaze_pic_cpu.c
@@ -29,7 +29,7 @@
 
 static void microblaze_pic_cpu_handler(void *opaque, int irq, int level)
 {
-    CPUState *env = (CPUState *)opaque;
+    CPUMBState *env = (CPUMBState *)opaque;
     int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
 
     if (level)
@@ -38,7 +38,7 @@ static void microblaze_pic_cpu_handler(void *opaque, int irq, int level)
         cpu_reset_interrupt(env, type);
 }
 
-qemu_irq *microblaze_pic_init_cpu(CPUState *env)
+qemu_irq *microblaze_pic_init_cpu(CPUMBState *env)
 {
     return qemu_allocate_irqs(microblaze_pic_cpu_handler, env, 2);
 }
diff --git a/hw/microblaze_pic_cpu.h b/hw/microblaze_pic_cpu.h
index 4c76275..43090a4 100644
--- a/hw/microblaze_pic_cpu.h
+++ b/hw/microblaze_pic_cpu.h
@@ -3,6 +3,6 @@
 
 #include "qemu-common.h"
 
-qemu_irq *microblaze_pic_init_cpu(CPUState *env);
+qemu_irq *microblaze_pic_init_cpu(CPUMBState *env);
 
 #endif /*  MICROBLAZE_PIC_CPU_H */
diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c
index c87fa11..31a4348 100644
--- a/hw/petalogix_ml605_mmu.c
+++ b/hw/petalogix_ml605_mmu.c
@@ -54,7 +54,7 @@
 #define AXIENET_BASEADDR 0x82780000
 #define AXIDMA_BASEADDR 0x84600000
 
-static void machine_cpu_reset(CPUState *env)
+static void machine_cpu_reset(CPUMBState *env)
 {
     env->pvr.regs[10] = 0x0e000000; /* virtex 6 */
     /* setup pvr to match kernel setting */
@@ -75,7 +75,7 @@ petalogix_ml605_init(ram_addr_t ram_size,
 {
     MemoryRegion *address_space_mem = get_system_memory();
     DeviceState *dev;
-    CPUState *env;
+    CPUMBState *env;
     DriveInfo *dinfo;
     int i;
     target_phys_addr_t ddr_base = MEMORY_BASEADDR;
diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index 2cb0b1f..ff154c7 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -49,7 +49,7 @@
 #define UARTLITE_BASEADDR 0x84000000
 #define ETHLITE_BASEADDR 0x81000000
 
-static void machine_cpu_reset(CPUState *env)
+static void machine_cpu_reset(CPUMBState *env)
 {
     /* FIXME: move to machine specfic cpu reset */
     env->pvr.regs[10] = 0x0c000000; /* spartan 3a dsp family.  */
@@ -63,7 +63,7 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
                           const char *initrd_filename, const char *cpu_model)
 {
     DeviceState *dev;
-    CPUState *env;
+    CPUMBState *env;
     DriveInfo *dinfo;
     int i;
     target_phys_addr_t ddr_base = MEMORY_BASEADDR;
commit 7927df3a8bd9e501bba91a5897cc0d5ddd470ccd
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:23 2012 +0100

    m68k hw/: Don't use CPUState
    
    Scripted conversion:
      for file in hw/an5206.c hw/dummy_m68k.c hw/mcf.h hw/mcf5206.c hw/mcf5208.c hw/mcf_intc.c; do
        sed -i "s/CPUState/CPUM68KState/g" $file
      done
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/an5206.c b/hw/an5206.c
index d57306d..25407c0 100644
--- a/hw/an5206.c
+++ b/hw/an5206.c
@@ -24,7 +24,7 @@ static void an5206_init(ram_addr_t ram_size,
                      const char *kernel_filename, const char *kernel_cmdline,
                      const char *initrd_filename, const char *cpu_model)
 {
-    CPUState *env;
+    CPUM68KState *env;
     int kernel_size;
     uint64_t elf_entry;
     target_phys_addr_t entry;
diff --git a/hw/dummy_m68k.c b/hw/dummy_m68k.c
index e3c5740..7cc7a99 100644
--- a/hw/dummy_m68k.c
+++ b/hw/dummy_m68k.c
@@ -21,7 +21,7 @@ static void dummy_m68k_init(ram_addr_t ram_size,
                      const char *kernel_filename, const char *kernel_cmdline,
                      const char *initrd_filename, const char *cpu_model)
 {
-    CPUState *env;
+    CPUM68KState *env;
     MemoryRegion *address_space_mem =  get_system_memory();
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     int kernel_size;
diff --git a/hw/mcf.h b/hw/mcf.h
index baa790b..19a8b54 100644
--- a/hw/mcf.h
+++ b/hw/mcf.h
@@ -17,7 +17,7 @@ void mcf_uart_mm_init(struct MemoryRegion *sysmem,
 /* mcf_intc.c */
 qemu_irq *mcf_intc_init(struct MemoryRegion *sysmem,
                         target_phys_addr_t base,
-                        CPUState *env);
+                        CPUM68KState *env);
 
 /* mcf_fec.c */
 void mcf_fec_init(struct MemoryRegion *sysmem, NICInfo *nd,
@@ -25,6 +25,6 @@ void mcf_fec_init(struct MemoryRegion *sysmem, NICInfo *nd,
 
 /* mcf5206.c */
 qemu_irq *mcf5206_init(struct MemoryRegion *sysmem,
-                       uint32_t base, CPUState *env);
+                       uint32_t base, CPUM68KState *env);
 
 #endif
diff --git a/hw/mcf5206.c b/hw/mcf5206.c
index 5110d83..539b391 100644
--- a/hw/mcf5206.c
+++ b/hw/mcf5206.c
@@ -145,7 +145,7 @@ static m5206_timer_state *m5206_timer_init(qemu_irq irq)
 /* System Integration Module.  */
 
 typedef struct {
-    CPUState *env;
+    CPUM68KState *env;
     MemoryRegion iomem;
     m5206_timer_state *timer[2];
     void *uart[2];
@@ -525,7 +525,7 @@ static const MemoryRegionOps m5206_mbar_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-qemu_irq *mcf5206_init(MemoryRegion *sysmem, uint32_t base, CPUState *env)
+qemu_irq *mcf5206_init(MemoryRegion *sysmem, uint32_t base, CPUM68KState *env)
 {
     m5206_mbar_state *s;
     qemu_irq *pic;
diff --git a/hw/mcf5208.c b/hw/mcf5208.c
index aa11a75..d3ebe8d 100644
--- a/hw/mcf5208.c
+++ b/hw/mcf5208.c
@@ -192,7 +192,7 @@ static void mcf5208evb_init(ram_addr_t ram_size,
                      const char *kernel_filename, const char *kernel_cmdline,
                      const char *initrd_filename, const char *cpu_model)
 {
-    CPUState *env;
+    CPUM68KState *env;
     int kernel_size;
     uint64_t elf_entry;
     target_phys_addr_t entry;
diff --git a/hw/mcf_intc.c b/hw/mcf_intc.c
index 0b498dd..cc1a5f3 100644
--- a/hw/mcf_intc.c
+++ b/hw/mcf_intc.c
@@ -16,7 +16,7 @@ typedef struct {
     uint64_t ifr;
     uint64_t enabled;
     uint8_t icr[64];
-    CPUState *env;
+    CPUM68KState *env;
     int active_vector;
 } mcf_intc_state;
 
@@ -139,7 +139,7 @@ static const MemoryRegionOps mcf_intc_ops = {
 
 qemu_irq *mcf_intc_init(MemoryRegion *sysmem,
                         target_phys_addr_t base,
-                        CPUState *env)
+                        CPUM68KState *env)
 {
     mcf_intc_state *s;
 
commit 93a674024c282e215fce14c500f757dcf298816a
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:23 2012 +0100

    lm32 hw/: Don't use CPUState
    
    Scripted conversion:
      for file in hw/lm32_boards.c hw/milkymist.c; do
        sed -i "s/CPUState/CPULM32State/g" $file
      done
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c
index 51c8a0f..4dd4f0a 100644
--- a/hw/lm32_boards.c
+++ b/hw/lm32_boards.c
@@ -31,7 +31,7 @@
 #include "exec-memory.h"
 
 typedef struct {
-    CPUState *env;
+    CPULM32State *env;
     target_phys_addr_t bootstrap_pc;
     target_phys_addr_t flash_base;
     target_phys_addr_t hwsetup_base;
@@ -42,7 +42,7 @@ typedef struct {
 
 static void cpu_irq_handler(void *opaque, int irq, int level)
 {
-    CPUState *env = opaque;
+    CPULM32State *env = opaque;
 
     if (level) {
         cpu_interrupt(env, CPU_INTERRUPT_HARD);
@@ -54,7 +54,7 @@ static void cpu_irq_handler(void *opaque, int irq, int level)
 static void main_cpu_reset(void *opaque)
 {
     ResetInfo *reset_info = opaque;
-    CPUState *env = reset_info->env;
+    CPULM32State *env = reset_info->env;
 
     cpu_state_reset(env);
 
@@ -75,7 +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)
 {
-    CPUState *env;
+    CPULM32State *env;
     DriveInfo *dinfo;
     MemoryRegion *address_space_mem =  get_system_memory();
     MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
@@ -163,7 +163,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)
 {
-    CPUState *env;
+    CPULM32State *env;
     DriveInfo *dinfo;
     MemoryRegion *address_space_mem =  get_system_memory();
     MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
diff --git a/hw/milkymist.c b/hw/milkymist.c
index 7ec6554..8bb6a97 100644
--- a/hw/milkymist.c
+++ b/hw/milkymist.c
@@ -37,7 +37,7 @@
 #define KERNEL_LOAD_ADDR 0x40000000
 
 typedef struct {
-    CPUState *env;
+    CPULM32State *env;
     target_phys_addr_t bootstrap_pc;
     target_phys_addr_t flash_base;
     target_phys_addr_t initrd_base;
@@ -47,7 +47,7 @@ typedef struct {
 
 static void cpu_irq_handler(void *opaque, int irq, int level)
 {
-    CPUState *env = opaque;
+    CPULM32State *env = opaque;
 
     if (level) {
         cpu_interrupt(env, CPU_INTERRUPT_HARD);
@@ -59,7 +59,7 @@ static void cpu_irq_handler(void *opaque, int irq, int level)
 static void main_cpu_reset(void *opaque)
 {
     ResetInfo *reset_info = opaque;
-    CPUState *env = reset_info->env;
+    CPULM32State *env = reset_info->env;
 
     cpu_state_reset(env);
 
@@ -79,7 +79,7 @@ milkymist_init(ram_addr_t ram_size_not_used,
                           const char *kernel_cmdline,
                           const char *initrd_filename, const char *cpu_model)
 {
-    CPUState *env;
+    CPULM32State *env;
     int kernel_size;
     DriveInfo *dinfo;
     MemoryRegion *address_space_mem = get_system_memory();
commit 4a8fa5dca1780d7064abd9af578cba40cc0e666d
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:23 2012 +0100

    i386 hw/: Don't use CPUState
    
    Scripted conversion:
      for file in hw/apic.h hw/kvm/apic.c hw/kvmvapic.c hw/pc.c hw/vmport.c hw/xen_machine_pv.c; do
        sed -i "s/CPUState/CPUX86State/g" $file
      done
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/apic.h b/hw/apic.h
index d6d6d44..62179ce 100644
--- a/hw/apic.h
+++ b/hw/apic.h
@@ -22,7 +22,7 @@ void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip,
                                    TPRAccess access);
 
 /* pc.c */
-int cpu_is_bsp(CPUState *env);
+int cpu_is_bsp(CPUX86State *env);
 DeviceState *cpu_get_current_apic(void);
 
 #endif
diff --git a/hw/kvm/apic.c b/hw/kvm/apic.c
index 9ca68f8..ffe7a52 100644
--- a/hw/kvm/apic.c
+++ b/hw/kvm/apic.c
@@ -124,7 +124,7 @@ static void kvm_apic_vapic_base_update(APICCommonState *s)
 static void do_inject_external_nmi(void *data)
 {
     APICCommonState *s = data;
-    CPUState *env = s->cpu_env;
+    CPUX86State *env = s->cpu_env;
     uint32_t lvt;
     int ret;
 
diff --git a/hw/kvmvapic.c b/hw/kvmvapic.c
index e8bfeec..5d83625 100644
--- a/hw/kvmvapic.c
+++ b/hw/kvmvapic.c
@@ -142,7 +142,7 @@ static void update_guest_rom_state(VAPICROMState *s)
     write_guest_rom_state(s);
 }
 
-static int find_real_tpr_addr(VAPICROMState *s, CPUState *env)
+static int find_real_tpr_addr(VAPICROMState *s, CPUX86State *env)
 {
     target_phys_addr_t paddr;
     target_ulong addr;
@@ -185,7 +185,7 @@ static bool opcode_matches(uint8_t *opcode, const TPRInstruction *instr)
          modrm_reg(opcode[1]) == instr->modrm_reg);
 }
 
-static int evaluate_tpr_instruction(VAPICROMState *s, CPUState *env,
+static int evaluate_tpr_instruction(VAPICROMState *s, CPUX86State *env,
                                     target_ulong *pip, TPRAccess access)
 {
     const TPRInstruction *instr;
@@ -267,7 +267,7 @@ instruction_ok:
     return 0;
 }
 
-static int update_rom_mapping(VAPICROMState *s, CPUState *env, target_ulong ip)
+static int update_rom_mapping(VAPICROMState *s, CPUX86State *env, target_ulong ip)
 {
     target_phys_addr_t paddr;
     uint32_t rom_state_vaddr;
@@ -330,7 +330,7 @@ static int update_rom_mapping(VAPICROMState *s, CPUState *env, target_ulong ip)
  * cannot be accessed or is considered invalid. This also ensures that we are
  * not patching the wrong guest.
  */
-static int get_kpcr_number(CPUState *env)
+static int get_kpcr_number(CPUX86State *env)
 {
     struct kpcr {
         uint8_t  fill1[0x1c];
@@ -347,7 +347,7 @@ static int get_kpcr_number(CPUState *env)
     return kpcr.number;
 }
 
-static int vapic_enable(VAPICROMState *s, CPUState *env)
+static int vapic_enable(VAPICROMState *s, CPUX86State *env)
 {
     int cpu_number = get_kpcr_number(env);
     target_phys_addr_t vapic_paddr;
@@ -367,12 +367,12 @@ static int vapic_enable(VAPICROMState *s, CPUState *env)
     return 0;
 }
 
-static void patch_byte(CPUState *env, target_ulong addr, uint8_t byte)
+static void patch_byte(CPUX86State *env, target_ulong addr, uint8_t byte)
 {
     cpu_memory_rw_debug(env, addr, &byte, 1, 1);
 }
 
-static void patch_call(VAPICROMState *s, CPUState *env, target_ulong ip,
+static void patch_call(VAPICROMState *s, CPUX86State *env, target_ulong ip,
                        uint32_t target)
 {
     uint32_t offset;
@@ -382,7 +382,7 @@ static void patch_call(VAPICROMState *s, CPUState *env, target_ulong ip,
     cpu_memory_rw_debug(env, ip + 1, (void *)&offset, sizeof(offset), 1);
 }
 
-static void patch_instruction(VAPICROMState *s, CPUState *env, target_ulong ip)
+static void patch_instruction(VAPICROMState *s, CPUX86State *env, target_ulong ip)
 {
     target_phys_addr_t paddr;
     VAPICHandlers *handlers;
@@ -439,7 +439,7 @@ void vapic_report_tpr_access(DeviceState *dev, void *cpu, target_ulong ip,
                              TPRAccess access)
 {
     VAPICROMState *s = DO_UPCAST(VAPICROMState, busdev.qdev, dev);
-    CPUState *env = cpu;
+    CPUX86State *env = cpu;
 
     cpu_synchronize_state(env);
 
@@ -475,7 +475,7 @@ static void vapic_enable_tpr_reporting(bool enable)
     VAPICEnableTPRReporting info = {
         .enable = enable,
     };
-    CPUState *env;
+    CPUX86State *env;
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
         info.apic = env->apic_state;
@@ -606,7 +606,7 @@ static int vapic_prepare(VAPICROMState *s)
 static void vapic_write(void *opaque, target_phys_addr_t addr, uint64_t data,
                         unsigned int size)
 {
-    CPUState *env = cpu_single_env;
+    CPUX86State *env = cpu_single_env;
     target_phys_addr_t rom_paddr;
     VAPICROMState *s = opaque;
 
diff --git a/hw/pc.c b/hw/pc.c
index aca4460..83a1b5b 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -140,7 +140,7 @@ void cpu_smm_register(cpu_set_smm_t callback, void *arg)
     smm_arg = arg;
 }
 
-void cpu_smm_update(CPUState *env)
+void cpu_smm_update(CPUX86State *env)
 {
     if (smm_set && smm_arg && env == first_cpu)
         smm_set(!!(env->hflags & HF_SMM_MASK), smm_arg);
@@ -148,7 +148,7 @@ void cpu_smm_update(CPUState *env)
 
 
 /* IRQ handling */
-int cpu_get_pic_interrupt(CPUState *env)
+int cpu_get_pic_interrupt(CPUX86State *env)
 {
     int intno;
 
@@ -167,7 +167,7 @@ int cpu_get_pic_interrupt(CPUState *env)
 
 static void pic_irq_request(void *opaque, int irq, int level)
 {
-    CPUState *env = first_cpu;
+    CPUX86State *env = first_cpu;
 
     DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq);
     if (env->apic_state) {
@@ -522,7 +522,7 @@ type_init(port92_register_types)
 
 static void handle_a20_line_change(void *opaque, int irq, int level)
 {
-    CPUState *cpu = opaque;
+    CPUX86State *cpu = opaque;
 
     /* XXX: send to all CPUs ? */
     /* XXX: add logic to handle multiple A20 line sources */
@@ -869,7 +869,7 @@ void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd)
     nb_ne2k++;
 }
 
-int cpu_is_bsp(CPUState *env)
+int cpu_is_bsp(CPUX86State *env)
 {
     /* We hard-wire the BSP to the first CPU. */
     return env->cpu_index == 0;
@@ -917,7 +917,7 @@ static DeviceState *apic_init(void *env, uint8_t apic_id)
 
 void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
 {
-    CPUState *s = opaque;
+    CPUX86State *s = opaque;
 
     if (level) {
         cpu_interrupt(s, CPU_INTERRUPT_SMI);
@@ -926,15 +926,15 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
 
 static void pc_cpu_reset(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUX86State *env = opaque;
 
     cpu_state_reset(env);
     env->halted = !cpu_is_bsp(env);
 }
 
-static CPUState *pc_new_cpu(const char *cpu_model)
+static CPUX86State *pc_new_cpu(const char *cpu_model)
 {
-    CPUState *env;
+    CPUX86State *env;
 
     env = cpu_init(cpu_model);
     if (!env) {
@@ -1070,7 +1070,7 @@ DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus)
 
 static void cpu_request_exit(void *opaque, int irq, int level)
 {
-    CPUState *env = cpu_single_env;
+    CPUX86State *env = cpu_single_env;
 
     if (env && level) {
         cpu_exit(env);
diff --git a/hw/vmport.c b/hw/vmport.c
index 9373be9..a4f52ee 100644
--- a/hw/vmport.c
+++ b/hw/vmport.c
@@ -57,7 +57,7 @@ void vmport_register(unsigned char command, IOPortReadFunc *func, void *opaque)
 static uint32_t vmport_ioport_read(void *opaque, uint32_t addr)
 {
     VMPortState *s = opaque;
-    CPUState *env = cpu_single_env;
+    CPUX86State *env = cpu_single_env;
     unsigned char command;
     uint32_t eax;
 
@@ -83,21 +83,21 @@ static uint32_t vmport_ioport_read(void *opaque, uint32_t addr)
 
 static void vmport_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 {
-    CPUState *env = cpu_single_env;
+    CPUX86State *env = cpu_single_env;
 
     env->regs[R_EAX] = vmport_ioport_read(opaque, addr);
 }
 
 static uint32_t vmport_cmd_get_version(void *opaque, uint32_t addr)
 {
-    CPUState *env = cpu_single_env;
+    CPUX86State *env = cpu_single_env;
     env->regs[R_EBX] = VMPORT_MAGIC;
     return 6;
 }
 
 static uint32_t vmport_cmd_ram_size(void *opaque, uint32_t addr)
 {
-    CPUState *env = cpu_single_env;
+    CPUX86State *env = cpu_single_env;
     env->regs[R_EBX] = 0x1177;
     return ram_size;
 }
@@ -105,7 +105,7 @@ static uint32_t vmport_cmd_ram_size(void *opaque, uint32_t addr)
 /* vmmouse helpers */
 void vmmouse_get_data(uint32_t *data)
 {
-    CPUState *env = cpu_single_env;
+    CPUX86State *env = cpu_single_env;
 
     data[0] = env->regs[R_EAX]; data[1] = env->regs[R_EBX];
     data[2] = env->regs[R_ECX]; data[3] = env->regs[R_EDX];
@@ -114,7 +114,7 @@ void vmmouse_get_data(uint32_t *data)
 
 void vmmouse_set_data(const uint32_t *data)
 {
-    CPUState *env = cpu_single_env;
+    CPUX86State *env = cpu_single_env;
 
     env->regs[R_EAX] = data[0]; env->regs[R_EBX] = data[1];
     env->regs[R_ECX] = data[2]; env->regs[R_EDX] = data[3];
diff --git a/hw/xen_machine_pv.c b/hw/xen_machine_pv.c
index 7985d11..7eee770 100644
--- a/hw/xen_machine_pv.c
+++ b/hw/xen_machine_pv.c
@@ -36,7 +36,7 @@ static void xen_init_pv(ram_addr_t ram_size,
 			const char *initrd_filename,
 			const char *cpu_model)
 {
-    CPUState *env;
+    CPUX86State *env;
     DriveInfo *dinfo;
     int i;
 
commit fc9bb1769706d4b3ac48e52d4639505bc1ce7392
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:23 2012 +0100

    cris hw/: Don't use CPUState
    
    Scripted conversion:
      for file in hw/cris-boot.[hc] hw/cris_pic_cpu.c hw/axis_dev88.c hw/etraxfs.h hw/etraxfs_ser.c; do
        sed -i "s/CPUState/CPUCRISState/g" $file
      done
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index c9301fd..2304e35 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -247,7 +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)
 {
-    CPUState *env;
+    CPUCRISState *env;
     DeviceState *dev;
     SysBusDevice *s;
     DriveInfo *nand;
diff --git a/hw/cris-boot.c b/hw/cris-boot.c
index ade517d..ca6c52f 100644
--- a/hw/cris-boot.c
+++ b/hw/cris-boot.c
@@ -29,7 +29,7 @@
 
 static void main_cpu_reset(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUCRISState *env = opaque;
     struct cris_load_info *li;
 
     li = env->load_info;
@@ -60,7 +60,7 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
     return addr - 0x80000000LL;
 }
 
-void cris_load_image(CPUState *env, struct cris_load_info *li)
+void cris_load_image(CPUCRISState *env, struct cris_load_info *li)
 {
     uint64_t entry, high;
     int kcmdline_len;
diff --git a/hw/cris-boot.h b/hw/cris-boot.h
index e9caf8d..ecb9779 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(CPUState *env, struct cris_load_info *li);
+void cris_load_image(CPUCRISState *env, struct cris_load_info *li);
diff --git a/hw/cris_pic_cpu.c b/hw/cris_pic_cpu.c
index 06ae484..3da0e86 100644
--- a/hw/cris_pic_cpu.c
+++ b/hw/cris_pic_cpu.c
@@ -30,7 +30,7 @@
 
 static void cris_pic_cpu_handler(void *opaque, int irq, int level)
 {
-    CPUState *env = (CPUState *)opaque;
+    CPUCRISState *env = (CPUCRISState *)opaque;
     int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
 
     if (level)
@@ -39,7 +39,7 @@ static void cris_pic_cpu_handler(void *opaque, int irq, int level)
         cpu_reset_interrupt(env, type);
 }
 
-qemu_irq *cris_pic_init_cpu(CPUState *env)
+qemu_irq *cris_pic_init_cpu(CPUCRISState *env)
 {
     return qemu_allocate_irqs(cris_pic_cpu_handler, env, 2);
 }
diff --git a/hw/etraxfs.h b/hw/etraxfs.h
index 24e8fd8..c62f94b 100644
--- a/hw/etraxfs.h
+++ b/hw/etraxfs.h
@@ -25,7 +25,7 @@
 #include "net.h"
 #include "etraxfs_dma.h"
 
-qemu_irq *cris_pic_init_cpu(CPUState *env);
+qemu_irq *cris_pic_init_cpu(CPUCRISState *env);
 
 /* Instantiate an ETRAXFS Ethernet MAC.  */
 static inline DeviceState *
diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
index cecd819..5f16b17 100644
--- a/hw/etraxfs_ser.c
+++ b/hw/etraxfs_ser.c
@@ -78,7 +78,7 @@ static uint64_t
 ser_read(void *opaque, target_phys_addr_t addr, unsigned int size)
 {
     struct etrax_serial *s = opaque;
-    D(CPUState *env = s->env);
+    D(CPUCRISState *env = s->env);
     uint32_t r = 0;
 
     addr >>= 2;
@@ -116,7 +116,7 @@ ser_write(void *opaque, target_phys_addr_t addr,
     struct etrax_serial *s = opaque;
     uint32_t value = val64;
     unsigned char ch = val64;
-    D(CPUState *env = s->env);
+    D(CPUCRISState *env = s->env);
 
     D(qemu_log("%s " TARGET_FMT_plx "=%x\n",  __func__, addr, value));
     addr >>= 2;
commit 5ae93306826fba021a86355e5d91253c67c736bc
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:23 2012 +0100

    arm hw/: Don't use CPUState
    
    Scripted conversion:
      for file in hw/arm-misc.h hw/arm_boot.c hw/arm_pic.c hw/armv7m.c hw/exynos4210.h hw/highbank.c hw/integratorcp.c hw/musicpal.c hw/omap.h hw/pxa.h hw/pxa2xx_gpio.c hw/pxa2xx_pic.c hw/realview.c hw/strongarm.h hw/versatilepb.c hw/vexpress.c  hw/xilinx_zynq.c ; do
        sed -i "s/CPUState/CPUARMState/g" $file
      done
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/arm-misc.h b/hw/arm-misc.h
index 734bd82..2f46e21 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(CPUState *env);
+qemu_irq *arm_pic_init_cpu(CPUARMState *env);
 
 /* armv7m.c */
 qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
@@ -50,16 +50,16 @@ 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)(CPUState *env,
+    void (*write_secondary_boot)(CPUARMState *env,
                                  const struct arm_boot_info *info);
-    void (*secondary_cpu_reset_hook)(CPUState *env,
+    void (*secondary_cpu_reset_hook)(CPUARMState *env,
                                      const struct arm_boot_info *info);
     /* Used internally by arm_boot.c */
     int is_linux;
     target_phys_addr_t initrd_size;
     target_phys_addr_t entry;
 };
-void arm_load_kernel(CPUState *env, struct arm_boot_info *info);
+void arm_load_kernel(CPUARMState *env, 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 23b3f0a..7447f5c 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(CPUState *env,
+static void default_write_secondary(CPUARMState *env,
                                     const struct arm_boot_info *info)
 {
     int n;
@@ -72,7 +72,7 @@ static void default_write_secondary(CPUState *env,
                        info->smp_loader_start);
 }
 
-static void default_reset_secondary(CPUState *env,
+static void default_reset_secondary(CPUARMState *env,
                                     const struct arm_boot_info *info)
 {
     stl_phys_notdirty(info->smp_bootreg_addr, 0);
@@ -274,7 +274,7 @@ static int load_dtb(target_phys_addr_t addr, const struct arm_boot_info *binfo)
 
 static void do_cpu_reset(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUARMState *env = opaque;
     const struct arm_boot_info *info = env->boot_info;
 
     cpu_state_reset(env);
@@ -300,7 +300,7 @@ static void do_cpu_reset(void *opaque)
     }
 }
 
-void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
+void arm_load_kernel(CPUARMState *env, struct arm_boot_info *info)
 {
     int kernel_size;
     int initrd_size;
diff --git a/hw/arm_pic.c b/hw/arm_pic.c
index a2e8a73..1094965 100644
--- a/hw/arm_pic.c
+++ b/hw/arm_pic.c
@@ -13,7 +13,7 @@
 /* Input 0 is IRQ and input 1 is FIQ.  */
 static void arm_pic_cpu_handler(void *opaque, int irq, int level)
 {
-    CPUState *env = (CPUState *)opaque;
+    CPUARMState *env = (CPUARMState *)opaque;
     switch (irq) {
     case ARM_PIC_CPU_IRQ:
         if (level)
@@ -32,7 +32,7 @@ static void arm_pic_cpu_handler(void *opaque, int irq, int level)
     }
 }
 
-qemu_irq *arm_pic_init_cpu(CPUState *env)
+qemu_irq *arm_pic_init_cpu(CPUARMState *env)
 {
     return qemu_allocate_irqs(arm_pic_cpu_handler, env, 2);
 }
diff --git a/hw/armv7m.c b/hw/armv7m.c
index 9cf96f4..4aac076 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -149,7 +149,7 @@ static void armv7m_bitband_init(void)
 
 static void armv7m_reset(void *opaque)
 {
-    cpu_state_reset((CPUState *)opaque);
+    cpu_state_reset((CPUARMState *)opaque);
 }
 
 /* Init CPU and memory for a v7-M based board.
@@ -160,7 +160,7 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
                       int flash_size, int sram_size,
                       const char *kernel_filename, const char *cpu_model)
 {
-    CPUState *env;
+    CPUARMState *env;
     DeviceState *nvic;
     /* FIXME: make this local state.  */
     static qemu_irq pic[64];
diff --git a/hw/exynos4210.h b/hw/exynos4210.h
index e7522f8..c112e03 100644
--- a/hw/exynos4210.h
+++ b/hw/exynos4210.h
@@ -83,7 +83,7 @@ typedef struct Exynos4210Irq {
 } Exynos4210Irq;
 
 typedef struct Exynos4210State {
-    CPUState * env[EXYNOS4210_NCPUS];
+    CPUARMState * env[EXYNOS4210_NCPUS];
     Exynos4210Irq irqs;
     qemu_irq *irq_table;
 
diff --git a/hw/highbank.c b/hw/highbank.c
index 489c00e..906eed5 100644
--- a/hw/highbank.c
+++ b/hw/highbank.c
@@ -37,12 +37,12 @@
 /* Board init.  */
 static void highbank_cpu_reset(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUARMState *env = opaque;
 
     env->cp15.c15_config_base_address = GIC_BASE_ADDR;
 }
 
-static void hb_write_secondary(CPUState *env, const struct arm_boot_info *info)
+static void hb_write_secondary(CPUARMState *env, const struct arm_boot_info *info)
 {
     int n;
     uint32_t smpboot[] = {
@@ -66,7 +66,7 @@ static void hb_write_secondary(CPUState *env, const struct arm_boot_info *info)
     rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR);
 }
 
-static void hb_reset_secondary(CPUState *env, const struct arm_boot_info *info)
+static void hb_reset_secondary(CPUARMState *env, const struct arm_boot_info *info)
 {
     switch (info->nb_cpus) {
     case 4:
@@ -196,7 +196,7 @@ 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)
 {
-    CPUState *env = NULL;
+    CPUARMState *env = NULL;
     DeviceState *dev;
     SysBusDevice *busdev;
     qemu_irq *irqp;
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index 5b06c81..9bdb9e6 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)
 {
-    CPUState *env;
+    CPUARMState *env;
     MemoryRegion *address_space_mem = get_system_memory();
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
diff --git a/hw/musicpal.c b/hw/musicpal.c
index 187a1ae..c9f845a 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)
 {
-    CPUState *env;
+    CPUARMState *env;
     qemu_irq *cpu_pic;
     qemu_irq pic[32];
     DeviceState *dev;
diff --git a/hw/omap.h b/hw/omap.h
index 60fa34c..63ef847 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -813,7 +813,7 @@ struct omap_mpu_state_s {
         omap3630,
     } mpu_model;
 
-    CPUState *env;
+    CPUARMState *env;
 
     qemu_irq *drq;
 
diff --git a/hw/pxa.h b/hw/pxa.h
index e778739..025be34 100644
--- a/hw/pxa.h
+++ b/hw/pxa.h
@@ -65,11 +65,11 @@
 # define PXA2XX_INTERNAL_SIZE	0x40000
 
 /* pxa2xx_pic.c */
-DeviceState *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env);
+DeviceState *pxa2xx_pic_init(target_phys_addr_t base, CPUARMState *env);
 
 /* pxa2xx_gpio.c */
 DeviceState *pxa2xx_gpio_init(target_phys_addr_t base,
-                CPUState *env, DeviceState *pic, int lines);
+                CPUARMState *env, DeviceState *pic, int lines);
 void pxa2xx_gpio_read_notifier(DeviceState *dev, qemu_irq handler);
 
 /* pxa2xx_dma.c */
@@ -122,7 +122,7 @@ typedef struct PXA2xxI2SState PXA2xxI2SState;
 typedef struct PXA2xxFIrState PXA2xxFIrState;
 
 typedef struct {
-    CPUState *env;
+    CPUARMState *env;
     DeviceState *pic;
     qemu_irq reset;
     MemoryRegion sdram;
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index d5f5716..09a408b 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;
-    CPUState *cpu_env;
+    CPUARMState *cpu_env;
 
     /* XXX: GNU C vectors are more suitable */
     uint32_t ilevel[PXA2XX_GPIO_BANKS];
@@ -249,7 +249,7 @@ static const MemoryRegionOps pxa_gpio_ops = {
 };
 
 DeviceState *pxa2xx_gpio_init(target_phys_addr_t base,
-                CPUState *env, DeviceState *pic, int lines)
+                CPUARMState *env, DeviceState *pic, int lines)
 {
     DeviceState *dev;
 
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index 6b2bdb0..a806b80 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -34,7 +34,7 @@
 typedef struct {
     SysBusDevice busdev;
     MemoryRegion iomem;
-    CPUState *cpu_env;
+    CPUARMState *cpu_env;
     uint32_t int_enabled[2];
     uint32_t int_pending[2];
     uint32_t is_fiq[2];
@@ -245,7 +245,7 @@ static int pxa2xx_pic_post_load(void *opaque, int version_id)
     return 0;
 }
 
-DeviceState *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env)
+DeviceState *pxa2xx_pic_init(target_phys_addr_t base, CPUARMState *env)
 {
     DeviceState *dev = qdev_create(NULL, "pxa2xx_pic");
     PXA2xxPICState *s = FROM_SYSBUS(PXA2xxPICState, sysbus_from_qdev(dev));
diff --git a/hw/realview.c b/hw/realview.c
index 50ea67c..cf55204 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -128,7 +128,7 @@ static void realview_init(ram_addr_t ram_size,
                      const char *initrd_filename, const char *cpu_model,
                      enum realview_board_type board_type)
 {
-    CPUState *env = NULL;
+    CPUARMState *env = NULL;
     MemoryRegion *sysmem = get_system_memory();
     MemoryRegion *ram_lo = g_new(MemoryRegion, 1);
     MemoryRegion *ram_hi = g_new(MemoryRegion, 1);
diff --git a/hw/strongarm.h b/hw/strongarm.h
index 684f61b..02acac3 100644
--- a/hw/strongarm.h
+++ b/hw/strongarm.h
@@ -53,7 +53,7 @@ enum {
 };
 
 typedef struct {
-    CPUState *env;
+    CPUARMState *env;
     MemoryRegion sdram;
     DeviceState *pic;
     DeviceState *gpio;
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index c1687a5..25afb1e 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -167,7 +167,7 @@ static void versatile_init(ram_addr_t ram_size,
                      const char *initrd_filename, const char *cpu_model,
                      int board_id)
 {
-    CPUState *env;
+    CPUARMState *env;
     MemoryRegion *sysmem = get_system_memory();
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     qemu_irq *cpu_pic;
diff --git a/hw/vexpress.c b/hw/vexpress.c
index b9aafec..18d87ac 100644
--- a/hw/vexpress.c
+++ b/hw/vexpress.c
@@ -159,7 +159,7 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
                                   const char *cpu_model,
                                   qemu_irq *pic, uint32_t *proc_id)
 {
-    CPUState *env = NULL;
+    CPUARMState *env = NULL;
     MemoryRegion *sysmem = get_system_memory();
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     MemoryRegion *lowram = g_new(MemoryRegion, 1);
@@ -259,7 +259,7 @@ static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
                                    qemu_irq *pic, uint32_t *proc_id)
 {
     int n;
-    CPUState *env = NULL;
+    CPUARMState *env = NULL;
     MemoryRegion *sysmem = get_system_memory();
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     MemoryRegion *sram = g_new(MemoryRegion, 1);
diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c
index ea13e8c..7290c64 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)
 {
-    CPUState *env = NULL;
+    CPUARMState *env = NULL;
     MemoryRegion *address_space_mem = get_system_memory();
     MemoryRegion *ext_ram = g_new(MemoryRegion, 1);
     MemoryRegion *ocm_ram = g_new(MemoryRegion, 1);
commit 8b2aee2959c34ef7319067010bb517103144ac6b
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:23 2012 +0100

    alpha hw/: Don't use CPUState
    
    Scripted conversion:
      for file in hw/alpha_*.[hc]; do
        sed -i "s/CPUState/CPUAlphaState/g" $file
      done
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/alpha_dp264.c b/hw/alpha_dp264.c
index ea0fd95..9eb939f 100644
--- a/hw/alpha_dp264.c
+++ b/hw/alpha_dp264.c
@@ -49,7 +49,7 @@ static void clipper_init(ram_addr_t ram_size,
                          const char *initrd_filename,
                          const char *cpu_model)
 {
-    CPUState *cpus[4];
+    CPUAlphaState *cpus[4];
     PCIBus *pci_bus;
     ISABus *isa_bus;
     qemu_irq rtc_irq;
diff --git a/hw/alpha_sys.h b/hw/alpha_sys.h
index f9506c6..de40f8b 100644
--- a/hw/alpha_sys.h
+++ b/hw/alpha_sys.h
@@ -11,7 +11,7 @@
 #include "irq.h"
 
 
-PCIBus *typhoon_init(ram_addr_t, ISABus **, qemu_irq *, CPUState *[4],
+PCIBus *typhoon_init(ram_addr_t, ISABus **, qemu_irq *, CPUAlphaState *[4],
                      pci_map_irq_fn);
 
 /* alpha_pci.c.  */
diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c
index b539416..872e112 100644
--- a/hw/alpha_typhoon.c
+++ b/hw/alpha_typhoon.c
@@ -21,7 +21,7 @@ typedef struct TyphoonCchip {
     uint64_t drir;
     uint64_t dim[4];
     uint32_t iic[4];
-    CPUState *cpu[4];
+    CPUAlphaState *cpu[4];
 } TyphoonCchip;
 
 typedef struct TyphoonWindow {
@@ -52,7 +52,7 @@ typedef struct TyphoonState {
 } TyphoonState;
 
 /* Called when one of DRIR or DIM changes.  */
-static void cpu_irq_change(CPUState *env, uint64_t req)
+static void cpu_irq_change(CPUAlphaState *env, uint64_t req)
 {
     /* If there are any non-masked interrupts, tell the cpu.  */
     if (env) {
@@ -66,7 +66,7 @@ static void cpu_irq_change(CPUState *env, uint64_t req)
 
 static uint64_t cchip_read(void *opaque, target_phys_addr_t addr, unsigned size)
 {
-    CPUState *env = cpu_single_env;
+    CPUAlphaState *env = cpu_single_env;
     TyphoonState *s = opaque;
     uint64_t ret = 0;
 
@@ -347,7 +347,7 @@ static void cchip_write(void *opaque, target_phys_addr_t addr,
         if ((newval ^ oldval) & 0xff0) {
             int i;
             for (i = 0; i < 4; ++i) {
-                CPUState *env = s->cchip.cpu[i];
+                CPUAlphaState *env = s->cchip.cpu[i];
                 if (env) {
                     /* IPI can be either cleared or set by the write.  */
                     if (newval & (1 << (i + 8))) {
@@ -655,7 +655,7 @@ static void typhoon_set_timer_irq(void *opaque, int irq, int level)
 
     /* Deliver the interrupt to each CPU, considering each CPU's IIC.  */
     for (i = 0; i < 4; ++i) {
-        CPUState *env = s->cchip.cpu[i];
+        CPUAlphaState *env = s->cchip.cpu[i];
         if (env) {
             uint32_t iic = s->cchip.iic[i];
 
@@ -693,7 +693,7 @@ static void typhoon_alarm_timer(void *opaque)
 
 PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
                      qemu_irq *p_rtc_irq,
-                     CPUState *cpus[4], pci_map_irq_fn sys_map_irq)
+                     CPUAlphaState *cpus[4], pci_map_irq_fn sys_map_irq)
 {
     const uint64_t MB = 1024 * 1024;
     const uint64_t GB = 1024 * MB;
@@ -713,7 +713,7 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
 
     /* Remember the CPUs so that we can deliver interrupts to them.  */
     for (i = 0; i < 4; i++) {
-        CPUState *env = cpus[i];
+        CPUAlphaState *env = cpus[i];
         s->cchip.cpu[i] = env;
         if (env) {
             env->alarm_timer = qemu_new_timer_ns(rtc_clock,
commit d4a5b622b5522274597b4073ca236ae93b3816cf
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:23 2012 +0100

    xtensa-semi: Don't use CPUState
    
    Scripted conversion:
      sed -i "s/CPUState/CPUXtensaState/g" xtensa-semi.c
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/xtensa-semi.c b/xtensa-semi.c
index ba0e828..5754b77 100644
--- a/xtensa-semi.c
+++ b/xtensa-semi.c
@@ -55,7 +55,7 @@ enum {
     SELECT_ONE_EXCEPT = 3,
 };
 
-void HELPER(simcall)(CPUState *env)
+void HELPER(simcall)(CPUXtensaState *env)
 {
     uint32_t *regs = env->regs;
 
commit 71fc85e8c1dcc1eff1db5f3252c321df91b0d41c
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:23 2012 +0100

    m68k-semi: Don't use CPUState
    
    Scripted conversion:
      sed -i "s/CPUState/CPUM68KState/g" m68k-semi.c
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/m68k-semi.c b/m68k-semi.c
index bab01ee..3bb30cd 100644
--- a/m68k-semi.c
+++ b/m68k-semi.c
@@ -104,7 +104,7 @@ static int translate_openflags(int flags)
     return hf;
 }
 
-static void translate_stat(CPUState *env, target_ulong addr, struct stat *s)
+static void translate_stat(CPUM68KState *env, target_ulong addr, struct stat *s)
 {
     struct m68k_gdb_stat *p;
 
@@ -135,7 +135,7 @@ static void translate_stat(CPUState *env, target_ulong addr, struct stat *s)
 
 static int m68k_semi_is_fseek;
 
-static void m68k_semi_cb(CPUState *env, target_ulong ret, target_ulong err)
+static void m68k_semi_cb(CPUM68KState *env, target_ulong ret, target_ulong err)
 {
     target_ulong args;
 
commit 81926f476fb14ddf2bb394c448d48191322b80f8
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:23 2012 +0100

    arm-semi: Don't use CPUState
    
    Scripted conversion:
      sed -i "s/CPUState/CPUARMState/g" arm-semi.c
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/arm-semi.c b/arm-semi.c
index 873518a..8debd19 100644
--- a/arm-semi.c
+++ b/arm-semi.c
@@ -108,7 +108,7 @@ static inline uint32_t set_swi_errno(TaskState *ts, uint32_t code)
     return code;
 }
 #else
-static inline uint32_t set_swi_errno(CPUState *env, uint32_t code)
+static inline uint32_t set_swi_errno(CPUARMState *env, uint32_t code)
 {
     return code;
 }
@@ -122,7 +122,7 @@ static target_ulong arm_semi_syscall_len;
 static target_ulong syscall_err;
 #endif
 
-static void arm_semi_cb(CPUState *env, target_ulong ret, target_ulong err)
+static void arm_semi_cb(CPUARMState *env, target_ulong ret, target_ulong err)
 {
 #ifdef CONFIG_USER_ONLY
     TaskState *ts = env->opaque;
@@ -152,7 +152,7 @@ static void arm_semi_cb(CPUState *env, target_ulong ret, target_ulong err)
     }
 }
 
-static void arm_semi_flen_cb(CPUState *env, target_ulong ret, target_ulong err)
+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.  */
@@ -174,7 +174,7 @@ static void arm_semi_flen_cb(CPUState *env, target_ulong ret, target_ulong err)
     __arg;					\
 })
 #define SET_ARG(n, val) put_user_ual(val, args + (n) * 4)
-uint32_t do_arm_semihosting(CPUState *env)
+uint32_t do_arm_semihosting(CPUARMState *env)
 {
     target_ulong args;
     char * s;
@@ -184,7 +184,7 @@ uint32_t do_arm_semihosting(CPUState *env)
 #ifdef CONFIG_USER_ONLY
     TaskState *ts = env->opaque;
 #else
-    CPUState *ts = env;
+    CPUARMState *ts = env;
 #endif
 
     nr = env->regs[0];
commit 97129ac899633325000c4d40b53b1afa0975f541
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:23 2012 +0100

    target-xtensa: Don't overuse CPUState
    
    Scripted conversion:
      sed -i "s/CPUState/CPUXtensaState/g" target-xtensa/*.[hc]
      sed -i "s/#define CPUXtensaState/#define CPUState/" target-xtensa/cpu.h
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index fb8a727..b7723ca 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -356,27 +356,27 @@ int cpu_xtensa_exec(CPUXtensaState *s);
 void xtensa_register_core(XtensaConfigList *node);
 void do_interrupt(CPUXtensaState *s);
 void check_interrupts(CPUXtensaState *s);
-void xtensa_irq_init(CPUState *env);
-void *xtensa_get_extint(CPUState *env, unsigned extint);
-void xtensa_advance_ccount(CPUState *env, uint32_t d);
-void xtensa_timer_irq(CPUState *env, uint32_t id, uint32_t active);
-void xtensa_rearm_ccompare_timer(CPUState *env);
+void xtensa_irq_init(CPUXtensaState *env);
+void *xtensa_get_extint(CPUXtensaState *env, unsigned extint);
+void xtensa_advance_ccount(CPUXtensaState *env, uint32_t d);
+void xtensa_timer_irq(CPUXtensaState *env, uint32_t id, uint32_t active);
+void xtensa_rearm_ccompare_timer(CPUXtensaState *env);
 int cpu_xtensa_signal_handler(int host_signum, void *pinfo, void *puc);
 void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf);
-void xtensa_sync_window_from_phys(CPUState *env);
-void xtensa_sync_phys_from_window(CPUState *env);
-uint32_t xtensa_tlb_get_addr_mask(const CPUState *env, bool dtlb, uint32_t way);
-void split_tlb_entry_spec_way(const CPUState *env, uint32_t v, bool dtlb,
+void xtensa_sync_window_from_phys(CPUXtensaState *env);
+void xtensa_sync_phys_from_window(CPUXtensaState *env);
+uint32_t xtensa_tlb_get_addr_mask(const CPUXtensaState *env, bool dtlb, uint32_t way);
+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 CPUState *env, uint32_t addr, bool dtlb,
+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(CPUState *env, bool dtlb,
+void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb,
         unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte);
-int xtensa_get_physical_addr(CPUState *env,
+int xtensa_get_physical_addr(CPUXtensaState *env,
         uint32_t vaddr, int is_write, int mmu_idx,
         uint32_t *paddr, uint32_t *page_size, unsigned *access);
-void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env);
-void debug_exception_env(CPUState *new_env, uint32_t cause);
+void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUXtensaState *env);
+void debug_exception_env(CPUXtensaState *new_env, uint32_t cause);
 
 
 #define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
@@ -392,7 +392,7 @@ static inline bool xtensa_option_enabled(const XtensaConfig *config, int opt)
     return xtensa_option_bits_enabled(config, XTENSA_OPTION_BIT(opt));
 }
 
-static inline int xtensa_get_cintlevel(const CPUState *env)
+static inline int xtensa_get_cintlevel(const CPUXtensaState *env)
 {
     int level = (env->sregs[PS] & PS_INTLEVEL) >> PS_INTLEVEL_SHIFT;
     if ((env->sregs[PS] & PS_EXCM) && env->config->excm_level > level) {
@@ -401,7 +401,7 @@ static inline int xtensa_get_cintlevel(const CPUState *env)
     return level;
 }
 
-static inline int xtensa_get_ring(const CPUState *env)
+static inline int xtensa_get_ring(const CPUXtensaState *env)
 {
     if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
         return (env->sregs[PS] & PS_RING) >> PS_RING_SHIFT;
@@ -410,7 +410,7 @@ static inline int xtensa_get_ring(const CPUState *env)
     }
 }
 
-static inline int xtensa_get_cring(const CPUState *env)
+static inline int xtensa_get_cring(const CPUXtensaState *env)
 {
     if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU) &&
             (env->sregs[PS] & PS_EXCM) == 0) {
@@ -420,7 +420,7 @@ static inline int xtensa_get_cring(const CPUState *env)
     }
 }
 
-static inline xtensa_tlb_entry *xtensa_tlb_get_entry(CPUState *env,
+static inline xtensa_tlb_entry *xtensa_tlb_get_entry(CPUXtensaState *env,
         bool dtlb, unsigned wi, unsigned ei)
 {
     return dtlb ?
@@ -434,7 +434,7 @@ static inline xtensa_tlb_entry *xtensa_tlb_get_entry(CPUState *env,
 #define MMU_MODE2_SUFFIX _ring2
 #define MMU_MODE3_SUFFIX _ring3
 
-static inline int cpu_mmu_index(CPUState *env)
+static inline int cpu_mmu_index(CPUXtensaState *env)
 {
     return xtensa_get_cring(env);
 }
@@ -445,7 +445,7 @@ static inline int cpu_mmu_index(CPUState *env)
 #define XTENSA_TBFLAG_DEBUG 0x10
 #define XTENSA_TBFLAG_ICOUNT 0x20
 
-static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc,
         target_ulong *cs_base, int *flags)
 {
     *pc = env->pc;
@@ -472,12 +472,12 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
 #include "cpu-all.h"
 #include "exec-all.h"
 
-static inline int cpu_has_work(CPUState *env)
+static inline int cpu_has_work(CPUXtensaState *env)
 {
     return env->pending_irq_level;
 }
 
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+static inline void cpu_pc_from_tb(CPUXtensaState *env, TranslationBlock *tb)
 {
     env->pc = tb->pc;
 }
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index 077c20a..dab135c 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -33,7 +33,7 @@
 #include "hw/loader.h"
 #endif
 
-static void reset_mmu(CPUState *env);
+static void reset_mmu(CPUXtensaState *env);
 
 void cpu_state_reset(CPUXtensaState *env)
 {
@@ -57,7 +57,7 @@ void xtensa_register_core(XtensaConfigList *node)
     xtensa_cores = node;
 }
 
-static uint32_t check_hw_breakpoints(CPUState *env)
+static uint32_t check_hw_breakpoints(CPUXtensaState *env)
 {
     unsigned i;
 
@@ -72,7 +72,7 @@ static uint32_t check_hw_breakpoints(CPUState *env)
 
 static CPUDebugExcpHandler *prev_debug_excp_handler;
 
-static void breakpoint_handler(CPUState *env)
+static void breakpoint_handler(CPUXtensaState *env)
 {
     if (env->watchpoint_hit) {
         if (env->watchpoint_hit->flags & BP_CPU) {
@@ -139,7 +139,7 @@ void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf)
     }
 }
 
-target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_debug(CPUXtensaState *env, target_ulong addr)
 {
     uint32_t paddr;
     uint32_t page_size;
@@ -156,7 +156,7 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
     return ~0;
 }
 
-static uint32_t relocated_vector(CPUState *env, uint32_t vector)
+static uint32_t relocated_vector(CPUXtensaState *env, uint32_t vector)
 {
     if (xtensa_option_enabled(env->config,
                 XTENSA_OPTION_RELOCATABLE_VECTOR)) {
@@ -172,7 +172,7 @@ static uint32_t relocated_vector(CPUState *env, uint32_t vector)
  * For the level-1 interrupt convert it to either user, kernel or double
  * exception with the 'level-1 interrupt' exception cause.
  */
-static void handle_interrupt(CPUState *env)
+static void handle_interrupt(CPUXtensaState *env)
 {
     int level = env->pending_irq_level;
 
@@ -209,7 +209,7 @@ static void handle_interrupt(CPUState *env)
     }
 }
 
-void do_interrupt(CPUState *env)
+void do_interrupt(CPUXtensaState *env)
 {
     if (env->exception_index == EXC_IRQ) {
         qemu_log_mask(CPU_LOG_INT,
@@ -260,7 +260,7 @@ void do_interrupt(CPUState *env)
     check_interrupts(env);
 }
 
-static void reset_tlb_mmu_all_ways(CPUState *env,
+static void reset_tlb_mmu_all_ways(CPUXtensaState *env,
         const xtensa_tlb *tlb, xtensa_tlb_entry entry[][MAX_TLB_WAY_SIZE])
 {
     unsigned wi, ei;
@@ -273,7 +273,7 @@ static void reset_tlb_mmu_all_ways(CPUState *env,
     }
 }
 
-static void reset_tlb_mmu_ways56(CPUState *env,
+static void reset_tlb_mmu_ways56(CPUXtensaState *env,
         const xtensa_tlb *tlb, xtensa_tlb_entry entry[][MAX_TLB_WAY_SIZE])
 {
     if (!tlb->varway56) {
@@ -320,7 +320,7 @@ static void reset_tlb_mmu_ways56(CPUState *env,
     }
 }
 
-static void reset_tlb_region_way0(CPUState *env,
+static void reset_tlb_region_way0(CPUXtensaState *env,
         xtensa_tlb_entry entry[][MAX_TLB_WAY_SIZE])
 {
     unsigned ei;
@@ -334,7 +334,7 @@ static void reset_tlb_region_way0(CPUState *env,
     }
 }
 
-static void reset_mmu(CPUState *env)
+static void reset_mmu(CPUXtensaState *env)
 {
     if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
         env->sregs[RASID] = 0x04030201;
@@ -351,7 +351,7 @@ static void reset_mmu(CPUState *env)
     }
 }
 
-static unsigned get_ring(const CPUState *env, uint8_t asid)
+static unsigned get_ring(const CPUXtensaState *env, uint8_t asid)
 {
     unsigned i;
     for (i = 0; i < 4; ++i) {
@@ -371,7 +371,7 @@ static unsigned get_ring(const CPUState *env, uint8_t asid)
  * \param pring: [out] access ring
  * \return 0 if ok, exception cause code otherwise
  */
-int xtensa_tlb_lookup(const CPUState *env, uint32_t addr, bool dtlb,
+int xtensa_tlb_lookup(const CPUXtensaState *env, uint32_t addr, bool dtlb,
         uint32_t *pwi, uint32_t *pei, uint8_t *pring)
 {
     const xtensa_tlb *tlb = dtlb ?
@@ -458,10 +458,10 @@ static bool is_access_granted(unsigned access, int is_write)
     }
 }
 
-static int autorefill_mmu(CPUState *env, uint32_t vaddr, bool dtlb,
+static int autorefill_mmu(CPUXtensaState *env, uint32_t vaddr, bool dtlb,
         uint32_t *wi, uint32_t *ei, uint8_t *ring);
 
-static int get_physical_addr_mmu(CPUState *env,
+static int get_physical_addr_mmu(CPUXtensaState *env,
         uint32_t vaddr, int is_write, int mmu_idx,
         uint32_t *paddr, uint32_t *page_size, unsigned *access)
 {
@@ -504,7 +504,7 @@ static int get_physical_addr_mmu(CPUState *env,
     return 0;
 }
 
-static int autorefill_mmu(CPUState *env, uint32_t vaddr, bool dtlb,
+static int autorefill_mmu(CPUXtensaState *env, uint32_t vaddr, bool dtlb,
         uint32_t *wi, uint32_t *ei, uint8_t *ring)
 {
     uint32_t paddr;
@@ -532,7 +532,7 @@ static int autorefill_mmu(CPUState *env, uint32_t vaddr, bool dtlb,
     return ret;
 }
 
-static int get_physical_addr_region(CPUState *env,
+static int get_physical_addr_region(CPUXtensaState *env,
         uint32_t vaddr, int is_write, int mmu_idx,
         uint32_t *paddr, uint32_t *page_size, unsigned *access)
 {
@@ -563,7 +563,7 @@ static int get_physical_addr_region(CPUState *env,
  *
  * \return 0 if ok, exception cause code otherwise
  */
-int xtensa_get_physical_addr(CPUState *env,
+int xtensa_get_physical_addr(CPUXtensaState *env,
         uint32_t vaddr, int is_write, int mmu_idx,
         uint32_t *paddr, uint32_t *page_size, unsigned *access)
 {
@@ -584,7 +584,7 @@ int xtensa_get_physical_addr(CPUState *env,
 }
 
 static void dump_tlb(FILE *f, fprintf_function cpu_fprintf,
-        CPUState *env, bool dtlb)
+        CPUXtensaState *env, bool dtlb)
 {
     unsigned wi, ei;
     const xtensa_tlb *conf =
@@ -634,7 +634,7 @@ static void dump_tlb(FILE *f, fprintf_function cpu_fprintf,
     }
 }
 
-void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
+void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUXtensaState *env)
 {
     if (xtensa_option_bits_enabled(env->config,
                 XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_PROTECTION) |
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index e184cf6..cdef0db 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -70,10 +70,10 @@ static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
     }
 }
 
-void tlb_fill(CPUState *env1, target_ulong vaddr, int is_write, int mmu_idx,
+void tlb_fill(CPUXtensaState *env1, target_ulong vaddr, int is_write, int mmu_idx,
               void *retaddr)
 {
-    CPUState *saved_env = env;
+    CPUXtensaState *saved_env = env;
 
     env = env1;
     {
@@ -134,7 +134,7 @@ void HELPER(exception_cause_vaddr)(uint32_t pc, uint32_t cause, uint32_t vaddr)
     HELPER(exception_cause)(pc, cause);
 }
 
-void debug_exception_env(CPUState *new_env, uint32_t cause)
+void debug_exception_env(CPUXtensaState *new_env, uint32_t cause)
 {
     if (xtensa_get_cintlevel(new_env) < new_env->config->debug_level) {
         env = new_env;
@@ -168,7 +168,7 @@ uint32_t HELPER(nsau)(uint32_t v)
     return v ? clz32(v) : 32;
 }
 
-static void copy_window_from_phys(CPUState *env,
+static void copy_window_from_phys(CPUXtensaState *env,
         uint32_t window, uint32_t phys, uint32_t n)
 {
     assert(phys < env->config->nareg);
@@ -184,7 +184,7 @@ static void copy_window_from_phys(CPUState *env,
     }
 }
 
-static void copy_phys_from_window(CPUState *env,
+static void copy_phys_from_window(CPUXtensaState *env,
         uint32_t phys, uint32_t window, uint32_t n)
 {
     assert(phys < env->config->nareg);
@@ -201,22 +201,22 @@ static void copy_phys_from_window(CPUState *env,
 }
 
 
-static inline unsigned windowbase_bound(unsigned a, const CPUState *env)
+static inline unsigned windowbase_bound(unsigned a, const CPUXtensaState *env)
 {
     return a & (env->config->nareg / 4 - 1);
 }
 
-static inline unsigned windowstart_bit(unsigned a, const CPUState *env)
+static inline unsigned windowstart_bit(unsigned a, const CPUXtensaState *env)
 {
     return 1 << windowbase_bound(a, env);
 }
 
-void xtensa_sync_window_from_phys(CPUState *env)
+void xtensa_sync_window_from_phys(CPUXtensaState *env)
 {
     copy_window_from_phys(env, 0, env->sregs[WINDOW_BASE] * 4, 16);
 }
 
-void xtensa_sync_phys_from_window(CPUState *env)
+void xtensa_sync_phys_from_window(CPUXtensaState *env)
 {
     copy_phys_from_window(env, env->sregs[WINDOW_BASE] * 4, 0, 16);
 }
@@ -409,7 +409,7 @@ void HELPER(advance_ccount)(uint32_t d)
     xtensa_advance_ccount(env, d);
 }
 
-void HELPER(check_interrupts)(CPUState *env)
+void HELPER(check_interrupts)(CPUXtensaState *env)
 {
     check_interrupts(env);
 }
@@ -423,7 +423,7 @@ void HELPER(wsr_rasid)(uint32_t v)
     }
 }
 
-static uint32_t get_page_size(const CPUState *env, bool dtlb, uint32_t way)
+static uint32_t get_page_size(const CPUXtensaState *env, bool dtlb, uint32_t way)
 {
     uint32_t tlbcfg = env->sregs[dtlb ? DTLBCFG : ITLBCFG];
 
@@ -445,7 +445,7 @@ static uint32_t get_page_size(const CPUState *env, bool dtlb, uint32_t way)
 /*!
  * Get bit mask for the virtual address bits translated by the TLB way
  */
-uint32_t xtensa_tlb_get_addr_mask(const CPUState *env, bool dtlb, uint32_t way)
+uint32_t xtensa_tlb_get_addr_mask(const CPUXtensaState *env, bool dtlb, uint32_t way)
 {
     if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
         bool varway56 = dtlb ?
@@ -482,7 +482,7 @@ uint32_t xtensa_tlb_get_addr_mask(const CPUState *env, bool dtlb, uint32_t way)
  * Get bit mask for the 'VPN without index' field.
  * See ISA, 4.6.5.6, data format for RxTLB0
  */
-static uint32_t get_vpn_mask(const CPUState *env, bool dtlb, uint32_t way)
+static uint32_t get_vpn_mask(const CPUXtensaState *env, bool dtlb, uint32_t way)
 {
     if (way < 4) {
         bool is32 = (dtlb ?
@@ -511,7 +511,7 @@ static uint32_t get_vpn_mask(const CPUState *env, bool dtlb, uint32_t way)
  * Split virtual address into VPN (with index) and entry index
  * for the given TLB way
  */
-void split_tlb_entry_spec_way(const CPUState *env, uint32_t v, bool dtlb,
+void split_tlb_entry_spec_way(const CPUXtensaState *env, uint32_t v, bool dtlb,
         uint32_t *vpn, uint32_t wi, uint32_t *ei)
 {
     bool varway56 = dtlb ?
@@ -647,7 +647,7 @@ uint32_t HELPER(ptlb)(uint32_t v, uint32_t dtlb)
     }
 }
 
-void xtensa_tlb_set_entry(CPUState *env, bool dtlb,
+void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb,
         unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte)
 {
     xtensa_tlb_entry *entry = xtensa_tlb_get_entry(env, dtlb, wi, ei);
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 9e8e20a..e0ff72b 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -159,18 +159,18 @@ void xtensa_translate_init(void)
 
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
     cpu_pc = tcg_global_mem_new_i32(TCG_AREG0,
-            offsetof(CPUState, pc), "pc");
+            offsetof(CPUXtensaState, pc), "pc");
 
     for (i = 0; i < 16; i++) {
         cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
-                offsetof(CPUState, regs[i]),
+                offsetof(CPUXtensaState, regs[i]),
                 regnames[i]);
     }
 
     for (i = 0; i < 256; ++i) {
         if (sregnames[i]) {
             cpu_SR[i] = tcg_global_mem_new_i32(TCG_AREG0,
-                    offsetof(CPUState, sregs[i]),
+                    offsetof(CPUXtensaState, sregs[i]),
                     sregnames[i]);
         }
     }
@@ -178,7 +178,7 @@ void xtensa_translate_init(void)
     for (i = 0; i < 256; ++i) {
         if (uregnames[i]) {
             cpu_UR[i] = tcg_global_mem_new_i32(TCG_AREG0,
-                    offsetof(CPUState, uregs[i]),
+                    offsetof(CPUXtensaState, uregs[i]),
                     uregnames[i]);
         }
     }
@@ -2493,7 +2493,7 @@ invalid_opcode:
 #undef HAS_OPTION
 }
 
-static void check_breakpoint(CPUState *env, DisasContext *dc)
+static void check_breakpoint(CPUXtensaState *env, DisasContext *dc)
 {
     CPUBreakpoint *bp;
 
@@ -2508,7 +2508,7 @@ static void check_breakpoint(CPUState *env, DisasContext *dc)
     }
 }
 
-static void gen_ibreak_check(CPUState *env, DisasContext *dc)
+static void gen_ibreak_check(CPUXtensaState *env, DisasContext *dc)
 {
     unsigned i;
 
@@ -2522,7 +2522,7 @@ static void gen_ibreak_check(CPUState *env, DisasContext *dc)
 }
 
 static void gen_intermediate_code_internal(
-        CPUState *env, TranslationBlock *tb, int search_pc)
+        CPUXtensaState *env, TranslationBlock *tb, int search_pc)
 {
     DisasContext dc;
     int insn_count = 0;
@@ -2644,17 +2644,17 @@ static void gen_intermediate_code_internal(
     }
 }
 
-void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
+void gen_intermediate_code(CPUXtensaState *env, TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 0);
 }
 
-void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
+void gen_intermediate_code_pc(CPUXtensaState *env, TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 1);
 }
 
-void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
+void cpu_dump_state(CPUXtensaState *env, FILE *f, fprintf_function cpu_fprintf,
         int flags)
 {
     int i, j;
@@ -2692,7 +2692,7 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
     }
 }
 
-void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUXtensaState *env, TranslationBlock *tb, int pc_pos)
 {
     env->pc = gen_opc_pc[pc_pos];
 }
commit eb23b556aa57aca4c0a822236c4baf96ae2ac216
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:23 2012 +0100

    target-unicore32: Don't overuse CPUState
    
    Scripted conversion:
      sed -i "s/CPUState/CPUUniCore32State/g" target-unicore32/*.[hc]
      sed -i "s/#define CPUUniCore32State/#define CPUState/" target-unicore32/cpu.h
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-unicore32/cpu.h b/target-unicore32/cpu.h
index 923db05..171f0a9 100644
--- a/target-unicore32/cpu.h
+++ b/target-unicore32/cpu.h
@@ -92,9 +92,9 @@ typedef struct CPUUniCore32State {
 #define UC32_EXCP_TRAP          (ASR_MODE_TRAP)
 
 /* Return the current ASR value.  */
-target_ulong cpu_asr_read(CPUState *env1);
+target_ulong cpu_asr_read(CPUUniCore32State *env1);
 /* Set the ASR.  Note that some bits of mask must be all-set or all-clear.  */
-void cpu_asr_write(CPUState *env1, target_ulong val, target_ulong mask);
+void cpu_asr_write(CPUUniCore32State *env1, target_ulong val, target_ulong mask);
 
 /* UniCore-F64 system registers.  */
 #define UC32_UCF64_FPSCR                (31)
@@ -128,10 +128,10 @@ void cpu_asr_write(CPUState *env1, target_ulong val, target_ulong mask);
 #define cpu_signal_handler              uc32_cpu_signal_handler
 #define cpu_handle_mmu_fault            uc32_cpu_handle_mmu_fault
 
-CPUState *uc32_cpu_init(const char *cpu_model);
-int uc32_cpu_exec(CPUState *s);
+CPUUniCore32State *uc32_cpu_init(const char *cpu_model);
+int uc32_cpu_exec(CPUUniCore32State *s);
 int uc32_cpu_signal_handler(int host_signum, void *pinfo, void *puc);
-int uc32_cpu_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
+int uc32_cpu_handle_mmu_fault(CPUUniCore32State *env, target_ulong address, int rw,
                               int mmu_idx);
 
 #define CPU_SAVE_VERSION 2
@@ -140,12 +140,12 @@ int uc32_cpu_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
 #define MMU_MODE0_SUFFIX _kernel
 #define MMU_MODE1_SUFFIX _user
 #define MMU_USER_IDX 1
-static inline int cpu_mmu_index(CPUState *env)
+static inline int cpu_mmu_index(CPUUniCore32State *env)
 {
     return (env->uncached_asr & ASR_M) == ASR_MODE_USER ? 1 : 0;
 }
 
-static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
+static inline void cpu_clone_regs(CPUUniCore32State *env, target_ulong newsp)
 {
     if (newsp) {
         env->regs[29] = newsp;
@@ -153,7 +153,7 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
     env->regs[0] = 0;
 }
 
-static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
+static inline void cpu_set_tls(CPUUniCore32State *env, target_ulong newtls)
 {
     env->regs[16] = newtls;
 }
@@ -161,12 +161,12 @@ static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
 #include "cpu-all.h"
 #include "exec-all.h"
 
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+static inline void cpu_pc_from_tb(CPUUniCore32State *env, TranslationBlock *tb)
 {
     env->regs[31] = tb->pc;
 }
 
-static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+static inline void cpu_get_tb_cpu_state(CPUUniCore32State *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
     *pc = env->regs[31];
@@ -178,10 +178,10 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
 }
 
 void uc32_translate_init(void);
-void do_interrupt(CPUState *);
+void do_interrupt(CPUUniCore32State *);
 void switch_mode(CPUUniCore32State *, int);
 
-static inline bool cpu_has_work(CPUState *env)
+static inline bool cpu_has_work(CPUUniCore32State *env)
 {
     return env->interrupt_request &
         (CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
diff --git a/target-unicore32/helper.c b/target-unicore32/helper.c
index ee7f82b..6af492d 100644
--- a/target-unicore32/helper.c
+++ b/target-unicore32/helper.c
@@ -11,7 +11,7 @@
 #include "helper.h"
 #include "host-utils.h"
 
-static inline void set_feature(CPUState *env, int feature)
+static inline void set_feature(CPUUniCore32State *env, int feature)
 {
     env->features |= feature;
 }
@@ -43,13 +43,13 @@ static uint32_t uc32_cpu_find_by_name(const char *name)
     return id;
 }
 
-CPUState *uc32_cpu_init(const char *cpu_model)
+CPUUniCore32State *uc32_cpu_init(const char *cpu_model)
 {
-    CPUState *env;
+    CPUUniCore32State *env;
     uint32_t id;
     static int inited = 1;
 
-    env = g_malloc0(sizeof(CPUState));
+    env = g_malloc0(sizeof(CPUUniCore32State));
     cpu_exec_init(env);
 
     id = uc32_cpu_find_by_name(cpu_model);
@@ -94,12 +94,12 @@ uint32_t HELPER(clz)(uint32_t x)
     return clz32(x);
 }
 
-void do_interrupt(CPUState *env)
+void do_interrupt(CPUUniCore32State *env)
 {
     env->exception_index = -1;
 }
 
-int uc32_cpu_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
+int uc32_cpu_handle_mmu_fault(CPUUniCore32State *env, target_ulong address, int rw,
                               int mmu_idx)
 {
     env->exception_index = UC32_EXCP_TRAP;
@@ -108,44 +108,44 @@ int uc32_cpu_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
 }
 
 /* These should probably raise undefined insn exceptions.  */
-void HELPER(set_cp)(CPUState *env, uint32_t insn, uint32_t val)
+void HELPER(set_cp)(CPUUniCore32State *env, uint32_t insn, uint32_t val)
 {
     int op1 = (insn >> 8) & 0xf;
     cpu_abort(env, "cp%i insn %08x\n", op1, insn);
     return;
 }
 
-uint32_t HELPER(get_cp)(CPUState *env, uint32_t insn)
+uint32_t HELPER(get_cp)(CPUUniCore32State *env, uint32_t insn)
 {
     int op1 = (insn >> 8) & 0xf;
     cpu_abort(env, "cp%i insn %08x\n", op1, insn);
     return 0;
 }
 
-void HELPER(set_cp0)(CPUState *env, uint32_t insn, uint32_t val)
+void HELPER(set_cp0)(CPUUniCore32State *env, uint32_t insn, uint32_t val)
 {
     cpu_abort(env, "cp0 insn %08x\n", insn);
 }
 
-uint32_t HELPER(get_cp0)(CPUState *env, uint32_t insn)
+uint32_t HELPER(get_cp0)(CPUUniCore32State *env, uint32_t insn)
 {
     cpu_abort(env, "cp0 insn %08x\n", insn);
     return 0;
 }
 
-void switch_mode(CPUState *env, int mode)
+void switch_mode(CPUUniCore32State *env, int mode)
 {
     if (mode != ASR_MODE_USER) {
         cpu_abort(env, "Tried to switch out of user mode\n");
     }
 }
 
-void HELPER(set_r29_banked)(CPUState *env, uint32_t mode, uint32_t val)
+void HELPER(set_r29_banked)(CPUUniCore32State *env, uint32_t mode, uint32_t val)
 {
     cpu_abort(env, "banked r29 write\n");
 }
 
-uint32_t HELPER(get_r29_banked)(CPUState *env, uint32_t mode)
+uint32_t HELPER(get_r29_banked)(CPUUniCore32State *env, uint32_t mode)
 {
     cpu_abort(env, "banked r29 read\n");
     return 0;
@@ -178,7 +178,7 @@ static inline int ucf64_exceptbits_from_host(int host_bits)
     return target_bits;
 }
 
-uint32_t HELPER(ucf64_get_fpscr)(CPUState *env)
+uint32_t HELPER(ucf64_get_fpscr)(CPUUniCore32State *env)
 {
     int i;
     uint32_t fpscr;
@@ -212,7 +212,7 @@ static inline int ucf64_exceptbits_to_host(int target_bits)
     return host_bits;
 }
 
-void HELPER(ucf64_set_fpscr)(CPUState *env, uint32_t val)
+void HELPER(ucf64_set_fpscr)(CPUUniCore32State *env, uint32_t val)
 {
     int i;
     uint32_t changed;
@@ -246,42 +246,42 @@ void HELPER(ucf64_set_fpscr)(CPUState *env, uint32_t val)
     set_float_exception_flags(i, &env->ucf64.fp_status);
 }
 
-float32 HELPER(ucf64_adds)(float32 a, float32 b, CPUState *env)
+float32 HELPER(ucf64_adds)(float32 a, float32 b, CPUUniCore32State *env)
 {
     return float32_add(a, b, &env->ucf64.fp_status);
 }
 
-float64 HELPER(ucf64_addd)(float64 a, float64 b, CPUState *env)
+float64 HELPER(ucf64_addd)(float64 a, float64 b, CPUUniCore32State *env)
 {
     return float64_add(a, b, &env->ucf64.fp_status);
 }
 
-float32 HELPER(ucf64_subs)(float32 a, float32 b, CPUState *env)
+float32 HELPER(ucf64_subs)(float32 a, float32 b, CPUUniCore32State *env)
 {
     return float32_sub(a, b, &env->ucf64.fp_status);
 }
 
-float64 HELPER(ucf64_subd)(float64 a, float64 b, CPUState *env)
+float64 HELPER(ucf64_subd)(float64 a, float64 b, CPUUniCore32State *env)
 {
     return float64_sub(a, b, &env->ucf64.fp_status);
 }
 
-float32 HELPER(ucf64_muls)(float32 a, float32 b, CPUState *env)
+float32 HELPER(ucf64_muls)(float32 a, float32 b, CPUUniCore32State *env)
 {
     return float32_mul(a, b, &env->ucf64.fp_status);
 }
 
-float64 HELPER(ucf64_muld)(float64 a, float64 b, CPUState *env)
+float64 HELPER(ucf64_muld)(float64 a, float64 b, CPUUniCore32State *env)
 {
     return float64_mul(a, b, &env->ucf64.fp_status);
 }
 
-float32 HELPER(ucf64_divs)(float32 a, float32 b, CPUState *env)
+float32 HELPER(ucf64_divs)(float32 a, float32 b, CPUUniCore32State *env)
 {
     return float32_div(a, b, &env->ucf64.fp_status);
 }
 
-float64 HELPER(ucf64_divd)(float64 a, float64 b, CPUState *env)
+float64 HELPER(ucf64_divd)(float64 a, float64 b, CPUUniCore32State *env)
 {
     return float64_div(a, b, &env->ucf64.fp_status);
 }
@@ -307,7 +307,7 @@ float64 HELPER(ucf64_absd)(float64 a)
 }
 
 /* XXX: check quiet/signaling case */
-void HELPER(ucf64_cmps)(float32 a, float32 b, uint32_t c, CPUState *env)
+void HELPER(ucf64_cmps)(float32 a, float32 b, uint32_t c, CPUUniCore32State *env)
 {
     int flag;
     flag = float32_compare_quiet(a, b, &env->ucf64.fp_status);
@@ -355,7 +355,7 @@ void HELPER(ucf64_cmps)(float32 a, float32 b, uint32_t c, CPUState *env)
                     | (env->ucf64.xregs[UC32_UCF64_FPSCR] & 0x0fffffff);
 }
 
-void HELPER(ucf64_cmpd)(float64 a, float64 b, uint32_t c, CPUState *env)
+void HELPER(ucf64_cmpd)(float64 a, float64 b, uint32_t c, CPUUniCore32State *env)
 {
     int flag;
     flag = float64_compare_quiet(a, b, &env->ucf64.fp_status);
@@ -449,34 +449,34 @@ static inline uint64_t ucf64_dtoi(float64 d)
 }
 
 /* Integer to float conversion.  */
-float32 HELPER(ucf64_si2sf)(float32 x, CPUState *env)
+float32 HELPER(ucf64_si2sf)(float32 x, CPUUniCore32State *env)
 {
     return int32_to_float32(ucf64_stoi(x), &env->ucf64.fp_status);
 }
 
-float64 HELPER(ucf64_si2df)(float32 x, CPUState *env)
+float64 HELPER(ucf64_si2df)(float32 x, CPUUniCore32State *env)
 {
     return int32_to_float64(ucf64_stoi(x), &env->ucf64.fp_status);
 }
 
 /* Float to integer conversion.  */
-float32 HELPER(ucf64_sf2si)(float32 x, CPUState *env)
+float32 HELPER(ucf64_sf2si)(float32 x, CPUUniCore32State *env)
 {
     return ucf64_itos(float32_to_int32(x, &env->ucf64.fp_status));
 }
 
-float32 HELPER(ucf64_df2si)(float64 x, CPUState *env)
+float32 HELPER(ucf64_df2si)(float64 x, CPUUniCore32State *env)
 {
     return ucf64_itos(float64_to_int32(x, &env->ucf64.fp_status));
 }
 
 /* floating point conversion */
-float64 HELPER(ucf64_sf2df)(float32 x, CPUState *env)
+float64 HELPER(ucf64_sf2df)(float32 x, CPUUniCore32State *env)
 {
     return float32_to_float64(x, &env->ucf64.fp_status);
 }
 
-float32 HELPER(ucf64_df2sf)(float64 x, CPUState *env)
+float32 HELPER(ucf64_df2sf)(float64 x, CPUUniCore32State *env)
 {
     return float64_to_float32(x, &env->ucf64.fp_status);
 }
diff --git a/target-unicore32/op_helper.c b/target-unicore32/op_helper.c
index 6cf5255..638a020 100644
--- a/target-unicore32/op_helper.c
+++ b/target-unicore32/op_helper.c
@@ -28,9 +28,9 @@ static target_ulong asr_read(void)
         (env->CF << 29) | ((env->VF & 0x80000000) >> 3);
 }
 
-target_ulong cpu_asr_read(CPUState *env1)
+target_ulong cpu_asr_read(CPUUniCore32State *env1)
 {
-    CPUState *saved_env;
+    CPUUniCore32State *saved_env;
     target_ulong ret;
 
     saved_env = env;
@@ -61,9 +61,9 @@ static void asr_write(target_ulong val, target_ulong mask)
     env->uncached_asr = (env->uncached_asr & ~mask) | (val & mask);
 }
 
-void cpu_asr_write(CPUState *env1, target_ulong val, target_ulong mask)
+void cpu_asr_write(CPUUniCore32State *env1, target_ulong val, target_ulong mask)
 {
-    CPUState *saved_env;
+    CPUUniCore32State *saved_env;
 
     saved_env = env;
     env = env1;
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index 4d0aa43..3b3ba16 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -64,7 +64,7 @@ void uc32_translate_init(void)
 
     for (i = 0; i < 32; i++) {
         cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
-                                offsetof(CPUState, regs[i]), regnames[i]);
+                                offsetof(CPUUniCore32State, regs[i]), regnames[i]);
     }
 
 #define GEN_HELPER 2
@@ -94,7 +94,7 @@ static inline TCGv load_cpu_offset(int offset)
     return tmp;
 }
 
-#define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
+#define load_cpu_field(name) load_cpu_offset(offsetof(CPUUniCore32State, name))
 
 static inline void store_cpu_offset(TCGv var, int offset)
 {
@@ -103,7 +103,7 @@ static inline void store_cpu_offset(TCGv var, int offset)
 }
 
 #define store_cpu_field(var, name) \
-    store_cpu_offset(var, offsetof(CPUState, name))
+    store_cpu_offset(var, offsetof(CPUUniCore32State, name))
 
 /* Set a variable to the value of a CPU register.  */
 static void load_reg_var(DisasContext *s, TCGv var, int reg)
@@ -223,7 +223,7 @@ static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
     return tmp1;
 }
 
-#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
+#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUUniCore32State, CF))
 
 /* Set CF to the top bit of var.  */
 static void gen_set_CF_bit31(TCGv var)
@@ -237,8 +237,8 @@ static void gen_set_CF_bit31(TCGv var)
 /* Set N and Z flags from var.  */
 static inline void gen_logic_CC(TCGv var)
 {
-    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF));
-    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF));
+    tcg_gen_st_i32(var, cpu_env, offsetof(CPUUniCore32State, NF));
+    tcg_gen_st_i32(var, cpu_env, offsetof(CPUUniCore32State, ZF));
 }
 
 /* dest = T0 + T1 + CF. */
@@ -634,10 +634,10 @@ static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
 static inline long ucf64_reg_offset(int reg)
 {
     if (reg & 1) {
-        return offsetof(CPUState, ucf64.regs[reg >> 1])
+        return offsetof(CPUUniCore32State, ucf64.regs[reg >> 1])
           + offsetof(CPU_DoubleU, l.upper);
     } else {
-        return offsetof(CPUState, ucf64.regs[reg >> 1])
+        return offsetof(CPUUniCore32State, ucf64.regs[reg >> 1])
           + offsetof(CPU_DoubleU, l.lower);
     }
 }
@@ -646,7 +646,7 @@ static inline long ucf64_reg_offset(int reg)
 #define ucf64_gen_st32(var, reg) store_cpu_offset(var, ucf64_reg_offset(reg))
 
 /* UniCore-F64 single load/store I_offset */
-static void do_ucf64_ldst_i(CPUState *env, DisasContext *s, uint32_t insn)
+static void do_ucf64_ldst_i(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 {
     int offset;
     TCGv tmp;
@@ -692,7 +692,7 @@ static void do_ucf64_ldst_i(CPUState *env, DisasContext *s, uint32_t insn)
 }
 
 /* UniCore-F64 load/store multiple words */
-static void do_ucf64_ldst_m(CPUState *env, DisasContext *s, uint32_t insn)
+static void do_ucf64_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 {
     unsigned int i;
     int j, n, freg;
@@ -777,7 +777,7 @@ static void do_ucf64_ldst_m(CPUState *env, DisasContext *s, uint32_t insn)
 }
 
 /* UniCore-F64 mrc/mcr */
-static void do_ucf64_trans(CPUState *env, DisasContext *s, uint32_t insn)
+static void do_ucf64_trans(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 {
     TCGv tmp;
 
@@ -841,7 +841,7 @@ static void do_ucf64_trans(CPUState *env, DisasContext *s, uint32_t insn)
 }
 
 /* UniCore-F64 convert instructions */
-static void do_ucf64_fcvt(CPUState *env, DisasContext *s, uint32_t insn)
+static void do_ucf64_fcvt(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 {
     if (UCOP_UCF64_FMT == 3) {
         ILLEGAL;
@@ -907,7 +907,7 @@ static void do_ucf64_fcvt(CPUState *env, DisasContext *s, uint32_t insn)
 }
 
 /* UniCore-F64 compare instructions */
-static void do_ucf64_fcmp(CPUState *env, DisasContext *s, uint32_t insn)
+static void do_ucf64_fcmp(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 {
     if (UCOP_SET(25)) {
         ILLEGAL;
@@ -985,7 +985,7 @@ static void do_ucf64_fcmp(CPUState *env, DisasContext *s, uint32_t insn)
     } while (0)
 
 /* UniCore-F64 data processing */
-static void do_ucf64_datap(CPUState *env, DisasContext *s, uint32_t insn)
+static void do_ucf64_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 {
     if (UCOP_UCF64_FMT == 3) {
         ILLEGAL;
@@ -1018,7 +1018,7 @@ static void do_ucf64_datap(CPUState *env, DisasContext *s, uint32_t insn)
 }
 
 /* Disassemble an F64 instruction */
-static void disas_ucf64_insn(CPUState *env, DisasContext *s, uint32_t insn)
+static void disas_ucf64_insn(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 {
     if (!UCOP_SET(29)) {
         if (UCOP_SET(26)) {
@@ -1123,7 +1123,7 @@ static void gen_exception_return(DisasContext *s, TCGv pc)
     s->is_jmp = DISAS_UPDATE;
 }
 
-static void disas_coproc_insn(CPUState *env, DisasContext *s, uint32_t insn)
+static void disas_coproc_insn(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 {
     switch (UCOP_CPNUM) {
     case 2:
@@ -1168,7 +1168,7 @@ static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
 }
 
 /* data processing instructions */
-static void do_datap(CPUState *env, DisasContext *s, uint32_t insn)
+static void do_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 {
     TCGv tmp;
     TCGv tmp2;
@@ -1359,7 +1359,7 @@ static void do_datap(CPUState *env, DisasContext *s, uint32_t insn)
 }
 
 /* multiply */
-static void do_mult(CPUState *env, DisasContext *s, uint32_t insn)
+static void do_mult(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 {
     TCGv tmp;
     TCGv tmp2;
@@ -1399,7 +1399,7 @@ static void do_mult(CPUState *env, DisasContext *s, uint32_t insn)
 }
 
 /* miscellaneous instructions */
-static void do_misc(CPUState *env, DisasContext *s, uint32_t insn)
+static void do_misc(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 {
     unsigned int val;
     TCGv tmp;
@@ -1475,7 +1475,7 @@ static void do_misc(CPUState *env, DisasContext *s, uint32_t insn)
 }
 
 /* load/store I_offset and R_offset */
-static void do_ldst_ir(CPUState *env, DisasContext *s, uint32_t insn)
+static void do_ldst_ir(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 {
     unsigned int i;
     TCGv tmp;
@@ -1524,7 +1524,7 @@ static void do_ldst_ir(CPUState *env, DisasContext *s, uint32_t insn)
 }
 
 /* SWP instruction */
-static void do_swap(CPUState *env, DisasContext *s, uint32_t insn)
+static void do_swap(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 {
     TCGv addr;
     TCGv tmp;
@@ -1551,7 +1551,7 @@ static void do_swap(CPUState *env, DisasContext *s, uint32_t insn)
 }
 
 /* load/store hw/sb */
-static void do_ldst_hwsb(CPUState *env, DisasContext *s, uint32_t insn)
+static void do_ldst_hwsb(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 {
     TCGv addr;
     TCGv tmp;
@@ -1603,7 +1603,7 @@ static void do_ldst_hwsb(CPUState *env, DisasContext *s, uint32_t insn)
 }
 
 /* load/store multiple words */
-static void do_ldst_m(CPUState *env, DisasContext *s, uint32_t insn)
+static void do_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 {
     unsigned int val, i;
     int j, n, reg, user, loaded_base;
@@ -1743,7 +1743,7 @@ static void do_ldst_m(CPUState *env, DisasContext *s, uint32_t insn)
 }
 
 /* branch (and link) */
-static void do_branch(CPUState *env, DisasContext *s, uint32_t insn)
+static void do_branch(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
 {
     unsigned int val;
     int32_t offset;
@@ -1772,7 +1772,7 @@ static void do_branch(CPUState *env, DisasContext *s, uint32_t insn)
     gen_jmp(s, val);
 }
 
-static void disas_uc32_insn(CPUState *env, DisasContext *s)
+static void disas_uc32_insn(CPUUniCore32State *env, DisasContext *s)
 {
     unsigned int insn;
 
@@ -1850,7 +1850,7 @@ static void disas_uc32_insn(CPUState *env, DisasContext *s)
 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
    basic block 'tb'. If search_pc is TRUE, also generate PC
    information for each intermediate instruction. */
-static inline void gen_intermediate_code_internal(CPUState *env,
+static inline void gen_intermediate_code_internal(CPUUniCore32State *env,
         TranslationBlock *tb, int search_pc)
 {
     DisasContext dc1, *dc = &dc1;
@@ -2030,12 +2030,12 @@ done_generating:
     }
 }
 
-void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
+void gen_intermediate_code(CPUUniCore32State *env, TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 0);
 }
 
-void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
+void gen_intermediate_code_pc(CPUUniCore32State *env, TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 1);
 }
@@ -2046,7 +2046,7 @@ static const char *cpu_mode_names[16] = {
 };
 
 #define UCF64_DUMP_STATE
-void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
+void cpu_dump_state(CPUUniCore32State *env, FILE *f, fprintf_function cpu_fprintf,
         int flags)
 {
     int i;
@@ -2097,7 +2097,7 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
 #endif
 }
 
-void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUUniCore32State *env, TranslationBlock *tb, int pc_pos)
 {
     env->regs[31] = gen_opc_pc[pc_pos];
 }
commit c5f9864e892c473ee3b2cfe080c0def229dac2a7
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:22 2012 +0100

    target-sparc: Don't overuse CPUState
    
    Scripted conversion:
      sed -i "s/CPUState/CPUSPARCState/g" target-sparc/*.[hc]
      sed -i "s/#define CPUSPARCState/#define CPUState/" target-sparc/cpu.h
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-sparc/cc_helper.c b/target-sparc/cc_helper.c
index 04bd2cf..63bab07 100644
--- a/target-sparc/cc_helper.c
+++ b/target-sparc/cc_helper.c
@@ -20,12 +20,12 @@
 #include "cpu.h"
 #include "helper.h"
 
-static uint32_t compute_all_flags(CPUState *env)
+static uint32_t compute_all_flags(CPUSPARCState *env)
 {
     return env->psr & PSR_ICC;
 }
 
-static uint32_t compute_C_flags(CPUState *env)
+static uint32_t compute_C_flags(CPUSPARCState *env)
 {
     return env->psr & PSR_CARRY;
 }
@@ -43,12 +43,12 @@ static inline uint32_t get_NZ_icc(int32_t dst)
 }
 
 #ifdef TARGET_SPARC64
-static uint32_t compute_all_flags_xcc(CPUState *env)
+static uint32_t compute_all_flags_xcc(CPUSPARCState *env)
 {
     return env->xcc & PSR_ICC;
 }
 
-static uint32_t compute_C_flags_xcc(CPUState *env)
+static uint32_t compute_C_flags_xcc(CPUSPARCState *env)
 {
     return env->xcc & PSR_CARRY;
 }
@@ -76,7 +76,7 @@ static inline uint32_t get_V_div_icc(target_ulong src2)
     return ret;
 }
 
-static uint32_t compute_all_div(CPUState *env)
+static uint32_t compute_all_div(CPUSPARCState *env)
 {
     uint32_t ret;
 
@@ -85,7 +85,7 @@ static uint32_t compute_all_div(CPUState *env)
     return ret;
 }
 
-static uint32_t compute_C_div(CPUState *env)
+static uint32_t compute_C_div(CPUSPARCState *env)
 {
     return 0;
 }
@@ -155,7 +155,7 @@ static inline uint32_t get_V_add_xcc(target_ulong dst, target_ulong src1,
     return ret;
 }
 
-static uint32_t compute_all_add_xcc(CPUState *env)
+static uint32_t compute_all_add_xcc(CPUSPARCState *env)
 {
     uint32_t ret;
 
@@ -165,13 +165,13 @@ static uint32_t compute_all_add_xcc(CPUState *env)
     return ret;
 }
 
-static uint32_t compute_C_add_xcc(CPUState *env)
+static uint32_t compute_C_add_xcc(CPUSPARCState *env)
 {
     return get_C_add_xcc(CC_DST, CC_SRC);
 }
 #endif
 
-static uint32_t compute_all_add(CPUState *env)
+static uint32_t compute_all_add(CPUSPARCState *env)
 {
     uint32_t ret;
 
@@ -181,13 +181,13 @@ static uint32_t compute_all_add(CPUState *env)
     return ret;
 }
 
-static uint32_t compute_C_add(CPUState *env)
+static uint32_t compute_C_add(CPUSPARCState *env)
 {
     return get_C_add_icc(CC_DST, CC_SRC);
 }
 
 #ifdef TARGET_SPARC64
-static uint32_t compute_all_addx_xcc(CPUState *env)
+static uint32_t compute_all_addx_xcc(CPUSPARCState *env)
 {
     uint32_t ret;
 
@@ -197,7 +197,7 @@ static uint32_t compute_all_addx_xcc(CPUState *env)
     return ret;
 }
 
-static uint32_t compute_C_addx_xcc(CPUState *env)
+static uint32_t compute_C_addx_xcc(CPUSPARCState *env)
 {
     uint32_t ret;
 
@@ -206,7 +206,7 @@ static uint32_t compute_C_addx_xcc(CPUState *env)
 }
 #endif
 
-static uint32_t compute_all_addx(CPUState *env)
+static uint32_t compute_all_addx(CPUSPARCState *env)
 {
     uint32_t ret;
 
@@ -216,7 +216,7 @@ static uint32_t compute_all_addx(CPUState *env)
     return ret;
 }
 
-static uint32_t compute_C_addx(CPUState *env)
+static uint32_t compute_C_addx(CPUSPARCState *env)
 {
     uint32_t ret;
 
@@ -234,7 +234,7 @@ static inline uint32_t get_V_tag_icc(target_ulong src1, target_ulong src2)
     return ret;
 }
 
-static uint32_t compute_all_tadd(CPUState *env)
+static uint32_t compute_all_tadd(CPUSPARCState *env)
 {
     uint32_t ret;
 
@@ -245,7 +245,7 @@ static uint32_t compute_all_tadd(CPUState *env)
     return ret;
 }
 
-static uint32_t compute_all_taddtv(CPUState *env)
+static uint32_t compute_all_taddtv(CPUSPARCState *env)
 {
     uint32_t ret;
 
@@ -320,7 +320,7 @@ static inline uint32_t get_V_sub_xcc(target_ulong dst, target_ulong src1,
     return ret;
 }
 
-static uint32_t compute_all_sub_xcc(CPUState *env)
+static uint32_t compute_all_sub_xcc(CPUSPARCState *env)
 {
     uint32_t ret;
 
@@ -330,13 +330,13 @@ static uint32_t compute_all_sub_xcc(CPUState *env)
     return ret;
 }
 
-static uint32_t compute_C_sub_xcc(CPUState *env)
+static uint32_t compute_C_sub_xcc(CPUSPARCState *env)
 {
     return get_C_sub_xcc(CC_SRC, CC_SRC2);
 }
 #endif
 
-static uint32_t compute_all_sub(CPUState *env)
+static uint32_t compute_all_sub(CPUSPARCState *env)
 {
     uint32_t ret;
 
@@ -346,13 +346,13 @@ static uint32_t compute_all_sub(CPUState *env)
     return ret;
 }
 
-static uint32_t compute_C_sub(CPUState *env)
+static uint32_t compute_C_sub(CPUSPARCState *env)
 {
     return get_C_sub_icc(CC_SRC, CC_SRC2);
 }
 
 #ifdef TARGET_SPARC64
-static uint32_t compute_all_subx_xcc(CPUState *env)
+static uint32_t compute_all_subx_xcc(CPUSPARCState *env)
 {
     uint32_t ret;
 
@@ -362,7 +362,7 @@ static uint32_t compute_all_subx_xcc(CPUState *env)
     return ret;
 }
 
-static uint32_t compute_C_subx_xcc(CPUState *env)
+static uint32_t compute_C_subx_xcc(CPUSPARCState *env)
 {
     uint32_t ret;
 
@@ -371,7 +371,7 @@ static uint32_t compute_C_subx_xcc(CPUState *env)
 }
 #endif
 
-static uint32_t compute_all_subx(CPUState *env)
+static uint32_t compute_all_subx(CPUSPARCState *env)
 {
     uint32_t ret;
 
@@ -381,7 +381,7 @@ static uint32_t compute_all_subx(CPUState *env)
     return ret;
 }
 
-static uint32_t compute_C_subx(CPUState *env)
+static uint32_t compute_C_subx(CPUSPARCState *env)
 {
     uint32_t ret;
 
@@ -389,7 +389,7 @@ static uint32_t compute_C_subx(CPUState *env)
     return ret;
 }
 
-static uint32_t compute_all_tsub(CPUState *env)
+static uint32_t compute_all_tsub(CPUSPARCState *env)
 {
     uint32_t ret;
 
@@ -400,7 +400,7 @@ static uint32_t compute_all_tsub(CPUState *env)
     return ret;
 }
 
-static uint32_t compute_all_tsubtv(CPUState *env)
+static uint32_t compute_all_tsubtv(CPUSPARCState *env)
 {
     uint32_t ret;
 
@@ -409,26 +409,26 @@ static uint32_t compute_all_tsubtv(CPUState *env)
     return ret;
 }
 
-static uint32_t compute_all_logic(CPUState *env)
+static uint32_t compute_all_logic(CPUSPARCState *env)
 {
     return get_NZ_icc(CC_DST);
 }
 
-static uint32_t compute_C_logic(CPUState *env)
+static uint32_t compute_C_logic(CPUSPARCState *env)
 {
     return 0;
 }
 
 #ifdef TARGET_SPARC64
-static uint32_t compute_all_logic_xcc(CPUState *env)
+static uint32_t compute_all_logic_xcc(CPUSPARCState *env)
 {
     return get_NZ_xcc(CC_DST);
 }
 #endif
 
 typedef struct CCTable {
-    uint32_t (*compute_all)(CPUState *env); /* return all the flags */
-    uint32_t (*compute_c)(CPUState *env);  /* return the C flag */
+    uint32_t (*compute_all)(CPUSPARCState *env); /* return all the flags */
+    uint32_t (*compute_c)(CPUSPARCState *env);  /* return the C flag */
 } CCTable;
 
 static const CCTable icc_table[CC_OP_NB] = {
@@ -463,7 +463,7 @@ static const CCTable xcc_table[CC_OP_NB] = {
 };
 #endif
 
-void helper_compute_psr(CPUState *env)
+void helper_compute_psr(CPUSPARCState *env)
 {
     uint32_t new_psr;
 
@@ -476,7 +476,7 @@ void helper_compute_psr(CPUState *env)
     CC_OP = CC_OP_FLAGS;
 }
 
-uint32_t helper_compute_C_icc(CPUState *env)
+uint32_t helper_compute_C_icc(CPUSPARCState *env)
 {
     uint32_t ret;
 
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 8098669..2c2cea7 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -501,7 +501,7 @@ struct CPUSPARCState {
     sparc_def_t *def;
 
     void *irq_manager;
-    void (*qemu_irq_ack)(CPUState *env, void *irq_manager, int intno);
+    void (*qemu_irq_ack)(CPUSPARCState *env, void *irq_manager, int intno);
 
     /* Leon3 cache control */
     uint32_t cache_control;
@@ -517,10 +517,10 @@ int cpu_sparc_handle_mmu_fault(CPUSPARCState *env1, target_ulong address, int rw
                                int mmu_idx);
 #define cpu_handle_mmu_fault cpu_sparc_handle_mmu_fault
 target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev);
-void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env);
+void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUSPARCState *env);
 
 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
-int target_memory_rw_debug(CPUState *env, target_ulong addr,
+int target_memory_rw_debug(CPUSPARCState *env, target_ulong addr,
                            uint8_t *buf, int len, int is_write);
 #define TARGET_CPU_MEMORY_RW_DEBUG
 #endif
@@ -533,22 +533,22 @@ void gen_intermediate_code_init(CPUSPARCState *env);
 int cpu_sparc_exec(CPUSPARCState *s);
 
 /* win_helper.c */
-target_ulong cpu_get_psr(CPUState *env1);
-void cpu_put_psr(CPUState *env1, target_ulong val);
+target_ulong cpu_get_psr(CPUSPARCState *env1);
+void cpu_put_psr(CPUSPARCState *env1, target_ulong val);
 #ifdef TARGET_SPARC64
-target_ulong cpu_get_ccr(CPUState *env1);
-void cpu_put_ccr(CPUState *env1, target_ulong val);
-target_ulong cpu_get_cwp64(CPUState *env1);
-void cpu_put_cwp64(CPUState *env1, int cwp);
-void cpu_change_pstate(CPUState *env1, uint32_t new_pstate);
+target_ulong cpu_get_ccr(CPUSPARCState *env1);
+void cpu_put_ccr(CPUSPARCState *env1, target_ulong val);
+target_ulong cpu_get_cwp64(CPUSPARCState *env1);
+void cpu_put_cwp64(CPUSPARCState *env1, int cwp);
+void cpu_change_pstate(CPUSPARCState *env1, uint32_t new_pstate);
 #endif
-int cpu_cwp_inc(CPUState *env1, int cwp);
-int cpu_cwp_dec(CPUState *env1, int cwp);
-void cpu_set_cwp(CPUState *env1, int new_cwp);
+int cpu_cwp_inc(CPUSPARCState *env1, int cwp);
+int cpu_cwp_dec(CPUSPARCState *env1, int cwp);
+void cpu_set_cwp(CPUSPARCState *env1, int new_cwp);
 
 /* int_helper.c */
-void do_interrupt(CPUState *env);
-void leon3_irq_manager(CPUState *env, void *irq_manager, int intno);
+void do_interrupt(CPUSPARCState *env);
+void leon3_irq_manager(CPUSPARCState *env, void *irq_manager, int intno);
 
 /* sun4m.c, sun4u.c */
 void cpu_check_irqs(CPUSPARCState *env);
@@ -577,10 +577,10 @@ static inline int tlb_compare_context(const SparcTLBEntry *tlb,
 
 /* cpu-exec.c */
 #if !defined(CONFIG_USER_ONLY)
-void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr,
+void cpu_unassigned_access(CPUSPARCState *env1, target_phys_addr_t addr,
                            int is_write, int is_exec, int is_asi, int size);
 #if defined(TARGET_SPARC64)
-target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
+target_phys_addr_t cpu_get_phys_page_nofault(CPUSPARCState *env, target_ulong addr,
                                            int mmu_idx);
 
 #endif
@@ -617,23 +617,23 @@ int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
 #endif
 
 #if defined (TARGET_SPARC64)
-static inline int cpu_has_hypervisor(CPUState *env1)
+static inline int cpu_has_hypervisor(CPUSPARCState *env1)
 {
     return env1->def->features & CPU_FEATURE_HYPV;
 }
 
-static inline int cpu_hypervisor_mode(CPUState *env1)
+static inline int cpu_hypervisor_mode(CPUSPARCState *env1)
 {
     return cpu_has_hypervisor(env1) && (env1->hpstate & HS_PRIV);
 }
 
-static inline int cpu_supervisor_mode(CPUState *env1)
+static inline int cpu_supervisor_mode(CPUSPARCState *env1)
 {
     return env1->pstate & PS_PRIV;
 }
 #endif
 
-static inline int cpu_mmu_index(CPUState *env1)
+static inline int cpu_mmu_index(CPUSPARCState *env1)
 {
 #if defined(CONFIG_USER_ONLY)
     return MMU_USER_IDX;
@@ -652,7 +652,7 @@ static inline int cpu_mmu_index(CPUState *env1)
 #endif
 }
 
-static inline int cpu_interrupts_enabled(CPUState *env1)
+static inline int cpu_interrupts_enabled(CPUSPARCState *env1)
 {
 #if !defined (TARGET_SPARC64)
     if (env1->psret != 0)
@@ -665,7 +665,7 @@ static inline int cpu_interrupts_enabled(CPUState *env1)
     return 0;
 }
 
-static inline int cpu_pil_allowed(CPUState *env1, int pil)
+static inline int cpu_pil_allowed(CPUSPARCState *env1, int pil)
 {
 #if !defined(TARGET_SPARC64)
     /* level 15 is non-maskable on sparc v8 */
@@ -676,7 +676,7 @@ static inline int cpu_pil_allowed(CPUState *env1, int pil)
 }
 
 #if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
+static inline void cpu_clone_regs(CPUSPARCState *env, target_ulong newsp)
 {
     if (newsp)
         env->regwptr[22] = newsp;
@@ -694,13 +694,13 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
 void cpu_tick_set_count(CPUTimer *timer, uint64_t count);
 uint64_t cpu_tick_get_count(CPUTimer *timer);
 void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit);
-trap_state* cpu_tsptr(CPUState* env);
+trap_state* cpu_tsptr(CPUSPARCState* env);
 #endif
 
 #define TB_FLAG_FPU_ENABLED (1 << 4)
 #define TB_FLAG_AM_ENABLED (1 << 5)
 
-static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+static inline void cpu_get_tb_cpu_state(CPUSPARCState *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
     *pc = env->pc;
@@ -745,7 +745,7 @@ static inline bool tb_am_enabled(int tb_flags)
 #endif
 }
 
-static inline bool cpu_has_work(CPUState *env1)
+static inline bool cpu_has_work(CPUSPARCState *env1)
 {
     return (env1->interrupt_request & CPU_INTERRUPT_HARD) &&
            cpu_interrupts_enabled(env1);
@@ -753,7 +753,7 @@ static inline bool cpu_has_work(CPUState *env1)
 
 #include "exec-all.h"
 
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+static inline void cpu_pc_from_tb(CPUSPARCState *env, TranslationBlock *tb)
 {
     env->pc = tb->pc;
     env->npc = tb->cs_base;
diff --git a/target-sparc/cpu_init.c b/target-sparc/cpu_init.c
index bb8b761..29132fb 100644
--- a/target-sparc/cpu_init.c
+++ b/target-sparc/cpu_init.c
@@ -780,7 +780,7 @@ static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
 #define REGS_PER_LINE 8
 #endif
 
-void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
+void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf,
                     int flags)
 {
     int i, x;
diff --git a/target-sparc/fop_helper.c b/target-sparc/fop_helper.c
index c7a2512..9c64ef8 100644
--- a/target-sparc/fop_helper.c
+++ b/target-sparc/fop_helper.c
@@ -23,7 +23,7 @@
 #define QT0 (env->qt0)
 #define QT1 (env->qt1)
 
-static void check_ieee_exceptions(CPUState *env)
+static void check_ieee_exceptions(CPUSPARCState *env)
 {
     target_ulong status;
 
@@ -57,15 +57,15 @@ static void check_ieee_exceptions(CPUState *env)
     }
 }
 
-static inline void clear_float_exceptions(CPUState *env)
+static inline void clear_float_exceptions(CPUSPARCState *env)
 {
     set_float_exception_flags(0, &env->fp_status);
 }
 
-#define F_HELPER(name, p) void helper_f##name##p(CPUState *env)
+#define F_HELPER(name, p) void helper_f##name##p(CPUSPARCState *env)
 
 #define F_BINOP(name)                                           \
-    float32 helper_f ## name ## s (CPUState *env, float32 src1, \
+    float32 helper_f ## name ## s (CPUSPARCState *env, float32 src1, \
                                    float32 src2)                \
     {                                                           \
         float32 ret;                                            \
@@ -74,7 +74,7 @@ static inline void clear_float_exceptions(CPUState *env)
         check_ieee_exceptions(env);                             \
         return ret;                                             \
     }                                                           \
-    float64 helper_f ## name ## d (CPUState * env, float64 src1,\
+    float64 helper_f ## name ## d (CPUSPARCState * env, float64 src1,\
                                    float64 src2)                \
     {                                                           \
         float64 ret;                                            \
@@ -96,7 +96,7 @@ F_BINOP(mul);
 F_BINOP(div);
 #undef F_BINOP
 
-float64 helper_fsmuld(CPUState *env, float32 src1, float32 src2)
+float64 helper_fsmuld(CPUSPARCState *env, float32 src1, float32 src2)
 {
     float64 ret;
     clear_float_exceptions(env);
@@ -107,7 +107,7 @@ float64 helper_fsmuld(CPUState *env, float32 src1, float32 src2)
     return ret;
 }
 
-void helper_fdmulq(CPUState *env, float64 src1, float64 src2)
+void helper_fdmulq(CPUSPARCState *env, float64 src1, float64 src2)
 {
     clear_float_exceptions(env);
     QT0 = float128_mul(float64_to_float128(src1, &env->fp_status),
@@ -134,7 +134,7 @@ F_HELPER(neg, q)
 #endif
 
 /* Integer to float conversion.  */
-float32 helper_fitos(CPUState *env, int32_t src)
+float32 helper_fitos(CPUSPARCState *env, int32_t src)
 {
     /* Inexact error possible converting int to float.  */
     float32 ret;
@@ -144,20 +144,20 @@ float32 helper_fitos(CPUState *env, int32_t src)
     return ret;
 }
 
-float64 helper_fitod(CPUState *env, int32_t src)
+float64 helper_fitod(CPUSPARCState *env, int32_t src)
 {
     /* No possible exceptions converting int to double.  */
     return int32_to_float64(src, &env->fp_status);
 }
 
-void helper_fitoq(CPUState *env, int32_t src)
+void helper_fitoq(CPUSPARCState *env, int32_t src)
 {
     /* No possible exceptions converting int to long double.  */
     QT0 = int32_to_float128(src, &env->fp_status);
 }
 
 #ifdef TARGET_SPARC64
-float32 helper_fxtos(CPUState *env, int64_t src)
+float32 helper_fxtos(CPUSPARCState *env, int64_t src)
 {
     float32 ret;
     clear_float_exceptions(env);
@@ -166,7 +166,7 @@ float32 helper_fxtos(CPUState *env, int64_t src)
     return ret;
 }
 
-float64 helper_fxtod(CPUState *env, int64_t src)
+float64 helper_fxtod(CPUSPARCState *env, int64_t src)
 {
     float64 ret;
     clear_float_exceptions(env);
@@ -175,7 +175,7 @@ float64 helper_fxtod(CPUState *env, int64_t src)
     return ret;
 }
 
-void helper_fxtoq(CPUState *env, int64_t src)
+void helper_fxtoq(CPUSPARCState *env, int64_t src)
 {
     /* No possible exceptions converting long long to long double.  */
     QT0 = int64_to_float128(src, &env->fp_status);
@@ -184,7 +184,7 @@ void helper_fxtoq(CPUState *env, int64_t src)
 #undef F_HELPER
 
 /* floating point conversion */
-float32 helper_fdtos(CPUState *env, float64 src)
+float32 helper_fdtos(CPUSPARCState *env, float64 src)
 {
     float32 ret;
     clear_float_exceptions(env);
@@ -193,7 +193,7 @@ float32 helper_fdtos(CPUState *env, float64 src)
     return ret;
 }
 
-float64 helper_fstod(CPUState *env, float32 src)
+float64 helper_fstod(CPUSPARCState *env, float32 src)
 {
     float64 ret;
     clear_float_exceptions(env);
@@ -202,7 +202,7 @@ float64 helper_fstod(CPUState *env, float32 src)
     return ret;
 }
 
-float32 helper_fqtos(CPUState *env)
+float32 helper_fqtos(CPUSPARCState *env)
 {
     float32 ret;
     clear_float_exceptions(env);
@@ -211,14 +211,14 @@ float32 helper_fqtos(CPUState *env)
     return ret;
 }
 
-void helper_fstoq(CPUState *env, float32 src)
+void helper_fstoq(CPUSPARCState *env, float32 src)
 {
     clear_float_exceptions(env);
     QT0 = float32_to_float128(src, &env->fp_status);
     check_ieee_exceptions(env);
 }
 
-float64 helper_fqtod(CPUState *env)
+float64 helper_fqtod(CPUSPARCState *env)
 {
     float64 ret;
     clear_float_exceptions(env);
@@ -227,7 +227,7 @@ float64 helper_fqtod(CPUState *env)
     return ret;
 }
 
-void helper_fdtoq(CPUState *env, float64 src)
+void helper_fdtoq(CPUSPARCState *env, float64 src)
 {
     clear_float_exceptions(env);
     QT0 = float64_to_float128(src, &env->fp_status);
@@ -235,7 +235,7 @@ void helper_fdtoq(CPUState *env, float64 src)
 }
 
 /* Float to integer conversion.  */
-int32_t helper_fstoi(CPUState *env, float32 src)
+int32_t helper_fstoi(CPUSPARCState *env, float32 src)
 {
     int32_t ret;
     clear_float_exceptions(env);
@@ -244,7 +244,7 @@ int32_t helper_fstoi(CPUState *env, float32 src)
     return ret;
 }
 
-int32_t helper_fdtoi(CPUState *env, float64 src)
+int32_t helper_fdtoi(CPUSPARCState *env, float64 src)
 {
     int32_t ret;
     clear_float_exceptions(env);
@@ -253,7 +253,7 @@ int32_t helper_fdtoi(CPUState *env, float64 src)
     return ret;
 }
 
-int32_t helper_fqtoi(CPUState *env)
+int32_t helper_fqtoi(CPUSPARCState *env)
 {
     int32_t ret;
     clear_float_exceptions(env);
@@ -263,7 +263,7 @@ int32_t helper_fqtoi(CPUState *env)
 }
 
 #ifdef TARGET_SPARC64
-int64_t helper_fstox(CPUState *env, float32 src)
+int64_t helper_fstox(CPUSPARCState *env, float32 src)
 {
     int64_t ret;
     clear_float_exceptions(env);
@@ -272,7 +272,7 @@ int64_t helper_fstox(CPUState *env, float32 src)
     return ret;
 }
 
-int64_t helper_fdtox(CPUState *env, float64 src)
+int64_t helper_fdtox(CPUSPARCState *env, float64 src)
 {
     int64_t ret;
     clear_float_exceptions(env);
@@ -281,7 +281,7 @@ int64_t helper_fdtox(CPUState *env, float64 src)
     return ret;
 }
 
-int64_t helper_fqtox(CPUState *env)
+int64_t helper_fqtox(CPUSPARCState *env)
 {
     int64_t ret;
     clear_float_exceptions(env);
@@ -302,13 +302,13 @@ float64 helper_fabsd(float64 src)
     return float64_abs(src);
 }
 
-void helper_fabsq(CPUState *env)
+void helper_fabsq(CPUSPARCState *env)
 {
     QT0 = float128_abs(QT1);
 }
 #endif
 
-float32 helper_fsqrts(CPUState *env, float32 src)
+float32 helper_fsqrts(CPUSPARCState *env, float32 src)
 {
     float32 ret;
     clear_float_exceptions(env);
@@ -317,7 +317,7 @@ float32 helper_fsqrts(CPUState *env, float32 src)
     return ret;
 }
 
-float64 helper_fsqrtd(CPUState *env, float64 src)
+float64 helper_fsqrtd(CPUSPARCState *env, float64 src)
 {
     float64 ret;
     clear_float_exceptions(env);
@@ -326,7 +326,7 @@ float64 helper_fsqrtd(CPUState *env, float64 src)
     return ret;
 }
 
-void helper_fsqrtq(CPUState *env)
+void helper_fsqrtq(CPUSPARCState *env)
 {
     clear_float_exceptions(env);
     QT0 = float128_sqrt(QT1, &env->fp_status);
@@ -334,7 +334,7 @@ void helper_fsqrtq(CPUState *env)
 }
 
 #define GEN_FCMP(name, size, reg1, reg2, FS, E)                         \
-    void glue(helper_, name) (CPUState *env)                            \
+    void glue(helper_, name) (CPUSPARCState *env)                            \
     {                                                                   \
         env->fsr &= FSR_FTT_NMASK;                                      \
         if (E && (glue(size, _is_any_nan)(reg1) ||                      \
@@ -370,7 +370,7 @@ void helper_fsqrtq(CPUState *env)
         }                                                               \
     }
 #define GEN_FCMP_T(name, size, FS, E)                                   \
-    void glue(helper_, name)(CPUState *env, size src1, size src2)       \
+    void glue(helper_, name)(CPUSPARCState *env, size src1, size src2)       \
     {                                                                   \
         env->fsr &= FSR_FTT_NMASK;                                      \
         if (E && (glue(size, _is_any_nan)(src1) ||                      \
@@ -443,7 +443,7 @@ GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
 #undef GEN_FCMP_T
 #undef GEN_FCMP
 
-static inline void set_fsr(CPUState *env)
+static inline void set_fsr(CPUSPARCState *env)
 {
     int rnd_mode;
 
@@ -465,14 +465,14 @@ static inline void set_fsr(CPUState *env)
     set_float_rounding_mode(rnd_mode, &env->fp_status);
 }
 
-void helper_ldfsr(CPUState *env, uint32_t new_fsr)
+void helper_ldfsr(CPUSPARCState *env, uint32_t new_fsr)
 {
     env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
     set_fsr(env);
 }
 
 #ifdef TARGET_SPARC64
-void helper_ldxfsr(CPUState *env, uint64_t new_fsr)
+void helper_ldxfsr(CPUSPARCState *env, uint64_t new_fsr)
 {
     env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
     set_fsr(env);
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 037a72c..65e1740 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -22,13 +22,13 @@
 #include "helper.h"
 #include "sysemu.h"
 
-void helper_raise_exception(CPUState *env, int tt)
+void helper_raise_exception(CPUSPARCState *env, int tt)
 {
     env->exception_index = tt;
     cpu_loop_exit(env);
 }
 
-void helper_debug(CPUState *env)
+void helper_debug(CPUSPARCState *env)
 {
     env->exception_index = EXCP_DEBUG;
     cpu_loop_exit(env);
@@ -64,7 +64,7 @@ void helper_tick_set_limit(void *opaque, uint64_t limit)
 }
 #endif
 
-static target_ulong helper_udiv_common(CPUState *env, target_ulong a,
+static target_ulong helper_udiv_common(CPUSPARCState *env, target_ulong a,
                                        target_ulong b, int cc)
 {
     int overflow = 0;
@@ -92,17 +92,17 @@ static target_ulong helper_udiv_common(CPUState *env, target_ulong a,
     return x0;
 }
 
-target_ulong helper_udiv(CPUState *env, target_ulong a, target_ulong b)
+target_ulong helper_udiv(CPUSPARCState *env, target_ulong a, target_ulong b)
 {
     return helper_udiv_common(env, a, b, 0);
 }
 
-target_ulong helper_udiv_cc(CPUState *env, target_ulong a, target_ulong b)
+target_ulong helper_udiv_cc(CPUSPARCState *env, target_ulong a, target_ulong b)
 {
     return helper_udiv_common(env, a, b, 1);
 }
 
-static target_ulong helper_sdiv_common(CPUState *env, target_ulong a,
+static target_ulong helper_sdiv_common(CPUSPARCState *env, target_ulong a,
                                        target_ulong b, int cc)
 {
     int overflow = 0;
@@ -130,12 +130,12 @@ static target_ulong helper_sdiv_common(CPUState *env, target_ulong a,
     return x0;
 }
 
-target_ulong helper_sdiv(CPUState *env, target_ulong a, target_ulong b)
+target_ulong helper_sdiv(CPUSPARCState *env, target_ulong a, target_ulong b)
 {
     return helper_sdiv_common(env, a, b, 0);
 }
 
-target_ulong helper_sdiv_cc(CPUState *env, target_ulong a, target_ulong b)
+target_ulong helper_sdiv_cc(CPUSPARCState *env, target_ulong a, target_ulong b)
 {
     return helper_sdiv_common(env, a, b, 1);
 }
diff --git a/target-sparc/int32_helper.c b/target-sparc/int32_helper.c
index ac9d01e..5e33d50 100644
--- a/target-sparc/int32_helper.c
+++ b/target-sparc/int32_helper.c
@@ -58,7 +58,7 @@ static const char * const excp_names[0x80] = {
 };
 #endif
 
-void do_interrupt(CPUState *env)
+void do_interrupt(CPUSPARCState *env)
 {
     int cwp, intno = env->exception_index;
 
@@ -132,7 +132,7 @@ void do_interrupt(CPUState *env)
 }
 
 #if !defined(CONFIG_USER_ONLY)
-static void leon3_cache_control_int(CPUState *env)
+static void leon3_cache_control_int(CPUSPARCState *env)
 {
     uint32_t state = 0;
 
@@ -161,7 +161,7 @@ static void leon3_cache_control_int(CPUState *env)
     }
 }
 
-void leon3_irq_manager(CPUState *env, void *irq_manager, int intno)
+void leon3_irq_manager(CPUSPARCState *env, void *irq_manager, int intno)
 {
     leon3_irq_ack(irq_manager, intno);
     leon3_cache_control_int(env);
diff --git a/target-sparc/int64_helper.c b/target-sparc/int64_helper.c
index 1d471db..5e3eff7 100644
--- a/target-sparc/int64_helper.c
+++ b/target-sparc/int64_helper.c
@@ -59,7 +59,7 @@ static const char * const excp_names[0x80] = {
 };
 #endif
 
-void do_interrupt(CPUState *env)
+void do_interrupt(CPUSPARCState *env)
 {
     int intno = env->exception_index;
     trap_state *tsptr;
@@ -160,12 +160,12 @@ void do_interrupt(CPUState *env)
     env->exception_index = -1;
 }
 
-trap_state *cpu_tsptr(CPUState* env)
+trap_state *cpu_tsptr(CPUSPARCState* env)
 {
     return &env->ts[env->tl & MAXTL_MASK];
 }
 
-static bool do_modify_softint(CPUState *env, uint32_t value)
+static bool do_modify_softint(CPUSPARCState *env, uint32_t value)
 {
     if (env->softint != value) {
         env->softint = value;
@@ -179,21 +179,21 @@ static bool do_modify_softint(CPUState *env, uint32_t value)
     return false;
 }
 
-void helper_set_softint(CPUState *env, uint64_t value)
+void helper_set_softint(CPUSPARCState *env, uint64_t value)
 {
     if (do_modify_softint(env, env->softint | (uint32_t)value)) {
         trace_int_helper_set_softint(env->softint);
     }
 }
 
-void helper_clear_softint(CPUState *env, uint64_t value)
+void helper_clear_softint(CPUSPARCState *env, uint64_t value)
 {
     if (do_modify_softint(env, env->softint & (uint32_t)~value)) {
         trace_int_helper_clear_softint(env->softint);
     }
 }
 
-void helper_write_softint(CPUState *env, uint64_t value)
+void helper_write_softint(CPUSPARCState *env, uint64_t value)
 {
     if (do_modify_softint(env, (uint32_t)value)) {
         trace_int_helper_write_softint(env->softint);
diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
index b59707e..48d433c 100644
--- a/target-sparc/ldst_helper.c
+++ b/target-sparc/ldst_helper.c
@@ -129,7 +129,7 @@ static uint64_t ultrasparc_tag_target(uint64_t tag_access_register)
 
 static void replace_tlb_entry(SparcTLBEntry *tlb,
                               uint64_t tlb_tag, uint64_t tlb_tte,
-                              CPUState *env1)
+                              CPUSPARCState *env1)
 {
     target_ulong mask, size, va, offset;
 
@@ -152,7 +152,7 @@ static void replace_tlb_entry(SparcTLBEntry *tlb,
 }
 
 static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
-                      const char *strmmu, CPUState *env1)
+                      const char *strmmu, CPUSPARCState *env1)
 {
     unsigned int i;
     target_ulong mask;
@@ -213,7 +213,7 @@ static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
 
 static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
                                  uint64_t tlb_tag, uint64_t tlb_tte,
-                                 const char *strmmu, CPUState *env1)
+                                 const char *strmmu, CPUSPARCState *env1)
 {
     unsigned int i, replace_used;
 
@@ -263,7 +263,7 @@ static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
 
 #endif
 
-static inline target_ulong address_mask(CPUState *env1, target_ulong addr)
+static inline target_ulong address_mask(CPUSPARCState *env1, target_ulong addr)
 {
 #ifdef TARGET_SPARC64
     if (AM_CHECK(env1)) {
@@ -300,7 +300,7 @@ static inline int is_translating_asi(int asi)
 #endif
 }
 
-static inline target_ulong asi_address_mask(CPUState *env1,
+static inline target_ulong asi_address_mask(CPUSPARCState *env1,
                                             int asi, target_ulong addr)
 {
     if (is_translating_asi(asi)) {
@@ -323,7 +323,7 @@ void helper_check_align(target_ulong addr, uint32_t align)
 
 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) &&   \
     defined(DEBUG_MXCC)
-static void dump_mxcc(CPUState *env)
+static void dump_mxcc(CPUSPARCState *env)
 {
     printf("mxccdata: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
            "\n",
@@ -2358,10 +2358,10 @@ static void do_unassigned_access(target_phys_addr_t addr, int is_write,
 #endif
 
 #if !defined(CONFIG_USER_ONLY)
-void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr,
+void cpu_unassigned_access(CPUSPARCState *env1, target_phys_addr_t addr,
                            int is_write, int is_exec, int is_asi, int size)
 {
-    CPUState *saved_env;
+    CPUSPARCState *saved_env;
 
     saved_env = env;
     env = env1;
diff --git a/target-sparc/machine.c b/target-sparc/machine.c
index 235b088..eb4d87f 100644
--- a/target-sparc/machine.c
+++ b/target-sparc/machine.c
@@ -6,7 +6,7 @@
 
 void cpu_save(QEMUFile *f, void *opaque)
 {
-    CPUState *env = opaque;
+    CPUSPARCState *env = opaque;
     int i;
     uint32_t tmp;
 
@@ -111,7 +111,7 @@ void cpu_save(QEMUFile *f, void *opaque)
 
 int cpu_load(QEMUFile *f, void *opaque, int version_id)
 {
-    CPUState *env = opaque;
+    CPUSPARCState *env = opaque;
     int i;
     uint32_t tmp;
 
diff --git a/target-sparc/mmu_helper.c b/target-sparc/mmu_helper.c
index bdff1c3..11fb9f5 100644
--- a/target-sparc/mmu_helper.c
+++ b/target-sparc/mmu_helper.c
@@ -25,7 +25,7 @@
 
 #if defined(CONFIG_USER_ONLY)
 
-int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,
+int cpu_sparc_handle_mmu_fault(CPUSPARCState *env1, target_ulong address, int rw,
                                int mmu_idx)
 {
     if (rw & 2) {
@@ -76,7 +76,7 @@ static const int perm_table[2][8] = {
     }
 };
 
-static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
+static int get_physical_address(CPUSPARCState *env, target_phys_addr_t *physical,
                                 int *prot, int *access_index,
                                 target_ulong address, int rw, int mmu_idx,
                                 target_ulong *page_size)
@@ -198,7 +198,7 @@ static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
 }
 
 /* Perform address translation */
-int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
+int cpu_sparc_handle_mmu_fault(CPUSPARCState *env, target_ulong address, int rw,
                                int mmu_idx)
 {
     target_phys_addr_t paddr;
@@ -244,7 +244,7 @@ int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
     }
 }
 
-target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
+target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev)
 {
     target_phys_addr_t pde_ptr;
     uint32_t pde;
@@ -310,7 +310,7 @@ target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
     return 0;
 }
 
-void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
+void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUSPARCState *env)
 {
     target_ulong va, va1, va2;
     unsigned int n, m, o;
@@ -354,7 +354,7 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
  * reads (and only reads) in stack frames as if windows were flushed. We assume
  * that the sparc ABI is followed.
  */
-int target_memory_rw_debug(CPUState *env, target_ulong addr,
+int target_memory_rw_debug(CPUSPARCState *env, target_ulong addr,
                            uint8_t *buf, int len, int is_write)
 {
     int i;
@@ -479,7 +479,7 @@ static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
     return 0;
 }
 
-static int get_physical_address_data(CPUState *env,
+static int get_physical_address_data(CPUSPARCState *env,
                                      target_phys_addr_t *physical, int *prot,
                                      target_ulong address, int rw, int mmu_idx)
 {
@@ -598,7 +598,7 @@ static int get_physical_address_data(CPUState *env,
     return 1;
 }
 
-static int get_physical_address_code(CPUState *env,
+static int get_physical_address_code(CPUSPARCState *env,
                                      target_phys_addr_t *physical, int *prot,
                                      target_ulong address, int mmu_idx)
 {
@@ -667,7 +667,7 @@ static int get_physical_address_code(CPUState *env,
     return 1;
 }
 
-static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
+static int get_physical_address(CPUSPARCState *env, target_phys_addr_t *physical,
                                 int *prot, int *access_index,
                                 target_ulong address, int rw, int mmu_idx,
                                 target_ulong *page_size)
@@ -701,7 +701,7 @@ static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
 }
 
 /* Perform address translation */
-int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
+int cpu_sparc_handle_mmu_fault(CPUSPARCState *env, target_ulong address, int rw,
                                int mmu_idx)
 {
     target_ulong virt_addr, vaddr;
@@ -727,7 +727,7 @@ int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
     return 1;
 }
 
-void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
+void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUSPARCState *env)
 {
     unsigned int i;
     const char *mask;
@@ -813,7 +813,7 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
 
 #endif /* TARGET_SPARC64 */
 
-static int cpu_sparc_get_phys_page(CPUState *env, target_phys_addr_t *phys,
+static int cpu_sparc_get_phys_page(CPUSPARCState *env, target_phys_addr_t *phys,
                                    target_ulong addr, int rw, int mmu_idx)
 {
     target_ulong page_size;
@@ -824,7 +824,7 @@ static int cpu_sparc_get_phys_page(CPUState *env, target_phys_addr_t *phys,
 }
 
 #if defined(TARGET_SPARC64)
-target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
+target_phys_addr_t cpu_get_phys_page_nofault(CPUSPARCState *env, target_ulong addr,
                                            int mmu_idx)
 {
     target_phys_addr_t phys_addr;
@@ -836,7 +836,7 @@ target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
 }
 #endif
 
-target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_debug(CPUSPARCState *env, target_ulong addr)
 {
     target_phys_addr_t phys_addr;
     int mmu_idx = cpu_mmu_index(env);
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 02b660d..1aff125 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -54,11 +54,11 @@ static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
    NULL, it means that the function was called in C code (i.e. not
    from generated code or from helper.c) */
 /* XXX: fix it to restore all registers */
-void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
+void tlb_fill(CPUSPARCState *env1, target_ulong addr, int is_write, int mmu_idx,
               void *retaddr)
 {
     int ret;
-    CPUState *saved_env;
+    CPUSPARCState *saved_env;
 
     saved_env = env;
     env = env1;
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index d261112..ef176e9 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -2209,7 +2209,7 @@ static inline void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr, TCGv_ptr cpu_env)
 
     /* calculate offset to current trap state from env->ts, reuse r_tl */
     tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state));
-    tcg_gen_addi_ptr(r_tsptr, cpu_env, offsetof(CPUState, ts));
+    tcg_gen_addi_ptr(r_tsptr, cpu_env, offsetof(CPUSPARCState, ts));
 
     /* tsptr = env->ts[env->tl & MAXTL_MASK] */
     {
@@ -2600,7 +2600,7 @@ static void disas_sparc_insn(DisasContext * dc)
 
                         r_tickptr = tcg_temp_new_ptr();
                         tcg_gen_ld_ptr(r_tickptr, cpu_env,
-                                       offsetof(CPUState, tick));
+                                       offsetof(CPUSPARCState, tick));
                         gen_helper_tick_get_count(cpu_dst, r_tickptr);
                         tcg_temp_free_ptr(r_tickptr);
                         gen_movl_TN_reg(rd, cpu_dst);
@@ -2639,7 +2639,7 @@ static void disas_sparc_insn(DisasContext * dc)
 
                         r_tickptr = tcg_temp_new_ptr();
                         tcg_gen_ld_ptr(r_tickptr, cpu_env,
-                                       offsetof(CPUState, stick));
+                                       offsetof(CPUSPARCState, stick));
                         gen_helper_tick_get_count(cpu_dst, r_tickptr);
                         tcg_temp_free_ptr(r_tickptr);
                         gen_movl_TN_reg(rd, cpu_dst);
@@ -2752,7 +2752,7 @@ static void disas_sparc_insn(DisasContext * dc)
 
                         r_tickptr = tcg_temp_new_ptr();
                         tcg_gen_ld_ptr(r_tickptr, cpu_env,
-                                       offsetof(CPUState, tick));
+                                       offsetof(CPUSPARCState, tick));
                         gen_helper_tick_get_count(cpu_tmp0, r_tickptr);
                         gen_movl_TN_reg(rd, cpu_tmp0);
                         tcg_temp_free_ptr(r_tickptr);
@@ -3712,7 +3712,7 @@ static void disas_sparc_insn(DisasContext * dc)
                                                    cpu_src2);
                                     r_tickptr = tcg_temp_new_ptr();
                                     tcg_gen_ld_ptr(r_tickptr, cpu_env,
-                                                   offsetof(CPUState, tick));
+                                                   offsetof(CPUSPARCState, tick));
                                     gen_helper_tick_set_limit(r_tickptr,
                                                               cpu_tick_cmpr);
                                     tcg_temp_free_ptr(r_tickptr);
@@ -3730,7 +3730,7 @@ static void disas_sparc_insn(DisasContext * dc)
                                                    cpu_src2);
                                     r_tickptr = tcg_temp_new_ptr();
                                     tcg_gen_ld_ptr(r_tickptr, cpu_env,
-                                                   offsetof(CPUState, stick));
+                                                   offsetof(CPUSPARCState, stick));
                                     gen_helper_tick_set_count(r_tickptr,
                                                               cpu_dst);
                                     tcg_temp_free_ptr(r_tickptr);
@@ -3748,7 +3748,7 @@ static void disas_sparc_insn(DisasContext * dc)
                                                    cpu_src2);
                                     r_tickptr = tcg_temp_new_ptr();
                                     tcg_gen_ld_ptr(r_tickptr, cpu_env,
-                                                   offsetof(CPUState, stick));
+                                                   offsetof(CPUSPARCState, stick));
                                     gen_helper_tick_set_limit(r_tickptr,
                                                               cpu_stick_cmpr);
                                     tcg_temp_free_ptr(r_tickptr);
@@ -3857,7 +3857,7 @@ static void disas_sparc_insn(DisasContext * dc)
 
                                     r_tickptr = tcg_temp_new_ptr();
                                     tcg_gen_ld_ptr(r_tickptr, cpu_env,
-                                                   offsetof(CPUState, tick));
+                                                   offsetof(CPUSPARCState, tick));
                                     gen_helper_tick_set_count(r_tickptr,
                                                               cpu_tmp0);
                                     tcg_temp_free_ptr(r_tickptr);
@@ -3985,7 +3985,7 @@ static void disas_sparc_insn(DisasContext * dc)
                                     tcg_gen_mov_tl(cpu_hstick_cmpr, cpu_tmp0);
                                     r_tickptr = tcg_temp_new_ptr();
                                     tcg_gen_ld_ptr(r_tickptr, cpu_env,
-                                                   offsetof(CPUState, hstick));
+                                                   offsetof(CPUSPARCState, hstick));
                                     gen_helper_tick_set_limit(r_tickptr,
                                                               cpu_hstick_cmpr);
                                     tcg_temp_free_ptr(r_tickptr);
@@ -5045,13 +5045,13 @@ static void disas_sparc_insn(DisasContext * dc)
                 case 0x25: /* stfsr, V9 stxfsr */
 #ifdef TARGET_SPARC64
                     gen_address_mask(dc, cpu_addr);
-                    tcg_gen_ld_i64(cpu_tmp64, cpu_env, offsetof(CPUState, fsr));
+                    tcg_gen_ld_i64(cpu_tmp64, cpu_env, offsetof(CPUSPARCState, fsr));
                     if (rd == 1)
                         tcg_gen_qemu_st64(cpu_tmp64, cpu_addr, dc->mem_idx);
                     else
                         tcg_gen_qemu_st32(cpu_tmp64, cpu_addr, dc->mem_idx);
 #else
-                    tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUState, fsr));
+                    tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fsr));
                     tcg_gen_qemu_st32(cpu_tmp32, cpu_addr, dc->mem_idx);
 #endif
                     break;
@@ -5403,75 +5403,75 @@ void gen_intermediate_code_init(CPUSPARCState *env)
 
         cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
         cpu_regwptr = tcg_global_mem_new_ptr(TCG_AREG0,
-                                             offsetof(CPUState, regwptr),
+                                             offsetof(CPUSPARCState, regwptr),
                                              "regwptr");
 #ifdef TARGET_SPARC64
-        cpu_xcc = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, xcc),
+        cpu_xcc = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUSPARCState, xcc),
                                          "xcc");
-        cpu_asi = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, asi),
+        cpu_asi = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUSPARCState, asi),
                                          "asi");
-        cpu_fprs = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, fprs),
+        cpu_fprs = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUSPARCState, fprs),
                                           "fprs");
-        cpu_gsr = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, gsr),
+        cpu_gsr = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, gsr),
                                      "gsr");
         cpu_tick_cmpr = tcg_global_mem_new(TCG_AREG0,
-                                           offsetof(CPUState, tick_cmpr),
+                                           offsetof(CPUSPARCState, tick_cmpr),
                                            "tick_cmpr");
         cpu_stick_cmpr = tcg_global_mem_new(TCG_AREG0,
-                                            offsetof(CPUState, stick_cmpr),
+                                            offsetof(CPUSPARCState, stick_cmpr),
                                             "stick_cmpr");
         cpu_hstick_cmpr = tcg_global_mem_new(TCG_AREG0,
-                                             offsetof(CPUState, hstick_cmpr),
+                                             offsetof(CPUSPARCState, hstick_cmpr),
                                              "hstick_cmpr");
-        cpu_hintp = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, hintp),
+        cpu_hintp = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, hintp),
                                        "hintp");
-        cpu_htba = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, htba),
+        cpu_htba = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, htba),
                                       "htba");
-        cpu_hver = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, hver),
+        cpu_hver = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, hver),
                                       "hver");
         cpu_ssr = tcg_global_mem_new(TCG_AREG0,
-                                     offsetof(CPUState, ssr), "ssr");
+                                     offsetof(CPUSPARCState, ssr), "ssr");
         cpu_ver = tcg_global_mem_new(TCG_AREG0,
-                                     offsetof(CPUState, version), "ver");
+                                     offsetof(CPUSPARCState, version), "ver");
         cpu_softint = tcg_global_mem_new_i32(TCG_AREG0,
-                                             offsetof(CPUState, softint),
+                                             offsetof(CPUSPARCState, softint),
                                              "softint");
 #else
-        cpu_wim = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, wim),
+        cpu_wim = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, wim),
                                      "wim");
 #endif
-        cpu_cond = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, cond),
+        cpu_cond = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, cond),
                                       "cond");
-        cpu_cc_src = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, cc_src),
+        cpu_cc_src = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, cc_src),
                                         "cc_src");
         cpu_cc_src2 = tcg_global_mem_new(TCG_AREG0,
-                                         offsetof(CPUState, cc_src2),
+                                         offsetof(CPUSPARCState, cc_src2),
                                          "cc_src2");
-        cpu_cc_dst = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, cc_dst),
+        cpu_cc_dst = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, cc_dst),
                                         "cc_dst");
-        cpu_cc_op = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, cc_op),
+        cpu_cc_op = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUSPARCState, cc_op),
                                            "cc_op");
-        cpu_psr = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, psr),
+        cpu_psr = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUSPARCState, psr),
                                          "psr");
-        cpu_fsr = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, fsr),
+        cpu_fsr = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, fsr),
                                      "fsr");
-        cpu_pc = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, pc),
+        cpu_pc = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, pc),
                                     "pc");
-        cpu_npc = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, npc),
+        cpu_npc = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, npc),
                                      "npc");
-        cpu_y = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, y), "y");
+        cpu_y = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, y), "y");
 #ifndef CONFIG_USER_ONLY
-        cpu_tbr = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, tbr),
+        cpu_tbr = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, tbr),
                                      "tbr");
 #endif
         for (i = 1; i < 8; i++) {
             cpu_gregs[i] = tcg_global_mem_new(TCG_AREG0,
-                                              offsetof(CPUState, gregs[i]),
+                                              offsetof(CPUSPARCState, gregs[i]),
                                               gregnames[i]);
         }
         for (i = 0; i < TARGET_DPREGS; i++) {
             cpu_fpr[i] = tcg_global_mem_new_i64(TCG_AREG0,
-                                                offsetof(CPUState, fpr[i]),
+                                                offsetof(CPUSPARCState, fpr[i]),
                                                 fregnames[i]);
         }
 
@@ -5482,7 +5482,7 @@ void gen_intermediate_code_init(CPUSPARCState *env)
     }
 }
 
-void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUSPARCState *env, TranslationBlock *tb, int pc_pos)
 {
     target_ulong npc;
     env->pc = gen_opc_pc[pc_pos];
diff --git a/target-sparc/win_helper.c b/target-sparc/win_helper.c
index a68c649..3e82eb7 100644
--- a/target-sparc/win_helper.c
+++ b/target-sparc/win_helper.c
@@ -33,7 +33,7 @@ static inline void memcpy32(target_ulong *dst, const target_ulong *src)
     dst[7] = src[7];
 }
 
-void cpu_set_cwp(CPUState *env, int new_cwp)
+void cpu_set_cwp(CPUSPARCState *env, int new_cwp)
 {
     /* put the modified wrap registers at their proper location */
     if (env->cwp == env->nwindows - 1) {
@@ -48,7 +48,7 @@ void cpu_set_cwp(CPUState *env, int new_cwp)
     env->regwptr = env->regbase + (new_cwp * 16);
 }
 
-target_ulong cpu_get_psr(CPUState *env)
+target_ulong cpu_get_psr(CPUSPARCState *env)
 {
     helper_compute_psr(env);
 
@@ -64,7 +64,7 @@ target_ulong cpu_get_psr(CPUState *env)
 #endif
 }
 
-void cpu_put_psr(CPUState *env, target_ulong val)
+void cpu_put_psr(CPUSPARCState *env, target_ulong val)
 {
     env->psr = val & PSR_ICC;
 #if !defined(TARGET_SPARC64)
@@ -83,7 +83,7 @@ void cpu_put_psr(CPUState *env, target_ulong val)
     env->cc_op = CC_OP_FLAGS;
 }
 
-int cpu_cwp_inc(CPUState *env, int cwp)
+int cpu_cwp_inc(CPUSPARCState *env, int cwp)
 {
     if (unlikely(cwp >= env->nwindows)) {
         cwp -= env->nwindows;
@@ -91,7 +91,7 @@ int cpu_cwp_inc(CPUState *env, int cwp)
     return cwp;
 }
 
-int cpu_cwp_dec(CPUState *env, int cwp)
+int cpu_cwp_dec(CPUSPARCState *env, int cwp)
 {
     if (unlikely(cwp < 0)) {
         cwp += env->nwindows;
@@ -100,7 +100,7 @@ int cpu_cwp_dec(CPUState *env, int cwp)
 }
 
 #ifndef TARGET_SPARC64
-void helper_rett(CPUState *env)
+void helper_rett(CPUSPARCState *env)
 {
     unsigned int cwp;
 
@@ -119,7 +119,7 @@ void helper_rett(CPUState *env)
 
 /* XXX: use another pointer for %iN registers to avoid slow wrapping
    handling ? */
-void helper_save(CPUState *env)
+void helper_save(CPUSPARCState *env)
 {
     uint32_t cwp;
 
@@ -130,7 +130,7 @@ void helper_save(CPUState *env)
     cpu_set_cwp(env, cwp);
 }
 
-void helper_restore(CPUState *env)
+void helper_restore(CPUSPARCState *env)
 {
     uint32_t cwp;
 
@@ -141,7 +141,7 @@ void helper_restore(CPUState *env)
     cpu_set_cwp(env, cwp);
 }
 
-void helper_wrpsr(CPUState *env, target_ulong new_psr)
+void helper_wrpsr(CPUSPARCState *env, target_ulong new_psr)
 {
     if ((new_psr & PSR_CWP) >= env->nwindows) {
         helper_raise_exception(env, TT_ILL_INSN);
@@ -150,7 +150,7 @@ void helper_wrpsr(CPUState *env, target_ulong new_psr)
     }
 }
 
-target_ulong helper_rdpsr(CPUState *env)
+target_ulong helper_rdpsr(CPUSPARCState *env)
 {
     return cpu_get_psr(env);
 }
@@ -158,7 +158,7 @@ target_ulong helper_rdpsr(CPUState *env)
 #else
 /* XXX: use another pointer for %iN registers to avoid slow wrapping
    handling ? */
-void helper_save(CPUState *env)
+void helper_save(CPUSPARCState *env)
 {
     uint32_t cwp;
 
@@ -180,7 +180,7 @@ void helper_save(CPUState *env)
     }
 }
 
-void helper_restore(CPUState *env)
+void helper_restore(CPUSPARCState *env)
 {
     uint32_t cwp;
 
@@ -197,7 +197,7 @@ void helper_restore(CPUState *env)
     }
 }
 
-void helper_flushw(CPUState *env)
+void helper_flushw(CPUSPARCState *env)
 {
     if (env->cansave != env->nwindows - 2) {
         helper_raise_exception(env, TT_SPILL | (env->otherwin != 0 ?
@@ -207,7 +207,7 @@ void helper_flushw(CPUState *env)
     }
 }
 
-void helper_saved(CPUState *env)
+void helper_saved(CPUSPARCState *env)
 {
     env->cansave++;
     if (env->otherwin == 0) {
@@ -217,7 +217,7 @@ void helper_saved(CPUState *env)
     }
 }
 
-void helper_restored(CPUState *env)
+void helper_restored(CPUSPARCState *env)
 {
     env->canrestore++;
     if (env->cleanwin < env->nwindows - 1) {
@@ -230,7 +230,7 @@ void helper_restored(CPUState *env)
     }
 }
 
-target_ulong cpu_get_ccr(CPUState *env)
+target_ulong cpu_get_ccr(CPUSPARCState *env)
 {
     target_ulong psr;
 
@@ -239,19 +239,19 @@ target_ulong cpu_get_ccr(CPUState *env)
     return ((env->xcc >> 20) << 4) | ((psr & PSR_ICC) >> 20);
 }
 
-void cpu_put_ccr(CPUState *env, target_ulong val)
+void cpu_put_ccr(CPUSPARCState *env, target_ulong val)
 {
     env->xcc = (val >> 4) << 20;
     env->psr = (val & 0xf) << 20;
     CC_OP = CC_OP_FLAGS;
 }
 
-target_ulong cpu_get_cwp64(CPUState *env)
+target_ulong cpu_get_cwp64(CPUSPARCState *env)
 {
     return env->nwindows - 1 - env->cwp;
 }
 
-void cpu_put_cwp64(CPUState *env, int cwp)
+void cpu_put_cwp64(CPUSPARCState *env, int cwp)
 {
     if (unlikely(cwp >= env->nwindows || cwp < 0)) {
         cwp %= env->nwindows;
@@ -259,29 +259,29 @@ void cpu_put_cwp64(CPUState *env, int cwp)
     cpu_set_cwp(env, env->nwindows - 1 - cwp);
 }
 
-target_ulong helper_rdccr(CPUState *env)
+target_ulong helper_rdccr(CPUSPARCState *env)
 {
     return cpu_get_ccr(env);
 }
 
-void helper_wrccr(CPUState *env, target_ulong new_ccr)
+void helper_wrccr(CPUSPARCState *env, target_ulong new_ccr)
 {
     cpu_put_ccr(env, new_ccr);
 }
 
 /* CWP handling is reversed in V9, but we still use the V8 register
    order. */
-target_ulong helper_rdcwp(CPUState *env)
+target_ulong helper_rdcwp(CPUSPARCState *env)
 {
     return cpu_get_cwp64(env);
 }
 
-void helper_wrcwp(CPUState *env, target_ulong new_cwp)
+void helper_wrcwp(CPUSPARCState *env, target_ulong new_cwp)
 {
     cpu_put_cwp64(env, new_cwp);
 }
 
-static inline uint64_t *get_gregset(CPUState *env, uint32_t pstate)
+static inline uint64_t *get_gregset(CPUSPARCState *env, uint32_t pstate)
 {
     switch (pstate) {
     default:
@@ -298,7 +298,7 @@ static inline uint64_t *get_gregset(CPUState *env, uint32_t pstate)
     }
 }
 
-void cpu_change_pstate(CPUState *env, uint32_t new_pstate)
+void cpu_change_pstate(CPUSPARCState *env, uint32_t new_pstate)
 {
     uint32_t pstate_regs, new_pstate_regs;
     uint64_t *src, *dst;
@@ -325,7 +325,7 @@ void cpu_change_pstate(CPUState *env, uint32_t new_pstate)
     env->pstate = new_pstate;
 }
 
-void helper_wrpstate(CPUState *env, target_ulong new_state)
+void helper_wrpstate(CPUSPARCState *env, target_ulong new_state)
 {
     cpu_change_pstate(env, new_state & 0xf3f);
 
@@ -336,7 +336,7 @@ void helper_wrpstate(CPUState *env, target_ulong new_state)
 #endif
 }
 
-void helper_wrpil(CPUState *env, target_ulong new_pil)
+void helper_wrpil(CPUSPARCState *env, target_ulong new_pil)
 {
 #if !defined(CONFIG_USER_ONLY)
     trace_win_helper_wrpil(env->psrpil, (uint32_t)new_pil);
@@ -349,7 +349,7 @@ void helper_wrpil(CPUState *env, target_ulong new_pil)
 #endif
 }
 
-void helper_done(CPUState *env)
+void helper_done(CPUSPARCState *env)
 {
     trap_state *tsptr = cpu_tsptr(env);
 
@@ -370,7 +370,7 @@ void helper_done(CPUState *env)
 #endif
 }
 
-void helper_retry(CPUState *env)
+void helper_retry(CPUSPARCState *env)
 {
     trap_state *tsptr = cpu_tsptr(env);
 
commit 73e5716c8967d45b14aa08d315c5b3dda18465c4
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:22 2012 +0100

    target-sh4: Don't overuse CPUState
    
    Scripted conversion:
      sed -i "s/CPUState/CPUSH4State/g" target-sh4/*.[hc]
      sed -i "s/#define CPUSH4State/#define CPUState/" target-sh4/cpu.h
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index 7d7fdde..b45e54f 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -240,13 +240,13 @@ void cpu_load_tlb(CPUSH4State * env);
 #define MMU_MODE0_SUFFIX _kernel
 #define MMU_MODE1_SUFFIX _user
 #define MMU_USER_IDX 1
-static inline int cpu_mmu_index (CPUState *env)
+static inline int cpu_mmu_index (CPUSH4State *env)
 {
     return (env->sr & SR_MD) == 0 ? 1 : 0;
 }
 
 #if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
+static inline void cpu_clone_regs(CPUSH4State *env, target_ulong newsp)
 {
     if (newsp)
         env->gregs[15] = newsp;
@@ -348,7 +348,7 @@ static inline int cpu_ptel_pr (uint32_t ptel)
 
 #define TB_FLAG_PENDING_MOVCA  (1 << 4)
 
-static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+static inline void cpu_get_tb_cpu_state(CPUSH4State *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
     *pc = env->pc;
@@ -361,14 +361,14 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
             | (env->movcal_backup ? TB_FLAG_PENDING_MOVCA : 0); /* Bit 4 */
 }
 
-static inline bool cpu_has_work(CPUState *env)
+static inline bool cpu_has_work(CPUSH4State *env)
 {
     return env->interrupt_request & CPU_INTERRUPT_HARD;
 }
 
 #include "exec-all.h"
 
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+static inline void cpu_pc_from_tb(CPUSH4State *env, TranslationBlock *tb)
 {
     env->pc = tb->pc;
     env->flags = tb->flags;
diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index 006d1a9..5c57380 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -31,12 +31,12 @@
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt (CPUState *env)
+void do_interrupt (CPUSH4State *env)
 {
   env->exception_index = -1;
 }
 
-int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
+int cpu_sh4_handle_mmu_fault(CPUSH4State * env, target_ulong address, int rw,
                              int mmu_idx)
 {
     env->tea = address;
@@ -78,7 +78,7 @@ int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr)
 #define MMU_DADDR_ERROR_READ     (-12)
 #define MMU_DADDR_ERROR_WRITE    (-13)
 
-void do_interrupt(CPUState * env)
+void do_interrupt(CPUSH4State * env)
 {
     int do_irq = env->interrupt_request & CPU_INTERRUPT_HARD;
     int do_exp, irq_vector = env->exception_index;
@@ -202,7 +202,7 @@ void do_interrupt(CPUState * env)
     }
 }
 
-static void update_itlb_use(CPUState * env, int itlbnb)
+static void update_itlb_use(CPUSH4State * env, int itlbnb)
 {
     uint8_t or_mask = 0, and_mask = (uint8_t) - 1;
 
@@ -227,7 +227,7 @@ static void update_itlb_use(CPUState * env, int itlbnb)
     env->mmucr |= (or_mask << 24);
 }
 
-static int itlb_replacement(CPUState * env)
+static int itlb_replacement(CPUSH4State * env)
 {
     if ((env->mmucr & 0xe0000000) == 0xe0000000)
 	return 0;
@@ -243,7 +243,7 @@ static int itlb_replacement(CPUState * env)
 /* Find the corresponding entry in the right TLB
    Return entry, MMU_DTLB_MISS or MMU_DTLB_MULTIPLE
 */
-static int find_tlb_entry(CPUState * env, target_ulong address,
+static int find_tlb_entry(CPUSH4State * env, target_ulong address,
 			  tlb_t * entries, uint8_t nbtlb, int use_asid)
 {
     int match = MMU_DTLB_MISS;
@@ -269,7 +269,7 @@ static int find_tlb_entry(CPUState * env, target_ulong address,
     return match;
 }
 
-static void increment_urc(CPUState * env)
+static void increment_urc(CPUSH4State * env)
 {
     uint8_t urb, urc;
 
@@ -285,7 +285,7 @@ static void increment_urc(CPUState * env)
 /* Copy and utlb entry into itlb
    Return entry
 */
-static int copy_utlb_entry_itlb(CPUState *env, int utlb)
+static int copy_utlb_entry_itlb(CPUSH4State *env, int utlb)
 {
     int itlb;
 
@@ -303,7 +303,7 @@ static int copy_utlb_entry_itlb(CPUState *env, int utlb)
 /* Find itlb entry
    Return entry, MMU_ITLB_MISS, MMU_ITLB_MULTIPLE or MMU_DTLB_MULTIPLE
 */
-static int find_itlb_entry(CPUState * env, target_ulong address,
+static int find_itlb_entry(CPUSH4State * env, target_ulong address,
                            int use_asid)
 {
     int e;
@@ -321,7 +321,7 @@ static int find_itlb_entry(CPUState * env, target_ulong address,
 
 /* Find utlb entry
    Return entry, MMU_DTLB_MISS, MMU_DTLB_MULTIPLE */
-static int find_utlb_entry(CPUState * env, target_ulong address, int use_asid)
+static int find_utlb_entry(CPUSH4State * env, target_ulong address, int use_asid)
 {
     /* per utlb access */
     increment_urc(env);
@@ -337,7 +337,7 @@ static int find_utlb_entry(CPUState * env, target_ulong address, int use_asid)
    MMU_ITLB_MULTIPLE, MMU_ITLB_VIOLATION,
    MMU_IADDR_ERROR, MMU_DADDR_ERROR_READ, MMU_DADDR_ERROR_WRITE.
 */
-static int get_mmu_address(CPUState * env, target_ulong * physical,
+static int get_mmu_address(CPUSH4State * env, target_ulong * physical,
 			   int *prot, target_ulong address,
 			   int rw, int access_type)
 {
@@ -403,7 +403,7 @@ static int get_mmu_address(CPUState * env, target_ulong * physical,
     return n;
 }
 
-static int get_physical_address(CPUState * env, target_ulong * physical,
+static int get_physical_address(CPUSH4State * env, target_ulong * physical,
                                 int *prot, target_ulong address,
                                 int rw, int access_type)
 {
@@ -442,7 +442,7 @@ static int get_physical_address(CPUState * env, target_ulong * physical,
     return get_mmu_address(env, physical, prot, address, rw, access_type);
 }
 
-int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
+int cpu_sh4_handle_mmu_fault(CPUSH4State * env, target_ulong address, int rw,
                              int mmu_idx)
 {
     target_ulong physical;
@@ -503,7 +503,7 @@ int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
     return 0;
 }
 
-target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_debug(CPUSH4State * env, target_ulong addr)
 {
     target_ulong physical;
     int prot;
diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c
index b299576..30f762f 100644
--- a/target-sh4/op_helper.c
+++ b/target-sh4/op_helper.c
@@ -55,10 +55,10 @@ static void cpu_restore_state_from_retaddr(void *retaddr)
 #define SHIFT 3
 #include "softmmu_template.h"
 
-void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
+void tlb_fill(CPUSH4State *env1, target_ulong addr, int is_write, int mmu_idx,
               void *retaddr)
 {
-    CPUState *saved_env;
+    CPUSH4State *saved_env;
     int ret;
 
     saved_env = env;
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index c385de8..a337beb 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -103,47 +103,47 @@ static void sh4_translate_init(void)
 
     for (i = 0; i < 24; i++)
         cpu_gregs[i] = tcg_global_mem_new_i32(TCG_AREG0,
-                                              offsetof(CPUState, gregs[i]),
+                                              offsetof(CPUSH4State, gregs[i]),
                                               gregnames[i]);
 
     cpu_pc = tcg_global_mem_new_i32(TCG_AREG0,
-                                    offsetof(CPUState, pc), "PC");
+                                    offsetof(CPUSH4State, pc), "PC");
     cpu_sr = tcg_global_mem_new_i32(TCG_AREG0,
-                                    offsetof(CPUState, sr), "SR");
+                                    offsetof(CPUSH4State, sr), "SR");
     cpu_ssr = tcg_global_mem_new_i32(TCG_AREG0,
-                                     offsetof(CPUState, ssr), "SSR");
+                                     offsetof(CPUSH4State, ssr), "SSR");
     cpu_spc = tcg_global_mem_new_i32(TCG_AREG0,
-                                     offsetof(CPUState, spc), "SPC");
+                                     offsetof(CPUSH4State, spc), "SPC");
     cpu_gbr = tcg_global_mem_new_i32(TCG_AREG0,
-                                     offsetof(CPUState, gbr), "GBR");
+                                     offsetof(CPUSH4State, gbr), "GBR");
     cpu_vbr = tcg_global_mem_new_i32(TCG_AREG0,
-                                     offsetof(CPUState, vbr), "VBR");
+                                     offsetof(CPUSH4State, vbr), "VBR");
     cpu_sgr = tcg_global_mem_new_i32(TCG_AREG0,
-                                     offsetof(CPUState, sgr), "SGR");
+                                     offsetof(CPUSH4State, sgr), "SGR");
     cpu_dbr = tcg_global_mem_new_i32(TCG_AREG0,
-                                     offsetof(CPUState, dbr), "DBR");
+                                     offsetof(CPUSH4State, dbr), "DBR");
     cpu_mach = tcg_global_mem_new_i32(TCG_AREG0,
-                                      offsetof(CPUState, mach), "MACH");
+                                      offsetof(CPUSH4State, mach), "MACH");
     cpu_macl = tcg_global_mem_new_i32(TCG_AREG0,
-                                      offsetof(CPUState, macl), "MACL");
+                                      offsetof(CPUSH4State, macl), "MACL");
     cpu_pr = tcg_global_mem_new_i32(TCG_AREG0,
-                                    offsetof(CPUState, pr), "PR");
+                                    offsetof(CPUSH4State, pr), "PR");
     cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
-                                       offsetof(CPUState, fpscr), "FPSCR");
+                                       offsetof(CPUSH4State, fpscr), "FPSCR");
     cpu_fpul = tcg_global_mem_new_i32(TCG_AREG0,
-                                      offsetof(CPUState, fpul), "FPUL");
+                                      offsetof(CPUSH4State, fpul), "FPUL");
 
     cpu_flags = tcg_global_mem_new_i32(TCG_AREG0,
-				       offsetof(CPUState, flags), "_flags_");
+				       offsetof(CPUSH4State, flags), "_flags_");
     cpu_delayed_pc = tcg_global_mem_new_i32(TCG_AREG0,
-					    offsetof(CPUState, delayed_pc),
+					    offsetof(CPUSH4State, delayed_pc),
 					    "_delayed_pc_");
     cpu_ldst = tcg_global_mem_new_i32(TCG_AREG0,
-				      offsetof(CPUState, ldst), "_ldst_");
+				      offsetof(CPUSH4State, ldst), "_ldst_");
 
     for (i = 0; i < 32; i++)
         cpu_fregs[i] = tcg_global_mem_new_i32(TCG_AREG0,
-                                              offsetof(CPUState, fregs[i]),
+                                              offsetof(CPUSH4State, fregs[i]),
                                               fregnames[i]);
 
     /* register helpers */
@@ -153,7 +153,7 @@ static void sh4_translate_init(void)
     done_init = 1;
 }
 
-void cpu_dump_state(CPUState * env, FILE * f,
+void cpu_dump_state(CPUSH4State * env, FILE * f,
 		    int (*cpu_fprintf) (FILE * f, const char *fmt, ...),
 		    int flags)
 {
@@ -1918,7 +1918,7 @@ static void decode_opc(DisasContext * ctx)
 }
 
 static inline void
-gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
+gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb,
                                int search_pc)
 {
     DisasContext ctx;
@@ -2044,17 +2044,17 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
 #endif
 }
 
-void gen_intermediate_code(CPUState * env, struct TranslationBlock *tb)
+void gen_intermediate_code(CPUSH4State * env, struct TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 0);
 }
 
-void gen_intermediate_code_pc(CPUState * env, struct TranslationBlock *tb)
+void gen_intermediate_code_pc(CPUSH4State * env, struct TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 1);
 }
 
-void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb, int pc_pos)
 {
     env->pc = gen_opc_pc[pc_pos];
     env->flags = gen_opc_hflags[pc_pos];
commit a4e3ad19d2769b0d664131336839961f2285f423
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:22 2012 +0100

    target-s390x: Don't overuse CPUState
    
    Scripted conversion:
      sed -i "s/CPUState/CPUS390XState/g" target-s390x/*.[hc]
      sed -i "s/#define CPUS390XState/#define CPUState/" target-s390x/cpu.h
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index e892bec..af6cc4e 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -106,7 +106,7 @@ typedef struct CPUS390XState {
 } CPUS390XState;
 
 #if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
+static inline void cpu_clone_regs(CPUS390XState *env, target_ulong newsp)
 {
     if (newsp) {
         env->regs[15] = newsp;
@@ -233,7 +233,7 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
 #define FLAG_MASK_64            (PSW_MASK_64     >> 32)
 #define FLAG_MASK_32            0x00001000
 
-static inline int cpu_mmu_index (CPUState *env)
+static inline int cpu_mmu_index (CPUS390XState *env)
 {
     if (env->psw.mask & PSW_MASK_PSTATE) {
         return 1;
@@ -242,7 +242,7 @@ static inline int cpu_mmu_index (CPUState *env)
     return 0;
 }
 
-static inline void cpu_get_tb_cpu_state(CPUState* env, target_ulong *pc,
+static inline void cpu_get_tb_cpu_state(CPUS390XState* env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
     *pc = env->psw.addr;
@@ -275,7 +275,7 @@ CPUS390XState *cpu_s390x_init(const char *cpu_model);
 void s390x_translate_init(void);
 int cpu_s390x_exec(CPUS390XState *s);
 void cpu_s390x_close(CPUS390XState *s);
-void do_interrupt (CPUState *env);
+void do_interrupt (CPUS390XState *env);
 
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
@@ -288,42 +288,42 @@ int cpu_s390x_handle_mmu_fault (CPUS390XState *env, target_ulong address, int rw
 
 
 #ifndef CONFIG_USER_ONLY
-int s390_virtio_hypercall(CPUState *env, uint64_t mem, uint64_t hypercall);
+int s390_virtio_hypercall(CPUS390XState *env, uint64_t mem, uint64_t hypercall);
 
 #ifdef CONFIG_KVM
-void kvm_s390_interrupt(CPUState *env, int type, uint32_t code);
-void kvm_s390_virtio_irq(CPUState *env, int config_change, uint64_t token);
-void kvm_s390_interrupt_internal(CPUState *env, int type, uint32_t parm,
+void kvm_s390_interrupt(CPUS390XState *env, int type, uint32_t code);
+void kvm_s390_virtio_irq(CPUS390XState *env, int config_change, uint64_t token);
+void kvm_s390_interrupt_internal(CPUS390XState *env, int type, uint32_t parm,
                                  uint64_t parm64, int vm);
 #else
-static inline void kvm_s390_interrupt(CPUState *env, int type, uint32_t code)
+static inline void kvm_s390_interrupt(CPUS390XState *env, int type, uint32_t code)
 {
 }
 
-static inline void kvm_s390_virtio_irq(CPUState *env, int config_change,
+static inline void kvm_s390_virtio_irq(CPUS390XState *env, int config_change,
                                        uint64_t token)
 {
 }
 
-static inline void kvm_s390_interrupt_internal(CPUState *env, int type,
+static inline void kvm_s390_interrupt_internal(CPUS390XState *env, int type,
                                                uint32_t parm, uint64_t parm64,
                                                int vm)
 {
 }
 #endif
-CPUState *s390_cpu_addr2state(uint16_t cpu_addr);
-void s390_add_running_cpu(CPUState *env);
-unsigned s390_del_running_cpu(CPUState *env);
+CPUS390XState *s390_cpu_addr2state(uint16_t cpu_addr);
+void s390_add_running_cpu(CPUS390XState *env);
+unsigned s390_del_running_cpu(CPUS390XState *env);
 
 /* from s390-virtio-bus */
 extern const target_phys_addr_t virtio_size;
 
 #else
-static inline void s390_add_running_cpu(CPUState *env)
+static inline void s390_add_running_cpu(CPUS390XState *env)
 {
 }
 
-static inline unsigned s390_del_running_cpu(CPUState *env)
+static inline unsigned s390_del_running_cpu(CPUS390XState *env)
 {
     return 0;
 }
@@ -944,11 +944,11 @@ static inline void ebcdic_put(uint8_t *p, const char *ascii, int len)
 #define SIGP_STAT_INVALID_ORDER     0x00000002UL
 #define SIGP_STAT_RECEIVER_CHECK    0x00000001UL
 
-void load_psw(CPUState *env, uint64_t mask, uint64_t addr);
-int mmu_translate(CPUState *env, target_ulong vaddr, int rw, uint64_t asc,
+void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr);
+int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
                   target_ulong *raddr, int *flags);
-int sclp_service_call(CPUState *env, uint32_t sccb, uint64_t code);
-uint32_t calc_cc(CPUState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
+int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code);
+uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
                  uint64_t vr);
 
 #define TARGET_HAS_ICE 1
@@ -961,7 +961,7 @@ static inline uint64_t time2tod(uint64_t ns) {
     return (ns << 9) / 125;
 }
 
-static inline void cpu_inject_ext(CPUState *env, uint32_t code, uint32_t param,
+static inline void cpu_inject_ext(CPUS390XState *env, uint32_t code, uint32_t param,
                                   uint64_t param64)
 {
     if (env->ext_index == MAX_EXT_QUEUE - 1) {
@@ -980,13 +980,13 @@ static inline void cpu_inject_ext(CPUState *env, uint32_t code, uint32_t param,
     cpu_interrupt(env, CPU_INTERRUPT_HARD);
 }
 
-static inline bool cpu_has_work(CPUState *env)
+static inline bool cpu_has_work(CPUS390XState *env)
 {
     return (env->interrupt_request & CPU_INTERRUPT_HARD) &&
         (env->psw.mask & PSW_MASK_EXT);
 }
 
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock* tb)
+static inline void cpu_pc_from_tb(CPUS390XState *env, TranslationBlock* tb)
 {
     env->psw.addr = tb->pc;
 }
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 1a1cc0e..44d5048 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -53,7 +53,7 @@
 #ifndef CONFIG_USER_ONLY
 static void s390x_tod_timer(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUS390XState *env = opaque;
 
     env->pending_int |= INTERRUPT_TOD;
     cpu_interrupt(env, CPU_INTERRUPT_HARD);
@@ -61,7 +61,7 @@ static void s390x_tod_timer(void *opaque)
 
 static void s390x_cpu_timer(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUS390XState *env = opaque;
 
     env->pending_int |= INTERRUPT_CPUTIMER;
     cpu_interrupt(env, CPU_INTERRUPT_HARD);
@@ -102,12 +102,12 @@ CPUS390XState *cpu_s390x_init(const char *cpu_model)
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt (CPUState *env)
+void do_interrupt (CPUS390XState *env)
 {
     env->exception_index = -1;
 }
 
-int cpu_s390x_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
+int cpu_s390x_handle_mmu_fault (CPUS390XState *env, target_ulong address, int rw,
                                 int mmu_idx)
 {
     /* fprintf(stderr,"%s: address 0x%lx rw %d mmu_idx %d\n",
@@ -135,14 +135,14 @@ void cpu_state_reset(CPUS390XState *env)
 #ifndef CONFIG_USER_ONLY
 
 /* Ensure to exit the TB after this call! */
-static void trigger_pgm_exception(CPUState *env, uint32_t code, uint32_t ilc)
+static void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilc)
 {
     env->exception_index = EXCP_PGM;
     env->int_pgm_code = code;
     env->int_pgm_ilc = ilc;
 }
 
-static int trans_bits(CPUState *env, uint64_t mode)
+static int trans_bits(CPUS390XState *env, uint64_t mode)
 {
     int bits = 0;
 
@@ -164,7 +164,7 @@ static int trans_bits(CPUState *env, uint64_t mode)
     return bits;
 }
 
-static void trigger_prot_fault(CPUState *env, target_ulong vaddr, uint64_t mode)
+static void trigger_prot_fault(CPUS390XState *env, target_ulong vaddr, uint64_t mode)
 {
     int ilc = ILC_LATER_INC_2;
     int bits = trans_bits(env, mode) | 4;
@@ -175,7 +175,7 @@ static void trigger_prot_fault(CPUState *env, target_ulong vaddr, uint64_t mode)
     trigger_pgm_exception(env, PGM_PROTECTION, ilc);
 }
 
-static void trigger_page_fault(CPUState *env, target_ulong vaddr, uint32_t type,
+static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr, uint32_t type,
                                uint64_t asc, int rw)
 {
     int ilc = ILC_LATER;
@@ -192,7 +192,7 @@ static void trigger_page_fault(CPUState *env, target_ulong vaddr, uint32_t type,
     trigger_pgm_exception(env, type, ilc);
 }
 
-static int mmu_translate_asce(CPUState *env, target_ulong vaddr, uint64_t asc,
+static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr, uint64_t asc,
                               uint64_t asce, int level, target_ulong *raddr,
                               int *flags, int rw)
 {
@@ -274,7 +274,7 @@ static int mmu_translate_asce(CPUState *env, target_ulong vaddr, uint64_t asc,
     return 0;
 }
 
-static int mmu_translate_asc(CPUState *env, target_ulong vaddr, uint64_t asc,
+static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr, uint64_t asc,
                              target_ulong *raddr, int *flags, int rw)
 {
     uint64_t asce = 0;
@@ -343,7 +343,7 @@ static int mmu_translate_asc(CPUState *env, target_ulong vaddr, uint64_t asc,
     return r;
 }
 
-int mmu_translate(CPUState *env, target_ulong vaddr, int rw, uint64_t asc,
+int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
                   target_ulong *raddr, int *flags)
 {
     int r = -1;
@@ -404,7 +404,7 @@ out:
     return r;
 }
 
-int cpu_s390x_handle_mmu_fault (CPUState *env, target_ulong _vaddr, int rw,
+int cpu_s390x_handle_mmu_fault (CPUS390XState *env, target_ulong _vaddr, int rw,
                                 int mmu_idx)
 {
     uint64_t asc = env->psw.mask & PSW_MASK_ASC;
@@ -444,7 +444,7 @@ int cpu_s390x_handle_mmu_fault (CPUState *env, target_ulong _vaddr, int rw,
     return 0;
 }
 
-target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong vaddr)
+target_phys_addr_t cpu_get_phys_page_debug(CPUS390XState *env, target_ulong vaddr)
 {
     target_ulong raddr;
     int prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
@@ -462,7 +462,7 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong vaddr)
     return raddr;
 }
 
-void load_psw(CPUState *env, uint64_t mask, uint64_t addr)
+void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
 {
     if (mask & PSW_MASK_WAIT) {
         if (!(mask & (PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK))) {
@@ -481,7 +481,7 @@ void load_psw(CPUState *env, uint64_t mask, uint64_t addr)
     env->cc_op = (mask >> 13) & 3;
 }
 
-static uint64_t get_psw_mask(CPUState *env)
+static uint64_t get_psw_mask(CPUS390XState *env)
 {
     uint64_t r = env->psw.mask;
 
@@ -494,7 +494,7 @@ static uint64_t get_psw_mask(CPUState *env)
     return r;
 }
 
-static void do_svc_interrupt(CPUState *env)
+static void do_svc_interrupt(CPUS390XState *env)
 {
     uint64_t mask, addr;
     LowCore *lowcore;
@@ -514,7 +514,7 @@ static void do_svc_interrupt(CPUState *env)
     load_psw(env, mask, addr);
 }
 
-static void do_program_interrupt(CPUState *env)
+static void do_program_interrupt(CPUS390XState *env)
 {
     uint64_t mask, addr;
     LowCore *lowcore;
@@ -557,7 +557,7 @@ static void do_program_interrupt(CPUState *env)
 
 #define VIRTIO_SUBCODE_64 0x0D00
 
-static void do_ext_interrupt(CPUState *env)
+static void do_ext_interrupt(CPUS390XState *env)
 {
     uint64_t mask, addr;
     LowCore *lowcore;
@@ -597,7 +597,7 @@ static void do_ext_interrupt(CPUState *env)
     load_psw(env, mask, addr);
 }
 
-void do_interrupt (CPUState *env)
+void do_interrupt (CPUS390XState *env)
 {
     qemu_log("%s: %d at pc=%" PRIx64 "\n", __FUNCTION__, env->exception_index,
              env->psw.addr);
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index b1404bf..2b67231 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -72,7 +72,7 @@ int kvm_arch_init(KVMState *s)
     return 0;
 }
 
-int kvm_arch_init_vcpu(CPUState *env)
+int kvm_arch_init_vcpu(CPUS390XState *env)
 {
     int ret = 0;
 
@@ -83,12 +83,12 @@ int kvm_arch_init_vcpu(CPUState *env)
     return ret;
 }
 
-void kvm_arch_reset_vcpu(CPUState *env)
+void kvm_arch_reset_vcpu(CPUS390XState *env)
 {
     /* FIXME: add code to reset vcpu. */
 }
 
-int kvm_arch_put_registers(CPUState *env, int level)
+int kvm_arch_put_registers(CPUS390XState *env, int level)
 {
     struct kvm_regs regs;
     int ret;
@@ -114,7 +114,7 @@ int kvm_arch_put_registers(CPUState *env, int level)
     return ret;
 }
 
-int kvm_arch_get_registers(CPUState *env)
+int kvm_arch_get_registers(CPUS390XState *env)
 {
     int ret;
     struct kvm_regs regs;
@@ -135,7 +135,7 @@ int kvm_arch_get_registers(CPUState *env)
     return 0;
 }
 
-int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
+int kvm_arch_insert_sw_breakpoint(CPUS390XState *env, struct kvm_sw_breakpoint *bp)
 {
     static const uint8_t diag_501[] = {0x83, 0x24, 0x05, 0x01};
 
@@ -146,7 +146,7 @@ int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
     return 0;
 }
 
-int kvm_arch_remove_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
+int kvm_arch_remove_sw_breakpoint(CPUS390XState *env, struct kvm_sw_breakpoint *bp)
 {
     uint8_t t[4];
     static const uint8_t diag_501[] = {0x83, 0x24, 0x05, 0x01};
@@ -162,20 +162,20 @@ int kvm_arch_remove_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
     return 0;
 }
 
-void kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
+void kvm_arch_pre_run(CPUS390XState *env, struct kvm_run *run)
 {
 }
 
-void kvm_arch_post_run(CPUState *env, struct kvm_run *run)
+void kvm_arch_post_run(CPUS390XState *env, struct kvm_run *run)
 {
 }
 
-int kvm_arch_process_async_events(CPUState *env)
+int kvm_arch_process_async_events(CPUS390XState *env)
 {
     return env->halted;
 }
 
-void kvm_s390_interrupt_internal(CPUState *env, int type, uint32_t parm,
+void kvm_s390_interrupt_internal(CPUS390XState *env, int type, uint32_t parm,
                                  uint64_t parm64, int vm)
 {
     struct kvm_s390_interrupt kvmint;
@@ -201,23 +201,23 @@ void kvm_s390_interrupt_internal(CPUState *env, int type, uint32_t parm,
     }
 }
 
-void kvm_s390_virtio_irq(CPUState *env, int config_change, uint64_t token)
+void kvm_s390_virtio_irq(CPUS390XState *env, int config_change, uint64_t token)
 {
     kvm_s390_interrupt_internal(env, KVM_S390_INT_VIRTIO, config_change,
                                 token, 1);
 }
 
-void kvm_s390_interrupt(CPUState *env, int type, uint32_t code)
+void kvm_s390_interrupt(CPUS390XState *env, int type, uint32_t code)
 {
     kvm_s390_interrupt_internal(env, type, code, 0, 0);
 }
 
-static void enter_pgmcheck(CPUState *env, uint16_t code)
+static void enter_pgmcheck(CPUS390XState *env, uint16_t code)
 {
     kvm_s390_interrupt(env, KVM_S390_PROGRAM_INT, code);
 }
 
-static inline void setcc(CPUState *env, uint64_t cc)
+static inline void setcc(CPUS390XState *env, uint64_t cc)
 {
     env->kvm_run->psw_mask &= ~(3ull << 44);
     env->kvm_run->psw_mask |= (cc & 3) << 44;
@@ -226,7 +226,7 @@ static inline void setcc(CPUState *env, uint64_t cc)
     env->psw.mask |= (cc & 3) << 44;
 }
 
-static int kvm_sclp_service_call(CPUState *env, struct kvm_run *run,
+static int kvm_sclp_service_call(CPUS390XState *env, struct kvm_run *run,
                                  uint16_t ipbh0)
 {
     uint32_t sccb;
@@ -245,7 +245,7 @@ static int kvm_sclp_service_call(CPUState *env, struct kvm_run *run,
     return 0;
 }
 
-static int handle_priv(CPUState *env, struct kvm_run *run, uint8_t ipa1)
+static int handle_priv(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1)
 {
     int r = 0;
     uint16_t ipbh0 = (run->s390_sieic.ipb & 0xffff0000) >> 16;
@@ -264,7 +264,7 @@ static int handle_priv(CPUState *env, struct kvm_run *run, uint8_t ipa1)
     return r;
 }
 
-static int handle_hypercall(CPUState *env, struct kvm_run *run)
+static int handle_hypercall(CPUS390XState *env, struct kvm_run *run)
 {
     cpu_synchronize_state(env);
     env->regs[2] = s390_virtio_hypercall(env, env->regs[2], env->regs[1]);
@@ -272,7 +272,7 @@ static int handle_hypercall(CPUState *env, struct kvm_run *run)
     return 0;
 }
 
-static int handle_diag(CPUState *env, struct kvm_run *run, int ipb_code)
+static int handle_diag(CPUS390XState *env, struct kvm_run *run, int ipb_code)
 {
     int r = 0;
 
@@ -292,7 +292,7 @@ static int handle_diag(CPUState *env, struct kvm_run *run, int ipb_code)
     return r;
 }
 
-static int s390_cpu_restart(CPUState *env)
+static int s390_cpu_restart(CPUS390XState *env)
 {
     kvm_s390_interrupt(env, KVM_S390_RESTART, 0);
     s390_add_running_cpu(env);
@@ -301,14 +301,14 @@ static int s390_cpu_restart(CPUState *env)
     return 0;
 }
 
-static int s390_store_status(CPUState *env, uint32_t parameter)
+static int s390_store_status(CPUS390XState *env, uint32_t parameter)
 {
     /* XXX */
     fprintf(stderr, "XXX SIGP store status\n");
     return -1;
 }
 
-static int s390_cpu_initial_reset(CPUState *env)
+static int s390_cpu_initial_reset(CPUS390XState *env)
 {
     int i;
 
@@ -326,14 +326,14 @@ static int s390_cpu_initial_reset(CPUState *env)
     return 0;
 }
 
-static int handle_sigp(CPUState *env, struct kvm_run *run, uint8_t ipa1)
+static int handle_sigp(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1)
 {
     uint8_t order_code;
     uint32_t parameter;
     uint16_t cpu_addr;
     uint8_t t;
     int r = -1;
-    CPUState *target_env;
+    CPUS390XState *target_env;
 
     cpu_synchronize_state(env);
 
@@ -381,7 +381,7 @@ out:
     return 0;
 }
 
-static int handle_instruction(CPUState *env, struct kvm_run *run)
+static int handle_instruction(CPUS390XState *env, struct kvm_run *run)
 {
     unsigned int ipa0 = (run->s390_sieic.ipa & 0xff00);
     uint8_t ipa1 = run->s390_sieic.ipa & 0x00ff;
@@ -407,7 +407,7 @@ static int handle_instruction(CPUState *env, struct kvm_run *run)
     return 0;
 }
 
-static int handle_intercept(CPUState *env)
+static int handle_intercept(CPUS390XState *env)
 {
     struct kvm_run *run = env->kvm_run;
     int icpt_code = run->s390_sieic.icptcode;
@@ -443,7 +443,7 @@ static int handle_intercept(CPUState *env)
     return r;
 }
 
-int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
+int kvm_arch_handle_exit(CPUS390XState *env, struct kvm_run *run)
 {
     int ret = 0;
 
@@ -466,12 +466,12 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
     return ret;
 }
 
-bool kvm_arch_stop_on_emulation_error(CPUState *env)
+bool kvm_arch_stop_on_emulation_error(CPUS390XState *env)
 {
     return true;
 }
 
-int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr)
+int kvm_arch_on_sigbus_vcpu(CPUS390XState *env, int code, void *addr)
 {
     return 1;
 }
diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index 70d98a8..18fdbb2 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -56,11 +56,11 @@
    NULL, it means that the function was called in C code (i.e. not
    from generated code or from helper.c) */
 /* XXX: fix it to restore all registers */
-void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
+void tlb_fill(CPUS390XState *env1, target_ulong addr, int is_write, int mmu_idx,
               void *retaddr)
 {
     TranslationBlock *tb;
-    CPUState *saved_env;
+    CPUS390XState *saved_env;
     unsigned long pc;
     int ret;
 
@@ -101,7 +101,7 @@ void HELPER(exception)(uint32_t excp)
 }
 
 #ifndef CONFIG_USER_ONLY
-static void mvc_fast_memset(CPUState *env, uint32_t l, uint64_t dest,
+static void mvc_fast_memset(CPUS390XState *env, uint32_t l, uint64_t dest,
                             uint8_t byte)
 {
     target_phys_addr_t dest_phys;
@@ -123,7 +123,7 @@ static void mvc_fast_memset(CPUState *env, uint32_t l, uint64_t dest,
     cpu_physical_memory_unmap(dest_p, 1, len, len);
 }
 
-static void mvc_fast_memmove(CPUState *env, uint32_t l, uint64_t dest,
+static void mvc_fast_memmove(CPUS390XState *env, uint32_t l, uint64_t dest,
                              uint64_t src)
 {
     target_phys_addr_t dest_phys;
@@ -1790,7 +1790,7 @@ void HELPER(cksm)(uint32_t r1, uint32_t r2)
                     ((uint32_t)cksm + (cksm >> 32));
 }
 
-static inline uint32_t cc_calc_ltgt_32(CPUState *env, int32_t src,
+static inline uint32_t cc_calc_ltgt_32(CPUS390XState *env, int32_t src,
                                        int32_t dst)
 {
     if (src == dst) {
@@ -1802,12 +1802,12 @@ static inline uint32_t cc_calc_ltgt_32(CPUState *env, int32_t src,
     }
 }
 
-static inline uint32_t cc_calc_ltgt0_32(CPUState *env, int32_t dst)
+static inline uint32_t cc_calc_ltgt0_32(CPUS390XState *env, int32_t dst)
 {
     return cc_calc_ltgt_32(env, dst, 0);
 }
 
-static inline uint32_t cc_calc_ltgt_64(CPUState *env, int64_t src,
+static inline uint32_t cc_calc_ltgt_64(CPUS390XState *env, int64_t src,
                                        int64_t dst)
 {
     if (src == dst) {
@@ -1819,12 +1819,12 @@ static inline uint32_t cc_calc_ltgt_64(CPUState *env, int64_t src,
     }
 }
 
-static inline uint32_t cc_calc_ltgt0_64(CPUState *env, int64_t dst)
+static inline uint32_t cc_calc_ltgt0_64(CPUS390XState *env, int64_t dst)
 {
     return cc_calc_ltgt_64(env, dst, 0);
 }
 
-static inline uint32_t cc_calc_ltugtu_32(CPUState *env, uint32_t src,
+static inline uint32_t cc_calc_ltugtu_32(CPUS390XState *env, uint32_t src,
                                          uint32_t dst)
 {
     if (src == dst) {
@@ -1836,7 +1836,7 @@ static inline uint32_t cc_calc_ltugtu_32(CPUState *env, uint32_t src,
     }
 }
 
-static inline uint32_t cc_calc_ltugtu_64(CPUState *env, uint64_t src,
+static inline uint32_t cc_calc_ltugtu_64(CPUS390XState *env, uint64_t src,
                                          uint64_t dst)
 {
     if (src == dst) {
@@ -1848,7 +1848,7 @@ static inline uint32_t cc_calc_ltugtu_64(CPUState *env, uint64_t src,
     }
 }
 
-static inline uint32_t cc_calc_tm_32(CPUState *env, uint32_t val, uint32_t mask)
+static inline uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val, uint32_t mask)
 {
     HELPER_LOG("%s: val 0x%x mask 0x%x\n", __FUNCTION__, val, mask);
     uint16_t r = val & mask;
@@ -1862,7 +1862,7 @@ static inline uint32_t cc_calc_tm_32(CPUState *env, uint32_t val, uint32_t mask)
 }
 
 /* set condition code for test under mask */
-static inline uint32_t cc_calc_tm_64(CPUState *env, uint64_t val, uint32_t mask)
+static inline uint32_t cc_calc_tm_64(CPUS390XState *env, uint64_t val, uint32_t mask)
 {
     uint16_t r = val & mask;
     HELPER_LOG("%s: val 0x%lx mask 0x%x r 0x%x\n", __FUNCTION__, val, mask, r);
@@ -1883,12 +1883,12 @@ static inline uint32_t cc_calc_tm_64(CPUState *env, uint64_t val, uint32_t mask)
     }
 }
 
-static inline uint32_t cc_calc_nz(CPUState *env, uint64_t dst)
+static inline uint32_t cc_calc_nz(CPUS390XState *env, uint64_t dst)
 {
     return !!dst;
 }
 
-static inline uint32_t cc_calc_add_64(CPUState *env, int64_t a1, int64_t a2,
+static inline uint32_t cc_calc_add_64(CPUS390XState *env, int64_t a1, int64_t a2,
                                       int64_t ar)
 {
     if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
@@ -1904,7 +1904,7 @@ static inline uint32_t cc_calc_add_64(CPUState *env, int64_t a1, int64_t a2,
     }
 }
 
-static inline uint32_t cc_calc_addu_64(CPUState *env, uint64_t a1, uint64_t a2,
+static inline uint32_t cc_calc_addu_64(CPUS390XState *env, uint64_t a1, uint64_t a2,
                                        uint64_t ar)
 {
     if (ar == 0) {
@@ -1922,7 +1922,7 @@ static inline uint32_t cc_calc_addu_64(CPUState *env, uint64_t a1, uint64_t a2,
     }
 }
 
-static inline uint32_t cc_calc_sub_64(CPUState *env, int64_t a1, int64_t a2,
+static inline uint32_t cc_calc_sub_64(CPUS390XState *env, int64_t a1, int64_t a2,
                                       int64_t ar)
 {
     if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
@@ -1938,7 +1938,7 @@ static inline uint32_t cc_calc_sub_64(CPUState *env, int64_t a1, int64_t a2,
     }
 }
 
-static inline uint32_t cc_calc_subu_64(CPUState *env, uint64_t a1, uint64_t a2,
+static inline uint32_t cc_calc_subu_64(CPUS390XState *env, uint64_t a1, uint64_t a2,
                                        uint64_t ar)
 {
     if (ar == 0) {
@@ -1952,7 +1952,7 @@ static inline uint32_t cc_calc_subu_64(CPUState *env, uint64_t a1, uint64_t a2,
     }
 }
 
-static inline uint32_t cc_calc_abs_64(CPUState *env, int64_t dst)
+static inline uint32_t cc_calc_abs_64(CPUS390XState *env, int64_t dst)
 {
     if ((uint64_t)dst == 0x8000000000000000ULL) {
         return 3;
@@ -1963,12 +1963,12 @@ static inline uint32_t cc_calc_abs_64(CPUState *env, int64_t dst)
     }
 }
 
-static inline uint32_t cc_calc_nabs_64(CPUState *env, int64_t dst)
+static inline uint32_t cc_calc_nabs_64(CPUS390XState *env, int64_t dst)
 {
     return !!dst;
 }
 
-static inline uint32_t cc_calc_comp_64(CPUState *env, int64_t dst)
+static inline uint32_t cc_calc_comp_64(CPUS390XState *env, int64_t dst)
 {
     if ((uint64_t)dst == 0x8000000000000000ULL) {
         return 3;
@@ -1982,7 +1982,7 @@ static inline uint32_t cc_calc_comp_64(CPUState *env, int64_t dst)
 }
 
 
-static inline uint32_t cc_calc_add_32(CPUState *env, int32_t a1, int32_t a2,
+static inline uint32_t cc_calc_add_32(CPUS390XState *env, int32_t a1, int32_t a2,
                                       int32_t ar)
 {
     if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
@@ -1998,7 +1998,7 @@ static inline uint32_t cc_calc_add_32(CPUState *env, int32_t a1, int32_t a2,
     }
 }
 
-static inline uint32_t cc_calc_addu_32(CPUState *env, uint32_t a1, uint32_t a2,
+static inline uint32_t cc_calc_addu_32(CPUS390XState *env, uint32_t a1, uint32_t a2,
                                        uint32_t ar)
 {
     if (ar == 0) {
@@ -2016,7 +2016,7 @@ static inline uint32_t cc_calc_addu_32(CPUState *env, uint32_t a1, uint32_t a2,
     }
 }
 
-static inline uint32_t cc_calc_sub_32(CPUState *env, int32_t a1, int32_t a2,
+static inline uint32_t cc_calc_sub_32(CPUS390XState *env, int32_t a1, int32_t a2,
                                       int32_t ar)
 {
     if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
@@ -2032,7 +2032,7 @@ static inline uint32_t cc_calc_sub_32(CPUState *env, int32_t a1, int32_t a2,
     }
 }
 
-static inline uint32_t cc_calc_subu_32(CPUState *env, uint32_t a1, uint32_t a2,
+static inline uint32_t cc_calc_subu_32(CPUS390XState *env, uint32_t a1, uint32_t a2,
                                        uint32_t ar)
 {
     if (ar == 0) {
@@ -2046,7 +2046,7 @@ static inline uint32_t cc_calc_subu_32(CPUState *env, uint32_t a1, uint32_t a2,
     }
 }
 
-static inline uint32_t cc_calc_abs_32(CPUState *env, int32_t dst)
+static inline uint32_t cc_calc_abs_32(CPUS390XState *env, int32_t dst)
 {
     if ((uint32_t)dst == 0x80000000UL) {
         return 3;
@@ -2057,12 +2057,12 @@ static inline uint32_t cc_calc_abs_32(CPUState *env, int32_t dst)
     }
 }
 
-static inline uint32_t cc_calc_nabs_32(CPUState *env, int32_t dst)
+static inline uint32_t cc_calc_nabs_32(CPUS390XState *env, int32_t dst)
 {
     return !!dst;
 }
 
-static inline uint32_t cc_calc_comp_32(CPUState *env, int32_t dst)
+static inline uint32_t cc_calc_comp_32(CPUS390XState *env, int32_t dst)
 {
     if ((uint32_t)dst == 0x80000000UL) {
         return 3;
@@ -2076,7 +2076,7 @@ static inline uint32_t cc_calc_comp_32(CPUState *env, int32_t dst)
 }
 
 /* calculate condition code for insert character under mask insn */
-static inline uint32_t cc_calc_icm_32(CPUState *env, uint32_t mask, uint32_t val)
+static inline uint32_t cc_calc_icm_32(CPUS390XState *env, uint32_t mask, uint32_t val)
 {
     HELPER_LOG("%s: mask 0x%x val %d\n", __FUNCTION__, mask, val);
     uint32_t cc;
@@ -2107,7 +2107,7 @@ static inline uint32_t cc_calc_icm_32(CPUState *env, uint32_t mask, uint32_t val
     return cc;
 }
 
-static inline uint32_t cc_calc_slag(CPUState *env, uint64_t src, uint64_t shift)
+static inline uint32_t cc_calc_slag(CPUS390XState *env, uint64_t src, uint64_t shift)
 {
     uint64_t mask = ((1ULL << shift) - 1ULL) << (64 - shift);
     uint64_t match, r;
@@ -2136,7 +2136,7 @@ static inline uint32_t cc_calc_slag(CPUState *env, uint64_t src, uint64_t shift)
 }
 
 
-static inline uint32_t do_calc_cc(CPUState *env, uint32_t cc_op, uint64_t src,
+static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src,
                                   uint64_t dst, uint64_t vr)
 {
     uint32_t r = 0;
@@ -2249,7 +2249,7 @@ static inline uint32_t do_calc_cc(CPUState *env, uint32_t cc_op, uint64_t src,
     return r;
 }
 
-uint32_t calc_cc(CPUState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
+uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
                  uint64_t vr)
 {
     return do_calc_cc(env, cc_op, src, dst, vr);
@@ -2346,7 +2346,7 @@ void HELPER(load_psw)(uint64_t mask, uint64_t addr)
     cpu_loop_exit(env);
 }
 
-static void program_interrupt(CPUState *env, uint32_t code, int ilc)
+static void program_interrupt(CPUS390XState *env, uint32_t code, int ilc)
 {
     qemu_log("program interrupt at %#" PRIx64 "\n", env->psw.addr);
 
@@ -2362,13 +2362,13 @@ static void program_interrupt(CPUState *env, uint32_t code, int ilc)
     }
 }
 
-static void ext_interrupt(CPUState *env, int type, uint32_t param,
+static void ext_interrupt(CPUS390XState *env, int type, uint32_t param,
                           uint64_t param64)
 {
     cpu_inject_ext(env, type, param, param64);
 }
 
-int sclp_service_call(CPUState *env, uint32_t sccb, uint64_t code)
+int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code)
 {
     int r = 0;
     int shift = 0;
@@ -2481,7 +2481,7 @@ uint32_t HELPER(sck)(uint64_t a1)
     return 0;
 }
 
-static inline uint64_t clock_value(CPUState *env)
+static inline uint64_t clock_value(CPUS390XState *env)
 {
     uint64_t time;
 
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 8fab38c..9bf8c38 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -74,7 +74,7 @@ static inline uint64_t pc_to_link_info(DisasContext *s, uint64_t pc)
     return pc;
 }
 
-void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
+void cpu_dump_state(CPUS390XState *env, FILE *f, fprintf_function cpu_fprintf,
                     int flags)
 {
     int i;
@@ -148,25 +148,25 @@ void s390x_translate_init(void)
     char *p;
 
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
-    psw_addr = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUState, psw.addr),
+    psw_addr = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, psw.addr),
                                       "psw_addr");
-    psw_mask = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUState, psw.mask),
+    psw_mask = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, psw.mask),
                                       "psw_mask");
 
-    cc_op = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, cc_op),
+    cc_op = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUS390XState, cc_op),
                                    "cc_op");
-    cc_src = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUState, cc_src),
+    cc_src = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, cc_src),
                                     "cc_src");
-    cc_dst = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUState, cc_dst),
+    cc_dst = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, cc_dst),
                                     "cc_dst");
-    cc_vr = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUState, cc_vr),
+    cc_vr = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, cc_vr),
                                    "cc_vr");
 
     p = cpu_reg_names;
     for (i = 0; i < 16; i++) {
         snprintf(p, cpu_reg_names_size, "r%d", i);
         regs[i] = tcg_global_mem_new(TCG_AREG0,
-                                     offsetof(CPUState, regs[i]), p);
+                                     offsetof(CPUS390XState, regs[i]), p);
         p += (i < 10) ? 3 : 4;
         cpu_reg_names_size -= (i < 10) ? 3 : 4;
     }
@@ -182,14 +182,14 @@ static inline TCGv_i64 load_reg(int reg)
 static inline TCGv_i64 load_freg(int reg)
 {
     TCGv_i64 r = tcg_temp_new_i64();
-    tcg_gen_ld_i64(r, cpu_env, offsetof(CPUState, fregs[reg].d));
+    tcg_gen_ld_i64(r, cpu_env, offsetof(CPUS390XState, fregs[reg].d));
     return r;
 }
 
 static inline TCGv_i32 load_freg32(int reg)
 {
     TCGv_i32 r = tcg_temp_new_i32();
-    tcg_gen_ld_i32(r, cpu_env, offsetof(CPUState, fregs[reg].l.upper));
+    tcg_gen_ld_i32(r, cpu_env, offsetof(CPUS390XState, fregs[reg].l.upper));
     return r;
 }
 
@@ -214,7 +214,7 @@ static inline void store_reg(int reg, TCGv_i64 v)
 
 static inline void store_freg(int reg, TCGv_i64 v)
 {
-    tcg_gen_st_i64(v, cpu_env, offsetof(CPUState, fregs[reg].d));
+    tcg_gen_st_i64(v, cpu_env, offsetof(CPUS390XState, fregs[reg].d));
 }
 
 static inline void store_reg32(int reg, TCGv_i32 v)
@@ -257,7 +257,7 @@ static inline void store_reg8(int reg, TCGv_i64 v)
 
 static inline void store_freg32(int reg, TCGv_i32 v)
 {
-    tcg_gen_st_i32(v, cpu_env, offsetof(CPUState, fregs[reg].l.upper));
+    tcg_gen_st_i32(v, cpu_env, offsetof(CPUS390XState, fregs[reg].l.upper));
 }
 
 static inline void update_psw_addr(DisasContext *s)
@@ -361,11 +361,11 @@ static void gen_program_exception(DisasContext *s, int ilc, int code)
 
     /* remember what pgm exeption this was */
     tmp = tcg_const_i32(code);
-    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, int_pgm_code));
+    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_code));
     tcg_temp_free_i32(tmp);
 
     tmp = tcg_const_i32(ilc);
-    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, int_pgm_ilc));
+    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_ilc));
     tcg_temp_free_i32(tmp);
 
     /* advance past instruction */
@@ -2647,12 +2647,12 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         break;
     case 0x4e: /* SAR     R1,R2     [RRE] */
         tmp32_1 = load_reg32(r2);
-        tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUState, aregs[r1]));
+        tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, aregs[r1]));
         tcg_temp_free_i32(tmp32_1);
         break;
     case 0x4f: /* EAR     R1,R2     [RRE] */
         tmp32_1 = tcg_temp_new_i32();
-        tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUState, aregs[r2]));
+        tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, aregs[r2]));
         store_reg32(r1, tmp32_1);
         tcg_temp_free_i32(tmp32_1);
         break;
@@ -2807,7 +2807,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
         tmp2 = tcg_temp_new_i64();
-        tcg_gen_ld_i64(tmp2, cpu_env, offsetof(CPUState, psa));
+        tcg_gen_ld_i64(tmp2, cpu_env, offsetof(CPUS390XState, psa));
         tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i64(tmp2);
@@ -2819,7 +2819,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         tmp = get_address(s, 0, b2, d2);
         tmp2 = tcg_temp_new_i64();
         tmp32_1 = tcg_temp_new_i32();
-        tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUState, cpu_num));
+        tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, cpu_num));
         tcg_gen_extu_i32_i64(tmp2, tmp32_1);
         tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
         tcg_temp_free_i64(tmp);
@@ -2948,7 +2948,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         tmp32_1 = tcg_temp_new_i32();
         tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
         tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
-        tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUState, fpc));
+        tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i64(tmp2);
         tcg_temp_free_i32(tmp32_1);
@@ -3158,12 +3158,12 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
         break;
     case 0x84: /* SFPC        R1                [RRE] */
         tmp32_1 = load_reg32(r1);
-        tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUState, fpc));
+        tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
         tcg_temp_free_i32(tmp32_1);
         break;
     case 0x8c: /* EFPC        R1                [RRE] */
         tmp32_1 = tcg_temp_new_i32();
-        tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUState, fpc));
+        tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
         store_reg32(r1, tmp32_1);
         tcg_temp_free_i32(tmp32_1);
         break;
@@ -3929,8 +3929,8 @@ static void disas_s390_insn(DisasContext *s)
         tmp32_1 = tcg_const_i32(i);
         tmp32_2 = tcg_const_i32(ilc * 2);
         tmp32_3 = tcg_const_i32(EXCP_SVC);
-        tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUState, int_svc_code));
-        tcg_gen_st_i32(tmp32_2, cpu_env, offsetof(CPUState, int_svc_ilc));
+        tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, int_svc_code));
+        tcg_gen_st_i32(tmp32_2, cpu_env, offsetof(CPUS390XState, int_svc_ilc));
         gen_helper_exception(tmp32_3);
         s->is_jmp = DISAS_EXCP;
         tcg_temp_free_i32(tmp32_1);
@@ -4810,7 +4810,7 @@ static void disas_s390_insn(DisasContext *s)
             tmp32_1 = tcg_temp_new_i32();
             tmp = tcg_temp_new_i64();
             tmp2 = get_address(s, 0, b2, d2);
-            tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUState, fpc));
+            tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
             tcg_gen_extu_i32_i64(tmp, tmp32_1);
             tcg_gen_qemu_st32(tmp, tmp2, get_mem_index(s));
             tcg_temp_free_i32(tmp32_1);
@@ -5107,7 +5107,7 @@ static void disas_s390_insn(DisasContext *s)
     s->pc += (ilc * 2);
 }
 
-static inline void gen_intermediate_code_internal(CPUState *env,
+static inline void gen_intermediate_code_internal(CPUS390XState *env,
                                                   TranslationBlock *tb,
                                                   int search_pc)
 {
@@ -5223,17 +5223,17 @@ static inline void gen_intermediate_code_internal(CPUState *env,
 #endif
 }
 
-void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
+void gen_intermediate_code (CPUS390XState *env, struct TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 0);
 }
 
-void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
+void gen_intermediate_code_pc (CPUS390XState *env, struct TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 1);
 }
 
-void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUS390XState *env, TranslationBlock *tb, int pc_pos)
 {
     int cc_op;
     env->psw.addr = gen_opc_pc[pc_pos];
commit 1328c2bf21c67d6d4c11421e0ab707cb6ff42f4a
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:22 2012 +0100

    target-ppc: Don't overuse CPUState
    
    Scripted conversion:
      sed -i "s/CPUState/CPUPPCState/g" target-ppc/*.[hc]
      sed -i "s/#define CPUPPCState/#define CPUState/" target-ppc/cpu.h
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index ac753f3..3508d8a 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1173,12 +1173,12 @@ void store_40x_dbcr0 (CPUPPCState *env, uint32_t val);
 void store_40x_sler (CPUPPCState *env, uint32_t val);
 void store_booke_tcr (CPUPPCState *env, target_ulong val);
 void store_booke_tsr (CPUPPCState *env, target_ulong val);
-void booke206_flush_tlb(CPUState *env, int flags, const int check_iprot);
-target_phys_addr_t booke206_tlb_to_page_size(CPUState *env, ppcmas_tlb_t *tlb);
-int ppcemb_tlb_check(CPUState *env, ppcemb_tlb_t *tlb,
+void booke206_flush_tlb(CPUPPCState *env, int flags, const int check_iprot);
+target_phys_addr_t booke206_tlb_to_page_size(CPUPPCState *env, ppcmas_tlb_t *tlb);
+int ppcemb_tlb_check(CPUPPCState *env, ppcemb_tlb_t *tlb,
                      target_phys_addr_t *raddrp, target_ulong address,
                      uint32_t pid, int ext, int i);
-int ppcmas_tlb_check(CPUState *env, ppcmas_tlb_t *tlb,
+int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
                      target_phys_addr_t *raddrp, target_ulong address,
                      uint32_t pid);
 void ppc_tlb_invalidate_all (CPUPPCState *env);
@@ -1226,13 +1226,13 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val);
 #define MMU_MODE1_SUFFIX _kernel
 #define MMU_MODE2_SUFFIX _hypv
 #define MMU_USER_IDX 0
-static inline int cpu_mmu_index (CPUState *env)
+static inline int cpu_mmu_index (CPUPPCState *env)
 {
     return env->mmu_idx;
 }
 
 #if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
+static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp)
 {
     if (newsp)
         env->gpr[1] = newsp;
@@ -2056,7 +2056,7 @@ enum {
 
 /*****************************************************************************/
 
-static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+static inline void cpu_get_tb_cpu_state(CPUPPCState *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
     *pc = env->nip;
@@ -2064,7 +2064,7 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
     *flags = env->hflags;
 }
 
-static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
+static inline void cpu_set_tls(CPUPPCState *env, target_ulong newtls)
 {
 #if defined(TARGET_PPC64)
     /* The kernel checks TIF_32BIT here; we don't support loading 32-bit
@@ -2076,7 +2076,7 @@ static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
 }
 
 #if !defined(CONFIG_USER_ONLY)
-static inline int booke206_tlbm_id(CPUState *env, ppcmas_tlb_t *tlbm)
+static inline int booke206_tlbm_id(CPUPPCState *env, ppcmas_tlb_t *tlbm)
 {
     uintptr_t tlbml = (uintptr_t)tlbm;
     uintptr_t tlbl = (uintptr_t)env->tlb.tlbm;
@@ -2084,21 +2084,21 @@ static inline int booke206_tlbm_id(CPUState *env, ppcmas_tlb_t *tlbm)
     return (tlbml - tlbl) / sizeof(env->tlb.tlbm[0]);
 }
 
-static inline int booke206_tlb_size(CPUState *env, int tlbn)
+static inline int booke206_tlb_size(CPUPPCState *env, int tlbn)
 {
     uint32_t tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
     int r = tlbncfg & TLBnCFG_N_ENTRY;
     return r;
 }
 
-static inline int booke206_tlb_ways(CPUState *env, int tlbn)
+static inline int booke206_tlb_ways(CPUPPCState *env, int tlbn)
 {
     uint32_t tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
     int r = tlbncfg >> TLBnCFG_ASSOC_SHIFT;
     return r;
 }
 
-static inline int booke206_tlbm_to_tlbn(CPUState *env, ppcmas_tlb_t *tlbm)
+static inline int booke206_tlbm_to_tlbn(CPUPPCState *env, ppcmas_tlb_t *tlbm)
 {
     int id = booke206_tlbm_id(env, tlbm);
     int end = 0;
@@ -2115,14 +2115,14 @@ static inline int booke206_tlbm_to_tlbn(CPUState *env, ppcmas_tlb_t *tlbm)
     return 0;
 }
 
-static inline int booke206_tlbm_to_way(CPUState *env, ppcmas_tlb_t *tlb)
+static inline int booke206_tlbm_to_way(CPUPPCState *env, ppcmas_tlb_t *tlb)
 {
     int tlbn = booke206_tlbm_to_tlbn(env, tlb);
     int tlbid = booke206_tlbm_id(env, tlb);
     return tlbid & (booke206_tlb_ways(env, tlbn) - 1);
 }
 
-static inline ppcmas_tlb_t *booke206_get_tlbm(CPUState *env, const int tlbn,
+static inline ppcmas_tlb_t *booke206_get_tlbm(CPUPPCState *env, const int tlbn,
                                               target_ulong ea, int way)
 {
     int r;
@@ -2149,7 +2149,7 @@ static inline ppcmas_tlb_t *booke206_get_tlbm(CPUState *env, const int tlbn,
 }
 
 /* returns bitmap of supported page sizes for a given TLB */
-static inline uint32_t booke206_tlbnps(CPUState *env, const int tlbn)
+static inline uint32_t booke206_tlbnps(CPUPPCState *env, const int tlbn)
 {
     bool mav2 = false;
     uint32_t ret = 0;
@@ -2171,20 +2171,20 @@ static inline uint32_t booke206_tlbnps(CPUState *env, const int tlbn)
 
 #endif
 
-extern void (*cpu_ppc_hypercall)(CPUState *);
+extern void (*cpu_ppc_hypercall)(CPUPPCState *);
 
-static inline bool cpu_has_work(CPUState *env)
+static inline bool cpu_has_work(CPUPPCState *env)
 {
     return msr_ee && (env->interrupt_request & CPU_INTERRUPT_HARD);
 }
 
 #include "exec-all.h"
 
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+static inline void cpu_pc_from_tb(CPUPPCState *env, TranslationBlock *tb)
 {
     env->nip = tb->pc;
 }
 
-void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env);
+void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env);
 
 #endif /* !defined (__CPU_PPC_H__) */
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index f4552e8..bd711b6 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -67,13 +67,13 @@
 /*****************************************************************************/
 /* PowerPC Hypercall emulation */
 
-void (*cpu_ppc_hypercall)(CPUState *);
+void (*cpu_ppc_hypercall)(CPUPPCState *);
 
 /*****************************************************************************/
 /* PowerPC MMU emulation */
 
 #if defined(CONFIG_USER_ONLY)
-int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
+int cpu_ppc_handle_mmu_fault (CPUPPCState *env, target_ulong address, int rw,
                               int mmu_idx)
 {
     int exception, error_code;
@@ -291,7 +291,7 @@ static inline int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
 }
 
 /* Software driven TLB helpers */
-static inline int ppc6xx_tlb_getnum(CPUState *env, target_ulong eaddr, int way,
+static inline int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr, int way,
                                     int is_code)
 {
     int nr;
@@ -307,7 +307,7 @@ static inline int ppc6xx_tlb_getnum(CPUState *env, target_ulong eaddr, int way,
     return nr;
 }
 
-static inline void ppc6xx_tlb_invalidate_all(CPUState *env)
+static inline void ppc6xx_tlb_invalidate_all(CPUPPCState *env)
 {
     ppc6xx_tlb_t *tlb;
     int nr, max;
@@ -324,7 +324,7 @@ static inline void ppc6xx_tlb_invalidate_all(CPUState *env)
     tlb_flush(env, 1);
 }
 
-static inline void __ppc6xx_tlb_invalidate_virt(CPUState *env,
+static inline void __ppc6xx_tlb_invalidate_virt(CPUPPCState *env,
                                                 target_ulong eaddr,
                                                 int is_code, int match_epn)
 {
@@ -349,13 +349,13 @@ static inline void __ppc6xx_tlb_invalidate_virt(CPUState *env,
 #endif
 }
 
-static inline void ppc6xx_tlb_invalidate_virt(CPUState *env,
+static inline void ppc6xx_tlb_invalidate_virt(CPUPPCState *env,
                                               target_ulong eaddr, int is_code)
 {
     __ppc6xx_tlb_invalidate_virt(env, eaddr, is_code, 0);
 }
 
-void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
+void ppc6xx_tlb_store (CPUPPCState *env, target_ulong EPN, int way, int is_code,
                        target_ulong pte0, target_ulong pte1)
 {
     ppc6xx_tlb_t *tlb;
@@ -374,7 +374,7 @@ void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
     env->last_way = way;
 }
 
-static inline int ppc6xx_tlb_check(CPUState *env, mmu_ctx_t *ctx,
+static inline int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t *ctx,
                                    target_ulong eaddr, int rw, int access_type)
 {
     ppc6xx_tlb_t *tlb;
@@ -436,7 +436,7 @@ static inline int ppc6xx_tlb_check(CPUState *env, mmu_ctx_t *ctx,
 }
 
 /* Perform BAT hit & translation */
-static inline void bat_size_prot(CPUState *env, target_ulong *blp, int *validp,
+static inline void bat_size_prot(CPUPPCState *env, target_ulong *blp, int *validp,
                                  int *protp, target_ulong *BATu,
                                  target_ulong *BATl)
 {
@@ -461,7 +461,7 @@ static inline void bat_size_prot(CPUState *env, target_ulong *blp, int *validp,
     *protp = prot;
 }
 
-static inline void bat_601_size_prot(CPUState *env, target_ulong *blp,
+static inline void bat_601_size_prot(CPUPPCState *env, target_ulong *blp,
                                      int *validp, int *protp,
                                      target_ulong *BATu, target_ulong *BATl)
 {
@@ -486,7 +486,7 @@ static inline void bat_601_size_prot(CPUState *env, target_ulong *blp,
     *protp = prot;
 }
 
-static inline int get_bat(CPUState *env, mmu_ctx_t *ctx, target_ulong virtual,
+static inline int get_bat(CPUPPCState *env, mmu_ctx_t *ctx, target_ulong virtual,
                           int rw, int type)
 {
     target_ulong *BATlt, *BATut, *BATu, *BATl;
@@ -561,7 +561,7 @@ static inline int get_bat(CPUState *env, mmu_ctx_t *ctx, target_ulong virtual,
     return ret;
 }
 
-static inline target_phys_addr_t get_pteg_offset(CPUState *env,
+static inline target_phys_addr_t get_pteg_offset(CPUPPCState *env,
                                                  target_phys_addr_t hash,
                                                  int pte_size)
 {
@@ -569,7 +569,7 @@ static inline target_phys_addr_t get_pteg_offset(CPUState *env,
 }
 
 /* PTE table lookup */
-static inline int _find_pte(CPUState *env, mmu_ctx_t *ctx, int is_64b, int h,
+static inline int _find_pte(CPUPPCState *env, mmu_ctx_t *ctx, int is_64b, int h,
                             int rw, int type, int target_page_bits)
 {
     target_phys_addr_t pteg_off;
@@ -675,7 +675,7 @@ static inline int _find_pte(CPUState *env, mmu_ctx_t *ctx, int is_64b, int h,
     return ret;
 }
 
-static inline int find_pte(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
+static inline int find_pte(CPUPPCState *env, mmu_ctx_t *ctx, int h, int rw,
                            int type, int target_page_bits)
 {
 #if defined(TARGET_PPC64)
@@ -812,7 +812,7 @@ int ppc_load_slb_vsid (CPUPPCState *env, target_ulong rb, target_ulong *rt)
 #endif /* defined(TARGET_PPC64) */
 
 /* Perform segment based translation */
-static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
+static inline int get_segment(CPUPPCState *env, mmu_ctx_t *ctx,
                               target_ulong eaddr, int rw, int type)
 {
     target_phys_addr_t hash;
@@ -1002,7 +1002,7 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
 }
 
 /* Generic TLB check function for embedded PowerPC implementations */
-int ppcemb_tlb_check(CPUState *env, ppcemb_tlb_t *tlb,
+int ppcemb_tlb_check(CPUPPCState *env, ppcemb_tlb_t *tlb,
                      target_phys_addr_t *raddrp,
                      target_ulong address, uint32_t pid, int ext,
                      int i)
@@ -1055,7 +1055,7 @@ int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
 }
 
 /* Helpers specific to PowerPC 40x implementations */
-static inline void ppc4xx_tlb_invalidate_all(CPUState *env)
+static inline void ppc4xx_tlb_invalidate_all(CPUPPCState *env)
 {
     ppcemb_tlb_t *tlb;
     int i;
@@ -1067,7 +1067,7 @@ static inline void ppc4xx_tlb_invalidate_all(CPUState *env)
     tlb_flush(env, 1);
 }
 
-static inline void ppc4xx_tlb_invalidate_virt(CPUState *env,
+static inline void ppc4xx_tlb_invalidate_virt(CPUPPCState *env,
                                               target_ulong eaddr, uint32_t pid)
 {
 #if !defined(FLUSH_ALL_TLBS)
@@ -1091,7 +1091,7 @@ static inline void ppc4xx_tlb_invalidate_virt(CPUState *env,
 #endif
 }
 
-static int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
+static int mmu40x_get_physical_address (CPUPPCState *env, mmu_ctx_t *ctx,
                                  target_ulong address, int rw, int access_type)
 {
     ppcemb_tlb_t *tlb;
@@ -1162,7 +1162,7 @@ void store_40x_sler (CPUPPCState *env, uint32_t val)
     env->spr[SPR_405_SLER] = val;
 }
 
-static inline int mmubooke_check_tlb (CPUState *env, ppcemb_tlb_t *tlb,
+static inline int mmubooke_check_tlb (CPUPPCState *env, ppcemb_tlb_t *tlb,
                                       target_phys_addr_t *raddr, int *prot,
                                       target_ulong address, int rw,
                                       int access_type, int i)
@@ -1232,7 +1232,7 @@ found_tlb:
     return ret;
 }
 
-static int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
+static int mmubooke_get_physical_address (CPUPPCState *env, mmu_ctx_t *ctx,
                                           target_ulong address, int rw,
                                           int access_type)
 {
@@ -1264,7 +1264,7 @@ static int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
     return ret;
 }
 
-void booke206_flush_tlb(CPUState *env, int flags, const int check_iprot)
+void booke206_flush_tlb(CPUPPCState *env, int flags, const int check_iprot)
 {
     int tlb_size;
     int i, j;
@@ -1285,7 +1285,7 @@ void booke206_flush_tlb(CPUState *env, int flags, const int check_iprot)
     tlb_flush(env, 1);
 }
 
-target_phys_addr_t booke206_tlb_to_page_size(CPUState *env, ppcmas_tlb_t *tlb)
+target_phys_addr_t booke206_tlb_to_page_size(CPUPPCState *env, ppcmas_tlb_t *tlb)
 {
     int tlbm_size;
 
@@ -1295,7 +1295,7 @@ target_phys_addr_t booke206_tlb_to_page_size(CPUState *env, ppcmas_tlb_t *tlb)
 }
 
 /* TLB check function for MAS based SoftTLBs */
-int ppcmas_tlb_check(CPUState *env, ppcmas_tlb_t *tlb,
+int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
                      target_phys_addr_t *raddrp,
                      target_ulong address, uint32_t pid)
 {
@@ -1331,7 +1331,7 @@ int ppcmas_tlb_check(CPUState *env, ppcmas_tlb_t *tlb,
     return 0;
 }
 
-static int mmubooke206_check_tlb(CPUState *env, ppcmas_tlb_t *tlb,
+static int mmubooke206_check_tlb(CPUPPCState *env, ppcmas_tlb_t *tlb,
                                  target_phys_addr_t *raddr, int *prot,
                                  target_ulong address, int rw,
                                  int access_type)
@@ -1417,7 +1417,7 @@ found_tlb:
     return ret;
 }
 
-static int mmubooke206_get_physical_address(CPUState *env, mmu_ctx_t *ctx,
+static int mmubooke206_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
                                             target_ulong address, int rw,
                                             int access_type)
 {
@@ -1467,7 +1467,7 @@ static const char *book3e_tsize_to_str[32] = {
 };
 
 static void mmubooke206_dump_one_tlb(FILE *f, fprintf_function cpu_fprintf,
-                                     CPUState *env, int tlbn, int offset,
+                                     CPUPPCState *env, int tlbn, int offset,
                                      int tlbsize)
 {
     ppcmas_tlb_t *entry;
@@ -1514,7 +1514,7 @@ static void mmubooke206_dump_one_tlb(FILE *f, fprintf_function cpu_fprintf,
 }
 
 static void mmubooke206_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
-                                 CPUState *env)
+                                 CPUPPCState *env)
 {
     int offset = 0;
     int i;
@@ -1538,7 +1538,7 @@ static void mmubooke206_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
 
 #if defined(TARGET_PPC64)
 static void mmubooks_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
-                              CPUState *env)
+                              CPUPPCState *env)
 {
     int i;
     uint64_t slbe, slbv;
@@ -1558,7 +1558,7 @@ static void mmubooks_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
 }
 #endif
 
-void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
+void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env)
 {
     switch (env->mmu_model) {
     case POWERPC_MMU_BOOKE206:
@@ -1575,7 +1575,7 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
     }
 }
 
-static inline int check_physical(CPUState *env, mmu_ctx_t *ctx,
+static inline int check_physical(CPUPPCState *env, mmu_ctx_t *ctx,
                                  target_ulong eaddr, int rw)
 {
     int in_plb, ret;
@@ -1641,7 +1641,7 @@ static inline int check_physical(CPUState *env, mmu_ctx_t *ctx,
     return ret;
 }
 
-int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
+int get_physical_address (CPUPPCState *env, mmu_ctx_t *ctx, target_ulong eaddr,
                           int rw, int access_type)
 {
     int ret;
@@ -1716,7 +1716,7 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
     return ret;
 }
 
-target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_debug (CPUPPCState *env, target_ulong addr)
 {
     mmu_ctx_t ctx;
 
@@ -1726,7 +1726,7 @@ target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
     return ctx.raddr & TARGET_PAGE_MASK;
 }
 
-static void booke206_update_mas_tlb_miss(CPUState *env, target_ulong address,
+static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong address,
                                      int rw)
 {
     env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
@@ -1767,7 +1767,7 @@ static void booke206_update_mas_tlb_miss(CPUState *env, target_ulong address,
 }
 
 /* Perform address translation */
-int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
+int cpu_ppc_handle_mmu_fault (CPUPPCState *env, target_ulong address, int rw,
                               int mmu_idx)
 {
     mmu_ctx_t ctx;
@@ -2434,19 +2434,19 @@ void ppc_store_msr (CPUPPCState *env, target_ulong value)
 /*****************************************************************************/
 /* Exception processing */
 #if defined (CONFIG_USER_ONLY)
-void do_interrupt (CPUState *env)
+void do_interrupt (CPUPPCState *env)
 {
     env->exception_index = POWERPC_EXCP_NONE;
     env->error_code = 0;
 }
 
-void ppc_hw_interrupt (CPUState *env)
+void ppc_hw_interrupt (CPUPPCState *env)
 {
     env->exception_index = POWERPC_EXCP_NONE;
     env->error_code = 0;
 }
 #else /* defined (CONFIG_USER_ONLY) */
-static inline void dump_syscall(CPUState *env)
+static inline void dump_syscall(CPUPPCState *env)
 {
     qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
                   " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
@@ -2459,7 +2459,7 @@ static inline void dump_syscall(CPUState *env)
 /* Note that this function should be greatly optimized
  * when called with a constant excp, from ppc_hw_interrupt
  */
-static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
+static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp)
 {
     target_ulong msr, new_msr, vector;
     int srr0, srr1, asrr0, asrr1;
@@ -3008,7 +3008,7 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
     }
 }
 
-void do_interrupt (CPUState *env)
+void do_interrupt (CPUPPCState *env)
 {
     powerpc_excp(env, env->excp_model, env->exception_index);
 }
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 50cfa02..aeb3de9 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -93,7 +93,7 @@ int kvm_arch_init(KVMState *s)
     return 0;
 }
 
-static int kvm_arch_sync_sregs(CPUState *cenv)
+static int kvm_arch_sync_sregs(CPUPPCState *cenv)
 {
     struct kvm_sregs sregs;
     int ret;
@@ -121,7 +121,7 @@ static int kvm_arch_sync_sregs(CPUState *cenv)
 }
 
 /* Set up a shared TLB array with KVM */
-static int kvm_booke206_tlb_init(CPUState *env)
+static int kvm_booke206_tlb_init(CPUPPCState *env)
 {
     struct kvm_book3e_206_tlb_params params = {};
     struct kvm_config_tlb cfg = {};
@@ -166,7 +166,7 @@ static int kvm_booke206_tlb_init(CPUState *env)
     return 0;
 }
 
-int kvm_arch_init_vcpu(CPUState *cenv)
+int kvm_arch_init_vcpu(CPUPPCState *cenv)
 {
     int ret;
 
@@ -189,11 +189,11 @@ int kvm_arch_init_vcpu(CPUState *cenv)
     return ret;
 }
 
-void kvm_arch_reset_vcpu(CPUState *env)
+void kvm_arch_reset_vcpu(CPUPPCState *env)
 {
 }
 
-static void kvm_sw_tlb_put(CPUState *env)
+static void kvm_sw_tlb_put(CPUPPCState *env)
 {
     struct kvm_dirty_tlb dirty_tlb;
     unsigned char *bitmap;
@@ -218,7 +218,7 @@ static void kvm_sw_tlb_put(CPUState *env)
     g_free(bitmap);
 }
 
-int kvm_arch_put_registers(CPUState *env, int level)
+int kvm_arch_put_registers(CPUPPCState *env, int level)
 {
     struct kvm_regs regs;
     int ret;
@@ -263,7 +263,7 @@ int kvm_arch_put_registers(CPUState *env, int level)
     return ret;
 }
 
-int kvm_arch_get_registers(CPUState *env)
+int kvm_arch_get_registers(CPUPPCState *env)
 {
     struct kvm_regs regs;
     struct kvm_sregs sregs;
@@ -440,7 +440,7 @@ int kvm_arch_get_registers(CPUState *env)
     return 0;
 }
 
-int kvmppc_set_interrupt(CPUState *env, int irq, int level)
+int kvmppc_set_interrupt(CPUPPCState *env, int irq, int level)
 {
     unsigned virq = level ? KVM_INTERRUPT_SET_LEVEL : KVM_INTERRUPT_UNSET;
 
@@ -465,7 +465,7 @@ int kvmppc_set_interrupt(CPUState *env, int irq, int level)
 #define PPC_INPUT_INT PPC6xx_INPUT_INT
 #endif
 
-void kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
+void kvm_arch_pre_run(CPUPPCState *env, struct kvm_run *run)
 {
     int r;
     unsigned irq;
@@ -498,16 +498,16 @@ void kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
      * anyways, so we will get a chance to deliver the rest. */
 }
 
-void kvm_arch_post_run(CPUState *env, struct kvm_run *run)
+void kvm_arch_post_run(CPUPPCState *env, struct kvm_run *run)
 {
 }
 
-int kvm_arch_process_async_events(CPUState *env)
+int kvm_arch_process_async_events(CPUPPCState *env)
 {
     return env->halted;
 }
 
-static int kvmppc_handle_halt(CPUState *env)
+static int kvmppc_handle_halt(CPUPPCState *env)
 {
     if (!(env->interrupt_request & CPU_INTERRUPT_HARD) && (msr_ee)) {
         env->halted = 1;
@@ -518,7 +518,7 @@ static int kvmppc_handle_halt(CPUState *env)
 }
 
 /* map dcr access to existing qemu dcr emulation */
-static int kvmppc_handle_dcr_read(CPUState *env, uint32_t dcrn, uint32_t *data)
+static int kvmppc_handle_dcr_read(CPUPPCState *env, uint32_t dcrn, uint32_t *data)
 {
     if (ppc_dcr_read(env->dcr_env, dcrn, data) < 0)
         fprintf(stderr, "Read to unhandled DCR (0x%x)\n", dcrn);
@@ -526,7 +526,7 @@ static int kvmppc_handle_dcr_read(CPUState *env, uint32_t dcrn, uint32_t *data)
     return 0;
 }
 
-static int kvmppc_handle_dcr_write(CPUState *env, uint32_t dcrn, uint32_t data)
+static int kvmppc_handle_dcr_write(CPUPPCState *env, uint32_t dcrn, uint32_t data)
 {
     if (ppc_dcr_write(env->dcr_env, dcrn, data) < 0)
         fprintf(stderr, "Write to unhandled DCR (0x%x)\n", dcrn);
@@ -534,7 +534,7 @@ static int kvmppc_handle_dcr_write(CPUState *env, uint32_t dcrn, uint32_t data)
     return 0;
 }
 
-int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
+int kvm_arch_handle_exit(CPUPPCState *env, struct kvm_run *run)
 {
     int ret;
 
@@ -704,7 +704,7 @@ uint32_t kvmppc_get_dfp(void)
     return kvmppc_read_int_cpu_dt("ibm,dfp");
 }
 
-int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len)
+int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len)
 {
     uint32_t *hc = (uint32_t*)buf;
 
@@ -734,7 +734,7 @@ int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len)
     return 0;
 }
 
-void kvmppc_set_papr(CPUState *env)
+void kvmppc_set_papr(CPUPPCState *env)
 {
     struct kvm_enable_cap cap = {};
     struct kvm_one_reg reg = {};
@@ -930,12 +930,12 @@ const ppc_def_t *kvmppc_host_cpu_def(void)
     return spec;
 }
 
-bool kvm_arch_stop_on_emulation_error(CPUState *env)
+bool kvm_arch_stop_on_emulation_error(CPUPPCState *env)
 {
     return true;
 }
 
-int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr)
+int kvm_arch_on_sigbus_vcpu(CPUPPCState *env, int code, void *addr)
 {
     return 1;
 }
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index f9c0198..8f1267c 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -19,9 +19,9 @@ uint32_t kvmppc_get_tbfreq(void);
 uint64_t kvmppc_get_clockfreq(void);
 uint32_t kvmppc_get_vmx(void);
 uint32_t kvmppc_get_dfp(void);
-int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len);
-int kvmppc_set_interrupt(CPUState *env, int irq, int level);
-void kvmppc_set_papr(CPUState *env);
+int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len);
+int kvmppc_set_interrupt(CPUPPCState *env, int irq, int level);
+void kvmppc_set_papr(CPUPPCState *env);
 int kvmppc_smt_threads(void);
 #ifndef CONFIG_USER_ONLY
 off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem);
@@ -52,17 +52,17 @@ static inline uint32_t kvmppc_get_dfp(void)
     return 0;
 }
 
-static inline int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len)
+static inline int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len)
 {
     return -1;
 }
 
-static inline int kvmppc_set_interrupt(CPUState *env, int irq, int level)
+static inline int kvmppc_set_interrupt(CPUPPCState *env, int irq, int level)
 {
     return -1;
 }
 
-static inline void kvmppc_set_papr(CPUState *env)
+static inline void kvmppc_set_papr(CPUPPCState *env)
 {
 }
 
diff --git a/target-ppc/machine.c b/target-ppc/machine.c
index 1c40d43..70e2582 100644
--- a/target-ppc/machine.c
+++ b/target-ppc/machine.c
@@ -4,7 +4,7 @@
 
 void cpu_save(QEMUFile *f, void *opaque)
 {
-    CPUState *env = (CPUState *)opaque;
+    CPUPPCState *env = (CPUPPCState *)opaque;
     unsigned int i, j;
 
     for (i = 0; i < 32; i++)
@@ -91,7 +91,7 @@ void cpu_save(QEMUFile *f, void *opaque)
 
 int cpu_load(QEMUFile *f, void *opaque, int version_id)
 {
-    CPUState *env = (CPUState *)opaque;
+    CPUPPCState *env = (CPUPPCState *)opaque;
     unsigned int i, j;
     target_ulong sdr1;
 
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 3f4e067..40927b6 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -3714,11 +3714,11 @@ uint32_t helper_efdcmpeq (uint64_t op1, uint64_t op2)
    NULL, it means that the function was called in C code (i.e. not
    from generated code or from helper.c) */
 /* XXX: fix it to restore all registers */
-void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
+void tlb_fill(CPUPPCState *env1, target_ulong addr, int is_write, int mmu_idx,
               void *retaddr)
 {
     TranslationBlock *tb;
-    CPUState *saved_env;
+    CPUPPCState *saved_env;
     unsigned long pc;
     int ret;
 
@@ -4200,7 +4200,7 @@ target_ulong helper_440_tlbsx (target_ulong address)
 
 /* PowerPC BookE 2.06 TLB management */
 
-static ppcmas_tlb_t *booke206_cur_tlb(CPUState *env)
+static ppcmas_tlb_t *booke206_cur_tlb(CPUPPCState *env)
 {
     uint32_t tlbncfg = 0;
     int esel = (env->spr[SPR_BOOKE_MAS0] & MAS0_ESEL_MASK) >> MAS0_ESEL_SHIFT;
@@ -4306,7 +4306,7 @@ void helper_booke206_tlbwe(void)
     }
 }
 
-static inline void booke206_tlb_to_mas(CPUState *env, ppcmas_tlb_t *tlb)
+static inline void booke206_tlb_to_mas(CPUPPCState *env, ppcmas_tlb_t *tlb)
 {
     int tlbn = booke206_tlbm_to_tlbn(env, tlb);
     int way = booke206_tlbm_to_way(env, tlb);
@@ -4387,7 +4387,7 @@ void helper_booke206_tlbsx(target_ulong address)
     env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
 }
 
-static inline void booke206_invalidate_ea_tlb(CPUState *env, int tlbn,
+static inline void booke206_invalidate_ea_tlb(CPUPPCState *env, int tlbn,
                                               uint32_t ea)
 {
     int i;
@@ -4553,7 +4553,7 @@ void helper_msgsnd(target_ulong rb)
 {
     int irq = dbell2irq(rb);
     int pir = rb & DBELL_PIRTAG_MASK;
-    CPUState *cenv;
+    CPUPPCState *cenv;
 
     if (irq < 0) {
         return;
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 8573e1f..3ec59a7 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -91,7 +91,7 @@ void ppc_translate_init(void)
     for (i = 0; i < 8; i++) {
         snprintf(p, cpu_reg_names_size, "crf%d", i);
         cpu_crf[i] = tcg_global_mem_new_i32(TCG_AREG0,
-                                            offsetof(CPUState, crf[i]), p);
+                                            offsetof(CPUPPCState, crf[i]), p);
         p += 5;
         cpu_reg_names_size -= 5;
     }
@@ -99,30 +99,30 @@ void ppc_translate_init(void)
     for (i = 0; i < 32; i++) {
         snprintf(p, cpu_reg_names_size, "r%d", i);
         cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
-                                        offsetof(CPUState, gpr[i]), p);
+                                        offsetof(CPUPPCState, gpr[i]), p);
         p += (i < 10) ? 3 : 4;
         cpu_reg_names_size -= (i < 10) ? 3 : 4;
 #if !defined(TARGET_PPC64)
         snprintf(p, cpu_reg_names_size, "r%dH", i);
         cpu_gprh[i] = tcg_global_mem_new_i32(TCG_AREG0,
-                                             offsetof(CPUState, gprh[i]), p);
+                                             offsetof(CPUPPCState, gprh[i]), p);
         p += (i < 10) ? 4 : 5;
         cpu_reg_names_size -= (i < 10) ? 4 : 5;
 #endif
 
         snprintf(p, cpu_reg_names_size, "fp%d", i);
         cpu_fpr[i] = tcg_global_mem_new_i64(TCG_AREG0,
-                                            offsetof(CPUState, fpr[i]), p);
+                                            offsetof(CPUPPCState, fpr[i]), p);
         p += (i < 10) ? 4 : 5;
         cpu_reg_names_size -= (i < 10) ? 4 : 5;
 
         snprintf(p, cpu_reg_names_size, "avr%dH", i);
 #ifdef HOST_WORDS_BIGENDIAN
         cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
-                                             offsetof(CPUState, avr[i].u64[0]), p);
+                                             offsetof(CPUPPCState, avr[i].u64[0]), p);
 #else
         cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
-                                             offsetof(CPUState, avr[i].u64[1]), p);
+                                             offsetof(CPUPPCState, avr[i].u64[1]), p);
 #endif
         p += (i < 10) ? 6 : 7;
         cpu_reg_names_size -= (i < 10) ? 6 : 7;
@@ -130,44 +130,44 @@ void ppc_translate_init(void)
         snprintf(p, cpu_reg_names_size, "avr%dL", i);
 #ifdef HOST_WORDS_BIGENDIAN
         cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
-                                             offsetof(CPUState, avr[i].u64[1]), p);
+                                             offsetof(CPUPPCState, avr[i].u64[1]), p);
 #else
         cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
-                                             offsetof(CPUState, avr[i].u64[0]), p);
+                                             offsetof(CPUPPCState, avr[i].u64[0]), p);
 #endif
         p += (i < 10) ? 6 : 7;
         cpu_reg_names_size -= (i < 10) ? 6 : 7;
     }
 
     cpu_nip = tcg_global_mem_new(TCG_AREG0,
-                                 offsetof(CPUState, nip), "nip");
+                                 offsetof(CPUPPCState, nip), "nip");
 
     cpu_msr = tcg_global_mem_new(TCG_AREG0,
-                                 offsetof(CPUState, msr), "msr");
+                                 offsetof(CPUPPCState, msr), "msr");
 
     cpu_ctr = tcg_global_mem_new(TCG_AREG0,
-                                 offsetof(CPUState, ctr), "ctr");
+                                 offsetof(CPUPPCState, ctr), "ctr");
 
     cpu_lr = tcg_global_mem_new(TCG_AREG0,
-                                offsetof(CPUState, lr), "lr");
+                                offsetof(CPUPPCState, lr), "lr");
 
 #if defined(TARGET_PPC64)
     cpu_cfar = tcg_global_mem_new(TCG_AREG0,
-                                  offsetof(CPUState, cfar), "cfar");
+                                  offsetof(CPUPPCState, cfar), "cfar");
 #endif
 
     cpu_xer = tcg_global_mem_new(TCG_AREG0,
-                                 offsetof(CPUState, xer), "xer");
+                                 offsetof(CPUPPCState, xer), "xer");
 
     cpu_reserve = tcg_global_mem_new(TCG_AREG0,
-                                     offsetof(CPUState, reserve_addr),
+                                     offsetof(CPUPPCState, reserve_addr),
                                      "reserve_addr");
 
     cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
-                                       offsetof(CPUState, fpscr), "fpscr");
+                                       offsetof(CPUPPCState, fpscr), "fpscr");
 
     cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0,
-                                             offsetof(CPUState, access_type), "access_type");
+                                             offsetof(CPUPPCState, access_type), "access_type");
 
     /* register helpers */
 #define GEN_HELPER 2
@@ -564,12 +564,12 @@ static inline target_ulong MASK(uint32_t start, uint32_t end)
 /* SPR load/store helpers */
 static inline void gen_load_spr(TCGv t, int reg)
 {
-    tcg_gen_ld_tl(t, cpu_env, offsetof(CPUState, spr[reg]));
+    tcg_gen_ld_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
 }
 
 static inline void gen_store_spr(int reg, TCGv t)
 {
-    tcg_gen_st_tl(t, cpu_env, offsetof(CPUState, spr[reg]));
+    tcg_gen_st_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
 }
 
 /* Invalid instruction */
@@ -3078,7 +3078,7 @@ static void gen_lwarx(DisasContext *ctx)
     gen_check_align(ctx, t0, 0x03);
     gen_qemu_ld32u(ctx, gpr, t0);
     tcg_gen_mov_tl(cpu_reserve, t0);
-    tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUState, reserve_val));
+    tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val));
     tcg_temp_free(t0);
 }
 
@@ -3089,9 +3089,9 @@ static void gen_conditional_store (DisasContext *ctx, TCGv EA,
     TCGv t0 = tcg_temp_new();
     uint32_t save_exception = ctx->exception;
 
-    tcg_gen_st_tl(EA, cpu_env, offsetof(CPUState, reserve_ea));
+    tcg_gen_st_tl(EA, cpu_env, offsetof(CPUPPCState, reserve_ea));
     tcg_gen_movi_tl(t0, (size << 5) | reg);
-    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, reserve_info));
+    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, reserve_info));
     tcg_temp_free(t0);
     gen_update_nip(ctx, ctx->nip-4);
     ctx->exception = POWERPC_EXCP_BRANCH;
@@ -3140,7 +3140,7 @@ static void gen_ldarx(DisasContext *ctx)
     gen_check_align(ctx, t0, 0x07);
     gen_qemu_ld64(ctx, gpr, t0);
     tcg_gen_mov_tl(cpu_reserve, t0);
-    tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUState, reserve_val));
+    tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val));
     tcg_temp_free(t0);
 }
 
@@ -3181,7 +3181,7 @@ static void gen_sync(DisasContext *ctx)
 static void gen_wait(DisasContext *ctx)
 {
     TCGv_i32 t0 = tcg_temp_new_i32();
-    tcg_gen_st_i32(t0, cpu_env, offsetof(CPUState, halted));
+    tcg_gen_st_i32(t0, cpu_env, offsetof(CPUPPCState, halted));
     tcg_temp_free_i32(t0);
     /* Stop translation, as the CPU is supposed to sleep from now */
     gen_exception_err(ctx, EXCP_HLT, 1);
@@ -6395,7 +6395,7 @@ static void gen_mfvscr(DisasContext *ctx)
     }
     tcg_gen_movi_i64(cpu_avrh[rD(ctx->opcode)], 0);
     t = tcg_temp_new_i32();
-    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, vscr));
+    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, vscr));
     tcg_gen_extu_i32_i64(cpu_avrl[rD(ctx->opcode)], t);
     tcg_temp_free_i32(t);
 }
@@ -6748,7 +6748,7 @@ static inline void gen_evmra(DisasContext *ctx)
     /* spe_acc := rA */
     tcg_gen_st_i64(cpu_gpr[rA(ctx->opcode)],
                    cpu_env,
-                   offsetof(CPUState, spe_acc));
+                   offsetof(CPUPPCState, spe_acc));
 #else
     TCGv_i64 tmp = tcg_temp_new_i64();
 
@@ -6756,7 +6756,7 @@ static inline void gen_evmra(DisasContext *ctx)
     tcg_gen_concat_i32_i64(tmp, cpu_gpr[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
 
     /* spe_acc := tmp */
-    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUState, spe_acc));
+    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
     tcg_temp_free_i64(tmp);
 
     /* rD := rA */
@@ -7399,7 +7399,7 @@ static inline void gen_evmwumia(DisasContext *ctx)
 
     /* acc := rD */
     gen_load_gpr64(tmp, rD(ctx->opcode));
-    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUState, spe_acc));
+    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
     tcg_temp_free_i64(tmp);
 }
 
@@ -7422,13 +7422,13 @@ static inline void gen_evmwumiaa(DisasContext *ctx)
     gen_load_gpr64(tmp, rD(ctx->opcode));
 
     /* Load acc */
-    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUState, spe_acc));
+    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
 
     /* acc := tmp + acc */
     tcg_gen_add_i64(acc, acc, tmp);
 
     /* Store acc */
-    tcg_gen_st_i64(acc, cpu_env, offsetof(CPUState, spe_acc));
+    tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
 
     /* rD := acc */
     gen_store_gpr64(rD(ctx->opcode), acc);
@@ -7476,7 +7476,7 @@ static inline void gen_evmwsmia(DisasContext *ctx)
 
     /* acc := rD */
     gen_load_gpr64(tmp, rD(ctx->opcode));
-    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUState, spe_acc));
+    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
 
     tcg_temp_free_i64(tmp);
 }
@@ -7495,13 +7495,13 @@ static inline void gen_evmwsmiaa(DisasContext *ctx)
     gen_load_gpr64(tmp, rD(ctx->opcode));
 
     /* Load acc */
-    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUState, spe_acc));
+    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
 
     /* acc := tmp + acc */
     tcg_gen_add_i64(acc, acc, tmp);
 
     /* Store acc */
-    tcg_gen_st_i64(acc, cpu_env, offsetof(CPUState, spe_acc));
+    tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
 
     /* rD := acc */
     gen_store_gpr64(rD(ctx->opcode), acc);
@@ -9277,7 +9277,7 @@ GEN_SPEOP_LDST(evstwwo, 0x1E, 2),
 
 /*****************************************************************************/
 /* Misc PowerPC helpers */
-void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
+void cpu_dump_state (CPUPPCState *env, FILE *f, fprintf_function cpu_fprintf,
                      int flags)
 {
 #define RGPL  4
@@ -9425,7 +9425,7 @@ void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
 #undef RFPL
 }
 
-void cpu_dump_statistics (CPUState *env, FILE*f, fprintf_function cpu_fprintf,
+void cpu_dump_statistics (CPUPPCState *env, FILE*f, fprintf_function cpu_fprintf,
                           int flags)
 {
 #if defined(DO_PPC_STATISTICS)
@@ -9473,7 +9473,7 @@ void cpu_dump_statistics (CPUState *env, FILE*f, fprintf_function cpu_fprintf,
 }
 
 /*****************************************************************************/
-static inline void gen_intermediate_code_internal(CPUState *env,
+static inline void gen_intermediate_code_internal(CPUPPCState *env,
                                                   TranslationBlock *tb,
                                                   int search_pc)
 {
@@ -9658,17 +9658,17 @@ static inline void gen_intermediate_code_internal(CPUState *env,
 #endif
 }
 
-void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
+void gen_intermediate_code (CPUPPCState *env, struct TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 0);
 }
 
-void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
+void gen_intermediate_code_pc (CPUPPCState *env, struct TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 1);
 }
 
-void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb, int pc_pos)
 {
     env->nip = gen_opc_pc[pc_pos];
 }
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 6253076..1ec6f42 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -268,12 +268,12 @@ static void spr_read_purr (void *opaque, int gprn, int sprn)
 /* IBAT0L...IBAT7L */
 static void spr_read_ibat (void *opaque, int gprn, int sprn)
 {
-    tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2]));
+    tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2]));
 }
 
 static void spr_read_ibat_h (void *opaque, int gprn, int sprn)
 {
-    tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, IBAT[sprn & 1][(sprn - SPR_IBAT4U) / 2]));
+    tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, IBAT[sprn & 1][(sprn - SPR_IBAT4U) / 2]));
 }
 
 static void spr_write_ibatu (void *opaque, int sprn, int gprn)
@@ -308,12 +308,12 @@ static void spr_write_ibatl_h (void *opaque, int sprn, int gprn)
 /* DBAT0L...DBAT7L */
 static void spr_read_dbat (void *opaque, int gprn, int sprn)
 {
-    tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, DBAT[sprn & 1][(sprn - SPR_DBAT0U) / 2]));
+    tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, DBAT[sprn & 1][(sprn - SPR_DBAT0U) / 2]));
 }
 
 static void spr_read_dbat_h (void *opaque, int gprn, int sprn)
 {
-    tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, DBAT[sprn & 1][((sprn - SPR_DBAT4U) / 2) + 4]));
+    tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, DBAT[sprn & 1][((sprn - SPR_DBAT4U) / 2) + 4]));
 }
 
 static void spr_write_dbatu (void *opaque, int sprn, int gprn)
@@ -355,20 +355,20 @@ static void spr_write_sdr1 (void *opaque, int sprn, int gprn)
 #if defined(TARGET_PPC64)
 static void spr_read_hior (void *opaque, int gprn, int sprn)
 {
-    tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, excp_prefix));
+    tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, excp_prefix));
 }
 
 static void spr_write_hior (void *opaque, int sprn, int gprn)
 {
     TCGv t0 = tcg_temp_new();
     tcg_gen_andi_tl(t0, cpu_gpr[gprn], 0x3FFFFF00000ULL);
-    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, excp_prefix));
+    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, excp_prefix));
     tcg_temp_free(t0);
 }
 
 static void spr_read_asr (void *opaque, int gprn, int sprn)
 {
-    tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, asr));
+    tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, asr));
 }
 
 static void spr_write_asr (void *opaque, int sprn, int gprn)
@@ -415,7 +415,7 @@ static void spr_write_hid0_601 (void *opaque, int sprn, int gprn)
 #if !defined(CONFIG_USER_ONLY)
 static void spr_read_601_ubat (void *opaque, int gprn, int sprn)
 {
-    tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2]));
+    tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2]));
 }
 
 static void spr_write_601_ubatu (void *opaque, int sprn, int gprn)
@@ -475,7 +475,7 @@ static void spr_write_booke_tsr (void *opaque, int sprn, int gprn)
 #if !defined(CONFIG_USER_ONLY)
 static void spr_read_403_pbr (void *opaque, int gprn, int sprn)
 {
-    tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, pb[sprn - SPR_403_PBL1]));
+    tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, pb[sprn - SPR_403_PBL1]));
 }
 
 static void spr_write_403_pbr (void *opaque, int sprn, int gprn)
@@ -498,7 +498,7 @@ static void spr_write_pir (void *opaque, int sprn, int gprn)
 static void spr_read_spefscr (void *opaque, int gprn, int sprn)
 {
     TCGv_i32 t0 = tcg_temp_new_i32();
-    tcg_gen_ld_i32(t0, cpu_env, offsetof(CPUState, spe_fscr));
+    tcg_gen_ld_i32(t0, cpu_env, offsetof(CPUPPCState, spe_fscr));
     tcg_gen_extu_i32_tl(cpu_gpr[gprn], t0);
     tcg_temp_free_i32(t0);
 }
@@ -507,7 +507,7 @@ static void spr_write_spefscr (void *opaque, int sprn, int gprn)
 {
     TCGv_i32 t0 = tcg_temp_new_i32();
     tcg_gen_trunc_tl_i32(t0, cpu_gpr[gprn]);
-    tcg_gen_st_i32(t0, cpu_env, offsetof(CPUState, spe_fscr));
+    tcg_gen_st_i32(t0, cpu_env, offsetof(CPUPPCState, spe_fscr));
     tcg_temp_free_i32(t0);
 }
 
@@ -516,9 +516,9 @@ static void spr_write_spefscr (void *opaque, int sprn, int gprn)
 static void spr_write_excp_prefix (void *opaque, int sprn, int gprn)
 {
     TCGv t0 = tcg_temp_new();
-    tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, ivpr_mask));
+    tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUPPCState, ivpr_mask));
     tcg_gen_and_tl(t0, t0, cpu_gpr[gprn]);
-    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, excp_prefix));
+    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, excp_prefix));
     gen_store_spr(sprn, t0);
     tcg_temp_free(t0);
 }
@@ -542,9 +542,9 @@ static void spr_write_excp_vector (void *opaque, int sprn, int gprn)
     }
 
     TCGv t0 = tcg_temp_new();
-    tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, ivor_mask));
+    tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUPPCState, ivor_mask));
     tcg_gen_and_tl(t0, t0, cpu_gpr[gprn]);
-    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, excp_vectors[sprn_offs]));
+    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, excp_vectors[sprn_offs]));
     gen_store_spr(sprn, t0);
     tcg_temp_free(t0);
 }
@@ -9768,7 +9768,7 @@ static void dump_ppc_insns (CPUPPCState *env)
 }
 #endif
 
-static int gdb_get_float_reg(CPUState *env, uint8_t *mem_buf, int n)
+static int gdb_get_float_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
 {
     if (n < 32) {
         stfq_p(mem_buf, env->fpr[n]);
@@ -9781,7 +9781,7 @@ static int gdb_get_float_reg(CPUState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int gdb_set_float_reg(CPUState *env, uint8_t *mem_buf, int n)
+static int gdb_set_float_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
 {
     if (n < 32) {
         env->fpr[n] = ldfq_p(mem_buf);
@@ -9794,7 +9794,7 @@ static int gdb_set_float_reg(CPUState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int gdb_get_avr_reg(CPUState *env, uint8_t *mem_buf, int n)
+static int gdb_get_avr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
 {
     if (n < 32) {
 #ifdef HOST_WORDS_BIGENDIAN
@@ -9817,7 +9817,7 @@ static int gdb_get_avr_reg(CPUState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int gdb_set_avr_reg(CPUState *env, uint8_t *mem_buf, int n)
+static int gdb_set_avr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
 {
     if (n < 32) {
 #ifdef HOST_WORDS_BIGENDIAN
@@ -9840,7 +9840,7 @@ static int gdb_set_avr_reg(CPUState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int gdb_get_spe_reg(CPUState *env, uint8_t *mem_buf, int n)
+static int gdb_get_spe_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
 {
     if (n < 32) {
 #if defined(TARGET_PPC64)
@@ -9861,7 +9861,7 @@ static int gdb_get_spe_reg(CPUState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int gdb_set_spe_reg(CPUState *env, uint8_t *mem_buf, int n)
+static int gdb_set_spe_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
 {
     if (n < 32) {
 #if defined(TARGET_PPC64)
commit 7db13fae2cec51a012ba83e5d6b3483a9c718737
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:22 2012 +0100

    target-mips: Don't overuse CPUState
    
    Scripted conversion:
      sed -i "s/CPUState/CPUMIPSState/g" target-mips/*.[hc]
      sed -i "s/#define CPUMIPSState/#define CPUState/" target-mips/cpu.h
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 71cb4e8..94381ec 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -495,7 +495,7 @@ void r4k_helper_tlbwr (void);
 void r4k_helper_tlbp (void);
 void r4k_helper_tlbr (void);
 
-void cpu_unassigned_access(CPUState *env, target_phys_addr_t addr,
+void cpu_unassigned_access(CPUMIPSState *env, target_phys_addr_t addr,
                            int is_write, int is_exec, int unused, int size);
 #endif
 
@@ -515,12 +515,12 @@ void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf);
 #define MMU_MODE1_SUFFIX _super
 #define MMU_MODE2_SUFFIX _user
 #define MMU_USER_IDX 2
-static inline int cpu_mmu_index (CPUState *env)
+static inline int cpu_mmu_index (CPUMIPSState *env)
 {
     return env->hflags & MIPS_HFLAG_KSU;
 }
 
-static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
+static inline void cpu_clone_regs(CPUMIPSState *env, target_ulong newsp)
 {
     if (newsp)
         env->active_tc.gpr[29] = newsp;
@@ -528,7 +528,7 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
     env->active_tc.gpr[2] = 0;
 }
 
-static inline int cpu_mips_hw_interrupts_pending(CPUState *env)
+static inline int cpu_mips_hw_interrupts_pending(CPUMIPSState *env)
 {
     int32_t pending;
     int32_t status;
@@ -636,28 +636,28 @@ CPUMIPSState *cpu_mips_init(const char *cpu_model);
 int cpu_mips_signal_handler(int host_signum, void *pinfo, void *puc);
 
 /* mips_timer.c */
-uint32_t cpu_mips_get_random (CPUState *env);
-uint32_t cpu_mips_get_count (CPUState *env);
-void cpu_mips_store_count (CPUState *env, uint32_t value);
-void cpu_mips_store_compare (CPUState *env, uint32_t value);
-void cpu_mips_start_count(CPUState *env);
-void cpu_mips_stop_count(CPUState *env);
+uint32_t cpu_mips_get_random (CPUMIPSState *env);
+uint32_t cpu_mips_get_count (CPUMIPSState *env);
+void cpu_mips_store_count (CPUMIPSState *env, uint32_t value);
+void cpu_mips_store_compare (CPUMIPSState *env, uint32_t value);
+void cpu_mips_start_count(CPUMIPSState *env);
+void cpu_mips_stop_count(CPUMIPSState *env);
 
 /* mips_int.c */
-void cpu_mips_soft_irq(CPUState *env, int irq, int level);
+void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level);
 
 /* helper.c */
-int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
+int cpu_mips_handle_mmu_fault (CPUMIPSState *env, target_ulong address, int rw,
                                int mmu_idx);
 #define cpu_handle_mmu_fault cpu_mips_handle_mmu_fault
-void do_interrupt (CPUState *env);
+void do_interrupt (CPUMIPSState *env);
 #if !defined(CONFIG_USER_ONLY)
-void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra);
-target_phys_addr_t cpu_mips_translate_address (CPUState *env, target_ulong address,
+void r4k_invalidate_tlb (CPUMIPSState *env, int idx, int use_extra);
+target_phys_addr_t cpu_mips_translate_address (CPUMIPSState *env, target_ulong address,
 		                               int rw);
 #endif
 
-static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
     *pc = env->active_tc.PC;
@@ -665,12 +665,12 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
     *flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
 }
 
-static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
+static inline void cpu_set_tls(CPUMIPSState *env, target_ulong newtls)
 {
     env->tls_value = newtls;
 }
 
-static inline int mips_vpe_active(CPUState *env)
+static inline int mips_vpe_active(CPUMIPSState *env)
 {
     int active = 1;
 
@@ -701,7 +701,7 @@ static inline int mips_vpe_active(CPUState *env)
     return active;
 }
 
-static inline int cpu_has_work(CPUState *env)
+static inline int cpu_has_work(CPUMIPSState *env)
 {
     int has_work = 0;
 
@@ -730,7 +730,7 @@ static inline int cpu_has_work(CPUState *env)
 
 #include "exec-all.h"
 
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+static inline void cpu_pc_from_tb(CPUMIPSState *env, TranslationBlock *tb)
 {
     env->active_tc.PC = tb->pc;
     env->hflags &= ~MIPS_HFLAG_BMASK;
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 4d1cf98..ddf9cb7 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -36,7 +36,7 @@ enum {
 #if !defined(CONFIG_USER_ONLY)
 
 /* no MMU emulation */
-int no_mmu_map_address (CPUState *env, target_phys_addr_t *physical, int *prot,
+int no_mmu_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int *prot,
                         target_ulong address, int rw, int access_type)
 {
     *physical = address;
@@ -45,7 +45,7 @@ int no_mmu_map_address (CPUState *env, target_phys_addr_t *physical, int *prot,
 }
 
 /* fixed mapping MMU emulation */
-int fixed_mmu_map_address (CPUState *env, target_phys_addr_t *physical, int *prot,
+int fixed_mmu_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int *prot,
                            target_ulong address, int rw, int access_type)
 {
     if (address <= (int32_t)0x7FFFFFFFUL) {
@@ -63,7 +63,7 @@ int fixed_mmu_map_address (CPUState *env, target_phys_addr_t *physical, int *pro
 }
 
 /* MIPS32/MIPS64 R4000-style MMU emulation */
-int r4k_map_address (CPUState *env, target_phys_addr_t *physical, int *prot,
+int r4k_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int *prot,
                      target_ulong address, int rw, int access_type)
 {
     uint8_t ASID = env->CP0_EntryHi & 0xFF;
@@ -99,7 +99,7 @@ int r4k_map_address (CPUState *env, target_phys_addr_t *physical, int *prot,
     return TLBRET_NOMATCH;
 }
 
-static int get_physical_address (CPUState *env, target_phys_addr_t *physical,
+static int get_physical_address (CPUMIPSState *env, target_phys_addr_t *physical,
                                 int *prot, target_ulong address,
                                 int rw, int access_type)
 {
@@ -201,7 +201,7 @@ static int get_physical_address (CPUState *env, target_phys_addr_t *physical,
 }
 #endif
 
-static void raise_mmu_exception(CPUState *env, target_ulong address,
+static void raise_mmu_exception(CPUMIPSState *env, target_ulong address,
                                 int rw, int tlb_error)
 {
     int exception = 0, error_code = 0;
@@ -254,7 +254,7 @@ static void raise_mmu_exception(CPUState *env, target_ulong address,
 }
 
 #if !defined(CONFIG_USER_ONLY)
-target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_debug(CPUMIPSState *env, target_ulong addr)
 {
     target_phys_addr_t phys_addr;
     int prot;
@@ -265,7 +265,7 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 }
 #endif
 
-int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
+int cpu_mips_handle_mmu_fault (CPUMIPSState *env, target_ulong address, int rw,
                                int mmu_idx)
 {
 #if !defined(CONFIG_USER_ONLY)
@@ -308,7 +308,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
 }
 
 #if !defined(CONFIG_USER_ONLY)
-target_phys_addr_t cpu_mips_translate_address(CPUState *env, target_ulong address, int rw)
+target_phys_addr_t cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, int rw)
 {
     target_phys_addr_t physical;
     int prot;
@@ -367,7 +367,7 @@ static const char * const excp_names[EXCP_LAST + 1] = {
 };
 
 #if !defined(CONFIG_USER_ONLY)
-static target_ulong exception_resume_pc (CPUState *env)
+static target_ulong exception_resume_pc (CPUMIPSState *env)
 {
     target_ulong bad_pc;
     target_ulong isa_mode;
@@ -383,7 +383,7 @@ static target_ulong exception_resume_pc (CPUState *env)
     return bad_pc;
 }
 
-static void set_hflags_for_handler (CPUState *env)
+static void set_hflags_for_handler (CPUMIPSState *env)
 {
     /* Exception handlers are entered in 32-bit mode.  */
     env->hflags &= ~(MIPS_HFLAG_M16);
@@ -396,7 +396,7 @@ static void set_hflags_for_handler (CPUState *env)
 }
 #endif
 
-void do_interrupt (CPUState *env)
+void do_interrupt (CPUMIPSState *env)
 {
 #if !defined(CONFIG_USER_ONLY)
     target_ulong offset;
@@ -637,7 +637,7 @@ void do_interrupt (CPUState *env)
 }
 
 #if !defined(CONFIG_USER_ONLY)
-void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra)
+void r4k_invalidate_tlb (CPUMIPSState *env, int idx, int use_extra)
 {
     r4k_tlb_t *tlb;
     target_ulong addr;
diff --git a/target-mips/machine.c b/target-mips/machine.c
index a506ee0..23504ba 100644
--- a/target-mips/machine.c
+++ b/target-mips/machine.c
@@ -42,7 +42,7 @@ static void save_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
 
 void cpu_save(QEMUFile *f, void *opaque)
 {
-    CPUState *env = opaque;
+    CPUMIPSState *env = opaque;
     int i;
 
     /* Save active TC */
@@ -190,7 +190,7 @@ static void load_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
 
 int cpu_load(QEMUFile *f, void *opaque, int version_id)
 {
-    CPUState *env = opaque;
+    CPUMIPSState *env = opaque;
     int i;
 
     if (version_id != 3)
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 87e9799..3a20731 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -29,10 +29,10 @@
 #endif /* !defined(CONFIG_USER_ONLY) */
 
 #ifndef CONFIG_USER_ONLY
-static inline void cpu_mips_tlb_flush (CPUState *env, int flush_global);
+static inline void cpu_mips_tlb_flush (CPUMIPSState *env, int flush_global);
 #endif
 
-static inline void compute_hflags(CPUState *env)
+static inline void compute_hflags(CPUMIPSState *env)
 {
     env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
                      MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
@@ -750,14 +750,14 @@ void helper_sdm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
 
 #ifndef CONFIG_USER_ONLY
 /* SMP helpers.  */
-static int mips_vpe_is_wfi(CPUState *c)
+static int mips_vpe_is_wfi(CPUMIPSState *c)
 {
     /* If the VPE is halted but otherwise active, it means it's waiting for
        an interrupt.  */
     return c->halted && mips_vpe_active(c);
 }
 
-static inline void mips_vpe_wake(CPUState *c)
+static inline void mips_vpe_wake(CPUMIPSState *c)
 {
     /* Dont set ->halted = 0 directly, let it be done via cpu_has_work
        because there might be other conditions that state that c should
@@ -765,7 +765,7 @@ static inline void mips_vpe_wake(CPUState *c)
     cpu_interrupt(c, CPU_INTERRUPT_WAKE);
 }
 
-static inline void mips_vpe_sleep(CPUState *c)
+static inline void mips_vpe_sleep(CPUMIPSState *c)
 {
     /* The VPE was shut off, really go to bed.
        Reset any old _WAKE requests.  */
@@ -773,7 +773,7 @@ static inline void mips_vpe_sleep(CPUState *c)
     cpu_reset_interrupt(c, CPU_INTERRUPT_WAKE);
 }
 
-static inline void mips_tc_wake(CPUState *c, int tc)
+static inline void mips_tc_wake(CPUMIPSState *c, int tc)
 {
     /* FIXME: TC reschedule.  */
     if (mips_vpe_active(c) && !mips_vpe_is_wfi(c)) {
@@ -781,7 +781,7 @@ static inline void mips_tc_wake(CPUState *c, int tc)
     }
 }
 
-static inline void mips_tc_sleep(CPUState *c, int tc)
+static inline void mips_tc_sleep(CPUMIPSState *c, int tc)
 {
     /* FIXME: TC reschedule.  */
     if (!mips_vpe_active(c)) {
@@ -791,14 +791,14 @@ static inline void mips_tc_sleep(CPUState *c, int tc)
 
 /* tc should point to an int with the value of the global TC index.
    This function will transform it into a local index within the
-   returned CPUState.
+   returned CPUMIPSState.
 
    FIXME: This code assumes that all VPEs have the same number of TCs,
           which depends on runtime setup. Can probably be fixed by
-          walking the list of CPUStates.  */
-static CPUState *mips_cpu_map_tc(int *tc)
+          walking the list of CPUMIPSStates.  */
+static CPUMIPSState *mips_cpu_map_tc(int *tc)
 {
-    CPUState *other;
+    CPUMIPSState *other;
     int vpe_idx, nr_threads = env->nr_threads;
     int tc_idx = *tc;
 
@@ -823,7 +823,7 @@ static CPUState *mips_cpu_map_tc(int *tc)
    These helper call synchronizes the regs for a given cpu.  */
 
 /* Called for updates to CP0_Status.  */
-static void sync_c0_status(CPUState *cpu, int tc)
+static void sync_c0_status(CPUMIPSState *cpu, int tc)
 {
     int32_t tcstatus, *tcst;
     uint32_t v = cpu->CP0_Status;
@@ -858,7 +858,7 @@ static void sync_c0_status(CPUState *cpu, int tc)
 }
 
 /* Called for updates to CP0_TCStatus.  */
-static void sync_c0_tcstatus(CPUState *cpu, int tc, target_ulong v)
+static void sync_c0_tcstatus(CPUMIPSState *cpu, int tc, target_ulong v)
 {
     uint32_t status;
     uint32_t tcu, tmx, tasid, tksu;
@@ -889,7 +889,7 @@ static void sync_c0_tcstatus(CPUState *cpu, int tc, target_ulong v)
 }
 
 /* Called for updates to CP0_EntryHi.  */
-static void sync_c0_entryhi(CPUState *cpu, int tc)
+static void sync_c0_entryhi(CPUMIPSState *cpu, int tc)
 {
     int32_t *tcst;
     uint32_t asid, v = cpu->CP0_EntryHi;
@@ -935,7 +935,7 @@ target_ulong helper_mfc0_tcstatus (void)
 target_ulong helper_mftc0_tcstatus(void)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other_tc == other->current_tc)
         return other->active_tc.CP0_TCStatus;
@@ -951,7 +951,7 @@ target_ulong helper_mfc0_tcbind (void)
 target_ulong helper_mftc0_tcbind(void)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other_tc == other->current_tc)
         return other->active_tc.CP0_TCBind;
@@ -967,7 +967,7 @@ target_ulong helper_mfc0_tcrestart (void)
 target_ulong helper_mftc0_tcrestart(void)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other_tc == other->current_tc)
         return other->active_tc.PC;
@@ -983,7 +983,7 @@ target_ulong helper_mfc0_tchalt (void)
 target_ulong helper_mftc0_tchalt(void)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other_tc == other->current_tc)
         return other->active_tc.CP0_TCHalt;
@@ -999,7 +999,7 @@ target_ulong helper_mfc0_tccontext (void)
 target_ulong helper_mftc0_tccontext(void)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other_tc == other->current_tc)
         return other->active_tc.CP0_TCContext;
@@ -1015,7 +1015,7 @@ target_ulong helper_mfc0_tcschedule (void)
 target_ulong helper_mftc0_tcschedule(void)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other_tc == other->current_tc)
         return other->active_tc.CP0_TCSchedule;
@@ -1031,7 +1031,7 @@ target_ulong helper_mfc0_tcschefback (void)
 target_ulong helper_mftc0_tcschefback(void)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other_tc == other->current_tc)
         return other->active_tc.CP0_TCScheFBack;
@@ -1047,7 +1047,7 @@ target_ulong helper_mfc0_count (void)
 target_ulong helper_mftc0_entryhi(void)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     return other->CP0_EntryHi;
 }
@@ -1056,7 +1056,7 @@ target_ulong helper_mftc0_cause(void)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
     int32_t tccause;
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other_tc == other->current_tc) {
         tccause = other->CP0_Cause;
@@ -1070,7 +1070,7 @@ target_ulong helper_mftc0_cause(void)
 target_ulong helper_mftc0_status(void)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     return other->CP0_Status;
 }
@@ -1103,7 +1103,7 @@ target_ulong helper_mftc0_debug(void)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
     int32_t tcstatus;
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other_tc == other->current_tc)
         tcstatus = other->active_tc.CP0_Debug_tcstatus;
@@ -1201,7 +1201,7 @@ void helper_mtc0_vpecontrol (target_ulong arg1)
 void helper_mttc0_vpecontrol(target_ulong arg1)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
     uint32_t mask;
     uint32_t newval;
 
@@ -1217,7 +1217,7 @@ void helper_mttc0_vpecontrol(target_ulong arg1)
 target_ulong helper_mftc0_vpecontrol(void)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
     /* FIXME: Mask away return zero on read bits.  */
     return other->CP0_VPEControl;
 }
@@ -1225,7 +1225,7 @@ target_ulong helper_mftc0_vpecontrol(void)
 target_ulong helper_mftc0_vpeconf0(void)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     return other->CP0_VPEConf0;
 }
@@ -1250,7 +1250,7 @@ void helper_mtc0_vpeconf0 (target_ulong arg1)
 void helper_mttc0_vpeconf0(target_ulong arg1)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
     uint32_t mask = 0;
     uint32_t newval;
 
@@ -1311,7 +1311,7 @@ void helper_mtc0_tcstatus (target_ulong arg1)
 void helper_mttc0_tcstatus (target_ulong arg1)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other_tc == other->current_tc)
         other->active_tc.CP0_TCStatus = arg1;
@@ -1336,7 +1336,7 @@ void helper_mttc0_tcbind (target_ulong arg1)
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
     uint32_t mask = (1 << CP0TCBd_TBE);
     uint32_t newval;
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
         mask |= (1 << CP0TCBd_CurVPE);
@@ -1360,7 +1360,7 @@ void helper_mtc0_tcrestart (target_ulong arg1)
 void helper_mttc0_tcrestart (target_ulong arg1)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other_tc == other->current_tc) {
         other->active_tc.PC = arg1;
@@ -1390,7 +1390,7 @@ void helper_mtc0_tchalt (target_ulong arg1)
 void helper_mttc0_tchalt (target_ulong arg1)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     // TODO: Halt TC / Restart (if allocated+active) TC.
 
@@ -1414,7 +1414,7 @@ void helper_mtc0_tccontext (target_ulong arg1)
 void helper_mttc0_tccontext (target_ulong arg1)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other_tc == other->current_tc)
         other->active_tc.CP0_TCContext = arg1;
@@ -1430,7 +1430,7 @@ void helper_mtc0_tcschedule (target_ulong arg1)
 void helper_mttc0_tcschedule (target_ulong arg1)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other_tc == other->current_tc)
         other->active_tc.CP0_TCSchedule = arg1;
@@ -1446,7 +1446,7 @@ void helper_mtc0_tcschefback (target_ulong arg1)
 void helper_mttc0_tcschefback (target_ulong arg1)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other_tc == other->current_tc)
         other->active_tc.CP0_TCScheFBack = arg1;
@@ -1542,7 +1542,7 @@ void helper_mtc0_entryhi (target_ulong arg1)
 void helper_mttc0_entryhi(target_ulong arg1)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     other->CP0_EntryHi = arg1;
     sync_c0_entryhi(other, other_tc);
@@ -1584,7 +1584,7 @@ void helper_mtc0_status (target_ulong arg1)
 void helper_mttc0_status(target_ulong arg1)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     other->CP0_Status = arg1 & ~0xf1000018;
     sync_c0_status(other, other_tc);
@@ -1602,7 +1602,7 @@ void helper_mtc0_srsctl (target_ulong arg1)
     env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (arg1 & mask);
 }
 
-static void mtc0_cause(CPUState *cpu, target_ulong arg1)
+static void mtc0_cause(CPUMIPSState *cpu, target_ulong arg1)
 {
     uint32_t mask = 0x00C00300;
     uint32_t old = cpu->CP0_Cause;
@@ -1638,7 +1638,7 @@ void helper_mtc0_cause(target_ulong arg1)
 void helper_mttc0_cause(target_ulong arg1)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     mtc0_cause(other, arg1);
 }
@@ -1646,7 +1646,7 @@ void helper_mttc0_cause(target_ulong arg1)
 target_ulong helper_mftc0_epc(void)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     return other->CP0_EPC;
 }
@@ -1654,7 +1654,7 @@ target_ulong helper_mftc0_epc(void)
 target_ulong helper_mftc0_ebase(void)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     return other->CP0_EBase;
 }
@@ -1668,14 +1668,14 @@ void helper_mtc0_ebase (target_ulong arg1)
 void helper_mttc0_ebase(target_ulong arg1)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
     other->CP0_EBase = (other->CP0_EBase & ~0x3FFFF000) | (arg1 & 0x3FFFF000);
 }
 
 target_ulong helper_mftc0_configx(target_ulong idx)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     switch (idx) {
     case 0: return other->CP0_Config0;
@@ -1746,7 +1746,7 @@ void helper_mttc0_debug(target_ulong arg1)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
     uint32_t val = arg1 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     /* XXX: Might be wrong, check with EJTAG spec. */
     if (other_tc == other->current_tc)
@@ -1787,7 +1787,7 @@ void helper_mtc0_datahi (target_ulong arg1)
 target_ulong helper_mftgpr(uint32_t sel)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other_tc == other->current_tc)
         return other->active_tc.gpr[sel];
@@ -1798,7 +1798,7 @@ target_ulong helper_mftgpr(uint32_t sel)
 target_ulong helper_mftlo(uint32_t sel)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other_tc == other->current_tc)
         return other->active_tc.LO[sel];
@@ -1809,7 +1809,7 @@ target_ulong helper_mftlo(uint32_t sel)
 target_ulong helper_mfthi(uint32_t sel)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other_tc == other->current_tc)
         return other->active_tc.HI[sel];
@@ -1820,7 +1820,7 @@ target_ulong helper_mfthi(uint32_t sel)
 target_ulong helper_mftacx(uint32_t sel)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other_tc == other->current_tc)
         return other->active_tc.ACX[sel];
@@ -1831,7 +1831,7 @@ target_ulong helper_mftacx(uint32_t sel)
 target_ulong helper_mftdsp(void)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other_tc == other->current_tc)
         return other->active_tc.DSPControl;
@@ -1842,7 +1842,7 @@ target_ulong helper_mftdsp(void)
 void helper_mttgpr(target_ulong arg1, uint32_t sel)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other_tc == other->current_tc)
         other->active_tc.gpr[sel] = arg1;
@@ -1853,7 +1853,7 @@ void helper_mttgpr(target_ulong arg1, uint32_t sel)
 void helper_mttlo(target_ulong arg1, uint32_t sel)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other_tc == other->current_tc)
         other->active_tc.LO[sel] = arg1;
@@ -1864,7 +1864,7 @@ void helper_mttlo(target_ulong arg1, uint32_t sel)
 void helper_mtthi(target_ulong arg1, uint32_t sel)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other_tc == other->current_tc)
         other->active_tc.HI[sel] = arg1;
@@ -1875,7 +1875,7 @@ void helper_mtthi(target_ulong arg1, uint32_t sel)
 void helper_mttacx(target_ulong arg1, uint32_t sel)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other_tc == other->current_tc)
         other->active_tc.ACX[sel] = arg1;
@@ -1886,7 +1886,7 @@ void helper_mttacx(target_ulong arg1, uint32_t sel)
 void helper_mttdsp(target_ulong arg1)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
-    CPUState *other = mips_cpu_map_tc(&other_tc);
+    CPUMIPSState *other = mips_cpu_map_tc(&other_tc);
 
     if (other_tc == other->current_tc)
         other->active_tc.DSPControl = arg1;
@@ -1909,7 +1909,7 @@ target_ulong helper_emt(void)
 
 target_ulong helper_dvpe(void)
 {
-    CPUState *other_cpu = first_cpu;
+    CPUMIPSState *other_cpu = first_cpu;
     target_ulong prev = env->mvp->CP0_MVPControl;
 
     do {
@@ -1925,7 +1925,7 @@ target_ulong helper_dvpe(void)
 
 target_ulong helper_evpe(void)
 {
-    CPUState *other_cpu = first_cpu;
+    CPUMIPSState *other_cpu = first_cpu;
     target_ulong prev = env->mvp->CP0_MVPControl;
 
     do {
@@ -1981,14 +1981,14 @@ target_ulong helper_yield(target_ulong arg)
 
 #ifndef CONFIG_USER_ONLY
 /* TLB management */
-static void cpu_mips_tlb_flush (CPUState *env, int flush_global)
+static void cpu_mips_tlb_flush (CPUMIPSState *env, int flush_global)
 {
     /* Flush qemu's TLB and discard all shadowed entries.  */
     tlb_flush (env, flush_global);
     env->tlb->tlb_in_use = env->tlb->nb_tlb;
 }
 
-static void r4k_mips_tlb_flush_extra (CPUState *env, int first)
+static void r4k_mips_tlb_flush_extra (CPUMIPSState *env, int first)
 {
     /* Discard entries from env->tlb[first] onwards.  */
     while (env->tlb->tlb_in_use > first) {
@@ -2316,11 +2316,11 @@ static void do_unaligned_access (target_ulong addr, int is_write, int is_user, v
     helper_raise_exception ((is_write == 1) ? EXCP_AdES : EXCP_AdEL);
 }
 
-void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
+void tlb_fill(CPUMIPSState *env1, target_ulong addr, int is_write, int mmu_idx,
               void *retaddr)
 {
     TranslationBlock *tb;
-    CPUState *saved_env;
+    CPUMIPSState *saved_env;
     unsigned long pc;
     int ret;
 
@@ -2343,7 +2343,7 @@ void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
     env = saved_env;
 }
 
-void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr,
+void cpu_unassigned_access(CPUMIPSState *env1, target_phys_addr_t addr,
                            int is_write, int is_exec, int unused, int size)
 {
     env = env1;
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 5061e78..a663b74 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -602,7 +602,7 @@ static inline void gen_load_srsgpr (int from, int to)
         TCGv_i32 t2 = tcg_temp_new_i32();
         TCGv_ptr addr = tcg_temp_new_ptr();
 
-        tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
+        tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
         tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
         tcg_gen_andi_i32(t2, t2, 0xf);
         tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
@@ -625,7 +625,7 @@ static inline void gen_store_srsgpr (int from, int to)
         TCGv_ptr addr = tcg_temp_new_ptr();
 
         gen_load_gpr(t0, from);
-        tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
+        tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
         tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
         tcg_gen_andi_i32(t2, t2, 0xf);
         tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
@@ -642,28 +642,28 @@ static inline void gen_store_srsgpr (int from, int to)
 /* Floating point register moves. */
 static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
 {
-    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
+    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
 }
 
 static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
 {
-    tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
+    tcg_gen_st_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
 }
 
 static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
 {
-    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
+    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
 }
 
 static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
 {
-    tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
+    tcg_gen_st_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
 }
 
 static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
 {
     if (ctx->hflags & MIPS_HFLAG_F64) {
-        tcg_gen_ld_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
+        tcg_gen_ld_i64(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].d));
     } else {
         TCGv_i32 t0 = tcg_temp_new_i32();
         TCGv_i32 t1 = tcg_temp_new_i32();
@@ -678,7 +678,7 @@ static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
 static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
 {
     if (ctx->hflags & MIPS_HFLAG_F64) {
-        tcg_gen_st_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
+        tcg_gen_st_i64(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].d));
     } else {
         TCGv_i64 t0 = tcg_temp_new_i64();
         TCGv_i32 t1 = tcg_temp_new_i32();
@@ -728,7 +728,7 @@ static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
     }
 }
 
-static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
+static inline void restore_cpu_state (CPUMIPSState *env, DisasContext *ctx)
 {
     ctx->saved_hflags = ctx->hflags;
     switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
@@ -826,7 +826,7 @@ static inline void check_cp1_registers(DisasContext *ctx, int regs)
 
 /* This code generates a "reserved instruction" exception if the
    CPU does not support the instruction set corresponding to flags. */
-static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
+static inline void check_insn(CPUMIPSState *env, DisasContext *ctx, int flags)
 {
     if (unlikely(!(env->insn_flags & flags)))
         generate_exception(ctx, EXCP_RI);
@@ -940,8 +940,8 @@ static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx)    \
     TCGv t0 = tcg_temp_new();                                              \
     tcg_gen_mov_tl(t0, arg1);                                              \
     tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx);                         \
-    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, lladdr));                \
-    tcg_gen_st_tl(ret, cpu_env, offsetof(CPUState, llval));                \
+    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr));                \
+    tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval));                \
     tcg_temp_free(t0);                                                     \
 }
 #else
@@ -967,14 +967,14 @@ static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx)
                                                                              \
     tcg_gen_andi_tl(t0, arg2, almask);                                       \
     tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);                              \
-    tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr));          \
+    tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));          \
     generate_exception(ctx, EXCP_AdES);                                      \
     gen_set_label(l1);                                                       \
-    tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, lladdr));                  \
+    tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr));                  \
     tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2);                            \
     tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20));                        \
-    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, llreg));                   \
-    tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUState, llnewval));              \
+    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg));                   \
+    tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval));              \
     gen_helper_0i(raise_exception, EXCP_SC);                                 \
     gen_set_label(l2);                                                       \
     tcg_gen_movi_tl(t0, 0);                                                  \
@@ -1025,7 +1025,7 @@ static target_ulong pc_relative_pc (DisasContext *ctx)
 }
 
 /* Load */
-static void gen_ld (CPUState *env, DisasContext *ctx, uint32_t opc,
+static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
                     int rt, int base, int16_t offset)
 {
     const char *opn = "ld";
@@ -1313,7 +1313,7 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
     tcg_temp_free(t0);
 }
 
-static void gen_cop1_ldst(CPUState *env, DisasContext *ctx,
+static void gen_cop1_ldst(CPUMIPSState *env, DisasContext *ctx,
                           uint32_t op, int rt, int rs, int16_t imm)
 {
     if (env->CP0_Config1 & (1 << CP0C1_FP)) {
@@ -1325,7 +1325,7 @@ static void gen_cop1_ldst(CPUState *env, DisasContext *ctx,
 }
 
 /* Arithmetic with immediate operand */
-static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
+static void gen_arith_imm (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
                            int rt, int rs, int16_t imm)
 {
     target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
@@ -1413,7 +1413,7 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
 }
 
 /* Logic with immediate operand */
-static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
+static void gen_logic_imm (CPUMIPSState *env, uint32_t opc, int rt, int rs, int16_t imm)
 {
     target_ulong uimm;
     const char *opn = "imm logic";
@@ -1456,7 +1456,7 @@ static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t
 }
 
 /* Set on less than with immediate operand */
-static void gen_slt_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
+static void gen_slt_imm (CPUMIPSState *env, uint32_t opc, int rt, int rs, int16_t imm)
 {
     target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
     const char *opn = "imm arith";
@@ -1485,7 +1485,7 @@ static void gen_slt_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t im
 }
 
 /* Shifts with immediate operand */
-static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
+static void gen_shift_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
                           int rt, int rs, int16_t imm)
 {
     target_ulong uimm = ((uint16_t)imm) & 0x1f;
@@ -1577,7 +1577,7 @@ static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
 }
 
 /* Arithmetic */
-static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
+static void gen_arith (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
                        int rd, int rs, int rt)
 {
     const char *opn = "arith";
@@ -1757,7 +1757,7 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
 }
 
 /* Conditional move */
-static void gen_cond_move (CPUState *env, uint32_t opc, int rd, int rs, int rt)
+static void gen_cond_move (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
 {
     const char *opn = "cond move";
     int l1;
@@ -1795,7 +1795,7 @@ static void gen_cond_move (CPUState *env, uint32_t opc, int rd, int rs, int rt)
 }
 
 /* Logic */
-static void gen_logic (CPUState *env, uint32_t opc, int rd, int rs, int rt)
+static void gen_logic (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
 {
     const char *opn = "logic";
 
@@ -1856,7 +1856,7 @@ static void gen_logic (CPUState *env, uint32_t opc, int rd, int rs, int rt)
 }
 
 /* Set on lower than */
-static void gen_slt (CPUState *env, uint32_t opc, int rd, int rs, int rt)
+static void gen_slt (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
 {
     const char *opn = "slt";
     TCGv t0, t1;
@@ -1888,7 +1888,7 @@ static void gen_slt (CPUState *env, uint32_t opc, int rd, int rs, int rt)
 }
 
 /* Shifts */
-static void gen_shift (CPUState *env, DisasContext *ctx, uint32_t opc,
+static void gen_shift (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
                        int rd, int rs, int rt)
 {
     const char *opn = "shifts";
@@ -3171,7 +3171,7 @@ static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
     tcg_gen_st_tl(arg, cpu_env, off);
 }
 
-static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
+static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
 {
     const char *rn = "invalid";
 
@@ -3182,7 +3182,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 0:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
             rn = "Index";
             break;
         case 1:
@@ -3212,37 +3212,37 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
             break;
         case 1:
             check_insn(env, ctx, ASE_MT);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
             rn = "VPEControl";
             break;
         case 2:
             check_insn(env, ctx, ASE_MT);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
             rn = "VPEConf0";
             break;
         case 3:
             check_insn(env, ctx, ASE_MT);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
             rn = "VPEConf1";
             break;
         case 4:
             check_insn(env, ctx, ASE_MT);
-            gen_mfc0_load64(arg, offsetof(CPUState, CP0_YQMask));
+            gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
             rn = "YQMask";
             break;
         case 5:
             check_insn(env, ctx, ASE_MT);
-            gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPESchedule));
+            gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
             rn = "VPESchedule";
             break;
         case 6:
             check_insn(env, ctx, ASE_MT);
-            gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPEScheFBack));
+            gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
             rn = "VPEScheFBack";
             break;
         case 7:
             check_insn(env, ctx, ASE_MT);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
             rn = "VPEOpt";
             break;
         default:
@@ -3252,7 +3252,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 2:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
             tcg_gen_ext32s_tl(arg, arg);
             rn = "EntryLo0";
             break;
@@ -3298,7 +3298,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 3:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
             tcg_gen_ext32s_tl(arg, arg);
             rn = "EntryLo1";
             break;
@@ -3309,7 +3309,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 4:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
             tcg_gen_ext32s_tl(arg, arg);
             rn = "Context";
             break;
@@ -3324,12 +3324,12 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 5:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
             rn = "PageMask";
             break;
         case 1:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
             rn = "PageGrain";
             break;
         default:
@@ -3339,32 +3339,32 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 6:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
             rn = "Wired";
             break;
         case 1:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
             rn = "SRSConf0";
             break;
         case 2:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
             rn = "SRSConf1";
             break;
         case 3:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
             rn = "SRSConf2";
             break;
         case 4:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
             rn = "SRSConf3";
             break;
         case 5:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
             rn = "SRSConf4";
             break;
         default:
@@ -3375,7 +3375,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
         switch (sel) {
         case 0:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
             rn = "HWREna";
             break;
         default:
@@ -3385,7 +3385,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 8:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
             tcg_gen_ext32s_tl(arg, arg);
             rn = "BadVAddr";
             break;
@@ -3416,7 +3416,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 10:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
             tcg_gen_ext32s_tl(arg, arg);
             rn = "EntryHi";
             break;
@@ -3427,7 +3427,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 11:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
             rn = "Compare";
             break;
         /* 6,7 are implementation dependent */
@@ -3438,22 +3438,22 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 12:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
             rn = "Status";
             break;
         case 1:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
             rn = "IntCtl";
             break;
         case 2:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
             rn = "SRSCtl";
             break;
         case 3:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
             rn = "SRSMap";
             break;
         default:
@@ -3463,7 +3463,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 13:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
             rn = "Cause";
             break;
         default:
@@ -3473,7 +3473,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 14:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
             tcg_gen_ext32s_tl(arg, arg);
             rn = "EPC";
             break;
@@ -3484,12 +3484,12 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 15:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
             rn = "PRid";
             break;
         case 1:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
             rn = "EBase";
             break;
         default:
@@ -3499,29 +3499,29 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 16:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
             rn = "Config";
             break;
         case 1:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
             rn = "Config1";
             break;
         case 2:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
             rn = "Config2";
             break;
         case 3:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
             rn = "Config3";
             break;
         /* 4,5 are reserved */
         /* 6,7 are implementation dependent */
         case 6:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
             rn = "Config6";
             break;
         case 7:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
             rn = "Config7";
             break;
         default:
@@ -3563,7 +3563,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
         case 0:
 #if defined(TARGET_MIPS64)
             check_insn(env, ctx, ISA_MIPS3);
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
             tcg_gen_ext32s_tl(arg, arg);
             rn = "XContext";
             break;
@@ -3576,7 +3576,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
        /* Officially reserved, but sel 0 is used for R1x000 framemask */
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
             rn = "Framemask";
             break;
         default:
@@ -3617,7 +3617,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
         switch (sel) {
         case 0:
             /* EJTAG support */
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
             tcg_gen_ext32s_tl(arg, arg);
             rn = "DEPC";
             break;
@@ -3628,7 +3628,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 25:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
             rn = "Performance0";
             break;
         case 1:
@@ -3683,14 +3683,14 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
         case 2:
         case 4:
         case 6:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
             rn = "TagLo";
             break;
         case 1:
         case 3:
         case 5:
         case 7:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
             rn = "DataLo";
             break;
         default:
@@ -3703,14 +3703,14 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
         case 2:
         case 4:
         case 6:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
             rn = "TagHi";
             break;
         case 1:
         case 3:
         case 5:
         case 7:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
             rn = "DataHi";
             break;
         default:
@@ -3720,7 +3720,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 30:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
             tcg_gen_ext32s_tl(arg, arg);
             rn = "ErrorEPC";
             break;
@@ -3732,7 +3732,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
         switch (sel) {
         case 0:
             /* EJTAG support */
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
             rn = "DESAVE";
             break;
         default:
@@ -3751,7 +3751,7 @@ die:
     generate_exception(ctx, EXCP_RI);
 }
 
-static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
+static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
 {
     const char *rn = "invalid";
 
@@ -3815,12 +3815,12 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
             break;
         case 5:
             check_insn(env, ctx, ASE_MT);
-            gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPESchedule));
+            gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
             rn = "VPESchedule";
             break;
         case 6:
             check_insn(env, ctx, ASE_MT);
-            gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPEScheFBack));
+            gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
             rn = "VPEScheFBack";
             break;
         case 7:
@@ -4024,7 +4024,7 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
             break;
         case 3:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
+            gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
             rn = "SRSMap";
@@ -4047,7 +4047,7 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 14:
         switch (sel) {
         case 0:
-            gen_mtc0_store64(arg, offsetof(CPUState, CP0_EPC));
+            gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
             rn = "EPC";
             break;
         default:
@@ -4207,7 +4207,7 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
         switch (sel) {
         case 0:
             /* EJTAG support */
-            gen_mtc0_store64(arg, offsetof(CPUState, CP0_DEPC));
+            gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
             rn = "DEPC";
             break;
         default:
@@ -4310,7 +4310,7 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 30:
         switch (sel) {
         case 0:
-            gen_mtc0_store64(arg, offsetof(CPUState, CP0_ErrorEPC));
+            gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
             rn = "ErrorEPC";
             break;
         default:
@@ -4321,7 +4321,7 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
         switch (sel) {
         case 0:
             /* EJTAG support */
-            gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
+            gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
             rn = "DESAVE";
             break;
         default:
@@ -4348,7 +4348,7 @@ die:
 }
 
 #if defined(TARGET_MIPS64)
-static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
+static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
 {
     const char *rn = "invalid";
 
@@ -4359,7 +4359,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 0:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
             rn = "Index";
             break;
         case 1:
@@ -4389,37 +4389,37 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
             break;
         case 1:
             check_insn(env, ctx, ASE_MT);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
             rn = "VPEControl";
             break;
         case 2:
             check_insn(env, ctx, ASE_MT);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
             rn = "VPEConf0";
             break;
         case 3:
             check_insn(env, ctx, ASE_MT);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
             rn = "VPEConf1";
             break;
         case 4:
             check_insn(env, ctx, ASE_MT);
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_YQMask));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
             rn = "YQMask";
             break;
         case 5:
             check_insn(env, ctx, ASE_MT);
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
             rn = "VPESchedule";
             break;
         case 6:
             check_insn(env, ctx, ASE_MT);
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
             rn = "VPEScheFBack";
             break;
         case 7:
             check_insn(env, ctx, ASE_MT);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
             rn = "VPEOpt";
             break;
         default:
@@ -4429,7 +4429,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 2:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
             rn = "EntryLo0";
             break;
         case 1:
@@ -4474,7 +4474,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 3:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
             rn = "EntryLo1";
             break;
         default:
@@ -4484,7 +4484,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 4:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
             rn = "Context";
             break;
         case 1:
@@ -4498,12 +4498,12 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 5:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
             rn = "PageMask";
             break;
         case 1:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
             rn = "PageGrain";
             break;
         default:
@@ -4513,32 +4513,32 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 6:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
             rn = "Wired";
             break;
         case 1:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
             rn = "SRSConf0";
             break;
         case 2:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
             rn = "SRSConf1";
             break;
         case 3:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
             rn = "SRSConf2";
             break;
         case 4:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
             rn = "SRSConf3";
             break;
         case 5:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
             rn = "SRSConf4";
             break;
         default:
@@ -4549,7 +4549,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
         switch (sel) {
         case 0:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
             rn = "HWREna";
             break;
         default:
@@ -4559,7 +4559,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 8:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
             rn = "BadVAddr";
             break;
         default:
@@ -4589,7 +4589,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 10:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
             rn = "EntryHi";
             break;
         default:
@@ -4599,7 +4599,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 11:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
             rn = "Compare";
             break;
         /* 6,7 are implementation dependent */
@@ -4610,22 +4610,22 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 12:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
             rn = "Status";
             break;
         case 1:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
             rn = "IntCtl";
             break;
         case 2:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
             rn = "SRSCtl";
             break;
         case 3:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
             rn = "SRSMap";
             break;
         default:
@@ -4635,7 +4635,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 13:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
             rn = "Cause";
             break;
         default:
@@ -4645,7 +4645,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 14:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
             rn = "EPC";
             break;
         default:
@@ -4655,12 +4655,12 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 15:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
             rn = "PRid";
             break;
         case 1:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
             rn = "EBase";
             break;
         default:
@@ -4670,28 +4670,28 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 16:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
             rn = "Config";
             break;
         case 1:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
             rn = "Config1";
             break;
         case 2:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
             rn = "Config2";
             break;
         case 3:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
             rn = "Config3";
             break;
        /* 6,7 are implementation dependent */
         case 6:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
             rn = "Config6";
             break;
         case 7:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
             rn = "Config7";
             break;
         default:
@@ -4732,7 +4732,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
         switch (sel) {
         case 0:
             check_insn(env, ctx, ISA_MIPS3);
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
             rn = "XContext";
             break;
         default:
@@ -4743,7 +4743,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
        /* Officially reserved, but sel 0 is used for R1x000 framemask */
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
             rn = "Framemask";
             break;
         default:
@@ -4784,7 +4784,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
         switch (sel) {
         case 0:
             /* EJTAG support */
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
             rn = "DEPC";
             break;
         default:
@@ -4794,7 +4794,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 25:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
             rn = "Performance0";
             break;
         case 1:
@@ -4850,14 +4850,14 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
         case 2:
         case 4:
         case 6:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
             rn = "TagLo";
             break;
         case 1:
         case 3:
         case 5:
         case 7:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
             rn = "DataLo";
             break;
         default:
@@ -4870,14 +4870,14 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
         case 2:
         case 4:
         case 6:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
             rn = "TagHi";
             break;
         case 1:
         case 3:
         case 5:
         case 7:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
             rn = "DataHi";
             break;
         default:
@@ -4887,7 +4887,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 30:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
             rn = "ErrorEPC";
             break;
         default:
@@ -4898,7 +4898,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
         switch (sel) {
         case 0:
             /* EJTAG support */
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
             rn = "DESAVE";
             break;
         default:
@@ -4917,7 +4917,7 @@ die:
     generate_exception(ctx, EXCP_RI);
 }
 
-static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
+static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
 {
     const char *rn = "invalid";
 
@@ -4981,12 +4981,12 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
             break;
         case 5:
             check_insn(env, ctx, ASE_MT);
-            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
+            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
             rn = "VPESchedule";
             break;
         case 6:
             check_insn(env, ctx, ASE_MT);
-            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
+            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
             rn = "VPEScheFBack";
             break;
         case 7:
@@ -5194,7 +5194,7 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
             break;
         case 3:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
+            gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
             rn = "SRSMap";
@@ -5227,7 +5227,7 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 14:
         switch (sel) {
         case 0:
-            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
+            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
             rn = "EPC";
             break;
         default:
@@ -5374,7 +5374,7 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
         switch (sel) {
         case 0:
             /* EJTAG support */
-            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
+            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
             rn = "DEPC";
             break;
         default:
@@ -5477,7 +5477,7 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 30:
         switch (sel) {
         case 0:
-            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
+            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
             rn = "ErrorEPC";
             break;
         default:
@@ -5488,7 +5488,7 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
         switch (sel) {
         case 0:
             /* EJTAG support */
-            gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
+            gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
             rn = "DESAVE";
             break;
         default:
@@ -5515,7 +5515,7 @@ die:
 }
 #endif /* TARGET_MIPS64 */
 
-static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
+static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
                      int u, int sel, int h)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
@@ -5732,7 +5732,7 @@ die:
     generate_exception(ctx, EXCP_RI);
 }
 
-static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
+static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
                      int u, int sel, int h)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
@@ -5929,7 +5929,7 @@ die:
     generate_exception(ctx, EXCP_RI);
 }
 
-static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
+static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
 {
     const char *opn = "ldst";
 
@@ -6053,7 +6053,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int
 #endif /* !CONFIG_USER_ONLY */
 
 /* CP1 Branches (before delay slot) */
-static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
+static void gen_compute_branch1 (CPUMIPSState *env, DisasContext *ctx, uint32_t op,
                                  int32_t cc, int32_t offset)
 {
     target_ulong btarget;
@@ -8108,7 +8108,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
 }
 
 static void
-gen_rdhwr (CPUState *env, DisasContext *ctx, int rt, int rd)
+gen_rdhwr (CPUMIPSState *env, DisasContext *ctx, int rt, int rd)
 {
     TCGv t0;
 
@@ -8138,7 +8138,7 @@ gen_rdhwr (CPUState *env, DisasContext *ctx, int rt, int rd)
         break;
     case 29:
 #if defined(CONFIG_USER_ONLY)
-        tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
+        tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, tls_value));
         gen_store_gpr(t0, rt);
         break;
 #else
@@ -8153,7 +8153,7 @@ gen_rdhwr (CPUState *env, DisasContext *ctx, int rt, int rd)
     tcg_temp_free(t0);
 }
 
-static void handle_delay_slot (CPUState *env, DisasContext *ctx,
+static void handle_delay_slot (CPUMIPSState *env, DisasContext *ctx,
                                int insn_bytes)
 {
     if (ctx->hflags & MIPS_HFLAG_BMASK) {
@@ -8619,7 +8619,7 @@ static void gen_addiupc (DisasContext *ctx, int rx, int imm,
 }
 
 #if defined(TARGET_MIPS64)
-static void decode_i64_mips16 (CPUState *env, DisasContext *ctx,
+static void decode_i64_mips16 (CPUMIPSState *env, DisasContext *ctx,
                                int ry, int funct, int16_t offset,
                                int extended)
 {
@@ -8671,7 +8671,7 @@ static void decode_i64_mips16 (CPUState *env, DisasContext *ctx,
 }
 #endif
 
-static int decode_extended_mips16_opc (CPUState *env, DisasContext *ctx,
+static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
                                        int *is_branch)
 {
     int extend = lduw_code(ctx->pc + 2);
@@ -8863,7 +8863,7 @@ static int decode_extended_mips16_opc (CPUState *env, DisasContext *ctx,
     return 4;
 }
 
-static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
+static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
                               int *is_branch)
 {
     int rx, ry;
@@ -9777,14 +9777,14 @@ static int mmreg2 (int r)
 /* Zero-extended immediate */
 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
 
-static void gen_addiur1sp (CPUState *env, DisasContext *ctx)
+static void gen_addiur1sp (CPUMIPSState *env, DisasContext *ctx)
 {
     int rd = mmreg(uMIPS_RD(ctx->opcode));
 
     gen_arith_imm(env, ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
 }
 
-static void gen_addiur2 (CPUState *env, DisasContext *ctx)
+static void gen_addiur2 (CPUMIPSState *env, DisasContext *ctx)
 {
     static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
     int rd = mmreg(uMIPS_RD(ctx->opcode));
@@ -9793,7 +9793,7 @@ static void gen_addiur2 (CPUState *env, DisasContext *ctx)
     gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
 }
 
-static void gen_addiusp (CPUState *env, DisasContext *ctx)
+static void gen_addiusp (CPUMIPSState *env, DisasContext *ctx)
 {
     int encoded = ZIMM(ctx->opcode, 1, 9);
     int decoded;
@@ -9811,7 +9811,7 @@ static void gen_addiusp (CPUState *env, DisasContext *ctx)
     gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, decoded << 2);
 }
 
-static void gen_addius5 (CPUState *env, DisasContext *ctx)
+static void gen_addius5 (CPUMIPSState *env, DisasContext *ctx)
 {
     int imm = SIMM(ctx->opcode, 1, 4);
     int rd = (ctx->opcode >> 5) & 0x1f;
@@ -9819,7 +9819,7 @@ static void gen_addius5 (CPUState *env, DisasContext *ctx)
     gen_arith_imm(env, ctx, OPC_ADDIU, rd, rd, imm);
 }
 
-static void gen_andi16 (CPUState *env, DisasContext *ctx)
+static void gen_andi16 (CPUMIPSState *env, DisasContext *ctx)
 {
     static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
                                  31, 32, 63, 64, 255, 32768, 65535 };
@@ -9872,7 +9872,7 @@ static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
 }
 
 
-static void gen_pool16c_insn (CPUState *env, DisasContext *ctx, int *is_branch)
+static void gen_pool16c_insn (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
 {
     int rd = mmreg((ctx->opcode >> 3) & 0x7);
     int rs = mmreg(ctx->opcode & 0x7);
@@ -10087,7 +10087,7 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
     tcg_temp_free(t1);
 }
 
-static void gen_pool32axf (CPUState *env, DisasContext *ctx, int rt, int rs,
+static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
                            int *is_branch)
 {
     int extension = (ctx->opcode >> 6) & 0x3f;
@@ -10361,7 +10361,7 @@ enum {
     FMT_DWL_L = 2
 };
 
-static void gen_pool32fxf (CPUState *env, DisasContext *ctx, int rt, int rs)
+static void gen_pool32fxf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
 {
     int extension = (ctx->opcode >> 6) & 0x3ff;
     uint32_t mips32_op;
@@ -10607,7 +10607,7 @@ static void gen_pool32fxf (CPUState *env, DisasContext *ctx, int rt, int rs)
     }
 }
 
-static void decode_micromips32_opc (CPUState *env, DisasContext *ctx,
+static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
                                     uint16_t insn_hw1, int *is_branch)
 {
     int32_t offset;
@@ -11365,7 +11365,7 @@ static void decode_micromips32_opc (CPUState *env, DisasContext *ctx,
     }
 }
 
-static int decode_micromips_opc (CPUState *env, DisasContext *ctx, int *is_branch)
+static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
 {
     uint32_t op;
 
@@ -11682,7 +11682,7 @@ static int decode_micromips_opc (CPUState *env, DisasContext *ctx, int *is_branc
 
 #endif
 
-static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
+static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
 {
     int32_t offset;
     int rs, rt, rd, sa;
@@ -12369,7 +12369,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
 }
 
 static inline void
-gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
+gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
                                 int search_pc)
 {
     DisasContext ctx;
@@ -12522,17 +12522,17 @@ done_generating:
 #endif
 }
 
-void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
+void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 0);
 }
 
-void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
+void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 1);
 }
 
-static void fpu_dump_state(CPUState *env, FILE *f, fprintf_function fpu_fprintf,
+static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
                            int flags)
 {
     int i;
@@ -12579,7 +12579,7 @@ static void fpu_dump_state(CPUState *env, FILE *f, fprintf_function fpu_fprintf,
 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
 
 static void
-cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
+cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
                                 fprintf_function cpu_fprintf,
                                 int flags)
 {
@@ -12606,7 +12606,7 @@ cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
 }
 #endif
 
-void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
+void cpu_dump_state (CPUMIPSState *env, FILE *f, fprintf_function cpu_fprintf,
                      int flags)
 {
     int i;
@@ -12648,36 +12648,36 @@ static void mips_tcg_init(void)
     TCGV_UNUSED(cpu_gpr[0]);
     for (i = 1; i < 32; i++)
         cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
-                                        offsetof(CPUState, active_tc.gpr[i]),
+                                        offsetof(CPUMIPSState, active_tc.gpr[i]),
                                         regnames[i]);
     cpu_PC = tcg_global_mem_new(TCG_AREG0,
-                                offsetof(CPUState, active_tc.PC), "PC");
+                                offsetof(CPUMIPSState, active_tc.PC), "PC");
     for (i = 0; i < MIPS_DSP_ACC; i++) {
         cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
-                                       offsetof(CPUState, active_tc.HI[i]),
+                                       offsetof(CPUMIPSState, active_tc.HI[i]),
                                        regnames_HI[i]);
         cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
-                                       offsetof(CPUState, active_tc.LO[i]),
+                                       offsetof(CPUMIPSState, active_tc.LO[i]),
                                        regnames_LO[i]);
         cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
-                                        offsetof(CPUState, active_tc.ACX[i]),
+                                        offsetof(CPUMIPSState, active_tc.ACX[i]),
                                         regnames_ACX[i]);
     }
     cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
-                                     offsetof(CPUState, active_tc.DSPControl),
+                                     offsetof(CPUMIPSState, active_tc.DSPControl),
                                      "DSPControl");
     bcond = tcg_global_mem_new(TCG_AREG0,
-                               offsetof(CPUState, bcond), "bcond");
+                               offsetof(CPUMIPSState, bcond), "bcond");
     btarget = tcg_global_mem_new(TCG_AREG0,
-                                 offsetof(CPUState, btarget), "btarget");
+                                 offsetof(CPUMIPSState, btarget), "btarget");
     hflags = tcg_global_mem_new_i32(TCG_AREG0,
-                                    offsetof(CPUState, hflags), "hflags");
+                                    offsetof(CPUMIPSState, hflags), "hflags");
 
     fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
-                                      offsetof(CPUState, active_fpu.fcr0),
+                                      offsetof(CPUMIPSState, active_fpu.fcr0),
                                       "fcr0");
     fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
-                                       offsetof(CPUState, active_fpu.fcr31),
+                                       offsetof(CPUMIPSState, active_fpu.fcr31),
                                        "fcr31");
 
     /* register helpers */
@@ -12841,7 +12841,7 @@ void cpu_state_reset(CPUMIPSState *env)
     env->exception_index = EXCP_NONE;
 }
 
-void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
 {
     env->active_tc.PC = gen_opc_pc[pc_pos];
     env->hflags &= ~MIPS_HFLAG_BMASK;
commit 68cee38a9c228ada5f7cac611a229f8c6d2674c6
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:22 2012 +0100

    target-microblaze: Don't overuse CPUState
    
    Scripted conversion:
      sed -i "s/CPUState/CPUMBState/g" target-microblaze/*.[hc]
      sed -i "s/#define CPUMBState/#define CPUState/" target-microblaze/cpu.h
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index 94ec43b..6ae5649 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -250,7 +250,7 @@ typedef struct CPUMBState {
 #define DRTE_FLAG	(1 << 17)
 #define DRTB_FLAG	(1 << 18)
 #define D_FLAG		(1 << 19)  /* Bit in ESR.  */
-/* TB dependent CPUState.  */
+/* TB dependent CPUMBState.  */
 #define IFLAGS_TB_MASK  (D_FLAG | IMM_FLAG | DRTI_FLAG | DRTE_FLAG | DRTB_FLAG)
     uint32_t iflags;
 
@@ -266,10 +266,10 @@ typedef struct CPUMBState {
     CPU_COMMON
 } CPUMBState;
 
-CPUState *cpu_mb_init(const char *cpu_model);
-int cpu_mb_exec(CPUState *s);
-void cpu_mb_close(CPUState *s);
-void do_interrupt(CPUState *env);
+CPUMBState *cpu_mb_init(const char *cpu_model);
+int cpu_mb_exec(CPUMBState *s);
+void cpu_mb_close(CPUMBState *s);
+void do_interrupt(CPUMBState *env);
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
    is returned if the signal was handled by the virtual CPU.  */
@@ -305,7 +305,7 @@ enum {
 #define MMU_USER_IDX    2
 /* See NB_MMU_MODES further up the file.  */
 
-static inline int cpu_mmu_index (CPUState *env)
+static inline int cpu_mmu_index (CPUMBState *env)
 {
         /* Are we in nommu mode?.  */
         if (!(env->sregs[SR_MSR] & MSR_VM))
@@ -316,12 +316,12 @@ static inline int cpu_mmu_index (CPUState *env)
         return MMU_KERNEL_IDX;
 }
 
-int cpu_mb_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
+int cpu_mb_handle_mmu_fault(CPUMBState *env, target_ulong address, int rw,
                             int mmu_idx);
 #define cpu_handle_mmu_fault cpu_mb_handle_mmu_fault
 
 #if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
+static inline void cpu_clone_regs(CPUMBState *env, target_ulong newsp)
 {
     if (newsp)
         env->regs[R_SP] = newsp;
@@ -329,23 +329,23 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
 }
 #endif
 
-static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
+static inline void cpu_set_tls(CPUMBState *env, target_ulong newtls)
 {
 }
 
-static inline int cpu_interrupts_enabled(CPUState *env)
+static inline int cpu_interrupts_enabled(CPUMBState *env)
 {
     return env->sregs[SR_MSR] & MSR_IE;
 }
 
 #include "cpu-all.h"
 
-static inline target_ulong cpu_get_pc(CPUState *env)
+static inline target_ulong cpu_get_pc(CPUMBState *env)
 {
     return env->sregs[SR_PC];
 }
 
-static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+static inline void cpu_get_tb_cpu_state(CPUMBState *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
     *pc = env->sregs[SR_PC];
@@ -355,18 +355,18 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
 }
 
 #if !defined(CONFIG_USER_ONLY)
-void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr,
+void cpu_unassigned_access(CPUMBState *env1, target_phys_addr_t addr,
                            int is_write, int is_exec, int is_asi, int size);
 #endif
 
-static inline bool cpu_has_work(CPUState *env)
+static inline bool cpu_has_work(CPUMBState *env)
 {
     return env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
 }
 
 #include "exec-all.h"
 
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+static inline void cpu_pc_from_tb(CPUMBState *env, TranslationBlock *tb)
 {
     env->sregs[SR_PC] = tb->pc;
 }
diff --git a/target-microblaze/helper.c b/target-microblaze/helper.c
index e1355ff..6e0e411 100644
--- a/target-microblaze/helper.c
+++ b/target-microblaze/helper.c
@@ -25,13 +25,13 @@
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt (CPUState *env)
+void do_interrupt (CPUMBState *env)
 {
     env->exception_index = -1;
     env->regs[14] = env->sregs[SR_PC];
 }
 
-int cpu_mb_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
+int cpu_mb_handle_mmu_fault(CPUMBState * env, target_ulong address, int rw,
                             int mmu_idx)
 {
     env->exception_index = 0xaa;
@@ -41,7 +41,7 @@ int cpu_mb_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
 
 #else /* !CONFIG_USER_ONLY */
 
-int cpu_mb_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
+int cpu_mb_handle_mmu_fault (CPUMBState *env, target_ulong address, int rw,
                              int mmu_idx)
 {
     unsigned int hit;
@@ -107,7 +107,7 @@ int cpu_mb_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
     return r;
 }
 
-void do_interrupt(CPUState *env)
+void do_interrupt(CPUMBState *env)
 {
     uint32_t t;
 
@@ -255,7 +255,7 @@ void do_interrupt(CPUState *env)
     }
 }
 
-target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_debug(CPUMBState * env, target_ulong addr)
 {
     target_ulong vaddr, paddr = 0;
     struct microblaze_mmu_lookup lu;
diff --git a/target-microblaze/mmu.c b/target-microblaze/mmu.c
index 7c34ac0..43092e5 100644
--- a/target-microblaze/mmu.c
+++ b/target-microblaze/mmu.c
@@ -31,7 +31,7 @@ static unsigned int tlb_decode_size(unsigned int f)
     return sizes[f];
 }
 
-static void mmu_flush_idx(CPUState *env, unsigned int idx)
+static void mmu_flush_idx(CPUMBState *env, unsigned int idx)
 {
     struct microblaze_mmu *mmu = &env->mmu;
     unsigned int tlb_size;
@@ -51,7 +51,7 @@ static void mmu_flush_idx(CPUState *env, unsigned int idx)
     }
 }
 
-static void mmu_change_pid(CPUState *env, unsigned int newpid) 
+static void mmu_change_pid(CPUMBState *env, unsigned int newpid) 
 {
     struct microblaze_mmu *mmu = &env->mmu;
     unsigned int i;
@@ -175,7 +175,7 @@ done:
 }
 
 /* Writes/reads to the MMU's special regs end up here.  */
-uint32_t mmu_read(CPUState *env, uint32_t rn)
+uint32_t mmu_read(CPUMBState *env, uint32_t rn)
 {
     unsigned int i;
     uint32_t r;
@@ -215,7 +215,7 @@ uint32_t mmu_read(CPUState *env, uint32_t rn)
     return r;
 }
 
-void mmu_write(CPUState *env, uint32_t rn, uint32_t v)
+void mmu_write(CPUMBState *env, uint32_t rn, uint32_t v)
 {
     unsigned int i;
     D(qemu_log("%s rn=%d=%x old=%x\n", __func__, rn, v, env->mmu.regs[rn]));
diff --git a/target-microblaze/mmu.h b/target-microblaze/mmu.h
index 56149a5..3f74dda 100644
--- a/target-microblaze/mmu.h
+++ b/target-microblaze/mmu.h
@@ -82,10 +82,10 @@ struct microblaze_mmu_lookup
     } err;
 };
 
-void mmu_flip_um(CPUState *env, unsigned int um);
+void mmu_flip_um(CPUMBState *env, unsigned int um);
 unsigned int mmu_translate(struct microblaze_mmu *mmu,
                            struct microblaze_mmu_lookup *lu,
                            target_ulong vaddr, int rw, int mmu_idx);
-uint32_t mmu_read(CPUState *env, uint32_t rn);
-void mmu_write(CPUState *env, uint32_t rn, uint32_t v);
+uint32_t mmu_read(CPUMBState *env, uint32_t rn);
+void mmu_write(CPUMBState *env, uint32_t rn, uint32_t v);
 void mmu_init(struct microblaze_mmu *mmu);
diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index 7232c71..76cc0e0 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -42,11 +42,11 @@
    NULL, it means that the function was called in C code (i.e. not
    from generated code or from helper.c) */
 /* XXX: fix it to restore all registers */
-void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
+void tlb_fill(CPUMBState *env1, target_ulong addr, int is_write, int mmu_idx,
               void *retaddr)
 {
     TranslationBlock *tb;
-    CPUState *saved_env;
+    CPUMBState *saved_env;
     unsigned long pc;
     int ret;
 
@@ -506,10 +506,10 @@ void helper_mmu_write(uint32_t rn, uint32_t v)
     mmu_write(env, rn, v);
 }
 
-void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr,
+void cpu_unassigned_access(CPUMBState *env1, target_phys_addr_t addr,
                            int is_write, int is_exec, int is_asi, int size)
 {
-    CPUState *saved_env;
+    CPUMBState *saved_env;
 
     saved_env = env;
     env = env1;
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index e34e88d..64cbfb8 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -53,7 +53,7 @@ static TCGv env_iflags;
 
 /* This is the state at translation time.  */
 typedef struct DisasContext {
-    CPUState *env;
+    CPUMBState *env;
     target_ulong pc;
 
     /* Decoder.  */
@@ -519,10 +519,10 @@ static void dec_msr(DisasContext *dc)
                 tcg_gen_andi_tl(cpu_SR[SR_FSR], cpu_R[dc->ra], 31);
                 break;
             case 0x800:
-                tcg_gen_st_tl(cpu_R[dc->ra], cpu_env, offsetof(CPUState, slr));
+                tcg_gen_st_tl(cpu_R[dc->ra], cpu_env, offsetof(CPUMBState, slr));
                 break;
             case 0x802:
-                tcg_gen_st_tl(cpu_R[dc->ra], cpu_env, offsetof(CPUState, shr));
+                tcg_gen_st_tl(cpu_R[dc->ra], cpu_env, offsetof(CPUMBState, shr));
                 break;
             default:
                 cpu_abort(dc->env, "unknown mts reg %x\n", sr);
@@ -551,10 +551,10 @@ static void dec_msr(DisasContext *dc)
                 tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_BTR]);
                 break;
             case 0x800:
-                tcg_gen_ld_tl(cpu_R[dc->rd], cpu_env, offsetof(CPUState, slr));
+                tcg_gen_ld_tl(cpu_R[dc->rd], cpu_env, offsetof(CPUMBState, slr));
                 break;
             case 0x802:
-                tcg_gen_ld_tl(cpu_R[dc->rd], cpu_env, offsetof(CPUState, shr));
+                tcg_gen_ld_tl(cpu_R[dc->rd], cpu_env, offsetof(CPUMBState, shr));
                 break;
             case 0x2000:
             case 0x2001:
@@ -571,7 +571,7 @@ static void dec_msr(DisasContext *dc)
             case 0x200c:
                 rn = sr & 0xf;
                 tcg_gen_ld_tl(cpu_R[dc->rd],
-                              cpu_env, offsetof(CPUState, pvr.regs[rn]));
+                              cpu_env, offsetof(CPUMBState, pvr.regs[rn]));
                 break;
             default:
                 cpu_abort(dc->env, "unknown mfs reg %x\n", sr);
@@ -1222,7 +1222,7 @@ static void dec_bcc(DisasContext *dc)
         dc->delayed_branch = 2;
         dc->tb_flags |= D_FLAG;
         tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
-                      cpu_env, offsetof(CPUState, bimm));
+                      cpu_env, offsetof(CPUMBState, bimm));
     }
 
     if (dec_alu_op_b_is_small_imm(dc)) {
@@ -1267,7 +1267,7 @@ static void dec_br(DisasContext *dc)
         dc->delayed_branch = 2;
         dc->tb_flags |= D_FLAG;
         tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
-                      cpu_env, offsetof(CPUState, bimm));
+                      cpu_env, offsetof(CPUMBState, bimm));
     }
     if (link && dc->rd)
         tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc);
@@ -1366,7 +1366,7 @@ static void dec_rts(DisasContext *dc)
     dc->delayed_branch = 2;
     dc->tb_flags |= D_FLAG;
     tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
-                  cpu_env, offsetof(CPUState, bimm));
+                  cpu_env, offsetof(CPUMBState, bimm));
 
     if (i_bit) {
         LOG_DIS("rtid ir=%x\n", dc->ir);
@@ -1632,7 +1632,7 @@ static inline void decode(DisasContext *dc)
     }
 }
 
-static void check_breakpoint(CPUState *env, DisasContext *dc)
+static void check_breakpoint(CPUMBState *env, DisasContext *dc)
 {
     CPUBreakpoint *bp;
 
@@ -1648,7 +1648,7 @@ static void check_breakpoint(CPUState *env, DisasContext *dc)
 
 /* generate intermediate code for basic block 'tb'.  */
 static void
-gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
+gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
                                int search_pc)
 {
     uint16_t *gen_opc_end;
@@ -1850,17 +1850,17 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
     assert(!dc->abort_at_next_insn);
 }
 
-void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
+void gen_intermediate_code (CPUMBState *env, struct TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 0);
 }
 
-void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
+void gen_intermediate_code_pc (CPUMBState *env, struct TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 1);
 }
 
-void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
+void cpu_dump_state (CPUMBState *env, FILE *f, fprintf_function cpu_fprintf,
                      int flags)
 {
     int i;
@@ -1888,13 +1888,13 @@ void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
     cpu_fprintf(f, "\n\n");
 }
 
-CPUState *cpu_mb_init (const char *cpu_model)
+CPUMBState *cpu_mb_init (const char *cpu_model)
 {
-    CPUState *env;
+    CPUMBState *env;
     static int tcg_initialized = 0;
     int i;
 
-    env = g_malloc0(sizeof(CPUState));
+    env = g_malloc0(sizeof(CPUMBState));
 
     cpu_exec_init(env);
     cpu_state_reset(env);
@@ -1909,28 +1909,28 @@ CPUState *cpu_mb_init (const char *cpu_model)
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
 
     env_debug = tcg_global_mem_new(TCG_AREG0, 
-                    offsetof(CPUState, debug),
+                    offsetof(CPUMBState, debug),
                     "debug0");
     env_iflags = tcg_global_mem_new(TCG_AREG0, 
-                    offsetof(CPUState, iflags),
+                    offsetof(CPUMBState, iflags),
                     "iflags");
     env_imm = tcg_global_mem_new(TCG_AREG0, 
-                    offsetof(CPUState, imm),
+                    offsetof(CPUMBState, imm),
                     "imm");
     env_btarget = tcg_global_mem_new(TCG_AREG0,
-                     offsetof(CPUState, btarget),
+                     offsetof(CPUMBState, btarget),
                      "btarget");
     env_btaken = tcg_global_mem_new(TCG_AREG0,
-                     offsetof(CPUState, btaken),
+                     offsetof(CPUMBState, btaken),
                      "btaken");
     for (i = 0; i < ARRAY_SIZE(cpu_R); i++) {
         cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
-                          offsetof(CPUState, regs[i]),
+                          offsetof(CPUMBState, regs[i]),
                           regnames[i]);
     }
     for (i = 0; i < ARRAY_SIZE(cpu_SR); i++) {
         cpu_SR[i] = tcg_global_mem_new(TCG_AREG0,
-                          offsetof(CPUState, sregs[i]),
+                          offsetof(CPUMBState, sregs[i]),
                           special_regnames[i]);
     }
 #define GEN_HELPER 2
@@ -1939,7 +1939,7 @@ CPUState *cpu_mb_init (const char *cpu_model)
     return env;
 }
 
-void cpu_state_reset(CPUState *env)
+void cpu_state_reset(CPUMBState *env)
 {
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
         qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
@@ -1991,7 +1991,7 @@ void cpu_state_reset(CPUState *env)
 #endif
 }
 
-void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb, int pc_pos)
 {
     env->sregs[SR_PC] = gen_opc_pc[pc_pos];
 }
commit 2b3e3cfe841d213297c0fd7845952d32e8b229d2
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:22 2012 +0100

    target-m68k: Don't overuse CPUState
    
    Scripted conversion:
      sed -i "s/CPUState/CPUM68KState/g" target-m68k/*.[hc]
      sed -i "s/#define CPUM68KState/#define CPUState/" target-m68k/cpu.h
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index 4cc3a35..2c83b89 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -120,8 +120,8 @@ void m68k_tcg_init(void);
 CPUM68KState *cpu_m68k_init(const char *cpu_model);
 int cpu_m68k_exec(CPUM68KState *s);
 void cpu_m68k_close(CPUM68KState *s);
-void do_interrupt(CPUState *env1);
-void do_interrupt_m68k_hardirq(CPUState *env1);
+void do_interrupt(CPUM68KState *env1);
+void do_interrupt_m68k_hardirq(CPUM68KState *env1);
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
    is returned if the signal was handled by the virtual CPU.  */
@@ -226,17 +226,17 @@ void register_m68k_insns (CPUM68KState *env);
 #define MMU_MODE0_SUFFIX _kernel
 #define MMU_MODE1_SUFFIX _user
 #define MMU_USER_IDX 1
-static inline int cpu_mmu_index (CPUState *env)
+static inline int cpu_mmu_index (CPUM68KState *env)
 {
     return (env->sr & SR_S) == 0 ? 1 : 0;
 }
 
-int cpu_m68k_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
+int cpu_m68k_handle_mmu_fault(CPUM68KState *env, target_ulong address, int rw,
                               int mmu_idx);
 #define cpu_handle_mmu_fault cpu_m68k_handle_mmu_fault
 
 #if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
+static inline void cpu_clone_regs(CPUM68KState *env, target_ulong newsp)
 {
     if (newsp)
         env->aregs[7] = newsp;
@@ -246,7 +246,7 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
 
 #include "cpu-all.h"
 
-static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+static inline void cpu_get_tb_cpu_state(CPUM68KState *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
     *pc = env->pc;
@@ -256,14 +256,14 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
             | ((env->macsr >> 4) & 0xf);        /* Bits 0-3 */
 }
 
-static inline bool cpu_has_work(CPUState *env)
+static inline bool cpu_has_work(CPUM68KState *env)
 {
     return env->interrupt_request & CPU_INTERRUPT_HARD;
 }
 
 #include "exec-all.h"
 
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+static inline void cpu_pc_from_tb(CPUM68KState *env, TranslationBlock *tb)
 {
     env->pc = tb->pc;
 }
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 3647366..1feed9b 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -56,7 +56,7 @@ void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
     }
 }
 
-static int fpu_gdb_get_reg(CPUState *env, uint8_t *mem_buf, int n)
+static int fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
 {
     if (n < 8) {
         stfq_p(mem_buf, env->fregs[n]);
@@ -70,7 +70,7 @@ static int fpu_gdb_get_reg(CPUState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int fpu_gdb_set_reg(CPUState *env, uint8_t *mem_buf, int n)
+static int fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
 {
     if (n < 8) {
         env->fregs[n] = ldfq_p(mem_buf);
@@ -338,7 +338,7 @@ void m68k_switch_sp(CPUM68KState *env)
 
 #if defined(CONFIG_USER_ONLY)
 
-int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
+int cpu_m68k_handle_mmu_fault (CPUM68KState *env, target_ulong address, int rw,
                                int mmu_idx)
 {
     env->exception_index = EXCP_ACCESS;
@@ -351,12 +351,12 @@ int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
 /* MMU */
 
 /* TODO: This will need fixing once the MMU is implemented.  */
-target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_debug(CPUM68KState *env, target_ulong addr)
 {
     return addr;
 }
 
-int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
+int cpu_m68k_handle_mmu_fault (CPUM68KState *env, target_ulong address, int rw,
                                int mmu_idx)
 {
     int prot;
@@ -407,7 +407,7 @@ uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
     return val;
 }
 
-uint32_t HELPER(subx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
+uint32_t HELPER(subx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
 {
     uint32_t res;
     uint32_t old_flags;
@@ -430,7 +430,7 @@ uint32_t HELPER(subx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
     return res;
 }
 
-uint32_t HELPER(addx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
+uint32_t HELPER(addx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
 {
     uint32_t res;
     uint32_t old_flags;
@@ -458,13 +458,13 @@ uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
     return a < b;
 }
 
-void HELPER(set_sr)(CPUState *env, uint32_t val)
+void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
 {
     env->sr = val & 0xffff;
     m68k_switch_sp(env);
 }
 
-uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
+uint32_t HELPER(shl_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
 {
     uint32_t result;
     uint32_t cf;
@@ -489,7 +489,7 @@ uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
     return result;
 }
 
-uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
+uint32_t HELPER(shr_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
 {
     uint32_t result;
     uint32_t cf;
@@ -514,7 +514,7 @@ uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
     return result;
 }
 
-uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
+uint32_t HELPER(sar_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
 {
     uint32_t result;
     uint32_t cf;
@@ -537,37 +537,37 @@ uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
 }
 
 /* FPU helpers.  */
-uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
+uint32_t HELPER(f64_to_i32)(CPUM68KState *env, float64 val)
 {
     return float64_to_int32(val, &env->fp_status);
 }
 
-float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
+float32 HELPER(f64_to_f32)(CPUM68KState *env, float64 val)
 {
     return float64_to_float32(val, &env->fp_status);
 }
 
-float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
+float64 HELPER(i32_to_f64)(CPUM68KState *env, uint32_t val)
 {
     return int32_to_float64(val, &env->fp_status);
 }
 
-float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
+float64 HELPER(f32_to_f64)(CPUM68KState *env, float32 val)
 {
     return float32_to_float64(val, &env->fp_status);
 }
 
-float64 HELPER(iround_f64)(CPUState *env, float64 val)
+float64 HELPER(iround_f64)(CPUM68KState *env, float64 val)
 {
     return float64_round_to_int(val, &env->fp_status);
 }
 
-float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
+float64 HELPER(itrunc_f64)(CPUM68KState *env, float64 val)
 {
     return float64_trunc_to_int(val, &env->fp_status);
 }
 
-float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
+float64 HELPER(sqrt_f64)(CPUM68KState *env, float64 val)
 {
     return float64_sqrt(val, &env->fp_status);
 }
@@ -582,27 +582,27 @@ float64 HELPER(chs_f64)(float64 val)
     return float64_chs(val);
 }
 
-float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
+float64 HELPER(add_f64)(CPUM68KState *env, float64 a, float64 b)
 {
     return float64_add(a, b, &env->fp_status);
 }
 
-float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
+float64 HELPER(sub_f64)(CPUM68KState *env, float64 a, float64 b)
 {
     return float64_sub(a, b, &env->fp_status);
 }
 
-float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
+float64 HELPER(mul_f64)(CPUM68KState *env, float64 a, float64 b)
 {
     return float64_mul(a, b, &env->fp_status);
 }
 
-float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
+float64 HELPER(div_f64)(CPUM68KState *env, float64 a, float64 b)
 {
     return float64_div(a, b, &env->fp_status);
 }
 
-float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
+float64 HELPER(sub_cmp_f64)(CPUM68KState *env, float64 a, float64 b)
 {
     /* ??? This may incorrectly raise exceptions.  */
     /* ??? Should flush denormals to zero.  */
@@ -620,7 +620,7 @@ float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
     return res;
 }
 
-uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
+uint32_t HELPER(compare_f64)(CPUM68KState *env, float64 val)
 {
     return float64_compare_quiet(val, float64_zero, &env->fp_status);
 }
@@ -629,7 +629,7 @@ uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
 /* FIXME: The MAC unit implementation is a bit of a mess.  Some helpers
    take values,  others take register numbers and manipulate the contents
    in-place.  */
-void HELPER(mac_move)(CPUState *env, uint32_t dest, uint32_t src)
+void HELPER(mac_move)(CPUM68KState *env, uint32_t dest, uint32_t src)
 {
     uint32_t mask;
     env->macc[dest] = env->macc[src];
@@ -640,7 +640,7 @@ void HELPER(mac_move)(CPUState *env, uint32_t dest, uint32_t src)
         env->macsr &= ~mask;
 }
 
-uint64_t HELPER(macmuls)(CPUState *env, uint32_t op1, uint32_t op2)
+uint64_t HELPER(macmuls)(CPUM68KState *env, uint32_t op1, uint32_t op2)
 {
     int64_t product;
     int64_t res;
@@ -660,7 +660,7 @@ uint64_t HELPER(macmuls)(CPUState *env, uint32_t op1, uint32_t op2)
     return res;
 }
 
-uint64_t HELPER(macmulu)(CPUState *env, uint32_t op1, uint32_t op2)
+uint64_t HELPER(macmulu)(CPUM68KState *env, uint32_t op1, uint32_t op2)
 {
     uint64_t product;
 
@@ -677,7 +677,7 @@ uint64_t HELPER(macmulu)(CPUState *env, uint32_t op1, uint32_t op2)
     return product;
 }
 
-uint64_t HELPER(macmulf)(CPUState *env, uint32_t op1, uint32_t op2)
+uint64_t HELPER(macmulf)(CPUM68KState *env, uint32_t op1, uint32_t op2)
 {
     uint64_t product;
     uint32_t remainder;
@@ -696,7 +696,7 @@ uint64_t HELPER(macmulf)(CPUState *env, uint32_t op1, uint32_t op2)
     return product;
 }
 
-void HELPER(macsats)(CPUState *env, uint32_t acc)
+void HELPER(macsats)(CPUM68KState *env, uint32_t acc)
 {
     int64_t tmp;
     int64_t result;
@@ -717,7 +717,7 @@ void HELPER(macsats)(CPUState *env, uint32_t acc)
     env->macc[acc] = result;
 }
 
-void HELPER(macsatu)(CPUState *env, uint32_t acc)
+void HELPER(macsatu)(CPUM68KState *env, uint32_t acc)
 {
     uint64_t val;
 
@@ -739,7 +739,7 @@ void HELPER(macsatu)(CPUState *env, uint32_t acc)
     env->macc[acc] = val;
 }
 
-void HELPER(macsatf)(CPUState *env, uint32_t acc)
+void HELPER(macsatf)(CPUM68KState *env, uint32_t acc)
 {
     int64_t sum;
     int64_t result;
@@ -758,7 +758,7 @@ void HELPER(macsatf)(CPUState *env, uint32_t acc)
     env->macc[acc] = result;
 }
 
-void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
+void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc)
 {
     uint64_t val;
     val = env->macc[acc];
@@ -784,12 +784,12 @@ void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
     }
 }
 
-void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
+void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op)
 {
     cpu_m68k_flush_flags(env, cc_op);
 }
 
-uint32_t HELPER(get_macf)(CPUState *env, uint64_t val)
+uint32_t HELPER(get_macf)(CPUM68KState *env, uint64_t val)
 {
     int rem;
     uint32_t result;
@@ -858,7 +858,7 @@ uint32_t HELPER(get_macu)(uint64_t val)
     }
 }
 
-uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
+uint32_t HELPER(get_mac_extf)(CPUM68KState *env, uint32_t acc)
 {
     uint32_t val;
     val = env->macc[acc] & 0x00ff;
@@ -868,7 +868,7 @@ uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
     return val;
 }
 
-uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
+uint32_t HELPER(get_mac_exti)(CPUM68KState *env, uint32_t acc)
 {
     uint32_t val;
     val = (env->macc[acc] >> 32) & 0xffff;
@@ -876,7 +876,7 @@ uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
     return val;
 }
 
-void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
+void HELPER(set_mac_extf)(CPUM68KState *env, uint32_t val, uint32_t acc)
 {
     int64_t res;
     int32_t tmp;
@@ -892,7 +892,7 @@ void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
     env->macc[acc + 1] = res;
 }
 
-void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
+void HELPER(set_mac_exts)(CPUM68KState *env, uint32_t val, uint32_t acc)
 {
     int64_t res;
     int32_t tmp;
@@ -906,7 +906,7 @@ void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
     env->macc[acc + 1] = res;
 }
 
-void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc)
+void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
 {
     uint64_t res;
     res = (uint32_t)env->macc[acc];
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index 2f7fe6b..bc8c1f0 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -22,12 +22,12 @@
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt(CPUState *env1)
+void do_interrupt(CPUM68KState *env1)
 {
     env1->exception_index = -1;
 }
 
-void do_interrupt_m68k_hardirq(CPUState *env1)
+void do_interrupt_m68k_hardirq(CPUM68KState *env1)
 {
 }
 
@@ -55,11 +55,11 @@ extern int semihosting_enabled;
    NULL, it means that the function was called in C code (i.e. not
    from generated code or from helper.c) */
 /* XXX: fix it to restore all registers */
-void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
+void tlb_fill(CPUM68KState *env1, target_ulong addr, int is_write, int mmu_idx,
               void *retaddr)
 {
     TranslationBlock *tb;
-    CPUState *saved_env;
+    CPUM68KState *saved_env;
     unsigned long pc;
     int ret;
 
@@ -161,9 +161,9 @@ static void do_interrupt_all(int is_hw)
     env->pc = ldl_kernel(env->vbr + vector);
 }
 
-void do_interrupt(CPUState *env1)
+void do_interrupt(CPUM68KState *env1)
 {
-    CPUState *saved_env;
+    CPUM68KState *saved_env;
 
     saved_env = env;
     env = env1;
@@ -171,9 +171,9 @@ void do_interrupt(CPUState *env1)
     env = saved_env;
 }
 
-void do_interrupt_m68k_hardirq(CPUState *env1)
+void do_interrupt_m68k_hardirq(CPUM68KState *env1)
 {
-    CPUState *saved_env;
+    CPUM68KState *saved_env;
 
     saved_env = env;
     env = env1;
@@ -193,7 +193,7 @@ void HELPER(raise_exception)(uint32_t tt)
     raise_exception(tt);
 }
 
-void HELPER(divu)(CPUState *env, uint32_t word)
+void HELPER(divu)(CPUM68KState *env, uint32_t word)
 {
     uint32_t num;
     uint32_t den;
@@ -223,7 +223,7 @@ void HELPER(divu)(CPUState *env, uint32_t word)
     env->cc_dest = flags;
 }
 
-void HELPER(divs)(CPUState *env, uint32_t word)
+void HELPER(divs)(CPUM68KState *env, uint32_t word)
 {
     int32_t num;
     int32_t den;
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 2bdd9dd..9fc1e31 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -68,8 +68,8 @@ void m68k_tcg_init(void)
     char *p;
     int i;
 
-#define DEFO32(name,  offset) QREG_##name = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, offset), #name);
-#define DEFO64(name,  offset) QREG_##name = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUState, offset), #name);
+#define DEFO32(name,  offset) QREG_##name = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUM68KState, offset), #name);
+#define DEFO64(name,  offset) QREG_##name = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUM68KState, offset), #name);
 #define DEFF64(name,  offset) DEFO64(name, offset)
 #include "qregs.def"
 #undef DEFO32
@@ -2937,7 +2937,7 @@ void register_m68k_insns (CPUM68KState *env)
 
 /* ??? Some of this implementation is not exception safe.  We should always
    write back the result to memory before setting the condition codes.  */
-static void disas_m68k_insn(CPUState * env, DisasContext *s)
+static void disas_m68k_insn(CPUM68KState * env, DisasContext *s)
 {
     uint16_t insn;
 
@@ -2949,7 +2949,7 @@ static void disas_m68k_insn(CPUState * env, DisasContext *s)
 
 /* generate intermediate code for basic block 'tb'.  */
 static inline void
-gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
+gen_intermediate_code_internal(CPUM68KState *env, TranslationBlock *tb,
                                int search_pc)
 {
     DisasContext dc1, *dc = &dc1;
@@ -3072,17 +3072,17 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
     //expand_target_qops();
 }
 
-void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
+void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 0);
 }
 
-void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
+void gen_intermediate_code_pc(CPUM68KState *env, TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 1);
 }
 
-void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
+void cpu_dump_state(CPUM68KState *env, FILE *f, fprintf_function cpu_fprintf,
                     int flags)
 {
     int i;
@@ -3103,7 +3103,7 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
     cpu_fprintf (f, "FPRESULT = %12g\n", *(double *)&env->fp_result);
 }
 
-void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUM68KState *env, TranslationBlock *tb, int pc_pos)
 {
     env->pc = gen_opc_pc[pc_pos];
 }
commit 6393c08de23548be82d53ad462ed5acad107da1f
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:22 2012 +0100

    target-lm32: Don't overuse CPUState
    
    Scripted conversion:
      sed -i "s/CPUState/CPULM32State/g" target-lm32/*.[hc]
      sed -i "s/#define CPULM32State/#define CPUState/" target-lm32/cpu.h
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index cc9b53b..684b2fa 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -36,7 +36,7 @@ typedef struct CPULM32State CPULM32State;
 
 #define NB_MMU_MODES 1
 #define TARGET_PAGE_BITS 12
-static inline int cpu_mmu_index(CPUState *env)
+static inline int cpu_mmu_index(CPULM32State *env)
 {
     return 0;
 }
@@ -185,18 +185,18 @@ typedef struct CPULM32State {
 } CPULM32State;
 
 
-CPUState *cpu_lm32_init(const char *cpu_model);
+CPULM32State *cpu_lm32_init(const char *cpu_model);
 void cpu_lm32_list(FILE *f, fprintf_function cpu_fprintf);
-int cpu_lm32_exec(CPUState *s);
-void cpu_lm32_close(CPUState *s);
-void do_interrupt(CPUState *env);
+int cpu_lm32_exec(CPULM32State *s);
+void cpu_lm32_close(CPULM32State *s);
+void do_interrupt(CPULM32State *env);
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
    is returned if the signal was handled by the virtual CPU.  */
 int cpu_lm32_signal_handler(int host_signum, void *pinfo,
                           void *puc);
 void lm32_translate_init(void);
-void cpu_lm32_set_phys_msb_ignore(CPUState *env, int value);
+void cpu_lm32_set_phys_msb_ignore(CPULM32State *env, int value);
 
 #define cpu_list cpu_lm32_list
 #define cpu_init cpu_lm32_init
@@ -206,12 +206,12 @@ void cpu_lm32_set_phys_msb_ignore(CPUState *env, int value);
 
 #define CPU_SAVE_VERSION 1
 
-int cpu_lm32_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
+int cpu_lm32_handle_mmu_fault(CPULM32State *env, target_ulong address, int rw,
                               int mmu_idx);
 #define cpu_handle_mmu_fault cpu_lm32_handle_mmu_fault
 
 #if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
+static inline void cpu_clone_regs(CPULM32State *env, target_ulong newsp)
 {
     if (newsp) {
         env->regs[R_SP] = newsp;
@@ -220,23 +220,23 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
 }
 #endif
 
-static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
+static inline void cpu_set_tls(CPULM32State *env, target_ulong newtls)
 {
 }
 
-static inline int cpu_interrupts_enabled(CPUState *env)
+static inline int cpu_interrupts_enabled(CPULM32State *env)
 {
     return env->ie & IE_IE;
 }
 
 #include "cpu-all.h"
 
-static inline target_ulong cpu_get_pc(CPUState *env)
+static inline target_ulong cpu_get_pc(CPULM32State *env)
 {
     return env->pc;
 }
 
-static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+static inline void cpu_get_tb_cpu_state(CPULM32State *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
     *pc = env->pc;
@@ -244,14 +244,14 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
     *flags = 0;
 }
 
-static inline bool cpu_has_work(CPUState *env)
+static inline bool cpu_has_work(CPULM32State *env)
 {
     return env->interrupt_request & CPU_INTERRUPT_HARD;
 }
 
 #include "exec-all.h"
 
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+static inline void cpu_pc_from_tb(CPULM32State *env, TranslationBlock *tb)
 {
     env->pc = tb->pc;
 }
diff --git a/target-lm32/helper.c b/target-lm32/helper.c
index 6834401..5db8f8d 100644
--- a/target-lm32/helper.c
+++ b/target-lm32/helper.c
@@ -20,7 +20,7 @@
 #include "cpu.h"
 #include "host-utils.h"
 
-int cpu_lm32_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
+int cpu_lm32_handle_mmu_fault(CPULM32State *env, target_ulong address, int rw,
                               int mmu_idx)
 {
     int prot;
@@ -37,12 +37,12 @@ int cpu_lm32_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
     return 0;
 }
 
-target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_debug(CPULM32State *env, target_ulong addr)
 {
     return addr & TARGET_PAGE_MASK;
 }
 
-void do_interrupt(CPUState *env)
+void do_interrupt(CPULM32State *env)
 {
     qemu_log_mask(CPU_LOG_INT,
             "exception at pc=%x type=%x\n", env->pc, env->exception_index);
@@ -192,9 +192,9 @@ static uint32_t cfg_by_def(const LM32Def *def)
     return cfg;
 }
 
-CPUState *cpu_lm32_init(const char *cpu_model)
+CPULM32State *cpu_lm32_init(const char *cpu_model)
 {
-    CPUState *env;
+    CPULM32State *env;
     const LM32Def *def;
     static int tcg_initialized;
 
@@ -203,7 +203,7 @@ CPUState *cpu_lm32_init(const char *cpu_model)
         return NULL;
     }
 
-    env = g_malloc0(sizeof(CPUState));
+    env = g_malloc0(sizeof(CPULM32State));
 
     env->features = def->features;
     env->num_bps = def->num_breakpoints;
@@ -226,7 +226,7 @@ CPUState *cpu_lm32_init(const char *cpu_model)
 /* Some soc ignores the MSB on the address bus. Thus creating a shadow memory
  * area. As a general rule, 0x00000000-0x7fffffff is cached, whereas
  * 0x80000000-0xffffffff is not cached and used to access IO devices. */
-void cpu_lm32_set_phys_msb_ignore(CPUState *env, int value)
+void cpu_lm32_set_phys_msb_ignore(CPULM32State *env, int value)
 {
     if (value) {
         env->flags |= LM32_FLAG_IGNORE_MSB;
@@ -235,7 +235,7 @@ void cpu_lm32_set_phys_msb_ignore(CPUState *env, int value)
     }
 }
 
-void cpu_state_reset(CPUState *env)
+void cpu_state_reset(CPULM32State *env)
 {
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
         qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
diff --git a/target-lm32/machine.c b/target-lm32/machine.c
index 70ca52a..6802e81 100644
--- a/target-lm32/machine.c
+++ b/target-lm32/machine.c
@@ -7,17 +7,17 @@ static const VMStateDescription vmstate_cpu = {
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .fields      = (VMStateField[]) {
-        VMSTATE_UINT32_ARRAY(regs, CPUState, 32),
-        VMSTATE_UINT32(pc, CPUState),
-        VMSTATE_UINT32(ie, CPUState),
-        VMSTATE_UINT32(icc, CPUState),
-        VMSTATE_UINT32(dcc, CPUState),
-        VMSTATE_UINT32(cc, CPUState),
-        VMSTATE_UINT32(eba, CPUState),
-        VMSTATE_UINT32(dc, CPUState),
-        VMSTATE_UINT32(deba, CPUState),
-        VMSTATE_UINT32_ARRAY(bp, CPUState, 4),
-        VMSTATE_UINT32_ARRAY(wp, CPUState, 4),
+        VMSTATE_UINT32_ARRAY(regs, CPULM32State, 32),
+        VMSTATE_UINT32(pc, CPULM32State),
+        VMSTATE_UINT32(ie, CPULM32State),
+        VMSTATE_UINT32(icc, CPULM32State),
+        VMSTATE_UINT32(dcc, CPULM32State),
+        VMSTATE_UINT32(cc, CPULM32State),
+        VMSTATE_UINT32(eba, CPULM32State),
+        VMSTATE_UINT32(dc, CPULM32State),
+        VMSTATE_UINT32(deba, CPULM32State),
+        VMSTATE_UINT32_ARRAY(bp, CPULM32State, 4),
+        VMSTATE_UINT32_ARRAY(wp, CPULM32State, 4),
         VMSTATE_END_OF_LIST()
     }
 };
diff --git a/target-lm32/op_helper.c b/target-lm32/op_helper.c
index 02be134..e9c9638 100644
--- a/target-lm32/op_helper.c
+++ b/target-lm32/op_helper.c
@@ -75,11 +75,11 @@ uint32_t helper_rcsr_jrx(void)
    NULL, it means that the function was called in C code (i.e. not
    from generated code or from helper.c) */
 /* XXX: fix it to restore all registers */
-void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
+void tlb_fill(CPULM32State *env1, target_ulong addr, int is_write, int mmu_idx,
               void *retaddr)
 {
     TranslationBlock *tb;
-    CPUState *saved_env;
+    CPULM32State *saved_env;
     unsigned long pc;
     int ret;
 
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index c80e48b..872a2ba 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -64,7 +64,7 @@ enum {
 
 /* This is the state at translation time.  */
 typedef struct DisasContext {
-    CPUState *env;
+    CPULM32State *env;
     target_ulong pc;
 
     /* Decoder.  */
@@ -987,7 +987,7 @@ static inline void decode(DisasContext *dc)
     decinfo[dc->opcode](dc);
 }
 
-static void check_breakpoint(CPUState *env, DisasContext *dc)
+static void check_breakpoint(CPULM32State *env, DisasContext *dc)
 {
     CPUBreakpoint *bp;
 
@@ -1003,7 +1003,7 @@ static void check_breakpoint(CPUState *env, DisasContext *dc)
 }
 
 /* generate intermediate code for basic block 'tb'.  */
-static void gen_intermediate_code_internal(CPUState *env,
+static void gen_intermediate_code_internal(CPULM32State *env,
         TranslationBlock *tb, int search_pc)
 {
     struct DisasContext ctx, *dc = &ctx;
@@ -1129,17 +1129,17 @@ static void gen_intermediate_code_internal(CPUState *env,
 #endif
 }
 
-void gen_intermediate_code(CPUState *env, struct TranslationBlock *tb)
+void gen_intermediate_code(CPULM32State *env, struct TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 0);
 }
 
-void gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb)
+void gen_intermediate_code_pc(CPULM32State *env, struct TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 1);
 }
 
-void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
+void cpu_dump_state(CPULM32State *env, FILE *f, fprintf_function cpu_fprintf,
                      int flags)
 {
     int i;
@@ -1171,7 +1171,7 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
     cpu_fprintf(f, "\n\n");
 }
 
-void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPULM32State *env, TranslationBlock *tb, int pc_pos)
 {
     env->pc = gen_opc_pc[pc_pos];
 }
@@ -1184,48 +1184,48 @@ void lm32_translate_init(void)
 
     for (i = 0; i < ARRAY_SIZE(cpu_R); i++) {
         cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
-                          offsetof(CPUState, regs[i]),
+                          offsetof(CPULM32State, regs[i]),
                           regnames[i]);
     }
 
     for (i = 0; i < ARRAY_SIZE(cpu_bp); i++) {
         cpu_bp[i] = tcg_global_mem_new(TCG_AREG0,
-                          offsetof(CPUState, bp[i]),
+                          offsetof(CPULM32State, bp[i]),
                           regnames[32+i]);
     }
 
     for (i = 0; i < ARRAY_SIZE(cpu_wp); i++) {
         cpu_wp[i] = tcg_global_mem_new(TCG_AREG0,
-                          offsetof(CPUState, wp[i]),
+                          offsetof(CPULM32State, wp[i]),
                           regnames[36+i]);
     }
 
     cpu_pc = tcg_global_mem_new(TCG_AREG0,
-                    offsetof(CPUState, pc),
+                    offsetof(CPULM32State, pc),
                     "pc");
     cpu_ie = tcg_global_mem_new(TCG_AREG0,
-                    offsetof(CPUState, ie),
+                    offsetof(CPULM32State, ie),
                     "ie");
     cpu_icc = tcg_global_mem_new(TCG_AREG0,
-                    offsetof(CPUState, icc),
+                    offsetof(CPULM32State, icc),
                     "icc");
     cpu_dcc = tcg_global_mem_new(TCG_AREG0,
-                    offsetof(CPUState, dcc),
+                    offsetof(CPULM32State, dcc),
                     "dcc");
     cpu_cc = tcg_global_mem_new(TCG_AREG0,
-                    offsetof(CPUState, cc),
+                    offsetof(CPULM32State, cc),
                     "cc");
     cpu_cfg = tcg_global_mem_new(TCG_AREG0,
-                    offsetof(CPUState, cfg),
+                    offsetof(CPULM32State, cfg),
                     "cfg");
     cpu_eba = tcg_global_mem_new(TCG_AREG0,
-                    offsetof(CPUState, eba),
+                    offsetof(CPULM32State, eba),
                     "eba");
     cpu_dc = tcg_global_mem_new(TCG_AREG0,
-                    offsetof(CPUState, dc),
+                    offsetof(CPULM32State, dc),
                     "dc");
     cpu_deba = tcg_global_mem_new(TCG_AREG0,
-                    offsetof(CPUState, deba),
+                    offsetof(CPULM32State, deba),
                     "deba");
 }
 
commit 317ac6201a22b32a376c42205338e49ea195194e
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:21 2012 +0100

    target-i386: Don't overuse CPUState
    
    Scripted conversion:
      sed -i "s/CPUState/CPUX86State/g" target-i386/*.[hc]
      sed -i "s/#define CPUX86State/#define CPUState/" target-i386/cpu.h
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 36e3d29..6e26d21 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -788,7 +788,7 @@ int cpu_x86_exec(CPUX86State *s);
 void cpu_x86_close(CPUX86State *s);
 void x86_cpu_list (FILE *f, fprintf_function cpu_fprintf, const char *optarg);
 void x86_cpudef_setup(void);
-int cpu_x86_support_mca_broadcast(CPUState *env);
+int cpu_x86_support_mca_broadcast(CPUX86State *env);
 
 int cpu_get_pic_interrupt(CPUX86State *s);
 /* MSDOS compatibility mode FPU exception support */
@@ -970,7 +970,7 @@ uint64_t cpu_get_tsc(CPUX86State *env);
 #define MMU_MODE0_SUFFIX _kernel
 #define MMU_MODE1_SUFFIX _user
 #define MMU_USER_IDX 1
-static inline int cpu_mmu_index (CPUState *env)
+static inline int cpu_mmu_index (CPUX86State *env)
 {
     return (env->hflags & HF_CPL_MASK) == 3 ? 1 : 0;
 }
@@ -1009,7 +1009,7 @@ static inline int cpu_mmu_index (CPUState *env)
 void optimize_flags_init(void);
 
 #if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
+static inline void cpu_clone_regs(CPUX86State *env, target_ulong newsp)
 {
     if (newsp)
         env->regs[R_ESP] = newsp;
@@ -1024,7 +1024,7 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
 #include "hw/apic.h"
 #endif
 
-static inline bool cpu_has_work(CPUState *env)
+static inline bool cpu_has_work(CPUX86State *env)
 {
     return ((env->interrupt_request & CPU_INTERRUPT_HARD) &&
             (env->eflags & IF_MASK)) ||
@@ -1036,12 +1036,12 @@ static inline bool cpu_has_work(CPUState *env)
 
 #include "exec-all.h"
 
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+static inline void cpu_pc_from_tb(CPUX86State *env, TranslationBlock *tb)
 {
     env->eip = tb->pc - tb->cs_base;
 }
 
-static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+static inline void cpu_get_tb_cpu_state(CPUX86State *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
     *cs_base = env->segs[R_CS].base;
@@ -1050,29 +1050,29 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
         (env->eflags & (IOPL_MASK | TF_MASK | RF_MASK | VM_MASK));
 }
 
-void do_cpu_init(CPUState *env);
-void do_cpu_sipi(CPUState *env);
+void do_cpu_init(CPUX86State *env);
+void do_cpu_sipi(CPUX86State *env);
 
 #define MCE_INJECT_BROADCAST    1
 #define MCE_INJECT_UNCOND_AO    2
 
-void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,
+void cpu_x86_inject_mce(Monitor *mon, CPUX86State *cenv, int bank,
                         uint64_t status, uint64_t mcg_status, uint64_t addr,
                         uint64_t misc, int flags);
 
 /* op_helper.c */
-void do_interrupt(CPUState *env);
-void do_interrupt_x86_hardirq(CPUState *env, int intno, int is_hw);
-void QEMU_NORETURN raise_exception_env(int exception_index, CPUState *nenv);
-void QEMU_NORETURN raise_exception_err_env(CPUState *nenv, int exception_index,
+void do_interrupt(CPUX86State *env);
+void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw);
+void QEMU_NORETURN raise_exception_env(int exception_index, CPUX86State *nenv);
+void QEMU_NORETURN raise_exception_err_env(CPUX86State *nenv, int exception_index,
                                            int error_code);
 
-void do_smm_enter(CPUState *env1);
+void do_smm_enter(CPUX86State *env1);
 
-void svm_check_intercept(CPUState *env1, uint32_t type);
+void svm_check_intercept(CPUX86State *env1, uint32_t type);
 
-uint32_t cpu_cc_compute_all(CPUState *env1, int op);
+uint32_t cpu_cc_compute_all(CPUX86State *env1, int op);
 
-void cpu_report_tpr_access(CPUState *env, TPRAccess access);
+void cpu_report_tpr_access(CPUX86State *env, TPRAccess access);
 
 #endif /* CPU_I386_H */
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 140c696..83122bf 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -27,7 +27,7 @@
 //#define DEBUG_MMU
 
 /* NOTE: must be called outside the CPU execute loop */
-void cpu_state_reset(CPUState *env)
+void cpu_state_reset(CPUX86State *env)
 {
     int i;
 
@@ -106,7 +106,7 @@ void cpu_x86_close(CPUX86State *env)
     g_free(env);
 }
 
-static void cpu_x86_version(CPUState *env, int *family, int *model)
+static void cpu_x86_version(CPUX86State *env, int *family, int *model)
 {
     int cpuver = env->cpuid_version;
 
@@ -119,7 +119,7 @@ static void cpu_x86_version(CPUState *env, int *family, int *model)
 }
 
 /* Broadcast MCA signal for processor version 06H_EH and above */
-int cpu_x86_support_mca_broadcast(CPUState *env)
+int cpu_x86_support_mca_broadcast(CPUX86State *env)
 {
     int family = 0;
     int model = 0;
@@ -191,7 +191,7 @@ static const char *cc_op_str[] = {
 };
 
 static void
-cpu_x86_dump_seg_cache(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
+cpu_x86_dump_seg_cache(CPUX86State *env, FILE *f, fprintf_function cpu_fprintf,
                        const char *name, struct SegmentCache *sc)
 {
 #ifdef TARGET_X86_64
@@ -248,7 +248,7 @@ done:
 #define DUMP_CODE_BYTES_TOTAL    50
 #define DUMP_CODE_BYTES_BACKWARD 20
 
-void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
+void cpu_dump_state(CPUX86State *env, FILE *f, fprintf_function cpu_fprintf,
                     int flags)
 {
     int eflags, i, nb;
@@ -857,7 +857,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
     return 1;
 }
 
-target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_debug(CPUX86State *env, target_ulong addr)
 {
     target_ulong pde_addr, pte_addr;
     uint64_t pte;
@@ -952,7 +952,7 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
     return paddr;
 }
 
-void hw_breakpoint_insert(CPUState *env, int index)
+void hw_breakpoint_insert(CPUX86State *env, int index)
 {
     int type, err = 0;
 
@@ -980,7 +980,7 @@ void hw_breakpoint_insert(CPUState *env, int index)
         env->cpu_breakpoint[index] = NULL;
 }
 
-void hw_breakpoint_remove(CPUState *env, int index)
+void hw_breakpoint_remove(CPUX86State *env, int index)
 {
     if (!env->cpu_breakpoint[index])
         return;
@@ -999,7 +999,7 @@ void hw_breakpoint_remove(CPUState *env, int index)
     }
 }
 
-int check_hw_breakpoints(CPUState *env, int force_dr6_update)
+int check_hw_breakpoints(CPUX86State *env, int force_dr6_update)
 {
     target_ulong dr6;
     int reg, type;
@@ -1023,7 +1023,7 @@ int check_hw_breakpoints(CPUState *env, int force_dr6_update)
 
 static CPUDebugExcpHandler *prev_debug_excp_handler;
 
-static void breakpoint_handler(CPUState *env)
+static void breakpoint_handler(CPUX86State *env)
 {
     CPUBreakpoint *bp;
 
@@ -1051,7 +1051,7 @@ static void breakpoint_handler(CPUState *env)
 
 typedef struct MCEInjectionParams {
     Monitor *mon;
-    CPUState *env;
+    CPUX86State *env;
     int bank;
     uint64_t status;
     uint64_t mcg_status;
@@ -1063,7 +1063,7 @@ typedef struct MCEInjectionParams {
 static void do_inject_x86_mce(void *data)
 {
     MCEInjectionParams *params = data;
-    CPUState *cenv = params->env;
+    CPUX86State *cenv = params->env;
     uint64_t *banks = cenv->mce_banks + 4 * params->bank;
 
     cpu_synchronize_state(cenv);
@@ -1133,7 +1133,7 @@ static void do_inject_x86_mce(void *data)
     }
 }
 
-void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,
+void cpu_x86_inject_mce(Monitor *mon, CPUX86State *cenv, int bank,
                         uint64_t status, uint64_t mcg_status, uint64_t addr,
                         uint64_t misc, int flags)
 {
@@ -1148,7 +1148,7 @@ void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,
         .flags = flags,
     };
     unsigned bank_num = cenv->mcg_cap & 0xff;
-    CPUState *env;
+    CPUX86State *env;
 
     if (!cenv->mcg_cap) {
         monitor_printf(mon, "MCE injection not supported\n");
@@ -1185,7 +1185,7 @@ void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,
     }
 }
 
-void cpu_report_tpr_access(CPUState *env, TPRAccess access)
+void cpu_report_tpr_access(CPUX86State *env, TPRAccess access)
 {
     TranslationBlock *tb;
 
@@ -1277,7 +1277,7 @@ CPUX86State *cpu_x86_init(const char *cpu_model)
 }
 
 #if !defined(CONFIG_USER_ONLY)
-void do_cpu_init(CPUState *env)
+void do_cpu_init(CPUX86State *env)
 {
     int sipi = env->interrupt_request & CPU_INTERRUPT_SIPI;
     uint64_t pat = env->pat;
@@ -1289,15 +1289,15 @@ void do_cpu_init(CPUState *env)
     env->halted = !cpu_is_bsp(env);
 }
 
-void do_cpu_sipi(CPUState *env)
+void do_cpu_sipi(CPUX86State *env)
 {
     apic_sipi(env->apic_state);
 }
 #else
-void do_cpu_init(CPUState *env)
+void do_cpu_init(CPUX86State *env)
 {
 }
-void do_cpu_sipi(CPUState *env)
+void do_cpu_sipi(CPUX86State *env)
 {
 }
 #endif
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 619d773..e74a9e4 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -221,7 +221,7 @@ static int kvm_get_mce_cap_supported(KVMState *s, uint64_t *mce_cap,
     return -ENOSYS;
 }
 
-static void kvm_mce_inject(CPUState *env, target_phys_addr_t paddr, int code)
+static void kvm_mce_inject(CPUX86State *env, target_phys_addr_t paddr, int code)
 {
     uint64_t status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN |
                       MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S;
@@ -246,7 +246,7 @@ static void hardware_memory_error(void)
     exit(1);
 }
 
-int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr)
+int kvm_arch_on_sigbus_vcpu(CPUX86State *env, int code, void *addr)
 {
     ram_addr_t ram_addr;
     target_phys_addr_t paddr;
@@ -306,7 +306,7 @@ int kvm_arch_on_sigbus(int code, void *addr)
     return 0;
 }
 
-static int kvm_inject_mce_oldstyle(CPUState *env)
+static int kvm_inject_mce_oldstyle(CPUX86State *env)
 {
     if (!kvm_has_vcpu_events() && env->exception_injected == EXCP12_MCHK) {
         unsigned int bank, bank_num = env->mcg_cap & 0xff;
@@ -338,14 +338,14 @@ static int kvm_inject_mce_oldstyle(CPUState *env)
 
 static void cpu_update_state(void *opaque, int running, RunState state)
 {
-    CPUState *env = opaque;
+    CPUX86State *env = opaque;
 
     if (running) {
         env->tsc_valid = false;
     }
 }
 
-int kvm_arch_init_vcpu(CPUState *env)
+int kvm_arch_init_vcpu(CPUX86State *env)
 {
     struct {
         struct kvm_cpuid2 cpuid;
@@ -577,7 +577,7 @@ int kvm_arch_init_vcpu(CPUState *env)
     return 0;
 }
 
-void kvm_arch_reset_vcpu(CPUState *env)
+void kvm_arch_reset_vcpu(CPUX86State *env)
 {
     env->exception_injected = -1;
     env->interrupt_injected = -1;
@@ -768,7 +768,7 @@ static void kvm_getput_reg(__u64 *kvm_reg, target_ulong *qemu_reg, int set)
     }
 }
 
-static int kvm_getput_regs(CPUState *env, int set)
+static int kvm_getput_regs(CPUX86State *env, int set)
 {
     struct kvm_regs regs;
     int ret = 0;
@@ -809,7 +809,7 @@ static int kvm_getput_regs(CPUState *env, int set)
     return ret;
 }
 
-static int kvm_put_fpu(CPUState *env)
+static int kvm_put_fpu(CPUX86State *env)
 {
     struct kvm_fpu fpu;
     int i;
@@ -841,7 +841,7 @@ static int kvm_put_fpu(CPUState *env)
 #define XSAVE_XSTATE_BV   128
 #define XSAVE_YMMH_SPACE  144
 
-static int kvm_put_xsave(CPUState *env)
+static int kvm_put_xsave(CPUX86State *env)
 {
     struct kvm_xsave* xsave = env->kvm_xsave_buf;
     uint16_t cwd, swd, twd;
@@ -875,7 +875,7 @@ static int kvm_put_xsave(CPUState *env)
     return r;
 }
 
-static int kvm_put_xcrs(CPUState *env)
+static int kvm_put_xcrs(CPUX86State *env)
 {
     struct kvm_xcrs xcrs;
 
@@ -890,7 +890,7 @@ static int kvm_put_xcrs(CPUState *env)
     return kvm_vcpu_ioctl(env, KVM_SET_XCRS, &xcrs);
 }
 
-static int kvm_put_sregs(CPUState *env)
+static int kvm_put_sregs(CPUX86State *env)
 {
     struct kvm_sregs sregs;
 
@@ -946,7 +946,7 @@ static void kvm_msr_entry_set(struct kvm_msr_entry *entry,
     entry->data = value;
 }
 
-static int kvm_put_msrs(CPUState *env, int level)
+static int kvm_put_msrs(CPUX86State *env, int level)
 {
     struct {
         struct kvm_msrs info;
@@ -1029,7 +1029,7 @@ static int kvm_put_msrs(CPUState *env, int level)
 }
 
 
-static int kvm_get_fpu(CPUState *env)
+static int kvm_get_fpu(CPUX86State *env)
 {
     struct kvm_fpu fpu;
     int i, ret;
@@ -1055,7 +1055,7 @@ static int kvm_get_fpu(CPUState *env)
     return 0;
 }
 
-static int kvm_get_xsave(CPUState *env)
+static int kvm_get_xsave(CPUX86State *env)
 {
     struct kvm_xsave* xsave = env->kvm_xsave_buf;
     int ret, i;
@@ -1093,7 +1093,7 @@ static int kvm_get_xsave(CPUState *env)
     return 0;
 }
 
-static int kvm_get_xcrs(CPUState *env)
+static int kvm_get_xcrs(CPUX86State *env)
 {
     int i, ret;
     struct kvm_xcrs xcrs;
@@ -1117,7 +1117,7 @@ static int kvm_get_xcrs(CPUState *env)
     return 0;
 }
 
-static int kvm_get_sregs(CPUState *env)
+static int kvm_get_sregs(CPUX86State *env)
 {
     struct kvm_sregs sregs;
     uint32_t hflags;
@@ -1201,7 +1201,7 @@ static int kvm_get_sregs(CPUState *env)
     return 0;
 }
 
-static int kvm_get_msrs(CPUState *env)
+static int kvm_get_msrs(CPUX86State *env)
 {
     struct {
         struct kvm_msrs info;
@@ -1331,14 +1331,14 @@ static int kvm_get_msrs(CPUState *env)
     return 0;
 }
 
-static int kvm_put_mp_state(CPUState *env)
+static int kvm_put_mp_state(CPUX86State *env)
 {
     struct kvm_mp_state mp_state = { .mp_state = env->mp_state };
 
     return kvm_vcpu_ioctl(env, KVM_SET_MP_STATE, &mp_state);
 }
 
-static int kvm_get_mp_state(CPUState *env)
+static int kvm_get_mp_state(CPUX86State *env)
 {
     struct kvm_mp_state mp_state;
     int ret;
@@ -1354,7 +1354,7 @@ static int kvm_get_mp_state(CPUState *env)
     return 0;
 }
 
-static int kvm_get_apic(CPUState *env)
+static int kvm_get_apic(CPUX86State *env)
 {
     DeviceState *apic = env->apic_state;
     struct kvm_lapic_state kapic;
@@ -1371,7 +1371,7 @@ static int kvm_get_apic(CPUState *env)
     return 0;
 }
 
-static int kvm_put_apic(CPUState *env)
+static int kvm_put_apic(CPUX86State *env)
 {
     DeviceState *apic = env->apic_state;
     struct kvm_lapic_state kapic;
@@ -1384,7 +1384,7 @@ static int kvm_put_apic(CPUState *env)
     return 0;
 }
 
-static int kvm_put_vcpu_events(CPUState *env, int level)
+static int kvm_put_vcpu_events(CPUX86State *env, int level)
 {
     struct kvm_vcpu_events events;
 
@@ -1418,7 +1418,7 @@ static int kvm_put_vcpu_events(CPUState *env, int level)
     return kvm_vcpu_ioctl(env, KVM_SET_VCPU_EVENTS, &events);
 }
 
-static int kvm_get_vcpu_events(CPUState *env)
+static int kvm_get_vcpu_events(CPUX86State *env)
 {
     struct kvm_vcpu_events events;
     int ret;
@@ -1453,7 +1453,7 @@ static int kvm_get_vcpu_events(CPUState *env)
     return 0;
 }
 
-static int kvm_guest_debug_workarounds(CPUState *env)
+static int kvm_guest_debug_workarounds(CPUX86State *env)
 {
     int ret = 0;
     unsigned long reinject_trap = 0;
@@ -1482,7 +1482,7 @@ static int kvm_guest_debug_workarounds(CPUState *env)
     return ret;
 }
 
-static int kvm_put_debugregs(CPUState *env)
+static int kvm_put_debugregs(CPUX86State *env)
 {
     struct kvm_debugregs dbgregs;
     int i;
@@ -1501,7 +1501,7 @@ static int kvm_put_debugregs(CPUState *env)
     return kvm_vcpu_ioctl(env, KVM_SET_DEBUGREGS, &dbgregs);
 }
 
-static int kvm_get_debugregs(CPUState *env)
+static int kvm_get_debugregs(CPUX86State *env)
 {
     struct kvm_debugregs dbgregs;
     int i, ret;
@@ -1523,7 +1523,7 @@ static int kvm_get_debugregs(CPUState *env)
     return 0;
 }
 
-int kvm_arch_put_registers(CPUState *env, int level)
+int kvm_arch_put_registers(CPUX86State *env, int level)
 {
     int ret;
 
@@ -1580,7 +1580,7 @@ int kvm_arch_put_registers(CPUState *env, int level)
     return 0;
 }
 
-int kvm_arch_get_registers(CPUState *env)
+int kvm_arch_get_registers(CPUX86State *env)
 {
     int ret;
 
@@ -1625,7 +1625,7 @@ int kvm_arch_get_registers(CPUState *env)
     return 0;
 }
 
-void kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
+void kvm_arch_pre_run(CPUX86State *env, struct kvm_run *run)
 {
     int ret;
 
@@ -1685,7 +1685,7 @@ void kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
     }
 }
 
-void kvm_arch_post_run(CPUState *env, struct kvm_run *run)
+void kvm_arch_post_run(CPUX86State *env, struct kvm_run *run)
 {
     if (run->if_flag) {
         env->eflags |= IF_MASK;
@@ -1696,7 +1696,7 @@ void kvm_arch_post_run(CPUState *env, struct kvm_run *run)
     cpu_set_apic_base(env->apic_state, run->apic_base);
 }
 
-int kvm_arch_process_async_events(CPUState *env)
+int kvm_arch_process_async_events(CPUX86State *env)
 {
     if (env->interrupt_request & CPU_INTERRUPT_MCE) {
         /* We must not raise CPU_INTERRUPT_MCE if it's not supported. */
@@ -1748,7 +1748,7 @@ int kvm_arch_process_async_events(CPUState *env)
     return env->halted;
 }
 
-static int kvm_handle_halt(CPUState *env)
+static int kvm_handle_halt(CPUX86State *env)
 {
     if (!((env->interrupt_request & CPU_INTERRUPT_HARD) &&
           (env->eflags & IF_MASK)) &&
@@ -1760,7 +1760,7 @@ static int kvm_handle_halt(CPUState *env)
     return 0;
 }
 
-static int kvm_handle_tpr_access(CPUState *env)
+static int kvm_handle_tpr_access(CPUX86State *env)
 {
     struct kvm_run *run = env->kvm_run;
 
@@ -1770,7 +1770,7 @@ static int kvm_handle_tpr_access(CPUState *env)
     return 1;
 }
 
-int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
+int kvm_arch_insert_sw_breakpoint(CPUX86State *env, struct kvm_sw_breakpoint *bp)
 {
     static const uint8_t int3 = 0xcc;
 
@@ -1781,7 +1781,7 @@ int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
     return 0;
 }
 
-int kvm_arch_remove_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
+int kvm_arch_remove_sw_breakpoint(CPUX86State *env, struct kvm_sw_breakpoint *bp)
 {
     uint8_t int3;
 
@@ -1924,7 +1924,7 @@ static int kvm_handle_debug(struct kvm_debug_exit_arch *arch_info)
     return ret;
 }
 
-void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
+void kvm_arch_update_guest_debug(CPUX86State *env, struct kvm_guest_debug *dbg)
 {
     const uint8_t type_code[] = {
         [GDB_BREAKPOINT_HW] = 0x0,
@@ -1961,7 +1961,7 @@ static bool host_supports_vmx(void)
 
 #define VMX_INVALID_GUEST_STATE 0x80000021
 
-int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
+int kvm_arch_handle_exit(CPUX86State *env, struct kvm_run *run)
 {
     uint64_t code;
     int ret;
@@ -2012,7 +2012,7 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
     return ret;
 }
 
-bool kvm_arch_stop_on_emulation_error(CPUState *env)
+bool kvm_arch_stop_on_emulation_error(CPUX86State *env)
 {
     kvm_cpu_synchronize_state(env);
     return !(env->cr[0] & CR0_PE_MASK) ||
diff --git a/target-i386/machine.c b/target-i386/machine.c
index d6e98ff..a8be058 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -171,14 +171,14 @@ static const VMStateInfo vmstate_fpreg_1_no_mmx = {
 
 static bool fpregs_is_0(void *opaque, int version_id)
 {
-    CPUState *env = opaque;
+    CPUX86State *env = opaque;
 
     return (env->fpregs_format_vmstate == 0);
 }
 
 static bool fpregs_is_1_mmx(void *opaque, int version_id)
 {
-    CPUState *env = opaque;
+    CPUX86State *env = opaque;
     int guess_mmx;
 
     guess_mmx = ((env->fptag_vmstate == 0xff) &&
@@ -188,7 +188,7 @@ static bool fpregs_is_1_mmx(void *opaque, int version_id)
 
 static bool fpregs_is_1_no_mmx(void *opaque, int version_id)
 {
-    CPUState *env = opaque;
+    CPUX86State *env = opaque;
     int guess_mmx;
 
     guess_mmx = ((env->fptag_vmstate == 0xff) &&
@@ -237,7 +237,7 @@ static const VMStateInfo vmstate_hack_uint64_as_uint32 = {
 
 static void cpu_pre_save(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUX86State *env = opaque;
     int i;
 
     /* FPU */
@@ -252,7 +252,7 @@ static void cpu_pre_save(void *opaque)
 
 static int cpu_post_load(void *opaque, int version_id)
 {
-    CPUState *env = opaque;
+    CPUX86State *env = opaque;
     int i;
 
     /* XXX: restore FPU round state */
@@ -274,7 +274,7 @@ static int cpu_post_load(void *opaque, int version_id)
 
 static bool async_pf_msr_needed(void *opaque)
 {
-    CPUState *cpu = opaque;
+    CPUX86State *cpu = opaque;
 
     return cpu->async_pf_en_msr != 0;
 }
@@ -285,14 +285,14 @@ static const VMStateDescription vmstate_async_pf_msr = {
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .fields      = (VMStateField []) {
-        VMSTATE_UINT64(async_pf_en_msr, CPUState),
+        VMSTATE_UINT64(async_pf_en_msr, CPUX86State),
         VMSTATE_END_OF_LIST()
     }
 };
 
 static bool fpop_ip_dp_needed(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUX86State *env = opaque;
 
     return env->fpop != 0 || env->fpip != 0 || env->fpdp != 0;
 }
@@ -303,16 +303,16 @@ static const VMStateDescription vmstate_fpop_ip_dp = {
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .fields      = (VMStateField []) {
-        VMSTATE_UINT16(fpop, CPUState),
-        VMSTATE_UINT64(fpip, CPUState),
-        VMSTATE_UINT64(fpdp, CPUState),
+        VMSTATE_UINT16(fpop, CPUX86State),
+        VMSTATE_UINT64(fpip, CPUX86State),
+        VMSTATE_UINT64(fpdp, CPUX86State),
         VMSTATE_END_OF_LIST()
     }
 };
 
 static bool tscdeadline_needed(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUX86State *env = opaque;
 
     return env->tsc_deadline != 0;
 }
@@ -323,14 +323,14 @@ static const VMStateDescription vmstate_msr_tscdeadline = {
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .fields      = (VMStateField []) {
-        VMSTATE_UINT64(tsc_deadline, CPUState),
+        VMSTATE_UINT64(tsc_deadline, CPUX86State),
         VMSTATE_END_OF_LIST()
     }
 };
 
 static bool misc_enable_needed(void *opaque)
 {
-    CPUState *env = opaque;
+    CPUX86State *env = opaque;
 
     return env->msr_ia32_misc_enable != MSR_IA32_MISC_ENABLE_DEFAULT;
 }
@@ -341,7 +341,7 @@ static const VMStateDescription vmstate_msr_ia32_misc_enable = {
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .fields      = (VMStateField []) {
-        VMSTATE_UINT64(msr_ia32_misc_enable, CPUState),
+        VMSTATE_UINT64(msr_ia32_misc_enable, CPUX86State),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -354,98 +354,98 @@ static const VMStateDescription vmstate_cpu = {
     .pre_save = cpu_pre_save,
     .post_load = cpu_post_load,
     .fields      = (VMStateField []) {
-        VMSTATE_UINTTL_ARRAY(regs, CPUState, CPU_NB_REGS),
-        VMSTATE_UINTTL(eip, CPUState),
-        VMSTATE_UINTTL(eflags, CPUState),
-        VMSTATE_UINT32(hflags, CPUState),
+        VMSTATE_UINTTL_ARRAY(regs, CPUX86State, CPU_NB_REGS),
+        VMSTATE_UINTTL(eip, CPUX86State),
+        VMSTATE_UINTTL(eflags, CPUX86State),
+        VMSTATE_UINT32(hflags, CPUX86State),
         /* FPU */
-        VMSTATE_UINT16(fpuc, CPUState),
-        VMSTATE_UINT16(fpus_vmstate, CPUState),
-        VMSTATE_UINT16(fptag_vmstate, CPUState),
-        VMSTATE_UINT16(fpregs_format_vmstate, CPUState),
-        VMSTATE_FP_REGS(fpregs, CPUState, 8),
-
-        VMSTATE_SEGMENT_ARRAY(segs, CPUState, 6),
-        VMSTATE_SEGMENT(ldt, CPUState),
-        VMSTATE_SEGMENT(tr, CPUState),
-        VMSTATE_SEGMENT(gdt, CPUState),
-        VMSTATE_SEGMENT(idt, CPUState),
-
-        VMSTATE_UINT32(sysenter_cs, CPUState),
+        VMSTATE_UINT16(fpuc, CPUX86State),
+        VMSTATE_UINT16(fpus_vmstate, CPUX86State),
+        VMSTATE_UINT16(fptag_vmstate, CPUX86State),
+        VMSTATE_UINT16(fpregs_format_vmstate, CPUX86State),
+        VMSTATE_FP_REGS(fpregs, CPUX86State, 8),
+
+        VMSTATE_SEGMENT_ARRAY(segs, CPUX86State, 6),
+        VMSTATE_SEGMENT(ldt, CPUX86State),
+        VMSTATE_SEGMENT(tr, CPUX86State),
+        VMSTATE_SEGMENT(gdt, CPUX86State),
+        VMSTATE_SEGMENT(idt, CPUX86State),
+
+        VMSTATE_UINT32(sysenter_cs, CPUX86State),
 #ifdef TARGET_X86_64
         /* Hack: In v7 size changed from 32 to 64 bits on x86_64 */
-        VMSTATE_HACK_UINT32(sysenter_esp, CPUState, less_than_7),
-        VMSTATE_HACK_UINT32(sysenter_eip, CPUState, less_than_7),
-        VMSTATE_UINTTL_V(sysenter_esp, CPUState, 7),
-        VMSTATE_UINTTL_V(sysenter_eip, CPUState, 7),
+        VMSTATE_HACK_UINT32(sysenter_esp, CPUX86State, less_than_7),
+        VMSTATE_HACK_UINT32(sysenter_eip, CPUX86State, less_than_7),
+        VMSTATE_UINTTL_V(sysenter_esp, CPUX86State, 7),
+        VMSTATE_UINTTL_V(sysenter_eip, CPUX86State, 7),
 #else
-        VMSTATE_UINTTL(sysenter_esp, CPUState),
-        VMSTATE_UINTTL(sysenter_eip, CPUState),
+        VMSTATE_UINTTL(sysenter_esp, CPUX86State),
+        VMSTATE_UINTTL(sysenter_eip, CPUX86State),
 #endif
 
-        VMSTATE_UINTTL(cr[0], CPUState),
-        VMSTATE_UINTTL(cr[2], CPUState),
-        VMSTATE_UINTTL(cr[3], CPUState),
-        VMSTATE_UINTTL(cr[4], CPUState),
-        VMSTATE_UINTTL_ARRAY(dr, CPUState, 8),
+        VMSTATE_UINTTL(cr[0], CPUX86State),
+        VMSTATE_UINTTL(cr[2], CPUX86State),
+        VMSTATE_UINTTL(cr[3], CPUX86State),
+        VMSTATE_UINTTL(cr[4], CPUX86State),
+        VMSTATE_UINTTL_ARRAY(dr, CPUX86State, 8),
         /* MMU */
-        VMSTATE_INT32(a20_mask, CPUState),
+        VMSTATE_INT32(a20_mask, CPUX86State),
         /* XMM */
-        VMSTATE_UINT32(mxcsr, CPUState),
-        VMSTATE_XMM_REGS(xmm_regs, CPUState, CPU_NB_REGS),
+        VMSTATE_UINT32(mxcsr, CPUX86State),
+        VMSTATE_XMM_REGS(xmm_regs, CPUX86State, CPU_NB_REGS),
 
 #ifdef TARGET_X86_64
-        VMSTATE_UINT64(efer, CPUState),
-        VMSTATE_UINT64(star, CPUState),
-        VMSTATE_UINT64(lstar, CPUState),
-        VMSTATE_UINT64(cstar, CPUState),
-        VMSTATE_UINT64(fmask, CPUState),
-        VMSTATE_UINT64(kernelgsbase, CPUState),
+        VMSTATE_UINT64(efer, CPUX86State),
+        VMSTATE_UINT64(star, CPUX86State),
+        VMSTATE_UINT64(lstar, CPUX86State),
+        VMSTATE_UINT64(cstar, CPUX86State),
+        VMSTATE_UINT64(fmask, CPUX86State),
+        VMSTATE_UINT64(kernelgsbase, CPUX86State),
 #endif
-        VMSTATE_UINT32_V(smbase, CPUState, 4),
-
-        VMSTATE_UINT64_V(pat, CPUState, 5),
-        VMSTATE_UINT32_V(hflags2, CPUState, 5),
-
-        VMSTATE_UINT32_TEST(halted, CPUState, version_is_5),
-        VMSTATE_UINT64_V(vm_hsave, CPUState, 5),
-        VMSTATE_UINT64_V(vm_vmcb, CPUState, 5),
-        VMSTATE_UINT64_V(tsc_offset, CPUState, 5),
-        VMSTATE_UINT64_V(intercept, CPUState, 5),
-        VMSTATE_UINT16_V(intercept_cr_read, CPUState, 5),
-        VMSTATE_UINT16_V(intercept_cr_write, CPUState, 5),
-        VMSTATE_UINT16_V(intercept_dr_read, CPUState, 5),
-        VMSTATE_UINT16_V(intercept_dr_write, CPUState, 5),
-        VMSTATE_UINT32_V(intercept_exceptions, CPUState, 5),
-        VMSTATE_UINT8_V(v_tpr, CPUState, 5),
+        VMSTATE_UINT32_V(smbase, CPUX86State, 4),
+
+        VMSTATE_UINT64_V(pat, CPUX86State, 5),
+        VMSTATE_UINT32_V(hflags2, CPUX86State, 5),
+
+        VMSTATE_UINT32_TEST(halted, CPUX86State, version_is_5),
+        VMSTATE_UINT64_V(vm_hsave, CPUX86State, 5),
+        VMSTATE_UINT64_V(vm_vmcb, CPUX86State, 5),
+        VMSTATE_UINT64_V(tsc_offset, CPUX86State, 5),
+        VMSTATE_UINT64_V(intercept, CPUX86State, 5),
+        VMSTATE_UINT16_V(intercept_cr_read, CPUX86State, 5),
+        VMSTATE_UINT16_V(intercept_cr_write, CPUX86State, 5),
+        VMSTATE_UINT16_V(intercept_dr_read, CPUX86State, 5),
+        VMSTATE_UINT16_V(intercept_dr_write, CPUX86State, 5),
+        VMSTATE_UINT32_V(intercept_exceptions, CPUX86State, 5),
+        VMSTATE_UINT8_V(v_tpr, CPUX86State, 5),
         /* MTRRs */
-        VMSTATE_UINT64_ARRAY_V(mtrr_fixed, CPUState, 11, 8),
-        VMSTATE_UINT64_V(mtrr_deftype, CPUState, 8),
-        VMSTATE_MTRR_VARS(mtrr_var, CPUState, 8, 8),
+        VMSTATE_UINT64_ARRAY_V(mtrr_fixed, CPUX86State, 11, 8),
+        VMSTATE_UINT64_V(mtrr_deftype, CPUX86State, 8),
+        VMSTATE_MTRR_VARS(mtrr_var, CPUX86State, 8, 8),
         /* KVM-related states */
-        VMSTATE_INT32_V(interrupt_injected, CPUState, 9),
-        VMSTATE_UINT32_V(mp_state, CPUState, 9),
-        VMSTATE_UINT64_V(tsc, CPUState, 9),
-        VMSTATE_INT32_V(exception_injected, CPUState, 11),
-        VMSTATE_UINT8_V(soft_interrupt, CPUState, 11),
-        VMSTATE_UINT8_V(nmi_injected, CPUState, 11),
-        VMSTATE_UINT8_V(nmi_pending, CPUState, 11),
-        VMSTATE_UINT8_V(has_error_code, CPUState, 11),
-        VMSTATE_UINT32_V(sipi_vector, CPUState, 11),
+        VMSTATE_INT32_V(interrupt_injected, CPUX86State, 9),
+        VMSTATE_UINT32_V(mp_state, CPUX86State, 9),
+        VMSTATE_UINT64_V(tsc, CPUX86State, 9),
+        VMSTATE_INT32_V(exception_injected, CPUX86State, 11),
+        VMSTATE_UINT8_V(soft_interrupt, CPUX86State, 11),
+        VMSTATE_UINT8_V(nmi_injected, CPUX86State, 11),
+        VMSTATE_UINT8_V(nmi_pending, CPUX86State, 11),
+        VMSTATE_UINT8_V(has_error_code, CPUX86State, 11),
+        VMSTATE_UINT32_V(sipi_vector, CPUX86State, 11),
         /* MCE */
-        VMSTATE_UINT64_V(mcg_cap, CPUState, 10),
-        VMSTATE_UINT64_V(mcg_status, CPUState, 10),
-        VMSTATE_UINT64_V(mcg_ctl, CPUState, 10),
-        VMSTATE_UINT64_ARRAY_V(mce_banks, CPUState, MCE_BANKS_DEF *4, 10),
+        VMSTATE_UINT64_V(mcg_cap, CPUX86State, 10),
+        VMSTATE_UINT64_V(mcg_status, CPUX86State, 10),
+        VMSTATE_UINT64_V(mcg_ctl, CPUX86State, 10),
+        VMSTATE_UINT64_ARRAY_V(mce_banks, CPUX86State, MCE_BANKS_DEF *4, 10),
         /* rdtscp */
-        VMSTATE_UINT64_V(tsc_aux, CPUState, 11),
+        VMSTATE_UINT64_V(tsc_aux, CPUX86State, 11),
         /* KVM pvclock msr */
-        VMSTATE_UINT64_V(system_time_msr, CPUState, 11),
-        VMSTATE_UINT64_V(wall_clock_msr, CPUState, 11),
+        VMSTATE_UINT64_V(system_time_msr, CPUX86State, 11),
+        VMSTATE_UINT64_V(wall_clock_msr, CPUX86State, 11),
         /* XSAVE related fields */
-        VMSTATE_UINT64_V(xcr0, CPUState, 12),
-        VMSTATE_UINT64_V(xstate_bv, CPUState, 12),
-        VMSTATE_YMMH_REGS_VARS(ymmh_regs, CPUState, CPU_NB_REGS, 12),
+        VMSTATE_UINT64_V(xcr0, CPUX86State, 12),
+        VMSTATE_UINT64_V(xstate_bv, CPUX86State, 12),
+        VMSTATE_YMMH_REGS_VARS(ymmh_regs, CPUX86State, CPU_NB_REGS, 12),
         VMSTATE_END_OF_LIST()
         /* The above list is not sorted /wrt version numbers, watch out! */
     },
diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index 63a08d6..c04ae44 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -125,7 +125,7 @@ static inline void load_eflags(int eflags, int update_mask)
 
 /* load efer and update the corresponding hflags. XXX: do consistency
    checks with cpuid bits ? */
-static inline void cpu_load_efer(CPUState *env, uint64_t val)
+static inline void cpu_load_efer(CPUX86State *env, uint64_t val)
 {
     env->efer = val;
     env->hflags &= ~(HF_LMA_MASK | HF_SVME_MASK);
@@ -1376,9 +1376,9 @@ static void do_interrupt_all(int intno, int is_int, int error_code,
 #endif
 }
 
-void do_interrupt(CPUState *env1)
+void do_interrupt(CPUX86State *env1)
 {
-    CPUState *saved_env;
+    CPUX86State *saved_env;
 
     saved_env = env;
     env = env1;
@@ -1406,9 +1406,9 @@ void do_interrupt(CPUState *env1)
     env = saved_env;
 }
 
-void do_interrupt_x86_hardirq(CPUState *env1, int intno, int is_hw)
+void do_interrupt_x86_hardirq(CPUX86State *env1, int intno, int is_hw)
 {
-    CPUState *saved_env;
+    CPUX86State *saved_env;
 
     saved_env = env;
     env = env1;
@@ -1492,7 +1492,7 @@ static void QEMU_NORETURN raise_exception_err(int exception_index,
     raise_interrupt(exception_index, 0, error_code, 0);
 }
 
-void raise_exception_err_env(CPUState *nenv, int exception_index,
+void raise_exception_err_env(CPUX86State *nenv, int exception_index,
                              int error_code)
 {
     env = nenv;
@@ -1504,7 +1504,7 @@ static void QEMU_NORETURN raise_exception(int exception_index)
     raise_interrupt(exception_index, 0, 0, 0);
 }
 
-void raise_exception_env(int exception_index, CPUState *nenv)
+void raise_exception_env(int exception_index, CPUX86State *nenv)
 {
     env = nenv;
     raise_exception(exception_index);
@@ -1513,7 +1513,7 @@ void raise_exception_env(int exception_index, CPUState *nenv)
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_smm_enter(CPUState *env1)
+void do_smm_enter(CPUX86State *env1)
 {
 }
 
@@ -1529,12 +1529,12 @@ void helper_rsm(void)
 #define SMM_REVISION_ID 0x00020000
 #endif
 
-void do_smm_enter(CPUState *env1)
+void do_smm_enter(CPUX86State *env1)
 {
     target_ulong sm_state;
     SegmentCache *dt;
     int i, offset;
-    CPUState *saved_env;
+    CPUX86State *saved_env;
 
     saved_env = env;
     env = env1;
@@ -5002,7 +5002,7 @@ void helper_boundl(target_ulong a0, int v)
    NULL, it means that the function was called in C code (i.e. not
    from generated code or from helper.c) */
 /* XXX: fix it to restore all registers */
-void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
+void tlb_fill(CPUX86State *env1, target_ulong addr, int is_write, int mmu_idx,
               void *retaddr)
 {
     TranslationBlock *tb;
@@ -5066,7 +5066,7 @@ void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
 {
 }
 
-void svm_check_intercept(CPUState *env1, uint32_t type)
+void svm_check_intercept(CPUX86State *env1, uint32_t type)
 {
 }
 
@@ -5101,7 +5101,7 @@ static inline void svm_load_seg(target_phys_addr_t addr, SegmentCache *sc)
 }
 
 static inline void svm_load_seg_cache(target_phys_addr_t addr, 
-                                      CPUState *env, int seg_reg)
+                                      CPUX86State *env, int seg_reg)
 {
     SegmentCache sc1, *sc = &sc1;
     svm_load_seg(addr, sc);
@@ -5460,9 +5460,9 @@ void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
     }
 }
 
-void svm_check_intercept(CPUState *env1, uint32_t type)
+void svm_check_intercept(CPUX86State *env1, uint32_t type)
 {
-    CPUState *saved_env;
+    CPUX86State *saved_env;
 
     saved_env = env;
     env = env1;
@@ -5840,9 +5840,9 @@ uint32_t helper_cc_compute_all(int op)
     }
 }
 
-uint32_t cpu_cc_compute_all(CPUState *env1, int op)
+uint32_t cpu_cc_compute_all(CPUX86State *env1, int op)
 {
-    CPUState *saved_env;
+    CPUX86State *saved_env;
     uint32_t ret;
 
     saved_env = env;
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 860b4a3..c1ede1a 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -388,7 +388,7 @@ static inline void gen_op_addl_T0_T1(void)
 
 static inline void gen_op_jmp_T0(void)
 {
-    tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, eip));
+    tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, eip));
 }
 
 static inline void gen_op_add_reg_im(int size, int reg, int32_t val)
@@ -453,12 +453,12 @@ static inline void gen_op_addl_A0_reg_sN(int shift, int reg)
 
 static inline void gen_op_movl_A0_seg(int reg)
 {
-    tcg_gen_ld32u_tl(cpu_A0, cpu_env, offsetof(CPUState, segs[reg].base) + REG_L_OFFSET);
+    tcg_gen_ld32u_tl(cpu_A0, cpu_env, offsetof(CPUX86State, segs[reg].base) + REG_L_OFFSET);
 }
 
 static inline void gen_op_addl_A0_seg(int reg)
 {
-    tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, segs[reg].base));
+    tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, segs[reg].base));
     tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
 #ifdef TARGET_X86_64
     tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
@@ -468,12 +468,12 @@ static inline void gen_op_addl_A0_seg(int reg)
 #ifdef TARGET_X86_64
 static inline void gen_op_movq_A0_seg(int reg)
 {
-    tcg_gen_ld_tl(cpu_A0, cpu_env, offsetof(CPUState, segs[reg].base));
+    tcg_gen_ld_tl(cpu_A0, cpu_env, offsetof(CPUX86State, segs[reg].base));
 }
 
 static inline void gen_op_addq_A0_seg(int reg)
 {
-    tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, segs[reg].base));
+    tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, segs[reg].base));
     tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
 }
 
@@ -583,7 +583,7 @@ static inline void gen_op_st_T1_A0(int idx)
 static inline void gen_jmp_im(target_ulong pc)
 {
     tcg_gen_movi_tl(cpu_tmp0, pc);
-    tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, eip));
+    tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, eip));
 }
 
 static inline void gen_string_movl_A0_ESI(DisasContext *s)
@@ -644,7 +644,7 @@ static inline void gen_string_movl_A0_EDI(DisasContext *s)
 
 static inline void gen_op_movl_T0_Dshift(int ot) 
 {
-    tcg_gen_ld32s_tl(cpu_T[0], cpu_env, offsetof(CPUState, df));
+    tcg_gen_ld32s_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, df));
     tcg_gen_shli_tl(cpu_T[0], cpu_T[0], ot);
 };
 
@@ -6466,11 +6466,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         break;
     case 0xfc: /* cld */
         tcg_gen_movi_i32(cpu_tmp2_i32, 1);
-        tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUState, df));
+        tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
         break;
     case 0xfd: /* std */
         tcg_gen_movi_i32(cpu_tmp2_i32, -1);
-        tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUState, df));
+        tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
         break;
 
         /************************/
@@ -7645,64 +7645,64 @@ void optimize_flags_init(void)
 {
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
     cpu_cc_op = tcg_global_mem_new_i32(TCG_AREG0,
-                                       offsetof(CPUState, cc_op), "cc_op");
-    cpu_cc_src = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, cc_src),
+                                       offsetof(CPUX86State, cc_op), "cc_op");
+    cpu_cc_src = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_src),
                                     "cc_src");
-    cpu_cc_dst = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, cc_dst),
+    cpu_cc_dst = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_dst),
                                     "cc_dst");
-    cpu_cc_tmp = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, cc_tmp),
+    cpu_cc_tmp = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_tmp),
                                     "cc_tmp");
 
 #ifdef TARGET_X86_64
     cpu_regs[R_EAX] = tcg_global_mem_new_i64(TCG_AREG0,
-                                             offsetof(CPUState, regs[R_EAX]), "rax");
+                                             offsetof(CPUX86State, regs[R_EAX]), "rax");
     cpu_regs[R_ECX] = tcg_global_mem_new_i64(TCG_AREG0,
-                                             offsetof(CPUState, regs[R_ECX]), "rcx");
+                                             offsetof(CPUX86State, regs[R_ECX]), "rcx");
     cpu_regs[R_EDX] = tcg_global_mem_new_i64(TCG_AREG0,
-                                             offsetof(CPUState, regs[R_EDX]), "rdx");
+                                             offsetof(CPUX86State, regs[R_EDX]), "rdx");
     cpu_regs[R_EBX] = tcg_global_mem_new_i64(TCG_AREG0,
-                                             offsetof(CPUState, regs[R_EBX]), "rbx");
+                                             offsetof(CPUX86State, regs[R_EBX]), "rbx");
     cpu_regs[R_ESP] = tcg_global_mem_new_i64(TCG_AREG0,
-                                             offsetof(CPUState, regs[R_ESP]), "rsp");
+                                             offsetof(CPUX86State, regs[R_ESP]), "rsp");
     cpu_regs[R_EBP] = tcg_global_mem_new_i64(TCG_AREG0,
-                                             offsetof(CPUState, regs[R_EBP]), "rbp");
+                                             offsetof(CPUX86State, regs[R_EBP]), "rbp");
     cpu_regs[R_ESI] = tcg_global_mem_new_i64(TCG_AREG0,
-                                             offsetof(CPUState, regs[R_ESI]), "rsi");
+                                             offsetof(CPUX86State, regs[R_ESI]), "rsi");
     cpu_regs[R_EDI] = tcg_global_mem_new_i64(TCG_AREG0,
-                                             offsetof(CPUState, regs[R_EDI]), "rdi");
+                                             offsetof(CPUX86State, regs[R_EDI]), "rdi");
     cpu_regs[8] = tcg_global_mem_new_i64(TCG_AREG0,
-                                         offsetof(CPUState, regs[8]), "r8");
+                                         offsetof(CPUX86State, regs[8]), "r8");
     cpu_regs[9] = tcg_global_mem_new_i64(TCG_AREG0,
-                                          offsetof(CPUState, regs[9]), "r9");
+                                          offsetof(CPUX86State, regs[9]), "r9");
     cpu_regs[10] = tcg_global_mem_new_i64(TCG_AREG0,
-                                          offsetof(CPUState, regs[10]), "r10");
+                                          offsetof(CPUX86State, regs[10]), "r10");
     cpu_regs[11] = tcg_global_mem_new_i64(TCG_AREG0,
-                                          offsetof(CPUState, regs[11]), "r11");
+                                          offsetof(CPUX86State, regs[11]), "r11");
     cpu_regs[12] = tcg_global_mem_new_i64(TCG_AREG0,
-                                          offsetof(CPUState, regs[12]), "r12");
+                                          offsetof(CPUX86State, regs[12]), "r12");
     cpu_regs[13] = tcg_global_mem_new_i64(TCG_AREG0,
-                                          offsetof(CPUState, regs[13]), "r13");
+                                          offsetof(CPUX86State, regs[13]), "r13");
     cpu_regs[14] = tcg_global_mem_new_i64(TCG_AREG0,
-                                          offsetof(CPUState, regs[14]), "r14");
+                                          offsetof(CPUX86State, regs[14]), "r14");
     cpu_regs[15] = tcg_global_mem_new_i64(TCG_AREG0,
-                                          offsetof(CPUState, regs[15]), "r15");
+                                          offsetof(CPUX86State, regs[15]), "r15");
 #else
     cpu_regs[R_EAX] = tcg_global_mem_new_i32(TCG_AREG0,
-                                             offsetof(CPUState, regs[R_EAX]), "eax");
+                                             offsetof(CPUX86State, regs[R_EAX]), "eax");
     cpu_regs[R_ECX] = tcg_global_mem_new_i32(TCG_AREG0,
-                                             offsetof(CPUState, regs[R_ECX]), "ecx");
+                                             offsetof(CPUX86State, regs[R_ECX]), "ecx");
     cpu_regs[R_EDX] = tcg_global_mem_new_i32(TCG_AREG0,
-                                             offsetof(CPUState, regs[R_EDX]), "edx");
+                                             offsetof(CPUX86State, regs[R_EDX]), "edx");
     cpu_regs[R_EBX] = tcg_global_mem_new_i32(TCG_AREG0,
-                                             offsetof(CPUState, regs[R_EBX]), "ebx");
+                                             offsetof(CPUX86State, regs[R_EBX]), "ebx");
     cpu_regs[R_ESP] = tcg_global_mem_new_i32(TCG_AREG0,
-                                             offsetof(CPUState, regs[R_ESP]), "esp");
+                                             offsetof(CPUX86State, regs[R_ESP]), "esp");
     cpu_regs[R_EBP] = tcg_global_mem_new_i32(TCG_AREG0,
-                                             offsetof(CPUState, regs[R_EBP]), "ebp");
+                                             offsetof(CPUX86State, regs[R_EBP]), "ebp");
     cpu_regs[R_ESI] = tcg_global_mem_new_i32(TCG_AREG0,
-                                             offsetof(CPUState, regs[R_ESI]), "esi");
+                                             offsetof(CPUX86State, regs[R_ESI]), "esi");
     cpu_regs[R_EDI] = tcg_global_mem_new_i32(TCG_AREG0,
-                                             offsetof(CPUState, regs[R_EDI]), "edi");
+                                             offsetof(CPUX86State, regs[R_EDI]), "edi");
 #endif
 
     /* register helpers */
@@ -7713,7 +7713,7 @@ void optimize_flags_init(void)
 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
    basic block 'tb'. If search_pc is TRUE, also generate PC
    information for each intermediate instruction. */
-static inline void gen_intermediate_code_internal(CPUState *env,
+static inline void gen_intermediate_code_internal(CPUX86State *env,
                                                   TranslationBlock *tb,
                                                   int search_pc)
 {
@@ -7890,17 +7890,17 @@ static inline void gen_intermediate_code_internal(CPUState *env,
     }
 }
 
-void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
+void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 0);
 }
 
-void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
+void gen_intermediate_code_pc(CPUX86State *env, TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 1);
 }
 
-void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, int pc_pos)
 {
     int cc_op;
 #ifdef DEBUG_DISAS
commit a1170bfd19cdf4bb405b73fea21c1bc4964e3354
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:21 2012 +0100

    target-cris: Don't overuse CPUState
    
    Scripted conversion:
      sed -i "s/CPUState/CPUCRISState/g" target-cris/*.[hc]
      sed -i "s/#define CPUCRISState/#define CPUState/" target-cris/cpu.h
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index 222a062..f38393a 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -225,17 +225,17 @@ enum {
 #define MMU_MODE0_SUFFIX _kernel
 #define MMU_MODE1_SUFFIX _user
 #define MMU_USER_IDX 1
-static inline int cpu_mmu_index (CPUState *env)
+static inline int cpu_mmu_index (CPUCRISState *env)
 {
 	return !!(env->pregs[PR_CCS] & U_FLAG);
 }
 
-int cpu_cris_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
+int cpu_cris_handle_mmu_fault(CPUCRISState *env, target_ulong address, int rw,
                               int mmu_idx);
 #define cpu_handle_mmu_fault cpu_cris_handle_mmu_fault
 
 #if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
+static inline void cpu_clone_regs(CPUCRISState *env, target_ulong newsp)
 {
     if (newsp)
         env->regs[14] = newsp;
@@ -260,7 +260,7 @@ static inline void cpu_set_tls(CPUCRISState *env, target_ulong newtls)
 
 #include "cpu-all.h"
 
-static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+static inline void cpu_get_tb_cpu_state(CPUCRISState *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
     *pc = env->pc;
@@ -273,14 +273,14 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
 #define cpu_list cris_cpu_list
 void cris_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 
-static inline bool cpu_has_work(CPUState *env)
+static inline bool cpu_has_work(CPUCRISState *env)
 {
     return env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
 }
 
 #include "exec-all.h"
 
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+static inline void cpu_pc_from_tb(CPUCRISState *env, TranslationBlock *tb)
 {
     env->pc = tb->pc;
 }
diff --git a/target-cris/helper.c b/target-cris/helper.c
index dd7f18e..8680f43 100644
--- a/target-cris/helper.c
+++ b/target-cris/helper.c
@@ -36,13 +36,13 @@
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt (CPUState *env)
+void do_interrupt (CPUCRISState *env)
 {
 	env->exception_index = -1;
 	env->pregs[PR_ERP] = env->pc;
 }
 
-int cpu_cris_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
+int cpu_cris_handle_mmu_fault(CPUCRISState * env, target_ulong address, int rw,
                               int mmu_idx)
 {
 	env->exception_index = 0xaa;
@@ -54,7 +54,7 @@ int cpu_cris_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
 #else /* !CONFIG_USER_ONLY */
 
 
-static void cris_shift_ccs(CPUState *env)
+static void cris_shift_ccs(CPUCRISState *env)
 {
 	uint32_t ccs;
 	/* Apply the ccs shift.  */
@@ -63,7 +63,7 @@ static void cris_shift_ccs(CPUState *env)
 	env->pregs[PR_CCS] = ccs;
 }
 
-int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
+int cpu_cris_handle_mmu_fault (CPUCRISState *env, target_ulong address, int rw,
                                int mmu_idx)
 {
 	struct cris_mmu_result res;
@@ -106,7 +106,7 @@ int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
 	return r;
 }
 
-static void do_interruptv10(CPUState *env)
+static void do_interruptv10(CPUCRISState *env)
 {
 	int ex_vec = -1;
 
@@ -162,7 +162,7 @@ static void do_interruptv10(CPUState *env)
 		      env->pregs[PR_ERP]);
 }
 
-void do_interrupt(CPUState *env)
+void do_interrupt(CPUCRISState *env)
 {
 	int ex_vec = -1;
 
@@ -246,7 +246,7 @@ void do_interrupt(CPUState *env)
 		   env->pregs[PR_ERP]);
 }
 
-target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_debug(CPUCRISState * env, target_ulong addr)
 {
 	uint32_t phy = addr;
 	struct cris_mmu_result res;
diff --git a/target-cris/mmu.c b/target-cris/mmu.c
index 5cd8f27..512e28b 100644
--- a/target-cris/mmu.c
+++ b/target-cris/mmu.c
@@ -31,7 +31,7 @@
 #define D_LOG(...) do { } while (0)
 #endif
 
-void cris_mmu_init(CPUState *env)
+void cris_mmu_init(CPUCRISState *env)
 {
 	env->mmu_rand_lfsr = 0xcccc;
 }
@@ -49,7 +49,7 @@ static inline unsigned int compute_polynom(unsigned int sr)
 	return f;
 }
 
-static void cris_mmu_update_rand_lfsr(CPUState *env)
+static void cris_mmu_update_rand_lfsr(CPUCRISState *env)
 {
 	unsigned int f;
 
@@ -70,7 +70,7 @@ static inline int cris_mmu_segmented_addr(int seg, uint32_t rw_mm_cfg)
 	return (1 << seg) & rw_mm_cfg;
 }
 
-static uint32_t cris_mmu_translate_seg(CPUState *env, int seg)
+static uint32_t cris_mmu_translate_seg(CPUCRISState *env, int seg)
 {
 	uint32_t base;
 	int i;
@@ -106,7 +106,7 @@ static inline void set_field(uint32_t *dst, unsigned int val,
 }
 
 #ifdef DEBUG
-static void dump_tlb(CPUState *env, int mmu)
+static void dump_tlb(CPUCRISState *env, int mmu)
 {
 	int set;
 	int idx;
@@ -128,7 +128,7 @@ static void dump_tlb(CPUState *env, int mmu)
 
 /* rw 0 = read, 1 = write, 2 = exec.  */
 static int cris_mmu_translate_page(struct cris_mmu_result *res,
-				   CPUState *env, uint32_t vaddr,
+				   CPUCRISState *env, uint32_t vaddr,
 				   int rw, int usermode, int debug)
 {
 	unsigned int vpage;
@@ -288,7 +288,7 @@ static int cris_mmu_translate_page(struct cris_mmu_result *res,
 	return !match;
 }
 
-void cris_mmu_flush_pid(CPUState *env, uint32_t pid)
+void cris_mmu_flush_pid(CPUCRISState *env, uint32_t pid)
 {
 	target_ulong vaddr;
 	unsigned int idx;
@@ -323,7 +323,7 @@ void cris_mmu_flush_pid(CPUState *env, uint32_t pid)
 }
 
 int cris_mmu_translate(struct cris_mmu_result *res,
-		       CPUState *env, uint32_t vaddr,
+		       CPUCRISState *env, uint32_t vaddr,
 		       int rw, int mmu_idx, int debug)
 {
 	int seg;
diff --git a/target-cris/mmu.h b/target-cris/mmu.h
index 459d809..8e249e8 100644
--- a/target-cris/mmu.h
+++ b/target-cris/mmu.h
@@ -10,8 +10,8 @@ struct cris_mmu_result
 	int bf_vec;
 };
 
-void cris_mmu_init(CPUState *env);
-void cris_mmu_flush_pid(CPUState *env, uint32_t pid);
+void cris_mmu_init(CPUCRISState *env);
+void cris_mmu_flush_pid(CPUCRISState *env, uint32_t pid);
 int cris_mmu_translate(struct cris_mmu_result *res,
-		       CPUState *env, uint32_t vaddr,
+		       CPUCRISState *env, uint32_t vaddr,
 		       int rw, int mmu_idx, int debug);
diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c
index 1eacc5f..c568e2b 100644
--- a/target-cris/op_helper.c
+++ b/target-cris/op_helper.c
@@ -56,11 +56,11 @@
    NULL, it means that the function was called in C code (i.e. not
    from generated code or from helper.c) */
 /* XXX: fix it to restore all registers */
-void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
+void tlb_fill(CPUCRISState *env1, target_ulong addr, int is_write, int mmu_idx,
               void *retaddr)
 {
     TranslationBlock *tb;
-    CPUState *saved_env;
+    CPUCRISState *saved_env;
     unsigned long pc;
     int ret;
 
@@ -201,7 +201,7 @@ void helper_movl_reg_sreg (uint32_t reg, uint32_t sreg)
 	env->regs[reg] = env->sregs[srs][sreg];
 }
 
-static void cris_ccs_rshift(CPUState *env)
+static void cris_ccs_rshift(CPUCRISState *env)
 {
 	uint32_t ccs;
 
diff --git a/target-cris/translate.c b/target-cris/translate.c
index f360c31..7224f46 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -74,7 +74,7 @@ static TCGv env_pc;
 
 /* This is the state at translation time.  */
 typedef struct DisasContext {
-	CPUState *env;
+	CPUCRISState *env;
 	target_ulong pc, ppc;
 
 	/* Decoder.  */
@@ -160,9 +160,9 @@ static int preg_sizes[] = {
 };
 
 #define t_gen_mov_TN_env(tn, member) \
- _t_gen_mov_TN_env((tn), offsetof(CPUState, member))
+ _t_gen_mov_TN_env((tn), offsetof(CPUCRISState, member))
 #define t_gen_mov_env_TN(member, tn) \
- _t_gen_mov_env_TN(offsetof(CPUState, member), (tn))
+ _t_gen_mov_env_TN(offsetof(CPUCRISState, member), (tn))
 
 static inline void t_gen_mov_TN_reg(TCGv tn, int r)
 {
@@ -179,13 +179,13 @@ static inline void t_gen_mov_reg_TN(int r, TCGv tn)
 
 static inline void _t_gen_mov_TN_env(TCGv tn, int offset)
 {
-	if (offset > sizeof (CPUState))
+	if (offset > sizeof (CPUCRISState))
 		fprintf(stderr, "wrong load from env from off=%d\n", offset);
 	tcg_gen_ld_tl(tn, cpu_env, offset);
 }
 static inline void _t_gen_mov_env_TN(int offset, TCGv tn)
 {
-	if (offset > sizeof (CPUState))
+	if (offset > sizeof (CPUCRISState))
 		fprintf(stderr, "wrong store to env at off=%d\n", offset);
 	tcg_gen_st_tl(tn, cpu_env, offset);
 }
@@ -3114,7 +3114,7 @@ static unsigned int crisv32_decoder(DisasContext *dc)
 	return insn_len;
 }
 
-static void check_breakpoint(CPUState *env, DisasContext *dc)
+static void check_breakpoint(CPUCRISState *env, DisasContext *dc)
 {
 	CPUBreakpoint *bp;
 
@@ -3168,7 +3168,7 @@ static void check_breakpoint(CPUState *env, DisasContext *dc)
 
 /* generate intermediate code for basic block 'tb'.  */
 static void
-gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
+gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb,
                                int search_pc)
 {
 	uint16_t *gen_opc_end;
@@ -3419,17 +3419,17 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
 #endif
 }
 
-void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
+void gen_intermediate_code (CPUCRISState *env, struct TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 0);
 }
 
-void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
+void gen_intermediate_code_pc (CPUCRISState *env, struct TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 1);
 }
 
-void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
+void cpu_dump_state (CPUCRISState *env, FILE *f, fprintf_function cpu_fprintf,
                      int flags)
 {
 	int i;
@@ -3532,41 +3532,41 @@ CPUCRISState *cpu_cris_init (const char *cpu_model)
 
 	cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
 	cc_x = tcg_global_mem_new(TCG_AREG0,
-				  offsetof(CPUState, cc_x), "cc_x");
+				  offsetof(CPUCRISState, cc_x), "cc_x");
 	cc_src = tcg_global_mem_new(TCG_AREG0,
-				    offsetof(CPUState, cc_src), "cc_src");
+				    offsetof(CPUCRISState, cc_src), "cc_src");
 	cc_dest = tcg_global_mem_new(TCG_AREG0,
-				     offsetof(CPUState, cc_dest),
+				     offsetof(CPUCRISState, cc_dest),
 				     "cc_dest");
 	cc_result = tcg_global_mem_new(TCG_AREG0,
-				       offsetof(CPUState, cc_result),
+				       offsetof(CPUCRISState, cc_result),
 				       "cc_result");
 	cc_op = tcg_global_mem_new(TCG_AREG0,
-				   offsetof(CPUState, cc_op), "cc_op");
+				   offsetof(CPUCRISState, cc_op), "cc_op");
 	cc_size = tcg_global_mem_new(TCG_AREG0,
-				     offsetof(CPUState, cc_size),
+				     offsetof(CPUCRISState, cc_size),
 				     "cc_size");
 	cc_mask = tcg_global_mem_new(TCG_AREG0,
-				     offsetof(CPUState, cc_mask),
+				     offsetof(CPUCRISState, cc_mask),
 				     "cc_mask");
 
 	env_pc = tcg_global_mem_new(TCG_AREG0, 
-				    offsetof(CPUState, pc),
+				    offsetof(CPUCRISState, pc),
 				    "pc");
 	env_btarget = tcg_global_mem_new(TCG_AREG0,
-					 offsetof(CPUState, btarget),
+					 offsetof(CPUCRISState, btarget),
 					 "btarget");
 	env_btaken = tcg_global_mem_new(TCG_AREG0,
-					 offsetof(CPUState, btaken),
+					 offsetof(CPUCRISState, btaken),
 					 "btaken");
 	for (i = 0; i < 16; i++) {
 		cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
-					      offsetof(CPUState, regs[i]),
+					      offsetof(CPUCRISState, regs[i]),
 					      regnames[i]);
 	}
 	for (i = 0; i < 16; i++) {
 		cpu_PR[i] = tcg_global_mem_new(TCG_AREG0,
-					       offsetof(CPUState, pregs[i]),
+					       offsetof(CPUCRISState, pregs[i]),
 					       pregnames[i]);
 	}
 
@@ -3596,7 +3596,7 @@ void cpu_state_reset(CPUCRISState *env)
 #endif
 }
 
-void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUCRISState *env, TranslationBlock *tb, int pc_pos)
 {
 	env->pc = gen_opc_pc[pc_pos];
 }
diff --git a/target-cris/translate_v10.c b/target-cris/translate_v10.c
index 95053b6..4ada3ed 100644
--- a/target-cris/translate_v10.c
+++ b/target-cris/translate_v10.c
@@ -1253,47 +1253,47 @@ static unsigned int crisv10_decoder(DisasContext *dc)
     return insn_len;
 }
 
-static CPUCRISState *cpu_crisv10_init (CPUState *env)
+static CPUCRISState *cpu_crisv10_init (CPUCRISState *env)
 {
 	int i;
 
 	cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
 	cc_x = tcg_global_mem_new(TCG_AREG0,
-				  offsetof(CPUState, cc_x), "cc_x");
+				  offsetof(CPUCRISState, cc_x), "cc_x");
 	cc_src = tcg_global_mem_new(TCG_AREG0,
-				    offsetof(CPUState, cc_src), "cc_src");
+				    offsetof(CPUCRISState, cc_src), "cc_src");
 	cc_dest = tcg_global_mem_new(TCG_AREG0,
-				     offsetof(CPUState, cc_dest),
+				     offsetof(CPUCRISState, cc_dest),
 				     "cc_dest");
 	cc_result = tcg_global_mem_new(TCG_AREG0,
-				       offsetof(CPUState, cc_result),
+				       offsetof(CPUCRISState, cc_result),
 				       "cc_result");
 	cc_op = tcg_global_mem_new(TCG_AREG0,
-				   offsetof(CPUState, cc_op), "cc_op");
+				   offsetof(CPUCRISState, cc_op), "cc_op");
 	cc_size = tcg_global_mem_new(TCG_AREG0,
-				     offsetof(CPUState, cc_size),
+				     offsetof(CPUCRISState, cc_size),
 				     "cc_size");
 	cc_mask = tcg_global_mem_new(TCG_AREG0,
-				     offsetof(CPUState, cc_mask),
+				     offsetof(CPUCRISState, cc_mask),
 				     "cc_mask");
 
 	env_pc = tcg_global_mem_new(TCG_AREG0, 
-				    offsetof(CPUState, pc),
+				    offsetof(CPUCRISState, pc),
 				    "pc");
 	env_btarget = tcg_global_mem_new(TCG_AREG0,
-					 offsetof(CPUState, btarget),
+					 offsetof(CPUCRISState, btarget),
 					 "btarget");
 	env_btaken = tcg_global_mem_new(TCG_AREG0,
-					 offsetof(CPUState, btaken),
+					 offsetof(CPUCRISState, btaken),
 					 "btaken");
 	for (i = 0; i < 16; i++) {
 		cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
-					      offsetof(CPUState, regs[i]),
+					      offsetof(CPUCRISState, regs[i]),
 					      regnames_v10[i]);
 	}
 	for (i = 0; i < 16; i++) {
 		cpu_PR[i] = tcg_global_mem_new(TCG_AREG0,
-					       offsetof(CPUState, pregs[i]),
+					       offsetof(CPUCRISState, pregs[i]),
 					       pregnames_v10[i]);
 	}
 
commit 0ecb72a58838d8a0d4edcad7db674d39bfd2e9bc
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:21 2012 +0100

    target-arm: Don't overuse CPUState
    
    Scripted conversion:
      sed -i "s/CPUState/CPUARMState/g" target-arm/*.[hc]
      sed -i "s/#define CPUARMState/#define CPUState/" target-arm/cpu.h
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>
    Acked-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 0d9b39c..2bbb5d1 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -461,13 +461,13 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
 #define MMU_MODE0_SUFFIX _kernel
 #define MMU_MODE1_SUFFIX _user
 #define MMU_USER_IDX 1
-static inline int cpu_mmu_index (CPUState *env)
+static inline int cpu_mmu_index (CPUARMState *env)
 {
     return (env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR ? 1 : 0;
 }
 
 #if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
+static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp)
 {
     if (newsp)
         env->regs[13] = newsp;
@@ -506,7 +506,7 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
 #define ARM_TBFLAG_CONDEXEC(F) \
     (((F) & ARM_TBFLAG_CONDEXEC_MASK) >> ARM_TBFLAG_CONDEXEC_SHIFT)
 
-static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
     int privmode;
@@ -529,7 +529,7 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
     }
 }
 
-static inline bool cpu_has_work(CPUState *env)
+static inline bool cpu_has_work(CPUARMState *env)
 {
     return env->interrupt_request &
         (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
@@ -537,7 +537,7 @@ static inline bool cpu_has_work(CPUState *env)
 
 #include "exec-all.h"
 
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+static inline void cpu_pc_from_tb(CPUARMState *env, TranslationBlock *tb)
 {
     env->regs[15] = tb->pc;
 }
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 13ff474..8a08db8 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -339,14 +339,14 @@ void cpu_state_reset(CPUARMState *env)
     set_float_detect_tininess(float_tininess_before_rounding,
                               &env->vfp.standard_fp_status);
     tlb_flush(env, 1);
-    /* Reset is a state change for some CPUState fields which we
+    /* Reset is a state change for some CPUARMState fields which we
      * bake assumptions about into translated code, so we need to
      * tb_flush().
      */
     tb_flush(env);
 }
 
-static int vfp_gdb_get_reg(CPUState *env, uint8_t *buf, int reg)
+static int vfp_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
 {
     int nregs;
 
@@ -373,7 +373,7 @@ static int vfp_gdb_get_reg(CPUState *env, uint8_t *buf, int reg)
     return 0;
 }
 
-static int vfp_gdb_set_reg(CPUState *env, uint8_t *buf, int reg)
+static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
 {
     int nregs;
 
@@ -498,7 +498,7 @@ void cpu_arm_close(CPUARMState *env)
     g_free(env);
 }
 
-static int bad_mode_switch(CPUState *env, int mode)
+static int bad_mode_switch(CPUARMState *env, int mode)
 {
     /* Return true if it is not valid for us to switch to
      * this CPU mode (ie all the UNPREDICTABLE cases in
@@ -628,12 +628,12 @@ uint32_t HELPER(abs)(uint32_t x)
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt (CPUState *env)
+void do_interrupt (CPUARMState *env)
 {
     env->exception_index = -1;
 }
 
-int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
+int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address, int rw,
                               int mmu_idx)
 {
     if (rw == 2) {
@@ -647,54 +647,54 @@ int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
 }
 
 /* These should probably raise undefined insn exceptions.  */
-void HELPER(set_cp)(CPUState *env, uint32_t insn, uint32_t val)
+void HELPER(set_cp)(CPUARMState *env, uint32_t insn, uint32_t val)
 {
     int op1 = (insn >> 8) & 0xf;
     cpu_abort(env, "cp%i insn %08x\n", op1, insn);
     return;
 }
 
-uint32_t HELPER(get_cp)(CPUState *env, uint32_t insn)
+uint32_t HELPER(get_cp)(CPUARMState *env, uint32_t insn)
 {
     int op1 = (insn >> 8) & 0xf;
     cpu_abort(env, "cp%i insn %08x\n", op1, insn);
     return 0;
 }
 
-void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
+void HELPER(set_cp15)(CPUARMState *env, uint32_t insn, uint32_t val)
 {
     cpu_abort(env, "cp15 insn %08x\n", insn);
 }
 
-uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
+uint32_t HELPER(get_cp15)(CPUARMState *env, uint32_t insn)
 {
     cpu_abort(env, "cp15 insn %08x\n", insn);
 }
 
 /* These should probably raise undefined insn exceptions.  */
-void HELPER(v7m_msr)(CPUState *env, uint32_t reg, uint32_t val)
+void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
 {
     cpu_abort(env, "v7m_mrs %d\n", reg);
 }
 
-uint32_t HELPER(v7m_mrs)(CPUState *env, uint32_t reg)
+uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
 {
     cpu_abort(env, "v7m_mrs %d\n", reg);
     return 0;
 }
 
-void switch_mode(CPUState *env, int mode)
+void switch_mode(CPUARMState *env, int mode)
 {
     if (mode != ARM_CPU_MODE_USR)
         cpu_abort(env, "Tried to switch out of user mode\n");
 }
 
-void HELPER(set_r13_banked)(CPUState *env, uint32_t mode, uint32_t val)
+void HELPER(set_r13_banked)(CPUARMState *env, uint32_t mode, uint32_t val)
 {
     cpu_abort(env, "banked r13 write\n");
 }
 
-uint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode)
+uint32_t HELPER(get_r13_banked)(CPUARMState *env, uint32_t mode)
 {
     cpu_abort(env, "banked r13 read\n");
     return 0;
@@ -703,7 +703,7 @@ uint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode)
 #else
 
 /* Map CPU modes onto saved register banks.  */
-static inline int bank_number(CPUState *env, int mode)
+static inline int bank_number(CPUARMState *env, int mode)
 {
     switch (mode) {
     case ARM_CPU_MODE_USR:
@@ -724,7 +724,7 @@ static inline int bank_number(CPUState *env, int mode)
     return -1;
 }
 
-void switch_mode(CPUState *env, int mode)
+void switch_mode(CPUARMState *env, int mode)
 {
     int old_mode;
     int i;
@@ -997,7 +997,7 @@ void do_interrupt(CPUARMState *env)
 /* Check section/page access permissions.
    Returns the page protection flags, or zero if the access is not
    permitted.  */
-static inline int check_ap(CPUState *env, int ap, int domain_prot,
+static inline int check_ap(CPUARMState *env, int ap, int domain_prot,
                            int access_type, int is_user)
 {
   int prot_ro;
@@ -1047,7 +1047,7 @@ static inline int check_ap(CPUState *env, int ap, int domain_prot,
   }
 }
 
-static uint32_t get_level1_table_address(CPUState *env, uint32_t address)
+static uint32_t get_level1_table_address(CPUARMState *env, uint32_t address)
 {
     uint32_t table;
 
@@ -1060,7 +1060,7 @@ static uint32_t get_level1_table_address(CPUState *env, uint32_t address)
     return table;
 }
 
-static int get_phys_addr_v5(CPUState *env, uint32_t address, int access_type,
+static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
 			    int is_user, uint32_t *phys_ptr, int *prot,
                             target_ulong *page_size)
 {
@@ -1155,7 +1155,7 @@ do_fault:
     return code | (domain << 4);
 }
 
-static int get_phys_addr_v6(CPUState *env, uint32_t address, int access_type,
+static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
 			    int is_user, uint32_t *phys_ptr, int *prot,
                             target_ulong *page_size)
 {
@@ -1259,7 +1259,7 @@ do_fault:
     return code | (domain << 4);
 }
 
-static int get_phys_addr_mpu(CPUState *env, uint32_t address, int access_type,
+static int get_phys_addr_mpu(CPUARMState *env, uint32_t address, int access_type,
 			     int is_user, uint32_t *phys_ptr, int *prot)
 {
     int n;
@@ -1319,7 +1319,7 @@ static int get_phys_addr_mpu(CPUState *env, uint32_t address, int access_type,
     return 0;
 }
 
-static inline int get_phys_addr(CPUState *env, uint32_t address,
+static inline int get_phys_addr(CPUARMState *env, uint32_t address,
                                 int access_type, int is_user,
                                 uint32_t *phys_ptr, int *prot,
                                 target_ulong *page_size)
@@ -1347,7 +1347,7 @@ static inline int get_phys_addr(CPUState *env, uint32_t address,
     }
 }
 
-int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address,
+int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address,
                               int access_type, int mmu_idx)
 {
     uint32_t phys_addr;
@@ -1380,7 +1380,7 @@ int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address,
     return 1;
 }
 
-target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_debug(CPUARMState *env, target_ulong addr)
 {
     uint32_t phys_addr;
     target_ulong page_size;
@@ -1395,7 +1395,7 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
     return phys_addr;
 }
 
-void HELPER(set_cp)(CPUState *env, uint32_t insn, uint32_t val)
+void HELPER(set_cp)(CPUARMState *env, uint32_t insn, uint32_t val)
 {
     int cp_num = (insn >> 8) & 0xf;
     int cp_info = (insn >> 5) & 7;
@@ -1407,7 +1407,7 @@ void HELPER(set_cp)(CPUState *env, uint32_t insn, uint32_t val)
                                  cp_info, src, operand, val);
 }
 
-uint32_t HELPER(get_cp)(CPUState *env, uint32_t insn)
+uint32_t HELPER(get_cp)(CPUARMState *env, uint32_t insn)
 {
     int cp_num = (insn >> 8) & 0xf;
     int cp_info = (insn >> 5) & 7;
@@ -1450,7 +1450,7 @@ static uint32_t extended_mpu_ap_bits(uint32_t val)
     return ret;
 }
 
-void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
+void HELPER(set_cp15)(CPUARMState *env, uint32_t insn, uint32_t val)
 {
     int op1;
     int op2;
@@ -1860,7 +1860,7 @@ bad_reg:
               (insn >> 16) & 0xf, crm, op1, op2);
 }
 
-uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
+uint32_t HELPER(get_cp15)(CPUARMState *env, uint32_t insn)
 {
     int op1;
     int op2;
@@ -2261,7 +2261,7 @@ bad_reg:
     return 0;
 }
 
-void HELPER(set_r13_banked)(CPUState *env, uint32_t mode, uint32_t val)
+void HELPER(set_r13_banked)(CPUARMState *env, uint32_t mode, uint32_t val)
 {
     if ((env->uncached_cpsr & CPSR_M) == mode) {
         env->regs[13] = val;
@@ -2270,7 +2270,7 @@ void HELPER(set_r13_banked)(CPUState *env, uint32_t mode, uint32_t val)
     }
 }
 
-uint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode)
+uint32_t HELPER(get_r13_banked)(CPUARMState *env, uint32_t mode)
 {
     if ((env->uncached_cpsr & CPSR_M) == mode) {
         return env->regs[13];
@@ -2279,7 +2279,7 @@ uint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode)
     }
 }
 
-uint32_t HELPER(v7m_mrs)(CPUState *env, uint32_t reg)
+uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
 {
     switch (reg) {
     case 0: /* APSR */
@@ -2316,7 +2316,7 @@ uint32_t HELPER(v7m_mrs)(CPUState *env, uint32_t reg)
     }
 }
 
-void HELPER(v7m_msr)(CPUState *env, uint32_t reg, uint32_t val)
+void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
 {
     switch (reg) {
     case 0: /* APSR */
@@ -2672,7 +2672,7 @@ static inline int vfp_exceptbits_from_host(int host_bits)
     return target_bits;
 }
 
-uint32_t HELPER(vfp_get_fpscr)(CPUState *env)
+uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
 {
     int i;
     uint32_t fpscr;
@@ -2686,7 +2686,7 @@ uint32_t HELPER(vfp_get_fpscr)(CPUState *env)
     return fpscr;
 }
 
-uint32_t vfp_get_fpscr(CPUState *env)
+uint32_t vfp_get_fpscr(CPUARMState *env)
 {
     return HELPER(vfp_get_fpscr)(env);
 }
@@ -2711,7 +2711,7 @@ static inline int vfp_exceptbits_to_host(int target_bits)
     return host_bits;
 }
 
-void HELPER(vfp_set_fpscr)(CPUState *env, uint32_t val)
+void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
 {
     int i;
     uint32_t changed;
@@ -2752,7 +2752,7 @@ void HELPER(vfp_set_fpscr)(CPUState *env, uint32_t val)
     set_float_exception_flags(0, &env->vfp.standard_fp_status);
 }
 
-void vfp_set_fpscr(CPUState *env, uint32_t val)
+void vfp_set_fpscr(CPUARMState *env, uint32_t val)
 {
     HELPER(vfp_set_fpscr)(env, val);
 }
@@ -2796,19 +2796,19 @@ float64 VFP_HELPER(abs, d)(float64 a)
     return float64_abs(a);
 }
 
-float32 VFP_HELPER(sqrt, s)(float32 a, CPUState *env)
+float32 VFP_HELPER(sqrt, s)(float32 a, CPUARMState *env)
 {
     return float32_sqrt(a, &env->vfp.fp_status);
 }
 
-float64 VFP_HELPER(sqrt, d)(float64 a, CPUState *env)
+float64 VFP_HELPER(sqrt, d)(float64 a, CPUARMState *env)
 {
     return float64_sqrt(a, &env->vfp.fp_status);
 }
 
 /* XXX: check quiet/signaling case */
 #define DO_VFP_cmp(p, type) \
-void VFP_HELPER(cmp, p)(type a, type b, CPUState *env)  \
+void VFP_HELPER(cmp, p)(type a, type b, CPUARMState *env)  \
 { \
     uint32_t flags; \
     switch(type ## _compare_quiet(a, b, &env->vfp.fp_status)) { \
@@ -2820,7 +2820,7 @@ void VFP_HELPER(cmp, p)(type a, type b, CPUState *env)  \
     env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28) \
         | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
 } \
-void VFP_HELPER(cmpe, p)(type a, type b, CPUState *env) \
+void VFP_HELPER(cmpe, p)(type a, type b, CPUARMState *env) \
 { \
     uint32_t flags; \
     switch(type ## _compare(a, b, &env->vfp.fp_status)) { \
@@ -2871,7 +2871,7 @@ FLOAT_CONVS(ui, d, 64, u)
 #undef FLOAT_CONVS
 
 /* floating point conversion */
-float64 VFP_HELPER(fcvtd, s)(float32 x, CPUState *env)
+float64 VFP_HELPER(fcvtd, s)(float32 x, CPUARMState *env)
 {
     float64 r = float32_to_float64(x, &env->vfp.fp_status);
     /* ARM requires that S<->D conversion of any kind of NaN generates
@@ -2880,7 +2880,7 @@ float64 VFP_HELPER(fcvtd, s)(float32 x, CPUState *env)
     return float64_maybe_silence_nan(r);
 }
 
-float32 VFP_HELPER(fcvts, d)(float64 x, CPUState *env)
+float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
 {
     float32 r =  float64_to_float32(x, &env->vfp.fp_status);
     /* ARM requires that S<->D conversion of any kind of NaN generates
@@ -2923,7 +2923,7 @@ VFP_CONV_FIX(ul, s, 32, uint32, u)
 #undef VFP_CONV_FIX
 
 /* Half precision conversions.  */
-static float32 do_fcvt_f16_to_f32(uint32_t a, CPUState *env, float_status *s)
+static float32 do_fcvt_f16_to_f32(uint32_t a, CPUARMState *env, float_status *s)
 {
     int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
     float32 r = float16_to_float32(make_float16(a), ieee, s);
@@ -2933,7 +2933,7 @@ static float32 do_fcvt_f16_to_f32(uint32_t a, CPUState *env, float_status *s)
     return r;
 }
 
-static uint32_t do_fcvt_f32_to_f16(float32 a, CPUState *env, float_status *s)
+static uint32_t do_fcvt_f32_to_f16(float32 a, CPUARMState *env, float_status *s)
 {
     int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
     float16 r = float32_to_float16(a, ieee, s);
@@ -2943,22 +2943,22 @@ static uint32_t do_fcvt_f32_to_f16(float32 a, CPUState *env, float_status *s)
     return float16_val(r);
 }
 
-float32 HELPER(neon_fcvt_f16_to_f32)(uint32_t a, CPUState *env)
+float32 HELPER(neon_fcvt_f16_to_f32)(uint32_t a, CPUARMState *env)
 {
     return do_fcvt_f16_to_f32(a, env, &env->vfp.standard_fp_status);
 }
 
-uint32_t HELPER(neon_fcvt_f32_to_f16)(float32 a, CPUState *env)
+uint32_t HELPER(neon_fcvt_f32_to_f16)(float32 a, CPUARMState *env)
 {
     return do_fcvt_f32_to_f16(a, env, &env->vfp.standard_fp_status);
 }
 
-float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, CPUState *env)
+float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, CPUARMState *env)
 {
     return do_fcvt_f16_to_f32(a, env, &env->vfp.fp_status);
 }
 
-uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, CPUState *env)
+uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, CPUARMState *env)
 {
     return do_fcvt_f32_to_f16(a, env, &env->vfp.fp_status);
 }
@@ -2967,7 +2967,7 @@ uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, CPUState *env)
 #define float32_three make_float32(0x40400000)
 #define float32_one_point_five make_float32(0x3fc00000)
 
-float32 HELPER(recps_f32)(float32 a, float32 b, CPUState *env)
+float32 HELPER(recps_f32)(float32 a, float32 b, CPUARMState *env)
 {
     float_status *s = &env->vfp.standard_fp_status;
     if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
@@ -2980,7 +2980,7 @@ float32 HELPER(recps_f32)(float32 a, float32 b, CPUState *env)
     return float32_sub(float32_two, float32_mul(a, b, s), s);
 }
 
-float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUState *env)
+float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUARMState *env)
 {
     float_status *s = &env->vfp.standard_fp_status;
     float32 product;
@@ -3005,7 +3005,7 @@ float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUState *env)
 /* The algorithm that must be used to calculate the estimate
  * is specified by the ARM ARM.
  */
-static float64 recip_estimate(float64 a, CPUState *env)
+static float64 recip_estimate(float64 a, CPUARMState *env)
 {
     /* These calculations mustn't set any fp exception flags,
      * so we use a local copy of the fp_status.
@@ -3031,7 +3031,7 @@ static float64 recip_estimate(float64 a, CPUState *env)
     return float64_div(int64_to_float64(q_int, s), float64_256, s);
 }
 
-float32 HELPER(recpe_f32)(float32 a, CPUState *env)
+float32 HELPER(recpe_f32)(float32 a, CPUARMState *env)
 {
     float_status *s = &env->vfp.standard_fp_status;
     float64 f64;
@@ -3075,7 +3075,7 @@ float32 HELPER(recpe_f32)(float32 a, CPUState *env)
 /* The algorithm that must be used to calculate the estimate
  * is specified by the ARM ARM.
  */
-static float64 recip_sqrt_estimate(float64 a, CPUState *env)
+static float64 recip_sqrt_estimate(float64 a, CPUARMState *env)
 {
     /* These calculations mustn't set any fp exception flags,
      * so we use a local copy of the fp_status.
@@ -3127,7 +3127,7 @@ static float64 recip_sqrt_estimate(float64 a, CPUState *env)
     return float64_div(int64_to_float64(q_int, s), float64_256, s);
 }
 
-float32 HELPER(rsqrte_f32)(float32 a, CPUState *env)
+float32 HELPER(rsqrte_f32)(float32 a, CPUARMState *env)
 {
     float_status *s = &env->vfp.standard_fp_status;
     int result_exp;
@@ -3178,7 +3178,7 @@ float32 HELPER(rsqrte_f32)(float32 a, CPUState *env)
     return make_float32(val);
 }
 
-uint32_t HELPER(recpe_u32)(uint32_t a, CPUState *env)
+uint32_t HELPER(recpe_u32)(uint32_t a, CPUARMState *env)
 {
     float64 f64;
 
@@ -3194,7 +3194,7 @@ uint32_t HELPER(recpe_u32)(uint32_t a, CPUState *env)
     return 0x80000000 | ((float64_val(f64) >> 21) & 0x7fffffff);
 }
 
-uint32_t HELPER(rsqrte_u32)(uint32_t a, CPUState *env)
+uint32_t HELPER(rsqrte_u32)(uint32_t a, CPUARMState *env)
 {
     float64 f64;
 
@@ -3228,7 +3228,7 @@ float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c, void *fpstp)
     return float64_muladd(a, b, c, 0, fpst);
 }
 
-void HELPER(set_teecr)(CPUState *env, uint32_t val)
+void HELPER(set_teecr)(CPUARMState *env, uint32_t val)
 {
     val &= 1;
     if (env->teecr != val) {
diff --git a/target-arm/iwmmxt_helper.c b/target-arm/iwmmxt_helper.c
index 843994d..1dd8d1a 100644
--- a/target-arm/iwmmxt_helper.c
+++ b/target-arm/iwmmxt_helper.c
@@ -162,7 +162,7 @@ uint64_t HELPER(iwmmxt_macuw)(uint64_t a, uint64_t b)
     SIMD64_SET(NBIT64(x), SIMD_NBIT) | \
     SIMD64_SET(ZBIT64(x), SIMD_ZBIT)
 #define IWMMXT_OP_UNPACK(S, SH0, SH1, SH2, SH3)			\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, b)))(CPUState *env, \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, b)))(CPUARMState *env, \
                                                  uint64_t a, uint64_t b) \
 {								\
     a =							        \
@@ -177,7 +177,7 @@ uint64_t HELPER(glue(iwmmxt_unpack, glue(S, b)))(CPUState *env, \
         NZBIT8(a >> 48, 6) | NZBIT8(a >> 56, 7);		\
     return a;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, w)))(CPUState *env, \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, w)))(CPUARMState *env, \
                                         uint64_t a, uint64_t b) \
 {								\
     a =							        \
@@ -190,7 +190,7 @@ uint64_t HELPER(glue(iwmmxt_unpack, glue(S, w)))(CPUState *env, \
         NZBIT8(a >> 32, 2) | NZBIT8(a >> 48, 3);		\
     return a;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, l)))(CPUState *env, \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, l)))(CPUARMState *env, \
                                         uint64_t a, uint64_t b) \
 {								\
     a =							        \
@@ -200,7 +200,7 @@ uint64_t HELPER(glue(iwmmxt_unpack, glue(S, l)))(CPUState *env, \
         NZBIT32(a >> 0, 0) | NZBIT32(a >> 32, 1);		\
     return a;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, ub)))(CPUState *env, \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, ub)))(CPUARMState *env, \
                                                   uint64_t x)   \
 {								\
     x =							        \
@@ -213,7 +213,7 @@ uint64_t HELPER(glue(iwmmxt_unpack, glue(S, ub)))(CPUState *env, \
         NZBIT16(x >> 32, 2) | NZBIT16(x >> 48, 3);		\
     return x;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, uw)))(CPUState *env, \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, uw)))(CPUARMState *env, \
                                                   uint64_t x)   \
 {								\
     x =							        \
@@ -223,14 +223,14 @@ uint64_t HELPER(glue(iwmmxt_unpack, glue(S, uw)))(CPUState *env, \
         NZBIT32(x >> 0, 0) | NZBIT32(x >> 32, 1);		\
     return x;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, ul)))(CPUState *env, \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, ul)))(CPUARMState *env, \
                                                   uint64_t x)   \
 {								\
     x = (((x >> SH0) & 0xffffffff) << 0);			\
     env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x >> 0);	\
     return x;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sb)))(CPUState *env, \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sb)))(CPUARMState *env, \
                                                   uint64_t x)   \
 {								\
     x =							        \
@@ -243,7 +243,7 @@ uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sb)))(CPUState *env, \
         NZBIT16(x >> 32, 2) | NZBIT16(x >> 48, 3);		\
     return x;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sw)))(CPUState *env, \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sw)))(CPUARMState *env, \
                                                   uint64_t x)   \
 {								\
     x =							        \
@@ -253,7 +253,7 @@ uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sw)))(CPUState *env, \
         NZBIT32(x >> 0, 0) | NZBIT32(x >> 32, 1);		\
     return x;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sl)))(CPUState *env, \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sl)))(CPUARMState *env, \
                                                   uint64_t x)   \
 {								\
     x = EXTEND32((x >> SH0) & 0xffffffff);			\
@@ -264,7 +264,7 @@ IWMMXT_OP_UNPACK(l, 0, 8, 16, 24)
 IWMMXT_OP_UNPACK(h, 32, 40, 48, 56)
 
 #define IWMMXT_OP_CMP(SUFF, Tb, Tw, Tl, O)			\
-uint64_t HELPER(glue(iwmmxt_, glue(SUFF, b)))(CPUState *env,    \
+uint64_t HELPER(glue(iwmmxt_, glue(SUFF, b)))(CPUARMState *env,    \
                                         uint64_t a, uint64_t b) \
 {								\
     a =							        \
@@ -279,7 +279,7 @@ uint64_t HELPER(glue(iwmmxt_, glue(SUFF, b)))(CPUState *env,    \
         NZBIT8(a >> 48, 6) | NZBIT8(a >> 56, 7);		\
     return a;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_, glue(SUFF, w)))(CPUState *env,    \
+uint64_t HELPER(glue(iwmmxt_, glue(SUFF, w)))(CPUARMState *env,    \
                                         uint64_t a, uint64_t b) \
 {								\
     a = CMP(0, Tw, O, 0xffff) | CMP(16, Tw, O, 0xffff) |	\
@@ -289,7 +289,7 @@ uint64_t HELPER(glue(iwmmxt_, glue(SUFF, w)))(CPUState *env,    \
         NZBIT16(a >> 32, 2) | NZBIT16(a >> 48, 3);		\
     return a;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_, glue(SUFF, l)))(CPUState *env,    \
+uint64_t HELPER(glue(iwmmxt_, glue(SUFF, l)))(CPUARMState *env,    \
                                         uint64_t a, uint64_t b) \
 {								\
     a = CMP(0, Tl, O, 0xffffffff) |				\
@@ -329,7 +329,7 @@ IWMMXT_OP_CMP(adds, int8_t, int16_t, int32_t, +)
 #define AVGB(SHR) ((( \
         ((a >> SHR) & 0xff) + ((b >> SHR) & 0xff) + round) >> 1) << SHR)
 #define IWMMXT_OP_AVGB(r)                                                 \
-uint64_t HELPER(iwmmxt_avgb##r)(CPUState *env, uint64_t a, uint64_t b)    \
+uint64_t HELPER(iwmmxt_avgb##r)(CPUARMState *env, uint64_t a, uint64_t b)    \
 {                                                                         \
     const int round = r;                                                  \
     a = AVGB(0) | AVGB(8) | AVGB(16) | AVGB(24) |                         \
@@ -353,7 +353,7 @@ IWMMXT_OP_AVGB(1)
 #define AVGW(SHR) ((( \
         ((a >> SHR) & 0xffff) + ((b >> SHR) & 0xffff) + round) >> 1) << SHR)
 #define IWMMXT_OP_AVGW(r)                                               \
-uint64_t HELPER(iwmmxt_avgw##r)(CPUState *env, uint64_t a, uint64_t b)  \
+uint64_t HELPER(iwmmxt_avgw##r)(CPUARMState *env, uint64_t a, uint64_t b)  \
 {                                                                       \
     const int round = r;                                                \
     a = AVGW(0) | AVGW(16) | AVGW(32) | AVGW(48);                       \
@@ -464,7 +464,7 @@ uint32_t HELPER(iwmmxt_msbl)(uint64_t x)
 }
 
 /* FIXME: Split wCASF setting into a separate op to avoid env use.  */
-uint64_t HELPER(iwmmxt_srlw)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_srlw)(CPUARMState *env, uint64_t x, uint32_t n)
 {
     x = (((x & (0xffffll << 0)) >> n) & (0xffffll << 0)) |
         (((x & (0xffffll << 16)) >> n) & (0xffffll << 16)) |
@@ -476,7 +476,7 @@ uint64_t HELPER(iwmmxt_srlw)(CPUState *env, uint64_t x, uint32_t n)
     return x;
 }
 
-uint64_t HELPER(iwmmxt_srll)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_srll)(CPUARMState *env, uint64_t x, uint32_t n)
 {
     x = ((x & (0xffffffffll << 0)) >> n) |
         ((x >> n) & (0xffffffffll << 32));
@@ -485,14 +485,14 @@ uint64_t HELPER(iwmmxt_srll)(CPUState *env, uint64_t x, uint32_t n)
     return x;
 }
 
-uint64_t HELPER(iwmmxt_srlq)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_srlq)(CPUARMState *env, uint64_t x, uint32_t n)
 {
     x >>= n;
     env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x);
     return x;
 }
 
-uint64_t HELPER(iwmmxt_sllw)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_sllw)(CPUARMState *env, uint64_t x, uint32_t n)
 {
     x = (((x & (0xffffll << 0)) << n) & (0xffffll << 0)) |
         (((x & (0xffffll << 16)) << n) & (0xffffll << 16)) |
@@ -504,7 +504,7 @@ uint64_t HELPER(iwmmxt_sllw)(CPUState *env, uint64_t x, uint32_t n)
     return x;
 }
 
-uint64_t HELPER(iwmmxt_slll)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_slll)(CPUARMState *env, uint64_t x, uint32_t n)
 {
     x = ((x << n) & (0xffffffffll << 0)) |
         ((x & (0xffffffffll << 32)) << n);
@@ -513,14 +513,14 @@ uint64_t HELPER(iwmmxt_slll)(CPUState *env, uint64_t x, uint32_t n)
     return x;
 }
 
-uint64_t HELPER(iwmmxt_sllq)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_sllq)(CPUARMState *env, uint64_t x, uint32_t n)
 {
     x <<= n;
     env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x);
     return x;
 }
 
-uint64_t HELPER(iwmmxt_sraw)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_sraw)(CPUARMState *env, uint64_t x, uint32_t n)
 {
     x = ((uint64_t) ((EXTEND16(x >> 0) >> n) & 0xffff) << 0) |
         ((uint64_t) ((EXTEND16(x >> 16) >> n) & 0xffff) << 16) |
@@ -532,7 +532,7 @@ uint64_t HELPER(iwmmxt_sraw)(CPUState *env, uint64_t x, uint32_t n)
     return x;
 }
 
-uint64_t HELPER(iwmmxt_sral)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_sral)(CPUARMState *env, uint64_t x, uint32_t n)
 {
     x = (((EXTEND32(x >> 0) >> n) & 0xffffffff) << 0) |
         (((EXTEND32(x >> 32) >> n) & 0xffffffff) << 32);
@@ -541,14 +541,14 @@ uint64_t HELPER(iwmmxt_sral)(CPUState *env, uint64_t x, uint32_t n)
     return x;
 }
 
-uint64_t HELPER(iwmmxt_sraq)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_sraq)(CPUARMState *env, uint64_t x, uint32_t n)
 {
     x = (int64_t) x >> n;
     env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x);
     return x;
 }
 
-uint64_t HELPER(iwmmxt_rorw)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_rorw)(CPUARMState *env, uint64_t x, uint32_t n)
 {
     x = ((((x & (0xffffll << 0)) >> n) |
           ((x & (0xffffll << 0)) << (16 - n))) & (0xffffll << 0)) |
@@ -564,7 +564,7 @@ uint64_t HELPER(iwmmxt_rorw)(CPUState *env, uint64_t x, uint32_t n)
     return x;
 }
 
-uint64_t HELPER(iwmmxt_rorl)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_rorl)(CPUARMState *env, uint64_t x, uint32_t n)
 {
     x = ((x & (0xffffffffll << 0)) >> n) |
         ((x >> n) & (0xffffffffll << 32)) |
@@ -575,14 +575,14 @@ uint64_t HELPER(iwmmxt_rorl)(CPUState *env, uint64_t x, uint32_t n)
     return x;
 }
 
-uint64_t HELPER(iwmmxt_rorq)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_rorq)(CPUARMState *env, uint64_t x, uint32_t n)
 {
     x = (x >> n) | (x << (64 - n));
     env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x);
     return x;
 }
 
-uint64_t HELPER(iwmmxt_shufh)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_shufh)(CPUARMState *env, uint64_t x, uint32_t n)
 {
     x = (((x >> ((n << 4) & 0x30)) & 0xffff) << 0) |
         (((x >> ((n << 2) & 0x30)) & 0xffff) << 16) |
@@ -595,7 +595,7 @@ uint64_t HELPER(iwmmxt_shufh)(CPUState *env, uint64_t x, uint32_t n)
 }
 
 /* TODO: Unsigned-Saturation */
-uint64_t HELPER(iwmmxt_packuw)(CPUState *env, uint64_t a, uint64_t b)
+uint64_t HELPER(iwmmxt_packuw)(CPUARMState *env, uint64_t a, uint64_t b)
 {
     a = (((a >> 0) & 0xff) << 0) | (((a >> 16) & 0xff) << 8) |
         (((a >> 32) & 0xff) << 16) | (((a >> 48) & 0xff) << 24) |
@@ -609,7 +609,7 @@ uint64_t HELPER(iwmmxt_packuw)(CPUState *env, uint64_t a, uint64_t b)
     return a;
 }
 
-uint64_t HELPER(iwmmxt_packul)(CPUState *env, uint64_t a, uint64_t b)
+uint64_t HELPER(iwmmxt_packul)(CPUARMState *env, uint64_t a, uint64_t b)
 {
     a = (((a >> 0) & 0xffff) << 0) | (((a >> 32) & 0xffff) << 16) |
         (((b >> 0) & 0xffff) << 32) | (((b >> 32) & 0xffff) << 48);
@@ -619,7 +619,7 @@ uint64_t HELPER(iwmmxt_packul)(CPUState *env, uint64_t a, uint64_t b)
     return a;
 }
 
-uint64_t HELPER(iwmmxt_packuq)(CPUState *env, uint64_t a, uint64_t b)
+uint64_t HELPER(iwmmxt_packuq)(CPUARMState *env, uint64_t a, uint64_t b)
 {
     a = (a & 0xffffffff) | ((b & 0xffffffff) << 32);
     env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
@@ -628,7 +628,7 @@ uint64_t HELPER(iwmmxt_packuq)(CPUState *env, uint64_t a, uint64_t b)
 }
 
 /* TODO: Signed-Saturation */
-uint64_t HELPER(iwmmxt_packsw)(CPUState *env, uint64_t a, uint64_t b)
+uint64_t HELPER(iwmmxt_packsw)(CPUARMState *env, uint64_t a, uint64_t b)
 {
     a = (((a >> 0) & 0xff) << 0) | (((a >> 16) & 0xff) << 8) |
         (((a >> 32) & 0xff) << 16) | (((a >> 48) & 0xff) << 24) |
@@ -642,7 +642,7 @@ uint64_t HELPER(iwmmxt_packsw)(CPUState *env, uint64_t a, uint64_t b)
     return a;
 }
 
-uint64_t HELPER(iwmmxt_packsl)(CPUState *env, uint64_t a, uint64_t b)
+uint64_t HELPER(iwmmxt_packsl)(CPUARMState *env, uint64_t a, uint64_t b)
 {
     a = (((a >> 0) & 0xffff) << 0) | (((a >> 32) & 0xffff) << 16) |
         (((b >> 0) & 0xffff) << 32) | (((b >> 32) & 0xffff) << 48);
@@ -652,7 +652,7 @@ uint64_t HELPER(iwmmxt_packsl)(CPUState *env, uint64_t a, uint64_t b)
     return a;
 }
 
-uint64_t HELPER(iwmmxt_packsq)(CPUState *env, uint64_t a, uint64_t b)
+uint64_t HELPER(iwmmxt_packsq)(CPUARMState *env, uint64_t a, uint64_t b)
 {
     a = (a & 0xffffffff) | ((b & 0xffffffff) << 32);
     env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index b51e35a..1e02d61 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -114,7 +114,7 @@ uint32_t HELPER(glue(neon_,name))(uint32_t arg1, uint32_t arg2) \
 NEON_VOP_BODY(vtype, n)
 
 #define NEON_VOP_ENV(name, vtype, n) \
-uint32_t HELPER(glue(neon_,name))(CPUState *env, uint32_t arg1, uint32_t arg2) \
+uint32_t HELPER(glue(neon_,name))(CPUARMState *env, uint32_t arg1, uint32_t arg2) \
 NEON_VOP_BODY(vtype, n)
 
 /* Pairwise operations.  */
@@ -172,7 +172,7 @@ NEON_VOP_ENV(qadd_u16, neon_u16, 2)
 #undef NEON_FN
 #undef NEON_USAT
 
-uint32_t HELPER(neon_qadd_u32)(CPUState *env, uint32_t a, uint32_t b)
+uint32_t HELPER(neon_qadd_u32)(CPUARMState *env, uint32_t a, uint32_t b)
 {
     uint32_t res = a + b;
     if (res < a) {
@@ -182,7 +182,7 @@ uint32_t HELPER(neon_qadd_u32)(CPUState *env, uint32_t a, uint32_t b)
     return res;
 }
 
-uint64_t HELPER(neon_qadd_u64)(CPUState *env, uint64_t src1, uint64_t src2)
+uint64_t HELPER(neon_qadd_u64)(CPUARMState *env, uint64_t src1, uint64_t src2)
 {
     uint64_t res;
 
@@ -214,7 +214,7 @@ NEON_VOP_ENV(qadd_s16, neon_s16, 2)
 #undef NEON_FN
 #undef NEON_SSAT
 
-uint32_t HELPER(neon_qadd_s32)(CPUState *env, uint32_t a, uint32_t b)
+uint32_t HELPER(neon_qadd_s32)(CPUARMState *env, uint32_t a, uint32_t b)
 {
     uint32_t res = a + b;
     if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT)) {
@@ -224,7 +224,7 @@ uint32_t HELPER(neon_qadd_s32)(CPUState *env, uint32_t a, uint32_t b)
     return res;
 }
 
-uint64_t HELPER(neon_qadd_s64)(CPUState *env, uint64_t src1, uint64_t src2)
+uint64_t HELPER(neon_qadd_s64)(CPUARMState *env, uint64_t src1, uint64_t src2)
 {
     uint64_t res;
 
@@ -252,7 +252,7 @@ NEON_VOP_ENV(qsub_u16, neon_u16, 2)
 #undef NEON_FN
 #undef NEON_USAT
 
-uint32_t HELPER(neon_qsub_u32)(CPUState *env, uint32_t a, uint32_t b)
+uint32_t HELPER(neon_qsub_u32)(CPUARMState *env, uint32_t a, uint32_t b)
 {
     uint32_t res = a - b;
     if (res > a) {
@@ -262,7 +262,7 @@ uint32_t HELPER(neon_qsub_u32)(CPUState *env, uint32_t a, uint32_t b)
     return res;
 }
 
-uint64_t HELPER(neon_qsub_u64)(CPUState *env, uint64_t src1, uint64_t src2)
+uint64_t HELPER(neon_qsub_u64)(CPUARMState *env, uint64_t src1, uint64_t src2)
 {
     uint64_t res;
 
@@ -295,7 +295,7 @@ NEON_VOP_ENV(qsub_s16, neon_s16, 2)
 #undef NEON_FN
 #undef NEON_SSAT
 
-uint32_t HELPER(neon_qsub_s32)(CPUState *env, uint32_t a, uint32_t b)
+uint32_t HELPER(neon_qsub_s32)(CPUARMState *env, uint32_t a, uint32_t b)
 {
     uint32_t res = a - b;
     if (((res ^ a) & SIGNBIT) && ((a ^ b) & SIGNBIT)) {
@@ -305,7 +305,7 @@ uint32_t HELPER(neon_qsub_s32)(CPUState *env, uint32_t a, uint32_t b)
     return res;
 }
 
-uint64_t HELPER(neon_qsub_s64)(CPUState *env, uint64_t src1, uint64_t src2)
+uint64_t HELPER(neon_qsub_s64)(CPUARMState *env, uint64_t src1, uint64_t src2)
 {
     uint64_t res;
 
@@ -661,7 +661,7 @@ NEON_VOP_ENV(qshl_u16, neon_u16, 2)
 NEON_VOP_ENV(qshl_u32, neon_u32, 1)
 #undef NEON_FN
 
-uint64_t HELPER(neon_qshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop)
+uint64_t HELPER(neon_qshl_u64)(CPUARMState *env, uint64_t val, uint64_t shiftop)
 {
     int8_t shift = (int8_t)shiftop;
     if (shift >= 64) {
@@ -716,7 +716,7 @@ NEON_VOP_ENV(qshl_s16, neon_s16, 2)
 NEON_VOP_ENV(qshl_s32, neon_s32, 1)
 #undef NEON_FN
 
-uint64_t HELPER(neon_qshl_s64)(CPUState *env, uint64_t valop, uint64_t shiftop)
+uint64_t HELPER(neon_qshl_s64)(CPUARMState *env, uint64_t valop, uint64_t shiftop)
 {
     int8_t shift = (uint8_t)shiftop;
     int64_t val = valop;
@@ -770,7 +770,7 @@ NEON_VOP_ENV(qshlu_s8, neon_u8, 4)
 NEON_VOP_ENV(qshlu_s16, neon_u16, 2)
 #undef NEON_FN
 
-uint32_t HELPER(neon_qshlu_s32)(CPUState *env, uint32_t valop, uint32_t shiftop)
+uint32_t HELPER(neon_qshlu_s32)(CPUARMState *env, uint32_t valop, uint32_t shiftop)
 {
     if ((int32_t)valop < 0) {
         SET_QC();
@@ -779,7 +779,7 @@ uint32_t HELPER(neon_qshlu_s32)(CPUState *env, uint32_t valop, uint32_t shiftop)
     return helper_neon_qshl_u32(env, valop, shiftop);
 }
 
-uint64_t HELPER(neon_qshlu_s64)(CPUState *env, uint64_t valop, uint64_t shiftop)
+uint64_t HELPER(neon_qshlu_s64)(CPUARMState *env, uint64_t valop, uint64_t shiftop)
 {
     if ((int64_t)valop < 0) {
         SET_QC();
@@ -818,7 +818,7 @@ NEON_VOP_ENV(qrshl_u16, neon_u16, 2)
 
 /* The addition of the rounding constant may overflow, so we use an
  * intermediate 64 bits accumulator.  */
-uint32_t HELPER(neon_qrshl_u32)(CPUState *env, uint32_t val, uint32_t shiftop)
+uint32_t HELPER(neon_qrshl_u32)(CPUARMState *env, uint32_t val, uint32_t shiftop)
 {
     uint32_t dest;
     int8_t shift = (int8_t)shiftop;
@@ -848,7 +848,7 @@ uint32_t HELPER(neon_qrshl_u32)(CPUState *env, uint32_t val, uint32_t shiftop)
 
 /* Handling addition overflow with 64 bits inputs values is more
  * tricky than with 32 bits values.  */
-uint64_t HELPER(neon_qrshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop)
+uint64_t HELPER(neon_qrshl_u64)(CPUARMState *env, uint64_t val, uint64_t shiftop)
 {
     int8_t shift = (int8_t)shiftop;
     if (shift >= 64) {
@@ -915,7 +915,7 @@ NEON_VOP_ENV(qrshl_s16, neon_s16, 2)
 
 /* The addition of the rounding constant may overflow, so we use an
  * intermediate 64 bits accumulator.  */
-uint32_t HELPER(neon_qrshl_s32)(CPUState *env, uint32_t valop, uint32_t shiftop)
+uint32_t HELPER(neon_qrshl_s32)(CPUARMState *env, uint32_t valop, uint32_t shiftop)
 {
     int32_t dest;
     int32_t val = (int32_t)valop;
@@ -944,7 +944,7 @@ uint32_t HELPER(neon_qrshl_s32)(CPUState *env, uint32_t valop, uint32_t shiftop)
 
 /* Handling addition overflow with 64 bits inputs values is more
  * tricky than with 32 bits values.  */
-uint64_t HELPER(neon_qrshl_s64)(CPUState *env, uint64_t valop, uint64_t shiftop)
+uint64_t HELPER(neon_qrshl_s64)(CPUARMState *env, uint64_t valop, uint64_t shiftop)
 {
     int8_t shift = (uint8_t)shiftop;
     int64_t val = valop;
@@ -1223,7 +1223,7 @@ uint32_t HELPER(neon_narrow_round_high_u16)(uint64_t x)
     return ((x >> 16) & 0xffff) | ((x >> 32) & 0xffff0000);
 }
 
-uint32_t HELPER(neon_unarrow_sat8)(CPUState *env, uint64_t x)
+uint32_t HELPER(neon_unarrow_sat8)(CPUARMState *env, uint64_t x)
 {
     uint16_t s;
     uint8_t d;
@@ -1250,7 +1250,7 @@ uint32_t HELPER(neon_unarrow_sat8)(CPUState *env, uint64_t x)
     return res;
 }
 
-uint32_t HELPER(neon_narrow_sat_u8)(CPUState *env, uint64_t x)
+uint32_t HELPER(neon_narrow_sat_u8)(CPUARMState *env, uint64_t x)
 {
     uint16_t s;
     uint8_t d;
@@ -1273,7 +1273,7 @@ uint32_t HELPER(neon_narrow_sat_u8)(CPUState *env, uint64_t x)
     return res;
 }
 
-uint32_t HELPER(neon_narrow_sat_s8)(CPUState *env, uint64_t x)
+uint32_t HELPER(neon_narrow_sat_s8)(CPUARMState *env, uint64_t x)
 {
     int16_t s;
     uint8_t d;
@@ -1296,7 +1296,7 @@ uint32_t HELPER(neon_narrow_sat_s8)(CPUState *env, uint64_t x)
     return res;
 }
 
-uint32_t HELPER(neon_unarrow_sat16)(CPUState *env, uint64_t x)
+uint32_t HELPER(neon_unarrow_sat16)(CPUARMState *env, uint64_t x)
 {
     uint32_t high;
     uint32_t low;
@@ -1319,7 +1319,7 @@ uint32_t HELPER(neon_unarrow_sat16)(CPUState *env, uint64_t x)
     return low | (high << 16);
 }
 
-uint32_t HELPER(neon_narrow_sat_u16)(CPUState *env, uint64_t x)
+uint32_t HELPER(neon_narrow_sat_u16)(CPUARMState *env, uint64_t x)
 {
     uint32_t high;
     uint32_t low;
@@ -1336,7 +1336,7 @@ uint32_t HELPER(neon_narrow_sat_u16)(CPUState *env, uint64_t x)
     return low | (high << 16);
 }
 
-uint32_t HELPER(neon_narrow_sat_s16)(CPUState *env, uint64_t x)
+uint32_t HELPER(neon_narrow_sat_s16)(CPUARMState *env, uint64_t x)
 {
     int32_t low;
     int32_t high;
@@ -1353,7 +1353,7 @@ uint32_t HELPER(neon_narrow_sat_s16)(CPUState *env, uint64_t x)
     return (uint16_t)low | (high << 16);
 }
 
-uint32_t HELPER(neon_unarrow_sat32)(CPUState *env, uint64_t x)
+uint32_t HELPER(neon_unarrow_sat32)(CPUARMState *env, uint64_t x)
 {
     if (x & 0x8000000000000000ull) {
         SET_QC();
@@ -1366,7 +1366,7 @@ uint32_t HELPER(neon_unarrow_sat32)(CPUState *env, uint64_t x)
     return x;
 }
 
-uint32_t HELPER(neon_narrow_sat_u32)(CPUState *env, uint64_t x)
+uint32_t HELPER(neon_narrow_sat_u32)(CPUARMState *env, uint64_t x)
 {
     if (x > 0xffffffffu) {
         SET_QC();
@@ -1375,7 +1375,7 @@ uint32_t HELPER(neon_narrow_sat_u32)(CPUState *env, uint64_t x)
     return x;
 }
 
-uint32_t HELPER(neon_narrow_sat_s32)(CPUState *env, uint64_t x)
+uint32_t HELPER(neon_narrow_sat_s32)(CPUARMState *env, uint64_t x)
 {
     if ((int64_t)x != (int32_t)x) {
         SET_QC();
@@ -1482,7 +1482,7 @@ uint64_t HELPER(neon_subl_u32)(uint64_t a, uint64_t b)
     return (a - b) ^ mask;
 }
 
-uint64_t HELPER(neon_addl_saturate_s32)(CPUState *env, uint64_t a, uint64_t b)
+uint64_t HELPER(neon_addl_saturate_s32)(CPUARMState *env, uint64_t a, uint64_t b)
 {
     uint32_t x, y;
     uint32_t low, high;
@@ -1504,7 +1504,7 @@ uint64_t HELPER(neon_addl_saturate_s32)(CPUState *env, uint64_t a, uint64_t b)
     return low | ((uint64_t)high << 32);
 }
 
-uint64_t HELPER(neon_addl_saturate_s64)(CPUState *env, uint64_t a, uint64_t b)
+uint64_t HELPER(neon_addl_saturate_s64)(CPUARMState *env, uint64_t a, uint64_t b)
 {
     uint64_t result;
 
@@ -1680,7 +1680,7 @@ uint64_t HELPER(neon_negl_u64)(uint64_t x)
     } else if (x < 0) { \
         x = -x; \
     }} while (0)
-uint32_t HELPER(neon_qabs_s8)(CPUState *env, uint32_t x)
+uint32_t HELPER(neon_qabs_s8)(CPUARMState *env, uint32_t x)
 {
     neon_s8 vec;
     NEON_UNPACK(neon_s8, vec, x);
@@ -1700,7 +1700,7 @@ uint32_t HELPER(neon_qabs_s8)(CPUState *env, uint32_t x)
     } else { \
         x = -x; \
     }} while (0)
-uint32_t HELPER(neon_qneg_s8)(CPUState *env, uint32_t x)
+uint32_t HELPER(neon_qneg_s8)(CPUARMState *env, uint32_t x)
 {
     neon_s8 vec;
     NEON_UNPACK(neon_s8, vec, x);
@@ -1720,7 +1720,7 @@ uint32_t HELPER(neon_qneg_s8)(CPUState *env, uint32_t x)
     } else if (x < 0) { \
         x = -x; \
     }} while (0)
-uint32_t HELPER(neon_qabs_s16)(CPUState *env, uint32_t x)
+uint32_t HELPER(neon_qabs_s16)(CPUARMState *env, uint32_t x)
 {
     neon_s16 vec;
     NEON_UNPACK(neon_s16, vec, x);
@@ -1738,7 +1738,7 @@ uint32_t HELPER(neon_qabs_s16)(CPUState *env, uint32_t x)
     } else { \
         x = -x; \
     }} while (0)
-uint32_t HELPER(neon_qneg_s16)(CPUState *env, uint32_t x)
+uint32_t HELPER(neon_qneg_s16)(CPUARMState *env, uint32_t x)
 {
     neon_s16 vec;
     NEON_UNPACK(neon_s16, vec, x);
@@ -1749,7 +1749,7 @@ uint32_t HELPER(neon_qneg_s16)(CPUState *env, uint32_t x)
 }
 #undef DO_QNEG16
 
-uint32_t HELPER(neon_qabs_s32)(CPUState *env, uint32_t x)
+uint32_t HELPER(neon_qabs_s32)(CPUARMState *env, uint32_t x)
 {
     if (x == SIGNBIT) {
         SET_QC();
@@ -1760,7 +1760,7 @@ uint32_t HELPER(neon_qabs_s32)(CPUState *env, uint32_t x)
     return x;
 }
 
-uint32_t HELPER(neon_qneg_s32)(CPUState *env, uint32_t x)
+uint32_t HELPER(neon_qneg_s32)(CPUARMState *env, uint32_t x)
 {
     if (x == SIGNBIT) {
         SET_QC();
@@ -1832,7 +1832,7 @@ uint32_t HELPER(neon_acgt_f32)(uint32_t a, uint32_t b, void *fpstp)
 
 #define ELEM(V, N, SIZE) (((V) >> ((N) * (SIZE))) & ((1ull << (SIZE)) - 1))
 
-void HELPER(neon_qunzip8)(CPUState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_qunzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
 {
     uint64_t zm0 = float64_val(env->vfp.regs[rm]);
     uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
@@ -1860,7 +1860,7 @@ void HELPER(neon_qunzip8)(CPUState *env, uint32_t rd, uint32_t rm)
     env->vfp.regs[rd + 1] = make_float64(d1);
 }
 
-void HELPER(neon_qunzip16)(CPUState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_qunzip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
 {
     uint64_t zm0 = float64_val(env->vfp.regs[rm]);
     uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
@@ -1880,7 +1880,7 @@ void HELPER(neon_qunzip16)(CPUState *env, uint32_t rd, uint32_t rm)
     env->vfp.regs[rd + 1] = make_float64(d1);
 }
 
-void HELPER(neon_qunzip32)(CPUState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_qunzip32)(CPUARMState *env, uint32_t rd, uint32_t rm)
 {
     uint64_t zm0 = float64_val(env->vfp.regs[rm]);
     uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
@@ -1896,7 +1896,7 @@ void HELPER(neon_qunzip32)(CPUState *env, uint32_t rd, uint32_t rm)
     env->vfp.regs[rd + 1] = make_float64(d1);
 }
 
-void HELPER(neon_unzip8)(CPUState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_unzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
 {
     uint64_t zm = float64_val(env->vfp.regs[rm]);
     uint64_t zd = float64_val(env->vfp.regs[rd]);
@@ -1912,7 +1912,7 @@ void HELPER(neon_unzip8)(CPUState *env, uint32_t rd, uint32_t rm)
     env->vfp.regs[rd] = make_float64(d0);
 }
 
-void HELPER(neon_unzip16)(CPUState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_unzip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
 {
     uint64_t zm = float64_val(env->vfp.regs[rm]);
     uint64_t zd = float64_val(env->vfp.regs[rd]);
@@ -1924,7 +1924,7 @@ void HELPER(neon_unzip16)(CPUState *env, uint32_t rd, uint32_t rm)
     env->vfp.regs[rd] = make_float64(d0);
 }
 
-void HELPER(neon_qzip8)(CPUState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_qzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
 {
     uint64_t zm0 = float64_val(env->vfp.regs[rm]);
     uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
@@ -1952,7 +1952,7 @@ void HELPER(neon_qzip8)(CPUState *env, uint32_t rd, uint32_t rm)
     env->vfp.regs[rd + 1] = make_float64(d1);
 }
 
-void HELPER(neon_qzip16)(CPUState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_qzip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
 {
     uint64_t zm0 = float64_val(env->vfp.regs[rm]);
     uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
@@ -1972,7 +1972,7 @@ void HELPER(neon_qzip16)(CPUState *env, uint32_t rd, uint32_t rm)
     env->vfp.regs[rd + 1] = make_float64(d1);
 }
 
-void HELPER(neon_qzip32)(CPUState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_qzip32)(CPUARMState *env, uint32_t rd, uint32_t rm)
 {
     uint64_t zm0 = float64_val(env->vfp.regs[rm]);
     uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
@@ -1988,7 +1988,7 @@ void HELPER(neon_qzip32)(CPUState *env, uint32_t rd, uint32_t rm)
     env->vfp.regs[rd + 1] = make_float64(d1);
 }
 
-void HELPER(neon_zip8)(CPUState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_zip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
 {
     uint64_t zm = float64_val(env->vfp.regs[rm]);
     uint64_t zd = float64_val(env->vfp.regs[rd]);
@@ -2004,7 +2004,7 @@ void HELPER(neon_zip8)(CPUState *env, uint32_t rd, uint32_t rm)
     env->vfp.regs[rd] = make_float64(d0);
 }
 
-void HELPER(neon_zip16)(CPUState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_zip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
 {
     uint64_t zm = float64_val(env->vfp.regs[rm]);
     uint64_t zd = float64_val(env->vfp.regs[rd]);
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 1892b35..c728432 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -75,11 +75,11 @@ uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def,
    NULL, it means that the function was called in C code (i.e. not
    from generated code or from helper.c) */
 /* XXX: fix it to restore all registers */
-void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
+void tlb_fill(CPUARMState *env1, target_ulong addr, int is_write, int mmu_idx,
               void *retaddr)
 {
     TranslationBlock *tb;
-    CPUState *saved_env;
+    CPUARMState *saved_env;
     unsigned long pc;
     int ret;
 
@@ -103,7 +103,7 @@ void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
 }
 #endif
 
-/* FIXME: Pass an axplicit pointer to QF to CPUState, and move saturating
+/* FIXME: Pass an axplicit pointer to QF to CPUARMState, and move saturating
    instructions into helper.c  */
 uint32_t HELPER(add_setq)(uint32_t a, uint32_t b)
 {
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 280bfca..2709010 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -111,20 +111,20 @@ void arm_translate_init(void)
 
     for (i = 0; i < 16; i++) {
         cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
-                                          offsetof(CPUState, regs[i]),
+                                          offsetof(CPUARMState, regs[i]),
                                           regnames[i]);
     }
     cpu_exclusive_addr = tcg_global_mem_new_i32(TCG_AREG0,
-        offsetof(CPUState, exclusive_addr), "exclusive_addr");
+        offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
     cpu_exclusive_val = tcg_global_mem_new_i32(TCG_AREG0,
-        offsetof(CPUState, exclusive_val), "exclusive_val");
+        offsetof(CPUARMState, exclusive_val), "exclusive_val");
     cpu_exclusive_high = tcg_global_mem_new_i32(TCG_AREG0,
-        offsetof(CPUState, exclusive_high), "exclusive_high");
+        offsetof(CPUARMState, exclusive_high), "exclusive_high");
 #ifdef CONFIG_USER_ONLY
     cpu_exclusive_test = tcg_global_mem_new_i32(TCG_AREG0,
-        offsetof(CPUState, exclusive_test), "exclusive_test");
+        offsetof(CPUARMState, exclusive_test), "exclusive_test");
     cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
-        offsetof(CPUState, exclusive_info), "exclusive_info");
+        offsetof(CPUARMState, exclusive_info), "exclusive_info");
 #endif
 
 #define GEN_HELPER 2
@@ -138,7 +138,7 @@ static inline TCGv load_cpu_offset(int offset)
     return tmp;
 }
 
-#define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
+#define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
 
 static inline void store_cpu_offset(TCGv var, int offset)
 {
@@ -147,7 +147,7 @@ static inline void store_cpu_offset(TCGv var, int offset)
 }
 
 #define store_cpu_field(var, name) \
-    store_cpu_offset(var, offsetof(CPUState, name))
+    store_cpu_offset(var, offsetof(CPUARMState, name))
 
 /* Set a variable to the value of a CPU register.  */
 static void load_reg_var(DisasContext *s, TCGv var, int reg)
@@ -368,7 +368,7 @@ static void gen_add16(TCGv t0, TCGv t1)
     tcg_temp_free_i32(t1);
 }
 
-#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
+#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, CF))
 
 /* Set CF to the top bit of var.  */
 static void gen_set_CF_bit31(TCGv var)
@@ -382,8 +382,8 @@ static void gen_set_CF_bit31(TCGv var)
 /* Set N and Z flags from var.  */
 static inline void gen_logic_CC(TCGv var)
 {
-    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF));
-    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF));
+    tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, NF));
+    tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, ZF));
 }
 
 /* T0 += T1 + CF.  */
@@ -523,13 +523,13 @@ static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
     case 1:
         tmp = tcg_temp_new_ptr();
-        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
+        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
         PAS_OP(s)
         tcg_temp_free_ptr(tmp);
         break;
     case 5:
         tmp = tcg_temp_new_ptr();
-        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
+        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
         PAS_OP(u)
         tcg_temp_free_ptr(tmp);
         break;
@@ -570,13 +570,13 @@ static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
     case 0:
         tmp = tcg_temp_new_ptr();
-        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
+        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
         PAS_OP(s)
         tcg_temp_free_ptr(tmp);
         break;
     case 4:
         tmp = tcg_temp_new_ptr();
-        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
+        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
         PAS_OP(u)
         tcg_temp_free_ptr(tmp);
         break;
@@ -725,7 +725,7 @@ static inline void gen_bx_im(DisasContext *s, uint32_t addr)
     if (s->thumb != (addr & 1)) {
         tmp = tcg_temp_new_i32();
         tcg_gen_movi_i32(tmp, addr & 1);
-        tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
+        tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, thumb));
         tcg_temp_free_i32(tmp);
     }
     tcg_gen_movi_i32(cpu_R[15], addr & ~1);
@@ -743,7 +743,7 @@ static inline void gen_bx(DisasContext *s, TCGv var)
 /* Variant of store_reg which uses branch&exchange logic when storing
    to r15 in ARM architecture v7 and above. The source must be a temporary
    and will be marked as dead. */
-static inline void store_reg_bx(CPUState *env, DisasContext *s,
+static inline void store_reg_bx(CPUARMState *env, DisasContext *s,
                                 int reg, TCGv var)
 {
     if (reg == 15 && ENABLE_ARCH_7) {
@@ -757,7 +757,7 @@ static inline void store_reg_bx(CPUState *env, DisasContext *s,
  * to r15 in ARM architecture v5T and above. This is used for storing
  * the results of a LDR/LDM/POP into r15, and corresponds to the cases
  * in the ARM ARM which use the LoadWritePC() pseudocode function. */
-static inline void store_reg_from_load(CPUState *env, DisasContext *s,
+static inline void store_reg_from_load(CPUARMState *env, DisasContext *s,
                                 int reg, TCGv var)
 {
     if (reg == 15 && ENABLE_ARCH_5) {
@@ -897,9 +897,9 @@ static TCGv_ptr get_fpstatus_ptr(int neon)
     TCGv_ptr statusptr = tcg_temp_new_ptr();
     int offset;
     if (neon) {
-        offset = offsetof(CPUState, vfp.standard_fp_status);
+        offset = offsetof(CPUARMState, vfp.standard_fp_status);
     } else {
-        offset = offsetof(CPUState, vfp.fp_status);
+        offset = offsetof(CPUARMState, vfp.fp_status);
     }
     tcg_gen_addi_ptr(statusptr, cpu_env, offset);
     return statusptr;
@@ -1147,24 +1147,24 @@ static inline void gen_mov_vreg_F0(int dp, int reg)
 
 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
 {
-    tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
+    tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
 }
 
 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
 {
-    tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
+    tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
 }
 
 static inline TCGv iwmmxt_load_creg(int reg)
 {
     TCGv var = tcg_temp_new_i32();
-    tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
+    tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
     return var;
 }
 
 static inline void iwmmxt_store_creg(int reg, TCGv var)
 {
-    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
+    tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
     tcg_temp_free_i32(var);
 }
 
@@ -1366,7 +1366,7 @@ static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv dest)
 
 /* Disassemble an iwMMXt instruction.  Returns nonzero if an error occurred
    (ie. an undefined instruction).  */
-static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
+static int disas_iwmmxt_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
 {
     int rd, wrd;
     int rdhi, rdlo, rd0, rd1, i;
@@ -2370,7 +2370,7 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
 
 /* Disassemble an XScale DSP instruction.  Returns nonzero if an error occurred
    (ie. an undefined instruction).  */
-static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
+static int disas_dsp_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
 {
     int acc, rd0, rd1, rdhi, rdlo;
     TCGv tmp, tmp2;
@@ -2440,7 +2440,7 @@ static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
 
 /* Disassemble system coprocessor instruction.  Return nonzero if
    instruction is not defined.  */
-static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
+static int disas_cp_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
 {
     TCGv tmp, tmp2;
     uint32_t rd = (insn >> 12) & 0xf;
@@ -2471,7 +2471,7 @@ static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
     return 0;
 }
 
-static int cp15_user_ok(CPUState *env, uint32_t insn)
+static int cp15_user_ok(CPUARMState *env, uint32_t insn)
 {
     int cpn = (insn >> 16) & 0xf;
     int cpm = insn & 0xf;
@@ -2501,7 +2501,7 @@ static int cp15_user_ok(CPUState *env, uint32_t insn)
     return 0;
 }
 
-static int cp15_tls_load_store(CPUState *env, DisasContext *s, uint32_t insn, uint32_t rd)
+static int cp15_tls_load_store(CPUARMState *env, DisasContext *s, uint32_t insn, uint32_t rd)
 {
     TCGv tmp;
     int cpn = (insn >> 16) & 0xf;
@@ -2552,7 +2552,7 @@ static int cp15_tls_load_store(CPUState *env, DisasContext *s, uint32_t insn, ui
 
 /* Disassemble system coprocessor (cp15) instruction.  Return nonzero if
    instruction is not defined.  */
-static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
+static int disas_cp15_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
 {
     uint32_t rd;
     TCGv tmp, tmp2;
@@ -2747,7 +2747,7 @@ static TCGv gen_load_and_replicate(DisasContext *s, TCGv addr, int size)
 
 /* Disassemble a VFP instruction.  Returns nonzero if an error occurred
    (ie. an undefined instruction).  */
-static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
+static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
 {
     uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
     int dp, veclen;
@@ -3586,7 +3586,7 @@ static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
 }
 
 /* Return the mask of PSR bits set by a MSR instruction.  */
-static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
+static uint32_t msr_mask(CPUARMState *env, DisasContext *s, int flags, int spsr) {
     uint32_t mask;
 
     mask = 0;
@@ -3946,7 +3946,7 @@ static struct {
 
 /* Translate a NEON load/store element instruction.  Return nonzero if the
    instruction is invalid.  */
-static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
+static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
 {
     int rd, rn, rm;
     int op;
@@ -4622,7 +4622,7 @@ static const uint8_t neon_2rm_sizes[] = {
    We process data in a mixture of 32-bit and 64-bit chunks.
    Mostly we use 32-bit chunks so we can use normal scalar instructions.  */
 
-static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
+static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
 {
     int op;
     int q;
@@ -6387,7 +6387,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
     return 0;
 }
 
-static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
+static int disas_cp14_read(CPUARMState * env, DisasContext *s, uint32_t insn)
 {
     int crn = (insn >> 16) & 0xf;
     int crm = insn & 0xf;
@@ -6445,7 +6445,7 @@ static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
     return 1;
 }
 
-static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
+static int disas_cp14_write(CPUARMState * env, DisasContext *s, uint32_t insn)
 {
     int crn = (insn >> 16) & 0xf;
     int crm = insn & 0xf;
@@ -6476,7 +6476,7 @@ static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
     return 1;
 }
 
-static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
+static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
 {
     int cpnum;
 
@@ -6696,7 +6696,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
 }
 #endif
 
-static void disas_arm_insn(CPUState * env, DisasContext *s)
+static void disas_arm_insn(CPUARMState * env, DisasContext *s)
 {
     unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
     TCGv tmp;
@@ -7587,7 +7587,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                         tmp = load_reg(s, rn);
                         tmp2 = load_reg(s, rm);
                         tmp3 = tcg_temp_new_i32();
-                        tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
+                        tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
                         gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
                         tcg_temp_free_i32(tmp3);
                         tcg_temp_free_i32(tmp2);
@@ -8077,7 +8077,7 @@ gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCG
 
 /* Translate a 32-bit thumb instruction.  Returns nonzero if the instruction
    is not legal.  */
-static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
+static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw1)
 {
     uint32_t insn, imm, shift, offset;
     uint32_t rd, rn, rm, rs;
@@ -8488,7 +8488,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                 case 0x10: /* sel */
                     tmp2 = load_reg(s, rm);
                     tmp3 = tcg_temp_new_i32();
-                    tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
+                    tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
                     gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
                     tcg_temp_free_i32(tmp3);
                     tcg_temp_free_i32(tmp2);
@@ -9145,7 +9145,7 @@ illegal_op:
     return 1;
 }
 
-static void disas_thumb_insn(CPUState *env, DisasContext *s)
+static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
 {
     uint32_t val, insn, op, rm, rn, rd, shift, cond;
     int32_t offset;
@@ -9830,7 +9830,7 @@ undef:
 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
    basic block 'tb'. If search_pc is TRUE, also generate PC
    information for each intermediate instruction. */
-static inline void gen_intermediate_code_internal(CPUState *env,
+static inline void gen_intermediate_code_internal(CPUARMState *env,
                                                   TranslationBlock *tb,
                                                   int search_pc)
 {
@@ -9885,22 +9885,22 @@ static inline void gen_intermediate_code_internal(CPUState *env,
     /* A note on handling of the condexec (IT) bits:
      *
      * We want to avoid the overhead of having to write the updated condexec
-     * bits back to the CPUState for every instruction in an IT block. So:
+     * bits back to the CPUARMState for every instruction in an IT block. So:
      * (1) if the condexec bits are not already zero then we write
-     * zero back into the CPUState now. This avoids complications trying
+     * zero back into the CPUARMState now. This avoids complications trying
      * to do it at the end of the block. (For example if we don't do this
      * it's hard to identify whether we can safely skip writing condexec
      * at the end of the TB, which we definitely want to do for the case
      * where a TB doesn't do anything with the IT state at all.)
      * (2) if we are going to leave the TB then we call gen_set_condexec()
-     * which will write the correct value into CPUState if zero is wrong.
+     * which will write the correct value into CPUARMState if zero is wrong.
      * This is done both for leaving the TB at the end, and for leaving
      * it because of an exception we know will happen, which is done in
      * gen_exception_insn(). The latter is necessary because we need to
      * leave the TB with the PC/IT state just prior to execution of the
      * instruction which caused the exception.
      * (3) if we leave the TB unexpectedly (eg a data abort on a load)
-     * then the CPUState will be wrong and we need to reset it.
+     * then the CPUARMState will be wrong and we need to reset it.
      * This is handled in the same way as restoration of the
      * PC in these situations: we will be called again with search_pc=1
      * and generate a mapping of the condexec bits for each PC in
@@ -9909,7 +9909,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
      *
      * Note that there are no instructions which can read the condexec
      * bits, and none which can write non-static values to them, so
-     * we don't need to care about whether CPUState is correct in the
+     * we don't need to care about whether CPUARMState is correct in the
      * middle of a TB.
      */
 
@@ -10103,12 +10103,12 @@ done_generating:
     }
 }
 
-void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
+void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 0);
 }
 
-void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
+void gen_intermediate_code_pc(CPUARMState *env, TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 1);
 }
@@ -10118,7 +10118,7 @@ static const char *cpu_mode_names[16] = {
   "???", "???", "???", "und", "???", "???", "???", "sys"
 };
 
-void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
+void cpu_dump_state(CPUARMState *env, FILE *f, fprintf_function cpu_fprintf,
                     int flags)
 {
     int i;
@@ -10170,7 +10170,7 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
 #endif
 }
 
-void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos)
 {
     env->regs[15] = gen_opc_pc[pc_pos];
     env->condexec_bits = gen_opc_condexec_bits[pc_pos];
commit 4d5712f19b464cce8a3fdfad055f3d5833bd0d08
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Mar 14 01:38:21 2012 +0100

    target-alpha: Don't overuse CPUState
    
    Scripted conversion:
      sed -i "s/CPUState/CPUAlphaState/g" target-alpha/*.[hc]
      sed -i "s/#define CPUAlphaState/#define CPUState/" target-alpha/cpu.h
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 5cd6fd8..ecc2a35 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -375,7 +375,7 @@ enum {
     PS_USER_MODE = 8
 };
 
-static inline int cpu_mmu_index(CPUState *env)
+static inline int cpu_mmu_index(CPUAlphaState *env)
 {
     if (env->pal_mode) {
         return MMU_KERNEL_IDX;
@@ -430,16 +430,16 @@ int cpu_alpha_exec(CPUAlphaState *s);
    is returned if the signal was handled by the virtual CPU.  */
 int cpu_alpha_signal_handler(int host_signum, void *pinfo,
                              void *puc);
-int cpu_alpha_handle_mmu_fault (CPUState *env, uint64_t address, int rw,
+int cpu_alpha_handle_mmu_fault (CPUAlphaState *env, uint64_t address, int rw,
                                 int mmu_idx);
 #define cpu_handle_mmu_fault cpu_alpha_handle_mmu_fault
-void do_interrupt (CPUState *env);
+void do_interrupt (CPUAlphaState *env);
 
-uint64_t cpu_alpha_load_fpcr (CPUState *env);
-void cpu_alpha_store_fpcr (CPUState *env, uint64_t val);
+uint64_t cpu_alpha_load_fpcr (CPUAlphaState *env);
+void cpu_alpha_store_fpcr (CPUAlphaState *env, uint64_t val);
 #ifndef CONFIG_USER_ONLY
-void swap_shadow_regs(CPUState *env);
-QEMU_NORETURN void cpu_unassigned_access(CPUState *env1,
+void swap_shadow_regs(CPUAlphaState *env);
+QEMU_NORETURN void cpu_unassigned_access(CPUAlphaState *env1,
                                          target_phys_addr_t addr, int is_write,
                                          int is_exec, int unused, int size);
 #endif
@@ -459,7 +459,7 @@ enum {
     TB_FLAGS_AMASK_PREFETCH = AMASK_PREFETCH << TB_FLAGS_AMASK_SHIFT,
 };
 
-static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+static inline void cpu_get_tb_cpu_state(CPUAlphaState *env, target_ulong *pc,
                                         target_ulong *cs_base, int *pflags)
 {
     int flags = 0;
@@ -481,7 +481,7 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
 }
 
 #if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
+static inline void cpu_clone_regs(CPUAlphaState *env, target_ulong newsp)
 {
     if (newsp) {
         env->ir[IR_SP] = newsp;
@@ -490,13 +490,13 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
     env->ir[IR_A3] = 0;
 }
 
-static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
+static inline void cpu_set_tls(CPUAlphaState *env, target_ulong newtls)
 {
     env->unique = newtls;
 }
 #endif
 
-static inline bool cpu_has_work(CPUState *env)
+static inline bool cpu_has_work(CPUAlphaState *env)
 {
     /* Here we are checking to see if the CPU should wake up from HALT.
        We will have gotten into this state only for WTINT from PALmode.  */
@@ -513,7 +513,7 @@ static inline bool cpu_has_work(CPUState *env)
 
 #include "exec-all.h"
 
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+static inline void cpu_pc_from_tb(CPUAlphaState *env, TranslationBlock *tb)
 {
     env->pc = tb->pc;
 }
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 06d2565..3f2e7c3 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -24,7 +24,7 @@
 #include "cpu.h"
 #include "softfloat.h"
 
-uint64_t cpu_alpha_load_fpcr (CPUState *env)
+uint64_t cpu_alpha_load_fpcr (CPUAlphaState *env)
 {
     uint64_t r = 0;
     uint8_t t;
@@ -94,7 +94,7 @@ uint64_t cpu_alpha_load_fpcr (CPUState *env)
     return r;
 }
 
-void cpu_alpha_store_fpcr (CPUState *env, uint64_t val)
+void cpu_alpha_store_fpcr (CPUAlphaState *env, uint64_t val)
 {
     uint8_t t;
 
@@ -159,7 +159,7 @@ void cpu_alpha_store_fpcr (CPUState *env, uint64_t val)
 }
 
 #if defined(CONFIG_USER_ONLY)
-int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
+int cpu_alpha_handle_mmu_fault (CPUAlphaState *env, target_ulong address, int rw,
                                 int mmu_idx)
 {
     env->exception_index = EXCP_MMFAULT;
@@ -167,7 +167,7 @@ int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
     return 1;
 }
 #else
-void swap_shadow_regs(CPUState *env)
+void swap_shadow_regs(CPUAlphaState *env)
 {
     uint64_t i0, i1, i2, i3, i4, i5, i6, i7;
 
@@ -200,7 +200,7 @@ void swap_shadow_regs(CPUState *env)
 }
 
 /* Returns the OSF/1 entMM failure indication, or -1 on success.  */
-static int get_physical_address(CPUState *env, target_ulong addr,
+static int get_physical_address(CPUAlphaState *env, target_ulong addr,
                                 int prot_need, int mmu_idx,
                                 target_ulong *pphys, int *pprot)
 {
@@ -306,7 +306,7 @@ static int get_physical_address(CPUState *env, target_ulong addr,
     return ret;
 }
 
-target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_debug(CPUAlphaState *env, target_ulong addr)
 {
     target_ulong phys;
     int prot, fail;
@@ -315,7 +315,7 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
     return (fail >= 0 ? -1 : phys);
 }
 
-int cpu_alpha_handle_mmu_fault(CPUState *env, target_ulong addr, int rw,
+int cpu_alpha_handle_mmu_fault(CPUAlphaState *env, target_ulong addr, int rw,
                                int mmu_idx)
 {
     target_ulong phys;
@@ -336,7 +336,7 @@ int cpu_alpha_handle_mmu_fault(CPUState *env, target_ulong addr, int rw,
 }
 #endif /* USER_ONLY */
 
-void do_interrupt (CPUState *env)
+void do_interrupt (CPUAlphaState *env)
 {
     int i = env->exception_index;
 
@@ -453,7 +453,7 @@ void do_interrupt (CPUState *env)
 #endif /* !USER_ONLY */
 }
 
-void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
+void cpu_dump_state (CPUAlphaState *env, FILE *f, fprintf_function cpu_fprintf,
                      int flags)
 {
     static const char *linux_reg_names[] = {
diff --git a/target-alpha/machine.c b/target-alpha/machine.c
index 76d70d9..1c9edd1 100644
--- a/target-alpha/machine.c
+++ b/target-alpha/machine.c
@@ -21,8 +21,8 @@ static const VMStateInfo vmstate_fpcr = {
 };
 
 static VMStateField vmstate_cpu_fields[] = {
-    VMSTATE_UINTTL_ARRAY(ir, CPUState, 31),
-    VMSTATE_UINTTL_ARRAY(fir, CPUState, 31),
+    VMSTATE_UINTTL_ARRAY(ir, CPUAlphaState, 31),
+    VMSTATE_UINTTL_ARRAY(fir, CPUAlphaState, 31),
     /* Save the architecture value of the fpcr, not the internally
        expanded version.  Since this architecture value does not
        exist in memory to be stored, this requires a but of hoop
@@ -37,33 +37,33 @@ static VMStateField vmstate_cpu_fields[] = {
         .flags = VMS_SINGLE,
         .offset = 0
     },
-    VMSTATE_UINTTL(pc, CPUState),
-    VMSTATE_UINTTL(unique, CPUState),
-    VMSTATE_UINTTL(lock_addr, CPUState),
-    VMSTATE_UINTTL(lock_value, CPUState),
+    VMSTATE_UINTTL(pc, CPUAlphaState),
+    VMSTATE_UINTTL(unique, CPUAlphaState),
+    VMSTATE_UINTTL(lock_addr, CPUAlphaState),
+    VMSTATE_UINTTL(lock_value, CPUAlphaState),
     /* Note that lock_st_addr is not saved; it is a temporary
        used during the execution of the st[lq]_c insns.  */
 
-    VMSTATE_UINT8(ps, CPUState),
-    VMSTATE_UINT8(intr_flag, CPUState),
-    VMSTATE_UINT8(pal_mode, CPUState),
-    VMSTATE_UINT8(fen, CPUState),
+    VMSTATE_UINT8(ps, CPUAlphaState),
+    VMSTATE_UINT8(intr_flag, CPUAlphaState),
+    VMSTATE_UINT8(pal_mode, CPUAlphaState),
+    VMSTATE_UINT8(fen, CPUAlphaState),
 
-    VMSTATE_UINT32(pcc_ofs, CPUState),
+    VMSTATE_UINT32(pcc_ofs, CPUAlphaState),
 
-    VMSTATE_UINTTL(trap_arg0, CPUState),
-    VMSTATE_UINTTL(trap_arg1, CPUState),
-    VMSTATE_UINTTL(trap_arg2, CPUState),
+    VMSTATE_UINTTL(trap_arg0, CPUAlphaState),
+    VMSTATE_UINTTL(trap_arg1, CPUAlphaState),
+    VMSTATE_UINTTL(trap_arg2, CPUAlphaState),
 
-    VMSTATE_UINTTL(exc_addr, CPUState),
-    VMSTATE_UINTTL(palbr, CPUState),
-    VMSTATE_UINTTL(ptbr, CPUState),
-    VMSTATE_UINTTL(vptptr, CPUState),
-    VMSTATE_UINTTL(sysval, CPUState),
-    VMSTATE_UINTTL(usp, CPUState),
+    VMSTATE_UINTTL(exc_addr, CPUAlphaState),
+    VMSTATE_UINTTL(palbr, CPUAlphaState),
+    VMSTATE_UINTTL(ptbr, CPUAlphaState),
+    VMSTATE_UINTTL(vptptr, CPUAlphaState),
+    VMSTATE_UINTTL(sysval, CPUAlphaState),
+    VMSTATE_UINTTL(usp, CPUAlphaState),
 
-    VMSTATE_UINTTL_ARRAY(shadow, CPUState, 8),
-    VMSTATE_UINTTL_ARRAY(scratch, CPUState, 24),
+    VMSTATE_UINTTL_ARRAY(shadow, CPUAlphaState, 8),
+    VMSTATE_UINTTL_ARRAY(scratch, CPUAlphaState, 24),
 
     VMSTATE_END_OF_LIST()
 };
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index cc102db..c77f009 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1329,7 +1329,7 @@ static void QEMU_NORETURN do_unaligned_access(target_ulong addr, int is_write,
     helper_excp(EXCP_UNALIGN, 0);
 }
 
-void QEMU_NORETURN cpu_unassigned_access(CPUState *env1,
+void QEMU_NORETURN cpu_unassigned_access(CPUAlphaState *env1,
                                          target_phys_addr_t addr, int is_write,
                                          int is_exec, int unused, int size)
 {
@@ -1360,10 +1360,10 @@ void QEMU_NORETURN cpu_unassigned_access(CPUState *env1,
    NULL, it means that the function was called in C code (i.e. not
    from generated code or from helper.c) */
 /* XXX: fix it to restore all registers */
-void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
+void tlb_fill(CPUAlphaState *env1, target_ulong addr, int is_write, int mmu_idx,
               void *retaddr)
 {
-    CPUState *saved_env;
+    CPUAlphaState *saved_env;
     int ret;
 
     saved_env = env;
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 1d2142b..b51fe5c 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -105,35 +105,35 @@ static void alpha_translate_init(void)
     for (i = 0; i < 31; i++) {
         sprintf(p, "ir%d", i);
         cpu_ir[i] = tcg_global_mem_new_i64(TCG_AREG0,
-                                           offsetof(CPUState, ir[i]), p);
+                                           offsetof(CPUAlphaState, ir[i]), p);
         p += (i < 10) ? 4 : 5;
 
         sprintf(p, "fir%d", i);
         cpu_fir[i] = tcg_global_mem_new_i64(TCG_AREG0,
-                                            offsetof(CPUState, fir[i]), p);
+                                            offsetof(CPUAlphaState, fir[i]), p);
         p += (i < 10) ? 5 : 6;
     }
 
     cpu_pc = tcg_global_mem_new_i64(TCG_AREG0,
-                                    offsetof(CPUState, pc), "pc");
+                                    offsetof(CPUAlphaState, pc), "pc");
 
     cpu_lock_addr = tcg_global_mem_new_i64(TCG_AREG0,
-					   offsetof(CPUState, lock_addr),
+					   offsetof(CPUAlphaState, lock_addr),
 					   "lock_addr");
     cpu_lock_st_addr = tcg_global_mem_new_i64(TCG_AREG0,
-					      offsetof(CPUState, lock_st_addr),
+					      offsetof(CPUAlphaState, lock_st_addr),
 					      "lock_st_addr");
     cpu_lock_value = tcg_global_mem_new_i64(TCG_AREG0,
-					    offsetof(CPUState, lock_value),
+					    offsetof(CPUAlphaState, lock_value),
 					    "lock_value");
 
     cpu_unique = tcg_global_mem_new_i64(TCG_AREG0,
-                                        offsetof(CPUState, unique), "unique");
+                                        offsetof(CPUAlphaState, unique), "unique");
 #ifndef CONFIG_USER_ONLY
     cpu_sysval = tcg_global_mem_new_i64(TCG_AREG0,
-                                        offsetof(CPUState, sysval), "sysval");
+                                        offsetof(CPUAlphaState, sysval), "sysval");
     cpu_usp = tcg_global_mem_new_i64(TCG_AREG0,
-                                     offsetof(CPUState, usp), "usp");
+                                     offsetof(CPUAlphaState, usp), "usp");
 #endif
 
     /* register helpers */
@@ -611,7 +611,7 @@ static void gen_qual_roundmode(DisasContext *ctx, int fn11)
         tcg_gen_movi_i32(tmp, float_round_down);
         break;
     case QUAL_RM_D:
-        tcg_gen_ld8u_i32(tmp, cpu_env, offsetof(CPUState, fpcr_dyn_round));
+        tcg_gen_ld8u_i32(tmp, cpu_env, offsetof(CPUAlphaState, fpcr_dyn_round));
         break;
     }
 
@@ -620,7 +620,7 @@ static void gen_qual_roundmode(DisasContext *ctx, int fn11)
        With CONFIG_SOFTFLOAT that expands to an out-of-line call that just
        sets the one field.  */
     tcg_gen_st8_i32(tmp, cpu_env,
-                    offsetof(CPUState, fp_status.float_rounding_mode));
+                    offsetof(CPUAlphaState, fp_status.float_rounding_mode));
 #else
     gen_helper_setroundmode(tmp);
 #endif
@@ -641,7 +641,7 @@ static void gen_qual_flushzero(DisasContext *ctx, int fn11)
     tmp = tcg_temp_new_i32();
     if (fn11) {
         /* Underflow is enabled, use the FPCR setting.  */
-        tcg_gen_ld8u_i32(tmp, cpu_env, offsetof(CPUState, fpcr_flush_to_zero));
+        tcg_gen_ld8u_i32(tmp, cpu_env, offsetof(CPUAlphaState, fpcr_flush_to_zero));
     } else {
         /* Underflow is disabled, force flush-to-zero.  */
         tcg_gen_movi_i32(tmp, 1);
@@ -649,7 +649,7 @@ static void gen_qual_flushzero(DisasContext *ctx, int fn11)
 
 #if defined(CONFIG_SOFTFLOAT_INLINE)
     tcg_gen_st8_i32(tmp, cpu_env,
-                    offsetof(CPUState, fp_status.flush_to_zero));
+                    offsetof(CPUAlphaState, fp_status.flush_to_zero));
 #else
     gen_helper_setflushzero(tmp);
 #endif
@@ -677,7 +677,7 @@ static void gen_fp_exc_clear(void)
 #if defined(CONFIG_SOFTFLOAT_INLINE)
     TCGv_i32 zero = tcg_const_i32(0);
     tcg_gen_st8_i32(zero, cpu_env,
-                    offsetof(CPUState, fp_status.float_exception_flags));
+                    offsetof(CPUAlphaState, fp_status.float_exception_flags));
     tcg_temp_free_i32(zero);
 #else
     gen_helper_fp_exc_clear();
@@ -696,7 +696,7 @@ static void gen_fp_exc_raise_ignore(int rc, int fn11, int ignore)
 
 #if defined(CONFIG_SOFTFLOAT_INLINE)
     tcg_gen_ld8u_i32(exc, cpu_env,
-                     offsetof(CPUState, fp_status.float_exception_flags));
+                     offsetof(CPUAlphaState, fp_status.float_exception_flags));
 #else
     gen_helper_fp_exc_get(exc);
 #endif
@@ -1456,11 +1456,11 @@ static void gen_rx(int ra, int set)
     TCGv_i32 tmp;
 
     if (ra != 31) {
-        tcg_gen_ld8u_i64(cpu_ir[ra], cpu_env, offsetof(CPUState, intr_flag));
+        tcg_gen_ld8u_i64(cpu_ir[ra], cpu_env, offsetof(CPUAlphaState, intr_flag));
     }
 
     tmp = tcg_const_i32(set);
-    tcg_gen_st8_i32(tmp, cpu_env, offsetof(CPUState, intr_flag));
+    tcg_gen_st8_i32(tmp, cpu_env, offsetof(CPUAlphaState, intr_flag));
     tcg_temp_free_i32(tmp);
 }
 
@@ -1504,7 +1504,7 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
             break;
         case 0x2D:
             /* WRVPTPTR */
-            tcg_gen_st_i64(cpu_ir[IR_A0], cpu_env, offsetof(CPUState, vptptr));
+            tcg_gen_st_i64(cpu_ir[IR_A0], cpu_env, offsetof(CPUAlphaState, vptptr));
             break;
         case 0x31:
             /* WRVAL */
@@ -1521,19 +1521,19 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
 
             /* Note that we already know we're in kernel mode, so we know
                that PS only contains the 3 IPL bits.  */
-            tcg_gen_ld8u_i64(cpu_ir[IR_V0], cpu_env, offsetof(CPUState, ps));
+            tcg_gen_ld8u_i64(cpu_ir[IR_V0], cpu_env, offsetof(CPUAlphaState, ps));
 
             /* But make sure and store only the 3 IPL bits from the user.  */
             tmp = tcg_temp_new();
             tcg_gen_andi_i64(tmp, cpu_ir[IR_A0], PS_INT_MASK);
-            tcg_gen_st8_i64(tmp, cpu_env, offsetof(CPUState, ps));
+            tcg_gen_st8_i64(tmp, cpu_env, offsetof(CPUAlphaState, ps));
             tcg_temp_free(tmp);
             break;
         }
 
         case 0x36:
             /* RDPS */
-            tcg_gen_ld8u_i64(cpu_ir[IR_V0], cpu_env, offsetof(CPUState, ps));
+            tcg_gen_ld8u_i64(cpu_ir[IR_V0], cpu_env, offsetof(CPUAlphaState, ps));
             break;
         case 0x38:
             /* WRUSP */
@@ -1546,7 +1546,7 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
         case 0x3C:
             /* WHAMI */
             tcg_gen_ld32s_i64(cpu_ir[IR_V0], cpu_env,
-                              offsetof(CPUState, cpu_index));
+                              offsetof(CPUAlphaState, cpu_index));
             break;
 
         default:
@@ -1654,7 +1654,7 @@ static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno)
     case 253:
         /* WAIT */
         tmp = tcg_const_i64(1);
-        tcg_gen_st32_i64(tmp, cpu_env, offsetof(CPUState, halted));
+        tcg_gen_st32_i64(tmp, cpu_env, offsetof(CPUAlphaState, halted));
         return gen_excp(ctx, EXCP_HLT, 0);
 
     case 252:
@@ -3107,7 +3107,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
                    address from EXC_ADDR.  This turns out to be useful for our
                    emulation PALcode, so continue to accept it.  */
                 TCGv tmp = tcg_temp_new();
-                tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUState, exc_addr));
+                tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUAlphaState, exc_addr));
                 gen_helper_hw_ret(tmp);
                 tcg_temp_free(tmp);
             } else {
@@ -3325,7 +3325,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
     return ret;
 }
 
-static inline void gen_intermediate_code_internal(CPUState *env,
+static inline void gen_intermediate_code_internal(CPUAlphaState *env,
                                                   TranslationBlock *tb,
                                                   int search_pc)
 {
@@ -3450,12 +3450,12 @@ static inline void gen_intermediate_code_internal(CPUState *env,
 #endif
 }
 
-void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
+void gen_intermediate_code (CPUAlphaState *env, struct TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 0);
 }
 
-void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
+void gen_intermediate_code_pc (CPUAlphaState *env, struct TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 1);
 }
@@ -3522,7 +3522,7 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
     return env;
 }
 
-void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb, int pc_pos)
 {
     env->pc = gen_opc_pc[pc_pos];
 }
commit b98e9ca8bb38c4a80af458dd16c906f36ce50112
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Feb 25 04:29:56 2012 +0100

    bsd-user: Don't overuse CPUState
    
    Use CPU*State where applicable.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/bsd-user/main.c b/bsd-user/main.c
index c3af395..78533d5 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -63,7 +63,7 @@ void gemu_log(const char *fmt, ...)
 }
 
 #if defined(TARGET_I386)
-int cpu_get_pic_interrupt(CPUState *env)
+int cpu_get_pic_interrupt(CPUX86State *env)
 {
     return -1;
 }
@@ -109,7 +109,7 @@ void cpu_list_unlock(void)
 /***********************************************************/
 /* CPUX86 core interface */
 
-void cpu_smm_update(CPUState *env)
+void cpu_smm_update(CPUX86State *env)
 {
 }
 
commit c91dcf0b8157e40f1d51d9ad34c2724798137ec1
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Feb 25 04:27:43 2012 +0100

    darwin-user: Don't overuse CPUState
    
    Use CPU*State where applicable.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/darwin-user/main.c b/darwin-user/main.c
index 13c1f05..f5cadc7 100644
--- a/darwin-user/main.c
+++ b/darwin-user/main.c
@@ -77,38 +77,38 @@ int cpu_get_pic_interrupt(CPUState *env)
 }
 #ifdef TARGET_PPC
 
-static inline uint64_t cpu_ppc_get_tb (CPUState *env)
+static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env)
 {
     /* TO FIX */
     return 0;
 }
 
-uint64_t cpu_ppc_load_tbl (CPUState *env)
+uint64_t cpu_ppc_load_tbl(CPUPPCState *env)
 {
     return cpu_ppc_get_tb(env);
 }
 
-uint32_t cpu_ppc_load_tbu (CPUState *env)
+uint32_t cpu_ppc_load_tbu(CPUPPCState *env)
 {
     return cpu_ppc_get_tb(env) >> 32;
 }
 
-uint64_t cpu_ppc_load_atbl (CPUState *env)
+uint64_t cpu_ppc_load_atbl(CPUPPCState *env)
 {
     return cpu_ppc_get_tb(env);
 }
 
-uint32_t cpu_ppc_load_atbu (CPUState *env)
+uint32_t cpu_ppc_load_atbu(CPUPPCState *env)
 {
     return cpu_ppc_get_tb(env) >> 32;
 }
 
-uint32_t cpu_ppc601_load_rtcu (CPUState *env)
+uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env)
 {
     cpu_ppc_load_tbu(env);
 }
 
-uint32_t cpu_ppc601_load_rtcl (CPUState *env)
+uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env)
 {
     return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
 }
diff --git a/darwin-user/signal.c b/darwin-user/signal.c
index 317ef92..8f9705d 100644
--- a/darwin-user/signal.c
+++ b/darwin-user/signal.c
@@ -315,7 +315,7 @@ get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size)
 }
 
 static void setup_frame(int sig, struct emulated_sigaction *ka,
-			void *set, CPUState *env)
+                        void *set, CPUX86State *env)
 {
 	void *frame;
 
@@ -336,7 +336,7 @@ give_sigsegv:
 	force_sig(SIGSEGV /* , current */);
 }
 
-long do_sigreturn(CPUState *env, int num)
+long do_sigreturn(CPUX86State *env, int num)
 {
     int i = 0;
     struct target_sigcontext *scp = get_int_arg(&i, env);
commit 053902488581f504149e1507fe5328cfd57caa23
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Feb 25 03:37:53 2012 +0100

    linux-user: Don't overuse CPUState
    
    In target-specific code use CPU*State.
    
    While at it, fix indentation on those lines.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 2fd4a93..48e3232 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -157,7 +157,7 @@ typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
  *
  * See linux kernel: arch/x86/include/asm/elf.h
  */
-static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
+static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *env)
 {
     (*regs)[0] = env->regs[15];
     (*regs)[1] = env->regs[14];
@@ -229,7 +229,7 @@ typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
  *
  * See linux kernel: arch/x86/include/asm/elf.h
  */
-static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
+static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *env)
 {
     (*regs)[0] = env->regs[R_EBX];
     (*regs)[1] = env->regs[R_ECX];
@@ -288,7 +288,7 @@ static inline void init_thread(struct target_pt_regs *regs,
 #define ELF_NREG    18
 typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
 
-static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
+static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUARMState *env)
 {
     (*regs)[0] = tswapl(env->regs[0]);
     (*regs)[1] = tswapl(env->regs[1]);
@@ -307,7 +307,7 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
     (*regs)[14] = tswapl(env->regs[14]);
     (*regs)[15] = tswapl(env->regs[15]);
 
-    (*regs)[16] = tswapl(cpsr_read((CPUState *)env));
+    (*regs)[16] = tswapl(cpsr_read((CPUARMState *)env));
     (*regs)[17] = tswapl(env->regs[0]); /* XXX */
 }
 
@@ -410,7 +410,7 @@ static inline void init_thread(struct target_pt_regs *regs,
 #define ELF_NREG    34
 typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
 
-static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
+static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUUniCore32State *env)
 {
     (*regs)[0] = env->regs[0];
     (*regs)[1] = env->regs[1];
@@ -445,7 +445,7 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
     (*regs)[30] = env->regs[30];
     (*regs)[31] = env->regs[31];
 
-    (*regs)[32] = cpu_asr_read((CPUState *)env);
+    (*regs)[32] = cpu_asr_read((CPUUniCore32State *)env);
     (*regs)[33] = env->regs[0]; /* XXX */
 }
 
@@ -572,7 +572,7 @@ enum {
 
 static uint32_t get_elf_hwcap(void)
 {
-    CPUState *e = thread_env;
+    CPUPPCState *e = thread_env;
     uint32_t features = 0;
 
     /* We don't have to be terribly complete here; the high points are
@@ -628,7 +628,7 @@ static inline void init_thread(struct target_pt_regs *_regs, struct image_info *
 #define ELF_NREG 48
 typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
 
-static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
+static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *env)
 {
     int i;
     target_ulong ccr = 0;
@@ -697,7 +697,7 @@ enum {
 };
 
 /* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs.  */
-static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
+static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMIPSState *env)
 {
     int i;
 
@@ -749,7 +749,7 @@ static inline void init_thread(struct target_pt_regs *regs,
 typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
 
 /* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs.  */
-static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
+static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMBState *env)
 {
     int i, pos = 0;
 
@@ -797,7 +797,7 @@ enum {
 };
 
 static inline void elf_core_copy_regs(target_elf_gregset_t *regs,
-                                      const CPUState *env)
+                                      const CPUSH4State *env)
 {
     int i;
 
@@ -862,7 +862,7 @@ static inline void init_thread(struct target_pt_regs *regs,
 #define ELF_NREG 20
 typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
 
-static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
+static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUM68KState *env)
 {
     (*regs)[0] = tswapl(env->dregs[1]);
     (*regs)[1] = tswapl(env->dregs[2]);
diff --git a/linux-user/m68k/syscall.h b/linux-user/m68k/syscall.h
index 2fd85dd..2618793 100644
--- a/linux-user/m68k/syscall.h
+++ b/linux-user/m68k/syscall.h
@@ -18,4 +18,4 @@ struct target_pt_regs {
 
 #define UNAME_MACHINE "m68k"
 
-void do_m68k_simcall(CPUState *, int);
+void do_m68k_simcall(CPUM68KState *, int);
diff --git a/linux-user/main.c b/linux-user/main.c
index 01129f2..3b48882 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -71,7 +71,7 @@ void gemu_log(const char *fmt, ...)
 }
 
 #if defined(TARGET_I386)
-int cpu_get_pic_interrupt(CPUState *env)
+int cpu_get_pic_interrupt(CPUX86State *env)
 {
     return -1;
 }
@@ -247,7 +247,7 @@ void cpu_list_unlock(void)
 /***********************************************************/
 /* CPUX86 core interface */
 
-void cpu_smm_update(CPUState *env)
+void cpu_smm_update(CPUX86State *env)
 {
 }
 
@@ -889,7 +889,7 @@ void cpu_loop(CPUARMState *env)
 
 #ifdef TARGET_UNICORE32
 
-void cpu_loop(CPUState *env)
+void cpu_loop(CPUUniCore32State *env)
 {
     int trapnr;
     unsigned int n, insn;
@@ -1226,36 +1226,36 @@ void cpu_loop (CPUSPARCState *env)
 #endif
 
 #ifdef TARGET_PPC
-static inline uint64_t cpu_ppc_get_tb (CPUState *env)
+static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env)
 {
     /* TO FIX */
     return 0;
 }
 
-uint64_t cpu_ppc_load_tbl (CPUState *env)
+uint64_t cpu_ppc_load_tbl(CPUPPCState *env)
 {
     return cpu_ppc_get_tb(env);
 }
 
-uint32_t cpu_ppc_load_tbu (CPUState *env)
+uint32_t cpu_ppc_load_tbu(CPUPPCState *env)
 {
     return cpu_ppc_get_tb(env) >> 32;
 }
 
-uint64_t cpu_ppc_load_atbl (CPUState *env)
+uint64_t cpu_ppc_load_atbl(CPUPPCState *env)
 {
     return cpu_ppc_get_tb(env);
 }
 
-uint32_t cpu_ppc_load_atbu (CPUState *env)
+uint32_t cpu_ppc_load_atbu(CPUPPCState *env)
 {
     return cpu_ppc_get_tb(env) >> 32;
 }
 
-uint32_t cpu_ppc601_load_rtcu (CPUState *env)
+uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env)
 __attribute__ (( alias ("cpu_ppc_load_tbu") ));
 
-uint32_t cpu_ppc601_load_rtcl (CPUState *env)
+uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env)
 {
     return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
 }
@@ -2276,7 +2276,7 @@ done_syscall:
 #endif
 
 #ifdef TARGET_SH4
-void cpu_loop (CPUState *env)
+void cpu_loop(CPUSH4State *env)
 {
     int trapnr, ret;
     target_siginfo_t info;
@@ -2335,7 +2335,7 @@ void cpu_loop (CPUState *env)
 #endif
 
 #ifdef TARGET_CRIS
-void cpu_loop (CPUState *env)
+void cpu_loop(CPUCRISState *env)
 {
     int trapnr, ret;
     target_siginfo_t info;
@@ -2393,7 +2393,7 @@ void cpu_loop (CPUState *env)
 #endif
 
 #ifdef TARGET_MICROBLAZE
-void cpu_loop (CPUState *env)
+void cpu_loop(CPUMBState *env)
 {
     int trapnr, ret;
     target_siginfo_t info;
@@ -2630,7 +2630,7 @@ static void do_store_exclusive(CPUAlphaState *env, int reg, int quad)
     queue_signal(env, TARGET_SIGSEGV, &info);
 }
 
-void cpu_loop (CPUState *env)
+void cpu_loop(CPUAlphaState *env)
 {
     int trapnr;
     target_siginfo_t info;
diff --git a/linux-user/signal.c b/linux-user/signal.c
index cefd2ff..f44f78e 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1205,14 +1205,14 @@ static const abi_ulong retcodes[4] = {
 
 #define __get_user_error(x,p,e) __get_user(x, p)
 
-static inline int valid_user_regs(CPUState *regs)
+static inline int valid_user_regs(CPUARMState *regs)
 {
     return 1;
 }
 
 static void
 setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
-		 CPUState *env, abi_ulong mask)
+                 CPUARMState *env, abi_ulong mask)
 {
 	__put_user(env->regs[0], &sc->arm_r0);
 	__put_user(env->regs[1], &sc->arm_r1);
@@ -1241,7 +1241,7 @@ setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
 }
 
 static inline abi_ulong
-get_sigframe(struct target_sigaction *ka, CPUState *regs, int framesize)
+get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
 {
 	unsigned long sp = regs->regs[13];
 
@@ -1257,7 +1257,7 @@ get_sigframe(struct target_sigaction *ka, CPUState *regs, int framesize)
 }
 
 static int
-setup_return(CPUState *env, struct target_sigaction *ka,
+setup_return(CPUARMState *env, struct target_sigaction *ka,
 	     abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
 {
 	abi_ulong handler = ka->_sa_handler;
@@ -1295,7 +1295,7 @@ setup_return(CPUState *env, struct target_sigaction *ka,
 	return 0;
 }
 
-static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUState *env)
+static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
 {
     int i;
     struct target_vfp_sigframe *vfpframe;
@@ -1312,7 +1312,8 @@ static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUState *env)
     return (abi_ulong*)(vfpframe+1);
 }
 
-static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace, CPUState *env)
+static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
+                                           CPUARMState *env)
 {
     int i;
     struct target_iwmmxt_sigframe *iwmmxtframe;
@@ -1332,7 +1333,7 @@ static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace, CPUState *env)
 }
 
 static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
-                              target_sigset_t *set, CPUState *env)
+                              target_sigset_t *set, CPUARMState *env)
 {
     struct target_sigaltstack stack;
     int i;
@@ -1367,7 +1368,7 @@ static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
 
 /* compare linux/arch/arm/kernel/signal.c:setup_frame() */
 static void setup_frame_v1(int usig, struct target_sigaction *ka,
-			   target_sigset_t *set, CPUState *regs)
+                           target_sigset_t *set, CPUARMState *regs)
 {
 	struct sigframe_v1 *frame;
 	abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
@@ -1391,7 +1392,7 @@ end:
 }
 
 static void setup_frame_v2(int usig, struct target_sigaction *ka,
-			   target_sigset_t *set, CPUState *regs)
+                           target_sigset_t *set, CPUARMState *regs)
 {
 	struct sigframe_v2 *frame;
 	abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
@@ -1408,7 +1409,7 @@ static void setup_frame_v2(int usig, struct target_sigaction *ka,
 }
 
 static void setup_frame(int usig, struct target_sigaction *ka,
-			target_sigset_t *set, CPUState *regs)
+                        target_sigset_t *set, CPUARMState *regs)
 {
     if (get_osversion() >= 0x020612) {
         setup_frame_v2(usig, ka, set, regs);
@@ -1420,7 +1421,7 @@ static void setup_frame(int usig, struct target_sigaction *ka,
 /* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
 static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
                               target_siginfo_t *info,
-			      target_sigset_t *set, CPUState *env)
+                              target_sigset_t *set, CPUARMState *env)
 {
 	struct rt_sigframe_v1 *frame;
 	abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
@@ -1464,7 +1465,7 @@ end:
 
 static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
                               target_siginfo_t *info,
-                              target_sigset_t *set, CPUState *env)
+                              target_sigset_t *set, CPUARMState *env)
 {
 	struct rt_sigframe_v2 *frame;
 	abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
@@ -1490,7 +1491,7 @@ static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
 
 static void setup_rt_frame(int usig, struct target_sigaction *ka,
                            target_siginfo_t *info,
-			   target_sigset_t *set, CPUState *env)
+                           target_sigset_t *set, CPUARMState *env)
 {
     if (get_osversion() >= 0x020612) {
         setup_rt_frame_v2(usig, ka, info, set, env);
@@ -1500,7 +1501,7 @@ static void setup_rt_frame(int usig, struct target_sigaction *ka,
 }
 
 static int
-restore_sigcontext(CPUState *env, struct target_sigcontext *sc)
+restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
 {
 	int err = 0;
         uint32_t cpsr;
@@ -1531,7 +1532,7 @@ restore_sigcontext(CPUState *env, struct target_sigcontext *sc)
 	return err;
 }
 
-static long do_sigreturn_v1(CPUState *env)
+static long do_sigreturn_v1(CPUARMState *env)
 {
         abi_ulong frame_addr;
 	struct sigframe_v1 *frame;
@@ -1578,7 +1579,7 @@ badframe:
 	return 0;
 }
 
-static abi_ulong *restore_sigframe_v2_vfp(CPUState *env, abi_ulong *regspace)
+static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
 {
     int i;
     abi_ulong magic, sz;
@@ -1608,7 +1609,8 @@ static abi_ulong *restore_sigframe_v2_vfp(CPUState *env, abi_ulong *regspace)
     return (abi_ulong*)(vfpframe + 1);
 }
 
-static abi_ulong *restore_sigframe_v2_iwmmxt(CPUState *env, abi_ulong *regspace)
+static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
+                                             abi_ulong *regspace)
 {
     int i;
     abi_ulong magic, sz;
@@ -1632,7 +1634,7 @@ static abi_ulong *restore_sigframe_v2_iwmmxt(CPUState *env, abi_ulong *regspace)
     return (abi_ulong*)(iwmmxtframe + 1);
 }
 
-static int do_sigframe_return_v2(CPUState *env, target_ulong frame_addr,
+static int do_sigframe_return_v2(CPUARMState *env, target_ulong frame_addr,
                                  struct target_ucontext_v2 *uc)
 {
     sigset_t host_set;
@@ -1671,7 +1673,7 @@ static int do_sigframe_return_v2(CPUState *env, target_ulong frame_addr,
     return 0;
 }
 
-static long do_sigreturn_v2(CPUState *env)
+static long do_sigreturn_v2(CPUARMState *env)
 {
         abi_ulong frame_addr;
 	struct sigframe_v2 *frame;
@@ -1700,7 +1702,7 @@ badframe:
 	return 0;
 }
 
-long do_sigreturn(CPUState *env)
+long do_sigreturn(CPUARMState *env)
 {
     if (get_osversion() >= 0x020612) {
         return do_sigreturn_v2(env);
@@ -1709,7 +1711,7 @@ long do_sigreturn(CPUState *env)
     }
 }
 
-static long do_rt_sigreturn_v1(CPUState *env)
+static long do_rt_sigreturn_v1(CPUARMState *env)
 {
         abi_ulong frame_addr;
 	struct rt_sigframe_v1 *frame;
@@ -1750,7 +1752,7 @@ badframe:
 	return 0;
 }
 
-static long do_rt_sigreturn_v2(CPUState *env)
+static long do_rt_sigreturn_v2(CPUARMState *env)
 {
         abi_ulong frame_addr;
 	struct rt_sigframe_v2 *frame;
@@ -1779,7 +1781,7 @@ badframe:
 	return 0;
 }
 
-long do_rt_sigreturn(CPUState *env)
+long do_rt_sigreturn(CPUARMState *env)
 {
     if (get_osversion() >= 0x020612) {
         return do_rt_sigreturn_v2(env);
@@ -1888,7 +1890,8 @@ struct target_rt_signal_frame {
 #define UREG_SP        UREG_O6
 
 static inline abi_ulong get_sigframe(struct target_sigaction *sa, 
-                                     CPUState *env, unsigned long framesize)
+                                     CPUSPARCState *env,
+                                     unsigned long framesize)
 {
 	abi_ulong sp;
 
@@ -1904,7 +1907,7 @@ static inline abi_ulong get_sigframe(struct target_sigaction *sa,
 }
 
 static int
-setup___siginfo(__siginfo_t *si, CPUState *env, abi_ulong mask)
+setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask)
 {
 	int err = 0, i;
 
@@ -1925,7 +1928,7 @@ setup___siginfo(__siginfo_t *si, CPUState *env, abi_ulong mask)
 #if 0
 static int
 setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
-		 CPUState *env, unsigned long mask)
+                 CPUSPARCState *env, unsigned long mask)
 {
 	int err = 0;
 
@@ -1943,7 +1946,7 @@ setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
 #define NF_ALIGNEDSZ  (((sizeof(struct target_signal_frame) + 7) & (~7)))
 
 static void setup_frame(int sig, struct target_sigaction *ka,
-			target_sigset_t *set, CPUState *env)
+                        target_sigset_t *set, CPUSPARCState *env)
 {
         abi_ulong sf_addr;
 	struct target_signal_frame *sf;
@@ -2032,7 +2035,7 @@ sigsegv:
 	force_sig(TARGET_SIGSEGV);
 }
 static inline int
-restore_fpu_state(CPUState *env, qemu_siginfo_fpu_t *fpu)
+restore_fpu_state(CPUSPARCState *env, qemu_siginfo_fpu_t *fpu)
 {
         int err;
 #if 0
@@ -2073,12 +2076,12 @@ restore_fpu_state(CPUState *env, qemu_siginfo_fpu_t *fpu)
 
 static void setup_rt_frame(int sig, struct target_sigaction *ka,
                            target_siginfo_t *info,
-			   target_sigset_t *set, CPUState *env)
+                           target_sigset_t *set, CPUSPARCState *env)
 {
     fprintf(stderr, "setup_rt_frame: not implemented\n");
 }
 
-long do_sigreturn(CPUState *env)
+long do_sigreturn(CPUSPARCState *env)
 {
         abi_ulong sf_addr;
         struct target_signal_frame *sf;
@@ -2151,7 +2154,7 @@ segv_and_exit:
 	force_sig(TARGET_SIGSEGV);
 }
 
-long do_rt_sigreturn(CPUState *env)
+long do_rt_sigreturn(CPUSPARCState *env)
 {
     fprintf(stderr, "do_rt_sigreturn: not implemented\n");
     return -TARGET_ENOSYS;
@@ -2427,25 +2430,25 @@ void sparc64_get_context(CPUSPARCState *env)
 # warning signal handling not implemented
 
 static void setup_frame(int sig, struct target_sigaction *ka,
-			target_sigset_t *set, CPUState *env)
+                        target_sigset_t *set, CPUMIPSState *env)
 {
     fprintf(stderr, "setup_frame: not implemented\n");
 }
 
 static void setup_rt_frame(int sig, struct target_sigaction *ka,
                            target_siginfo_t *info,
-			   target_sigset_t *set, CPUState *env)
+                           target_sigset_t *set, CPUMIPSState *env)
 {
     fprintf(stderr, "setup_rt_frame: not implemented\n");
 }
 
-long do_sigreturn(CPUState *env)
+long do_sigreturn(CPUMIPSState *env)
 {
     fprintf(stderr, "do_sigreturn: not implemented\n");
     return -TARGET_ENOSYS;
 }
 
-long do_rt_sigreturn(CPUState *env)
+long do_rt_sigreturn(CPUMIPSState *env)
 {
     fprintf(stderr, "do_rt_sigreturn: not implemented\n");
     return -TARGET_ENOSYS;
@@ -2456,25 +2459,25 @@ long do_rt_sigreturn(CPUState *env)
 # warning signal handling not implemented
 
 static void setup_frame(int sig, struct target_sigaction *ka,
-			target_sigset_t *set, CPUState *env)
+                        target_sigset_t *set, CPUMIPSState *env)
 {
     fprintf(stderr, "setup_frame: not implemented\n");
 }
 
 static void setup_rt_frame(int sig, struct target_sigaction *ka,
                            target_siginfo_t *info,
-			   target_sigset_t *set, CPUState *env)
+                           target_sigset_t *set, CPUMIPSState *env)
 {
     fprintf(stderr, "setup_rt_frame: not implemented\n");
 }
 
-long do_sigreturn(CPUState *env)
+long do_sigreturn(CPUMIPSState *env)
 {
     fprintf(stderr, "do_sigreturn: not implemented\n");
     return -TARGET_ENOSYS;
 }
 
-long do_rt_sigreturn(CPUState *env)
+long do_rt_sigreturn(CPUMIPSState *env)
 {
     fprintf(stderr, "do_rt_sigreturn: not implemented\n");
     return -TARGET_ENOSYS;
@@ -2546,7 +2549,7 @@ static inline int install_sigtramp(unsigned int *tramp,   unsigned int syscall)
 }
 
 static inline int
-setup_sigcontext(CPUState *regs, struct target_sigcontext *sc)
+setup_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
 {
     int err = 0;
 
@@ -2621,7 +2624,7 @@ setup_sigcontext(CPUState *regs, struct target_sigcontext *sc)
 }
 
 static inline int
-restore_sigcontext(CPUState *regs, struct target_sigcontext *sc)
+restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
 {
     int err = 0;
 
@@ -2692,7 +2695,7 @@ restore_sigcontext(CPUState *regs, struct target_sigcontext *sc)
  * Determine which stack to use..
  */
 static inline abi_ulong
-get_sigframe(struct target_sigaction *ka, CPUState *regs, size_t frame_size)
+get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
 {
     unsigned long sp;
 
@@ -2716,7 +2719,7 @@ get_sigframe(struct target_sigaction *ka, CPUState *regs, size_t frame_size)
 
 /* compare linux/arch/mips/kernel/signal.c:setup_frame() */
 static void setup_frame(int sig, struct target_sigaction * ka,
-                        target_sigset_t *set, CPUState *regs)
+                        target_sigset_t *set, CPUMIPSState *regs)
 {
     struct sigframe *frame;
     abi_ulong frame_addr;
@@ -2764,7 +2767,7 @@ give_sigsegv:
     return;
 }
 
-long do_sigreturn(CPUState *regs)
+long do_sigreturn(CPUMIPSState *regs)
 {
     struct sigframe *frame;
     abi_ulong frame_addr;
@@ -2815,7 +2818,7 @@ badframe:
 
 static void setup_rt_frame(int sig, struct target_sigaction *ka,
                            target_siginfo_t *info,
-			   target_sigset_t *set, CPUState *env)
+                           target_sigset_t *set, CPUMIPSState *env)
 {
     struct target_rt_sigframe *frame;
     abi_ulong frame_addr;
@@ -2873,7 +2876,7 @@ give_sigsegv:
     return;
 }
 
-long do_rt_sigreturn(CPUState *env)
+long do_rt_sigreturn(CPUMIPSState *env)
 {
     struct target_rt_sigframe *frame;
     abi_ulong frame_addr;
@@ -2974,7 +2977,7 @@ static abi_ulong get_sigframe(struct target_sigaction *ka,
 }
 
 static int setup_sigcontext(struct target_sigcontext *sc,
-			    CPUState *regs, unsigned long mask)
+                            CPUSH4State *regs, unsigned long mask)
 {
     int err = 0;
     int i;
@@ -3005,7 +3008,7 @@ static int setup_sigcontext(struct target_sigcontext *sc,
     return err;
 }
 
-static int restore_sigcontext(CPUState *regs, struct target_sigcontext *sc,
+static int restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc,
                               target_ulong *r0_p)
 {
     unsigned int err = 0;
@@ -3037,7 +3040,7 @@ static int restore_sigcontext(CPUState *regs, struct target_sigcontext *sc,
 }
 
 static void setup_frame(int sig, struct target_sigaction *ka,
-			target_sigset_t *set, CPUState *regs)
+                        target_sigset_t *set, CPUSH4State *regs)
 {
     struct target_sigframe *frame;
     abi_ulong frame_addr;
@@ -3089,7 +3092,7 @@ give_sigsegv:
 
 static void setup_rt_frame(int sig, struct target_sigaction *ka,
                            target_siginfo_t *info,
-			   target_sigset_t *set, CPUState *regs)
+                           target_sigset_t *set, CPUSH4State *regs)
 {
     struct target_rt_sigframe *frame;
     abi_ulong frame_addr;
@@ -3150,7 +3153,7 @@ give_sigsegv:
     force_sig(TARGET_SIGSEGV);
 }
 
-long do_sigreturn(CPUState *regs)
+long do_sigreturn(CPUSH4State *regs)
 {
     struct target_sigframe *frame;
     abi_ulong frame_addr;
@@ -3190,7 +3193,7 @@ badframe:
     return 0;
 }
 
-long do_rt_sigreturn(CPUState *regs)
+long do_rt_sigreturn(CPUSH4State *regs)
 {
     struct target_rt_sigframe *frame;
     abi_ulong frame_addr;
@@ -3257,7 +3260,7 @@ struct rt_signal_frame {
     uint32_t tramp[2];
 };
 
-static void setup_sigcontext(struct target_sigcontext *sc, CPUState *env)
+static void setup_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
 {
     __put_user(env->regs[0], &sc->regs.r0);
     __put_user(env->regs[1], &sc->regs.r1);
@@ -3294,7 +3297,7 @@ static void setup_sigcontext(struct target_sigcontext *sc, CPUState *env)
     __put_user(env->sregs[SR_PC], &sc->regs.pc);
 }
 
-static void restore_sigcontext(struct target_sigcontext *sc, CPUState *env)
+static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
 {
     __get_user(env->regs[0], &sc->regs.r0);
     __get_user(env->regs[1], &sc->regs.r1);
@@ -3332,7 +3335,7 @@ static void restore_sigcontext(struct target_sigcontext *sc, CPUState *env)
 }
 
 static abi_ulong get_sigframe(struct target_sigaction *ka,
-                              CPUState *env, int frame_size)
+                              CPUMBState *env, int frame_size)
 {
     abi_ulong sp = env->regs[1];
 
@@ -3343,7 +3346,7 @@ static abi_ulong get_sigframe(struct target_sigaction *ka,
 }
 
 static void setup_frame(int sig, struct target_sigaction *ka,
-			target_sigset_t *set, CPUState *env)
+                        target_sigset_t *set, CPUMBState *env)
 {
     struct target_signal_frame *frame;
     abi_ulong frame_addr;
@@ -3409,12 +3412,12 @@ static void setup_frame(int sig, struct target_sigaction *ka,
 
 static void setup_rt_frame(int sig, struct target_sigaction *ka,
                            target_siginfo_t *info,
-			   target_sigset_t *set, CPUState *env)
+                           target_sigset_t *set, CPUMBState *env)
 {
     fprintf(stderr, "Microblaze setup_rt_frame: not implemented\n");
 }
 
-long do_sigreturn(CPUState *env)
+long do_sigreturn(CPUMBState *env)
 {
     struct target_signal_frame *frame;
     abi_ulong frame_addr;
@@ -3449,7 +3452,7 @@ long do_sigreturn(CPUState *env)
     force_sig(TARGET_SIGSEGV);
 }
 
-long do_rt_sigreturn(CPUState *env)
+long do_rt_sigreturn(CPUMBState *env)
 {
     fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n");
     return -TARGET_ENOSYS;
@@ -3478,7 +3481,7 @@ struct rt_signal_frame {
         uint8_t retcode[8];       /* Trampoline code. */
 };
 
-static void setup_sigcontext(struct target_sigcontext *sc, CPUState *env)
+static void setup_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
 {
 	__put_user(env->regs[0], &sc->regs.r0);
 	__put_user(env->regs[1], &sc->regs.r1);
@@ -3501,7 +3504,7 @@ static void setup_sigcontext(struct target_sigcontext *sc, CPUState *env)
 	__put_user(env->pc, &sc->regs.erp);
 }
 
-static void restore_sigcontext(struct target_sigcontext *sc, CPUState *env)
+static void restore_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
 {
 	__get_user(env->regs[0], &sc->regs.r0);
 	__get_user(env->regs[1], &sc->regs.r1);
@@ -3524,7 +3527,7 @@ static void restore_sigcontext(struct target_sigcontext *sc, CPUState *env)
 	__get_user(env->pc, &sc->regs.erp);
 }
 
-static abi_ulong get_sigframe(CPUState *env, int framesize)
+static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
 {
 	abi_ulong sp;
 	/* Align the stack downwards to 4.  */
@@ -3533,7 +3536,7 @@ static abi_ulong get_sigframe(CPUState *env, int framesize)
 }
 
 static void setup_frame(int sig, struct target_sigaction *ka,
-			target_sigset_t *set, CPUState *env)
+                        target_sigset_t *set, CPUCRISState *env)
 {
 	struct target_signal_frame *frame;
 	abi_ulong frame_addr;
@@ -3584,12 +3587,12 @@ static void setup_frame(int sig, struct target_sigaction *ka,
 
 static void setup_rt_frame(int sig, struct target_sigaction *ka,
                            target_siginfo_t *info,
-			   target_sigset_t *set, CPUState *env)
+                           target_sigset_t *set, CPUCRISState *env)
 {
     fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
 }
 
-long do_sigreturn(CPUState *env)
+long do_sigreturn(CPUCRISState *env)
 {
 	struct target_signal_frame *frame;
 	abi_ulong frame_addr;
@@ -3620,7 +3623,7 @@ long do_sigreturn(CPUState *env)
 	force_sig(TARGET_SIGSEGV);
 }
 
-long do_rt_sigreturn(CPUState *env)
+long do_rt_sigreturn(CPUCRISState *env)
 {
     fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
     return -TARGET_ENOSYS;
@@ -3687,7 +3690,7 @@ typedef struct {
 } rt_sigframe;
 
 static inline abi_ulong
-get_sigframe(struct target_sigaction *ka, CPUState *env, size_t frame_size)
+get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size)
 {
     abi_ulong sp;
 
@@ -3712,7 +3715,7 @@ get_sigframe(struct target_sigaction *ka, CPUState *env, size_t frame_size)
     return (sp - frame_size) & -8ul;
 }
 
-static void save_sigregs(CPUState *env, target_sigregs *sregs)
+static void save_sigregs(CPUS390XState *env, target_sigregs *sregs)
 {
     int i;
     //save_access_regs(current->thread.acrs); FIXME
@@ -3738,7 +3741,7 @@ static void save_sigregs(CPUState *env, target_sigregs *sregs)
 }
 
 static void setup_frame(int sig, struct target_sigaction *ka,
-			target_sigset_t *set, CPUState *env)
+                        target_sigset_t *set, CPUS390XState *env)
 {
     sigframe *frame;
     abi_ulong frame_addr;
@@ -3805,7 +3808,7 @@ give_sigsegv:
 
 static void setup_rt_frame(int sig, struct target_sigaction *ka,
                            target_siginfo_t *info,
-                           target_sigset_t *set, CPUState *env)
+                           target_sigset_t *set, CPUS390XState *env)
 {
     int i;
     rt_sigframe *frame;
@@ -3869,7 +3872,7 @@ give_sigsegv:
 }
 
 static int
-restore_sigregs(CPUState *env, target_sigregs *sc)
+restore_sigregs(CPUS390XState *env, target_sigregs *sc)
 {
     int err = 0;
     int i;
@@ -3895,7 +3898,7 @@ restore_sigregs(CPUState *env, target_sigregs *sc)
     return err;
 }
 
-long do_sigreturn(CPUState *env)
+long do_sigreturn(CPUS390XState *env)
 {
     sigframe *frame;
     abi_ulong frame_addr = env->regs[15];
@@ -3927,7 +3930,7 @@ badframe:
     return 0;
 }
 
-long do_rt_sigreturn(CPUState *env)
+long do_rt_sigreturn(CPUS390XState *env)
 {
     rt_sigframe *frame;
     abi_ulong frame_addr = env->regs[15];
@@ -4107,7 +4110,7 @@ struct target_rt_sigframe {
 
 /* See arch/powerpc/kernel/signal.c.  */
 static target_ulong get_sigframe(struct target_sigaction *ka,
-                                 CPUState *env,
+                                 CPUPPCState *env,
                                  int frame_size)
 {
     target_ulong oldsp, newsp;
@@ -4125,7 +4128,7 @@ static target_ulong get_sigframe(struct target_sigaction *ka,
     return newsp;
 }
 
-static int save_user_regs(CPUState *env, struct target_mcontext *frame,
+static int save_user_regs(CPUPPCState *env, struct target_mcontext *frame,
                           int sigret)
 {
     target_ulong msr = env->msr;
@@ -4221,7 +4224,7 @@ static int save_user_regs(CPUState *env, struct target_mcontext *frame,
     return 0;
 }
 
-static int restore_user_regs(CPUState *env,
+static int restore_user_regs(CPUPPCState *env,
                              struct target_mcontext *frame, int sig)
 {
     target_ulong save_r2 = 0;
@@ -4320,7 +4323,7 @@ static int restore_user_regs(CPUState *env,
 }
 
 static void setup_frame(int sig, struct target_sigaction *ka,
-                        target_sigset_t *set, CPUState *env)
+                        target_sigset_t *set, CPUPPCState *env)
 {
     struct target_sigframe *frame;
     struct target_sigcontext *sc;
@@ -4382,7 +4385,7 @@ sigsegv:
 
 static void setup_rt_frame(int sig, struct target_sigaction *ka,
                            target_siginfo_t *info,
-                           target_sigset_t *set, CPUState *env)
+                           target_sigset_t *set, CPUPPCState *env)
 {
     struct target_rt_sigframe *rt_sf;
     struct target_mcontext *frame;
@@ -4450,7 +4453,7 @@ sigsegv:
 
 }
 
-long do_sigreturn(CPUState *env)
+long do_sigreturn(CPUPPCState *env)
 {
     struct target_sigcontext *sc = NULL;
     struct target_mcontext *sr = NULL;
@@ -4493,7 +4496,7 @@ sigsegv:
 }
 
 /* See arch/powerpc/kernel/signal_32.c.  */
-static int do_setcontext(struct target_ucontext *ucp, CPUState *env, int sig)
+static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
 {
     struct target_mcontext *mcp;
     target_ulong mcp_addr;
@@ -4528,7 +4531,7 @@ sigsegv:
 #endif
 }
 
-long do_rt_sigreturn(CPUState *env)
+long do_rt_sigreturn(CPUPPCState *env)
 {
     struct target_rt_sigframe *rt_sf = NULL;
     target_ulong rt_sf_addr;
@@ -4617,7 +4620,8 @@ struct target_rt_sigframe
 };
 
 static int
-setup_sigcontext(struct target_sigcontext *sc, CPUState *env, abi_ulong mask)
+setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
+                 abi_ulong mask)
 {
     int err = 0;
 
@@ -4634,7 +4638,7 @@ setup_sigcontext(struct target_sigcontext *sc, CPUState *env, abi_ulong mask)
 }
 
 static int
-restore_sigcontext(CPUState *env, struct target_sigcontext *sc, int *pd0)
+restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc, int *pd0)
 {
     int err = 0;
     int temp;
@@ -4656,7 +4660,8 @@ restore_sigcontext(CPUState *env, struct target_sigcontext *sc, int *pd0)
  * Determine which stack to use..
  */
 static inline abi_ulong
-get_sigframe(struct target_sigaction *ka, CPUState *regs, size_t frame_size)
+get_sigframe(struct target_sigaction *ka, CPUM68KState *regs,
+             size_t frame_size)
 {
     unsigned long sp;
 
@@ -4671,7 +4676,7 @@ get_sigframe(struct target_sigaction *ka, CPUState *regs, size_t frame_size)
 }
 
 static void setup_frame(int sig, struct target_sigaction *ka,
-			target_sigset_t *set, CPUState *env)
+                        target_sigset_t *set, CPUM68KState *env)
 {
     struct target_sigframe *frame;
     abi_ulong frame_addr;
@@ -4725,7 +4730,7 @@ give_sigsegv:
 }
 
 static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
-                                           CPUState *env)
+                                           CPUM68KState *env)
 {
     target_greg_t *gregs = uc->tuc_mcontext.gregs;
     int err;
@@ -4753,7 +4758,7 @@ static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
     return err;
 }
  
-static inline int target_rt_restore_ucontext(CPUState *env,
+static inline int target_rt_restore_ucontext(CPUM68KState *env,
                                              struct target_ucontext *uc,
                                              int *pd0)
 {
@@ -4795,7 +4800,7 @@ badframe:
 
 static void setup_rt_frame(int sig, struct target_sigaction *ka,
                            target_siginfo_t *info,
-			   target_sigset_t *set, CPUState *env)
+                           target_sigset_t *set, CPUM68KState *env)
 {
     struct target_rt_sigframe *frame;
     abi_ulong frame_addr;
@@ -4866,7 +4871,7 @@ give_sigsegv:
     force_sig(TARGET_SIGSEGV);
 }
 
-long do_sigreturn(CPUState *env)
+long do_sigreturn(CPUM68KState *env)
 {
     struct target_sigframe *frame;
     abi_ulong frame_addr = env->aregs[7] - 4;
@@ -4904,7 +4909,7 @@ badframe:
     return 0;
 }
 
-long do_rt_sigreturn(CPUState *env)
+long do_rt_sigreturn(CPUM68KState *env)
 {
     struct target_rt_sigframe *frame;
     abi_ulong frame_addr = env->aregs[7] - 4;
@@ -4985,7 +4990,7 @@ struct target_rt_sigframe {
 #define INSN_LDI_R0             0x201f0000
 #define INSN_CALLSYS            0x00000083
 
-static int setup_sigcontext(struct target_sigcontext *sc, CPUState *env,
+static int setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
                             abi_ulong frame_addr, target_sigset_t *set)
 {
     int i, err = 0;
@@ -5013,7 +5018,8 @@ static int setup_sigcontext(struct target_sigcontext *sc, CPUState *env,
     return err;
 }
 
-static int restore_sigcontext(CPUState *env, struct target_sigcontext *sc)
+static int restore_sigcontext(CPUAlphaState *env,
+                              struct target_sigcontext *sc)
 {
     uint64_t fpcr;
     int i, err = 0;
@@ -5034,7 +5040,8 @@ static int restore_sigcontext(CPUState *env, struct target_sigcontext *sc)
 }
 
 static inline abi_ulong get_sigframe(struct target_sigaction *sa,
-                                     CPUState *env, unsigned long framesize)
+                                     CPUAlphaState *env,
+                                     unsigned long framesize)
 {
     abi_ulong sp = env->ir[IR_SP];
 
@@ -5046,7 +5053,7 @@ static inline abi_ulong get_sigframe(struct target_sigaction *sa,
 }
 
 static void setup_frame(int sig, struct target_sigaction *ka,
-                        target_sigset_t *set, CPUState *env)
+                        target_sigset_t *set, CPUAlphaState *env)
 {
     abi_ulong frame_addr, r26;
     struct target_sigframe *frame;
@@ -5090,7 +5097,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
 
 static void setup_rt_frame(int sig, struct target_sigaction *ka,
                            target_siginfo_t *info,
-			   target_sigset_t *set, CPUState *env)
+                           target_sigset_t *set, CPUAlphaState *env)
 {
     abi_ulong frame_addr, r26;
     struct target_rt_sigframe *frame;
@@ -5144,7 +5151,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
     env->ir[IR_SP] = frame_addr;
 }
 
-long do_sigreturn(CPUState *env)
+long do_sigreturn(CPUAlphaState *env)
 {
     struct target_sigcontext *sc;
     abi_ulong sc_addr = env->ir[IR_A0];
@@ -5174,7 +5181,7 @@ long do_sigreturn(CPUState *env)
     force_sig(TARGET_SIGSEGV);
 }
 
-long do_rt_sigreturn(CPUState *env)
+long do_rt_sigreturn(CPUAlphaState *env)
 {
     abi_ulong frame_addr = env->ir[IR_A0];
     struct target_rt_sigframe *frame;
commit e544a19f8935e48bb90ecbba0e7e8faa7138c74a
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Feb 25 02:14:24 2012 +0100

    hw/mc146818: Drop unneeded #includes
    
    pc.h and apic.h are not needed; apic.h would drag in x86 CPUState and
    is now included directly for TARGET_I386.
    
    isa.h is already #included from mc146818rtc.h.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 8b5cf8c..2b59c36 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -24,8 +24,6 @@
 #include "hw.h"
 #include "qemu-timer.h"
 #include "sysemu.h"
-#include "pc.h"
-#include "isa.h"
 #include "mc146818rtc.h"
 
 #ifdef TARGET_I386
commit 15ecee74053afb3901e557d190d006451f6a0977
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu Feb 16 00:12:24 2012 +0100

    target-unicore32: Rename to CPUUniCore32State
    
    This aids in refactoring CPUState by adopting the common naming scheme.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-unicore32/cpu.h b/target-unicore32/cpu.h
index f725634..923db05 100644
--- a/target-unicore32/cpu.h
+++ b/target-unicore32/cpu.h
@@ -18,7 +18,7 @@
 
 #define ELF_MACHINE             EM_UNICORE32
 
-#define CPUState                struct CPUState_UniCore32
+#define CPUState                struct CPUUniCore32State
 
 #include "config.h"
 #include "qemu-common.h"
@@ -27,7 +27,7 @@
 
 #define NB_MMU_MODES            2
 
-typedef struct CPUState_UniCore32 {
+typedef struct CPUUniCore32State {
     /* Regs for current mode.  */
     uint32_t regs[32];
     /* Frequently accessed ASR bits are stored separately for efficiently.
@@ -71,7 +71,7 @@ typedef struct CPUState_UniCore32 {
     /* Internal CPU feature flags.  */
     uint32_t features;
 
-} CPUState_UniCore32;
+} CPUUniCore32State;
 
 #define ASR_M                   (0x1f)
 #define ASR_MODE_USER           (0x10)
@@ -179,7 +179,7 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
 
 void uc32_translate_init(void);
 void do_interrupt(CPUState *);
-void switch_mode(CPUState_UniCore32 *, int);
+void switch_mode(CPUUniCore32State *, int);
 
 static inline bool cpu_has_work(CPUState *env)
 {
commit cb15982158d62ea017f1ad584370176b586e1873
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri Feb 24 17:15:27 2012 +0100

    target-sparc: Typedef struct CPUSPARCState early
    
    Will be needed for qemu_irq_ack callback.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 38a7074..8098669 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -378,7 +378,9 @@ struct QEMUFile;
 void cpu_put_timer(struct QEMUFile *f, CPUTimer *s);
 void cpu_get_timer(struct QEMUFile *f, CPUTimer *s);
 
-typedef struct CPUSPARCState {
+typedef struct CPUSPARCState CPUSPARCState;
+
+struct CPUSPARCState {
     target_ulong gregs[8]; /* general registers */
     target_ulong *regwptr; /* pointer to current register window */
     target_ulong pc;       /* program counter */
@@ -503,7 +505,7 @@ typedef struct CPUSPARCState {
 
     /* Leon3 cache control */
     uint32_t cache_control;
-} CPUSPARCState;
+};
 
 #ifndef NO_CPU_IO_DEFS
 /* cpu_init.c */
commit 9b9a970a23625de4ae6b7461906a9a0d98d3ca95
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri Feb 24 16:59:17 2012 +0100

    target-lm32/microblaze: Typedef struct CPU{MB,LM32}State
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index b6b6b4c..cc9b53b 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -28,6 +28,7 @@
 #include "qemu-common.h"
 #include "cpu-defs.h"
 struct CPULM32State;
+typedef struct CPULM32State CPULM32State;
 
 #define TARGET_HAS_ICE 1
 
diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index 4092506..94ec43b 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -29,6 +29,7 @@
 #include "cpu-defs.h"
 #include "softfloat.h"
 struct CPUMBState;
+typedef struct CPUMBState CPUMBState;
 #if !defined(CONFIG_USER_ONLY)
 #include "mmu.h"
 #endif
commit f3840919e9c8a43ab2ca1138368f5ee38cce5da1
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon Feb 20 06:44:56 2012 +0100

    monitor: Avoid CPUState in read/write functions
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/gdbstub.c b/gdbstub.c
index ef95ac2..b5ec362 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -533,7 +533,7 @@ static const int gpr_map32[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
 #define IDX_XMM_REGS    (IDX_FP_REGS + 16)
 #define IDX_MXCSR_REG   (IDX_XMM_REGS + CPU_NB_REGS)
 
-static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_read_register(CPUX86State *env, uint8_t *mem_buf, int n)
 {
     if (n < CPU_NB_REGS) {
         if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
@@ -590,7 +590,7 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int cpu_x86_gdb_load_seg(CPUState *env, int sreg, uint8_t *mem_buf)
+static int cpu_x86_gdb_load_seg(CPUX86State *env, int sreg, uint8_t *mem_buf)
 {
     uint16_t selector = ldl_p(mem_buf);
 
@@ -615,7 +615,7 @@ static int cpu_x86_gdb_load_seg(CPUState *env, int sreg, uint8_t *mem_buf)
     return 4;
 }
 
-static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_write_register(CPUX86State *env, uint8_t *mem_buf, int n)
 {
     uint32_t tmp;
 
@@ -703,7 +703,7 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 #define GDB_CORE_XML "power-core.xml"
 #endif
 
-static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_read_register(CPUPPCState *env, uint8_t *mem_buf, int n)
 {
     if (n < 32) {
         /* gprs */
@@ -740,7 +740,7 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_write_register(CPUPPCState *env, uint8_t *mem_buf, int n)
 {
     if (n < 32) {
         /* gprs */
@@ -801,7 +801,7 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 #define GET_REGA(val) GET_REGL(val)
 #endif
 
-static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_read_register(CPUSPARCState *env, uint8_t *mem_buf, int n)
 {
     if (n < 8) {
         /* g0..g7 */
@@ -860,7 +860,7 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_write_register(CPUSPARCState *env, uint8_t *mem_buf, int n)
 {
 #if defined(TARGET_ABI32)
     abi_ulong tmp;
@@ -944,7 +944,7 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 #define NUM_CORE_REGS 26
 #define GDB_CORE_XML "arm-core.xml"
 
-static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_read_register(CPUARMState *env, uint8_t *mem_buf, int n)
 {
     if (n < 16) {
         /* Core integer register.  */
@@ -971,7 +971,7 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_write_register(CPUARMState *env, uint8_t *mem_buf, int n)
 {
     uint32_t tmp;
 
@@ -1014,7 +1014,7 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 
 #define GDB_CORE_XML "cf-core.xml"
 
-static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_read_register(CPUM68KState *env, uint8_t *mem_buf, int n)
 {
     if (n < 8) {
         /* D0-D7 */
@@ -1033,7 +1033,7 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_write_register(CPUM68KState *env, uint8_t *mem_buf, int n)
 {
     uint32_t tmp;
 
@@ -1058,7 +1058,7 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 
 #define NUM_CORE_REGS 73
 
-static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_read_register(CPUMIPSState *env, uint8_t *mem_buf, int n)
 {
     if (n < 32) {
         GET_REGL(env->active_tc.gpr[n]);
@@ -1104,7 +1104,7 @@ static unsigned int ieee_rm[] =
 #define RESTORE_ROUNDING_MODE \
     set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], &env->active_fpu.fp_status)
 
-static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_write_register(CPUMIPSState *env, uint8_t *mem_buf, int n)
 {
     target_ulong tmp;
 
@@ -1163,7 +1163,7 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 
 #define NUM_CORE_REGS 59
 
-static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_read_register(CPUSH4State *env, uint8_t *mem_buf, int n)
 {
     if (n < 8) {
         if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) {
@@ -1197,7 +1197,7 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_write_register(CPUSH4State *env, uint8_t *mem_buf, int n)
 {
     uint32_t tmp;
 
@@ -1244,7 +1244,7 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 
 #define NUM_CORE_REGS (32 + 5)
 
-static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_read_register(CPUMBState *env, uint8_t *mem_buf, int n)
 {
     if (n < 32) {
 	GET_REG32(env->regs[n]);
@@ -1254,7 +1254,7 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_write_register(CPUMBState *env, uint8_t *mem_buf, int n)
 {
     uint32_t tmp;
 
@@ -1275,7 +1275,7 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 #define NUM_CORE_REGS 49
 
 static int
-read_register_crisv10(CPUState *env, uint8_t *mem_buf, int n)
+read_register_crisv10(CPUCRISState *env, uint8_t *mem_buf, int n)
 {
     if (n < 15) {
         GET_REG32(env->regs[n]);
@@ -1307,7 +1307,7 @@ read_register_crisv10(CPUState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_read_register(CPUCRISState *env, uint8_t *mem_buf, int n)
 {
     uint8_t srs;
 
@@ -1337,7 +1337,7 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_write_register(CPUCRISState *env, uint8_t *mem_buf, int n)
 {
     uint32_t tmp;
 
@@ -1370,7 +1370,7 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 
 #define NUM_CORE_REGS 67
 
-static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_read_register(CPUAlphaState *env, uint8_t *mem_buf, int n)
 {
     uint64_t val;
     CPU_DoubleU d;
@@ -1404,7 +1404,7 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
     GET_REGL(val);
 }
 
-static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_write_register(CPUAlphaState *env, uint8_t *mem_buf, int n)
 {
     target_ulong tmp = ldtul_p(mem_buf);
     CPU_DoubleU d;
@@ -1440,7 +1440,7 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 
 #define NUM_CORE_REGS S390_NUM_TOTAL_REGS
 
-static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_read_register(CPUS390XState *env, uint8_t *mem_buf, int n)
 {
     switch (n) {
         case S390_PSWM_REGNUM: GET_REGL(env->psw.mask); break;
@@ -1464,7 +1464,7 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_write_register(CPUS390XState *env, uint8_t *mem_buf, int n)
 {
     target_ulong tmpl;
     uint32_t tmp32;
@@ -1494,7 +1494,7 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 #include "hw/lm32_pic.h"
 #define NUM_CORE_REGS (32 + 7)
 
-static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_read_register(CPULM32State *env, uint8_t *mem_buf, int n)
 {
     if (n < 32) {
         GET_REG32(env->regs[n]);
@@ -1527,7 +1527,7 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_write_register(CPULM32State *env, uint8_t *mem_buf, int n)
 {
     uint32_t tmp;
 
@@ -1573,7 +1573,7 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 #define NUM_CORE_REGS (env->config->gdb_regmap.num_regs)
 #define num_g_regs NUM_CORE_REGS
 
-static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_read_register(CPUXtensaState *env, uint8_t *mem_buf, int n)
 {
     const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n;
 
@@ -1610,7 +1610,7 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
     }
 }
 
-static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
+static int cpu_gdb_write_register(CPUXtensaState *env, uint8_t *mem_buf, int n)
 {
     uint32_t tmp;
     const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n;
commit e59d167fe42cfc46dd23d09686dd9bed0e3124de
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu Feb 16 00:40:47 2012 +0100

    monitor: Don't access registers through CPUState
    
    Use CPUX86State etc. instead (hand-converted).
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/monitor.c b/monitor.c
index cbdfbad..e3b72ff 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2696,30 +2696,30 @@ static const MonitorDef monitor_defs[] = {
 #ifdef TARGET_I386
 
 #define SEG(name, seg) \
-    { name, offsetof(CPUState, segs[seg].selector), NULL, MD_I32 },\
-    { name ".base", offsetof(CPUState, segs[seg].base) },\
-    { name ".limit", offsetof(CPUState, segs[seg].limit), NULL, MD_I32 },
-
-    { "eax", offsetof(CPUState, regs[0]) },
-    { "ecx", offsetof(CPUState, regs[1]) },
-    { "edx", offsetof(CPUState, regs[2]) },
-    { "ebx", offsetof(CPUState, regs[3]) },
-    { "esp|sp", offsetof(CPUState, regs[4]) },
-    { "ebp|fp", offsetof(CPUState, regs[5]) },
-    { "esi", offsetof(CPUState, regs[6]) },
-    { "edi", offsetof(CPUState, regs[7]) },
+    { name, offsetof(CPUX86State, segs[seg].selector), NULL, MD_I32 },\
+    { name ".base", offsetof(CPUX86State, segs[seg].base) },\
+    { name ".limit", offsetof(CPUX86State, segs[seg].limit), NULL, MD_I32 },
+
+    { "eax", offsetof(CPUX86State, regs[0]) },
+    { "ecx", offsetof(CPUX86State, regs[1]) },
+    { "edx", offsetof(CPUX86State, regs[2]) },
+    { "ebx", offsetof(CPUX86State, regs[3]) },
+    { "esp|sp", offsetof(CPUX86State, regs[4]) },
+    { "ebp|fp", offsetof(CPUX86State, regs[5]) },
+    { "esi", offsetof(CPUX86State, regs[6]) },
+    { "edi", offsetof(CPUX86State, regs[7]) },
 #ifdef TARGET_X86_64
-    { "r8", offsetof(CPUState, regs[8]) },
-    { "r9", offsetof(CPUState, regs[9]) },
-    { "r10", offsetof(CPUState, regs[10]) },
-    { "r11", offsetof(CPUState, regs[11]) },
-    { "r12", offsetof(CPUState, regs[12]) },
-    { "r13", offsetof(CPUState, regs[13]) },
-    { "r14", offsetof(CPUState, regs[14]) },
-    { "r15", offsetof(CPUState, regs[15]) },
+    { "r8", offsetof(CPUX86State, regs[8]) },
+    { "r9", offsetof(CPUX86State, regs[9]) },
+    { "r10", offsetof(CPUX86State, regs[10]) },
+    { "r11", offsetof(CPUX86State, regs[11]) },
+    { "r12", offsetof(CPUX86State, regs[12]) },
+    { "r13", offsetof(CPUX86State, regs[13]) },
+    { "r14", offsetof(CPUX86State, regs[14]) },
+    { "r15", offsetof(CPUX86State, regs[15]) },
 #endif
-    { "eflags", offsetof(CPUState, eflags) },
-    { "eip", offsetof(CPUState, eip) },
+    { "eflags", offsetof(CPUX86State, eflags) },
+    { "eip", offsetof(CPUX86State, eip) },
     SEG("cs", R_CS)
     SEG("ds", R_DS)
     SEG("es", R_ES)
@@ -2729,76 +2729,76 @@ static const MonitorDef monitor_defs[] = {
     { "pc", 0, monitor_get_pc, },
 #elif defined(TARGET_PPC)
     /* General purpose registers */
-    { "r0", offsetof(CPUState, gpr[0]) },
-    { "r1", offsetof(CPUState, gpr[1]) },
-    { "r2", offsetof(CPUState, gpr[2]) },
-    { "r3", offsetof(CPUState, gpr[3]) },
-    { "r4", offsetof(CPUState, gpr[4]) },
-    { "r5", offsetof(CPUState, gpr[5]) },
-    { "r6", offsetof(CPUState, gpr[6]) },
-    { "r7", offsetof(CPUState, gpr[7]) },
-    { "r8", offsetof(CPUState, gpr[8]) },
-    { "r9", offsetof(CPUState, gpr[9]) },
-    { "r10", offsetof(CPUState, gpr[10]) },
-    { "r11", offsetof(CPUState, gpr[11]) },
-    { "r12", offsetof(CPUState, gpr[12]) },
-    { "r13", offsetof(CPUState, gpr[13]) },
-    { "r14", offsetof(CPUState, gpr[14]) },
-    { "r15", offsetof(CPUState, gpr[15]) },
-    { "r16", offsetof(CPUState, gpr[16]) },
-    { "r17", offsetof(CPUState, gpr[17]) },
-    { "r18", offsetof(CPUState, gpr[18]) },
-    { "r19", offsetof(CPUState, gpr[19]) },
-    { "r20", offsetof(CPUState, gpr[20]) },
-    { "r21", offsetof(CPUState, gpr[21]) },
-    { "r22", offsetof(CPUState, gpr[22]) },
-    { "r23", offsetof(CPUState, gpr[23]) },
-    { "r24", offsetof(CPUState, gpr[24]) },
-    { "r25", offsetof(CPUState, gpr[25]) },
-    { "r26", offsetof(CPUState, gpr[26]) },
-    { "r27", offsetof(CPUState, gpr[27]) },
-    { "r28", offsetof(CPUState, gpr[28]) },
-    { "r29", offsetof(CPUState, gpr[29]) },
-    { "r30", offsetof(CPUState, gpr[30]) },
-    { "r31", offsetof(CPUState, gpr[31]) },
+    { "r0", offsetof(CPUPPCState, gpr[0]) },
+    { "r1", offsetof(CPUPPCState, gpr[1]) },
+    { "r2", offsetof(CPUPPCState, gpr[2]) },
+    { "r3", offsetof(CPUPPCState, gpr[3]) },
+    { "r4", offsetof(CPUPPCState, gpr[4]) },
+    { "r5", offsetof(CPUPPCState, gpr[5]) },
+    { "r6", offsetof(CPUPPCState, gpr[6]) },
+    { "r7", offsetof(CPUPPCState, gpr[7]) },
+    { "r8", offsetof(CPUPPCState, gpr[8]) },
+    { "r9", offsetof(CPUPPCState, gpr[9]) },
+    { "r10", offsetof(CPUPPCState, gpr[10]) },
+    { "r11", offsetof(CPUPPCState, gpr[11]) },
+    { "r12", offsetof(CPUPPCState, gpr[12]) },
+    { "r13", offsetof(CPUPPCState, gpr[13]) },
+    { "r14", offsetof(CPUPPCState, gpr[14]) },
+    { "r15", offsetof(CPUPPCState, gpr[15]) },
+    { "r16", offsetof(CPUPPCState, gpr[16]) },
+    { "r17", offsetof(CPUPPCState, gpr[17]) },
+    { "r18", offsetof(CPUPPCState, gpr[18]) },
+    { "r19", offsetof(CPUPPCState, gpr[19]) },
+    { "r20", offsetof(CPUPPCState, gpr[20]) },
+    { "r21", offsetof(CPUPPCState, gpr[21]) },
+    { "r22", offsetof(CPUPPCState, gpr[22]) },
+    { "r23", offsetof(CPUPPCState, gpr[23]) },
+    { "r24", offsetof(CPUPPCState, gpr[24]) },
+    { "r25", offsetof(CPUPPCState, gpr[25]) },
+    { "r26", offsetof(CPUPPCState, gpr[26]) },
+    { "r27", offsetof(CPUPPCState, gpr[27]) },
+    { "r28", offsetof(CPUPPCState, gpr[28]) },
+    { "r29", offsetof(CPUPPCState, gpr[29]) },
+    { "r30", offsetof(CPUPPCState, gpr[30]) },
+    { "r31", offsetof(CPUPPCState, gpr[31]) },
     /* Floating point registers */
-    { "f0", offsetof(CPUState, fpr[0]) },
-    { "f1", offsetof(CPUState, fpr[1]) },
-    { "f2", offsetof(CPUState, fpr[2]) },
-    { "f3", offsetof(CPUState, fpr[3]) },
-    { "f4", offsetof(CPUState, fpr[4]) },
-    { "f5", offsetof(CPUState, fpr[5]) },
-    { "f6", offsetof(CPUState, fpr[6]) },
-    { "f7", offsetof(CPUState, fpr[7]) },
-    { "f8", offsetof(CPUState, fpr[8]) },
-    { "f9", offsetof(CPUState, fpr[9]) },
-    { "f10", offsetof(CPUState, fpr[10]) },
-    { "f11", offsetof(CPUState, fpr[11]) },
-    { "f12", offsetof(CPUState, fpr[12]) },
-    { "f13", offsetof(CPUState, fpr[13]) },
-    { "f14", offsetof(CPUState, fpr[14]) },
-    { "f15", offsetof(CPUState, fpr[15]) },
-    { "f16", offsetof(CPUState, fpr[16]) },
-    { "f17", offsetof(CPUState, fpr[17]) },
-    { "f18", offsetof(CPUState, fpr[18]) },
-    { "f19", offsetof(CPUState, fpr[19]) },
-    { "f20", offsetof(CPUState, fpr[20]) },
-    { "f21", offsetof(CPUState, fpr[21]) },
-    { "f22", offsetof(CPUState, fpr[22]) },
-    { "f23", offsetof(CPUState, fpr[23]) },
-    { "f24", offsetof(CPUState, fpr[24]) },
-    { "f25", offsetof(CPUState, fpr[25]) },
-    { "f26", offsetof(CPUState, fpr[26]) },
-    { "f27", offsetof(CPUState, fpr[27]) },
-    { "f28", offsetof(CPUState, fpr[28]) },
-    { "f29", offsetof(CPUState, fpr[29]) },
-    { "f30", offsetof(CPUState, fpr[30]) },
-    { "f31", offsetof(CPUState, fpr[31]) },
-    { "fpscr", offsetof(CPUState, fpscr) },
+    { "f0", offsetof(CPUPPCState, fpr[0]) },
+    { "f1", offsetof(CPUPPCState, fpr[1]) },
+    { "f2", offsetof(CPUPPCState, fpr[2]) },
+    { "f3", offsetof(CPUPPCState, fpr[3]) },
+    { "f4", offsetof(CPUPPCState, fpr[4]) },
+    { "f5", offsetof(CPUPPCState, fpr[5]) },
+    { "f6", offsetof(CPUPPCState, fpr[6]) },
+    { "f7", offsetof(CPUPPCState, fpr[7]) },
+    { "f8", offsetof(CPUPPCState, fpr[8]) },
+    { "f9", offsetof(CPUPPCState, fpr[9]) },
+    { "f10", offsetof(CPUPPCState, fpr[10]) },
+    { "f11", offsetof(CPUPPCState, fpr[11]) },
+    { "f12", offsetof(CPUPPCState, fpr[12]) },
+    { "f13", offsetof(CPUPPCState, fpr[13]) },
+    { "f14", offsetof(CPUPPCState, fpr[14]) },
+    { "f15", offsetof(CPUPPCState, fpr[15]) },
+    { "f16", offsetof(CPUPPCState, fpr[16]) },
+    { "f17", offsetof(CPUPPCState, fpr[17]) },
+    { "f18", offsetof(CPUPPCState, fpr[18]) },
+    { "f19", offsetof(CPUPPCState, fpr[19]) },
+    { "f20", offsetof(CPUPPCState, fpr[20]) },
+    { "f21", offsetof(CPUPPCState, fpr[21]) },
+    { "f22", offsetof(CPUPPCState, fpr[22]) },
+    { "f23", offsetof(CPUPPCState, fpr[23]) },
+    { "f24", offsetof(CPUPPCState, fpr[24]) },
+    { "f25", offsetof(CPUPPCState, fpr[25]) },
+    { "f26", offsetof(CPUPPCState, fpr[26]) },
+    { "f27", offsetof(CPUPPCState, fpr[27]) },
+    { "f28", offsetof(CPUPPCState, fpr[28]) },
+    { "f29", offsetof(CPUPPCState, fpr[29]) },
+    { "f30", offsetof(CPUPPCState, fpr[30]) },
+    { "f31", offsetof(CPUPPCState, fpr[31]) },
+    { "fpscr", offsetof(CPUPPCState, fpscr) },
     /* Next instruction pointer */
-    { "nip|pc", offsetof(CPUState, nip) },
-    { "lr", offsetof(CPUState, lr) },
-    { "ctr", offsetof(CPUState, ctr) },
+    { "nip|pc", offsetof(CPUPPCState, nip) },
+    { "lr", offsetof(CPUPPCState, lr) },
+    { "ctr", offsetof(CPUPPCState, ctr) },
     { "decr", 0, &monitor_get_decr, },
     { "ccr", 0, &monitor_get_ccr, },
     /* Machine state register */
@@ -2808,105 +2808,105 @@ static const MonitorDef monitor_defs[] = {
     { "tbl", 0, &monitor_get_tbl, },
 #if defined(TARGET_PPC64)
     /* Address space register */
-    { "asr", offsetof(CPUState, asr) },
+    { "asr", offsetof(CPUPPCState, asr) },
 #endif
     /* Segment registers */
-    { "sdr1", offsetof(CPUState, spr[SPR_SDR1]) },
-    { "sr0", offsetof(CPUState, sr[0]) },
-    { "sr1", offsetof(CPUState, sr[1]) },
-    { "sr2", offsetof(CPUState, sr[2]) },
-    { "sr3", offsetof(CPUState, sr[3]) },
-    { "sr4", offsetof(CPUState, sr[4]) },
-    { "sr5", offsetof(CPUState, sr[5]) },
-    { "sr6", offsetof(CPUState, sr[6]) },
-    { "sr7", offsetof(CPUState, sr[7]) },
-    { "sr8", offsetof(CPUState, sr[8]) },
-    { "sr9", offsetof(CPUState, sr[9]) },
-    { "sr10", offsetof(CPUState, sr[10]) },
-    { "sr11", offsetof(CPUState, sr[11]) },
-    { "sr12", offsetof(CPUState, sr[12]) },
-    { "sr13", offsetof(CPUState, sr[13]) },
-    { "sr14", offsetof(CPUState, sr[14]) },
-    { "sr15", offsetof(CPUState, sr[15]) },
+    { "sdr1", offsetof(CPUPPCState, spr[SPR_SDR1]) },
+    { "sr0", offsetof(CPUPPCState, sr[0]) },
+    { "sr1", offsetof(CPUPPCState, sr[1]) },
+    { "sr2", offsetof(CPUPPCState, sr[2]) },
+    { "sr3", offsetof(CPUPPCState, sr[3]) },
+    { "sr4", offsetof(CPUPPCState, sr[4]) },
+    { "sr5", offsetof(CPUPPCState, sr[5]) },
+    { "sr6", offsetof(CPUPPCState, sr[6]) },
+    { "sr7", offsetof(CPUPPCState, sr[7]) },
+    { "sr8", offsetof(CPUPPCState, sr[8]) },
+    { "sr9", offsetof(CPUPPCState, sr[9]) },
+    { "sr10", offsetof(CPUPPCState, sr[10]) },
+    { "sr11", offsetof(CPUPPCState, sr[11]) },
+    { "sr12", offsetof(CPUPPCState, sr[12]) },
+    { "sr13", offsetof(CPUPPCState, sr[13]) },
+    { "sr14", offsetof(CPUPPCState, sr[14]) },
+    { "sr15", offsetof(CPUPPCState, sr[15]) },
     /* Too lazy to put BATs... */
-    { "pvr", offsetof(CPUState, spr[SPR_PVR]) },
-
-    { "srr0", offsetof(CPUState, spr[SPR_SRR0]) },
-    { "srr1", offsetof(CPUState, spr[SPR_SRR1]) },
-    { "sprg0", offsetof(CPUState, spr[SPR_SPRG0]) },
-    { "sprg1", offsetof(CPUState, spr[SPR_SPRG1]) },
-    { "sprg2", offsetof(CPUState, spr[SPR_SPRG2]) },
-    { "sprg3", offsetof(CPUState, spr[SPR_SPRG3]) },
-    { "sprg4", offsetof(CPUState, spr[SPR_SPRG4]) },
-    { "sprg5", offsetof(CPUState, spr[SPR_SPRG5]) },
-    { "sprg6", offsetof(CPUState, spr[SPR_SPRG6]) },
-    { "sprg7", offsetof(CPUState, spr[SPR_SPRG7]) },
-    { "pid", offsetof(CPUState, spr[SPR_BOOKE_PID]) },
-    { "csrr0", offsetof(CPUState, spr[SPR_BOOKE_CSRR0]) },
-    { "csrr1", offsetof(CPUState, spr[SPR_BOOKE_CSRR1]) },
-    { "esr", offsetof(CPUState, spr[SPR_BOOKE_ESR]) },
-    { "dear", offsetof(CPUState, spr[SPR_BOOKE_DEAR]) },
-    { "mcsr", offsetof(CPUState, spr[SPR_BOOKE_MCSR]) },
-    { "tsr", offsetof(CPUState, spr[SPR_BOOKE_TSR]) },
-    { "tcr", offsetof(CPUState, spr[SPR_BOOKE_TCR]) },
-    { "vrsave", offsetof(CPUState, spr[SPR_VRSAVE]) },
-    { "pir", offsetof(CPUState, spr[SPR_BOOKE_PIR]) },
-    { "mcsrr0", offsetof(CPUState, spr[SPR_BOOKE_MCSRR0]) },
-    { "mcsrr1", offsetof(CPUState, spr[SPR_BOOKE_MCSRR1]) },
-    { "decar", offsetof(CPUState, spr[SPR_BOOKE_DECAR]) },
-    { "ivpr", offsetof(CPUState, spr[SPR_BOOKE_IVPR]) },
-    { "epcr", offsetof(CPUState, spr[SPR_BOOKE_EPCR]) },
-    { "sprg8", offsetof(CPUState, spr[SPR_BOOKE_SPRG8]) },
-    { "ivor0", offsetof(CPUState, spr[SPR_BOOKE_IVOR0]) },
-    { "ivor1", offsetof(CPUState, spr[SPR_BOOKE_IVOR1]) },
-    { "ivor2", offsetof(CPUState, spr[SPR_BOOKE_IVOR2]) },
-    { "ivor3", offsetof(CPUState, spr[SPR_BOOKE_IVOR3]) },
-    { "ivor4", offsetof(CPUState, spr[SPR_BOOKE_IVOR4]) },
-    { "ivor5", offsetof(CPUState, spr[SPR_BOOKE_IVOR5]) },
-    { "ivor6", offsetof(CPUState, spr[SPR_BOOKE_IVOR6]) },
-    { "ivor7", offsetof(CPUState, spr[SPR_BOOKE_IVOR7]) },
-    { "ivor8", offsetof(CPUState, spr[SPR_BOOKE_IVOR8]) },
-    { "ivor9", offsetof(CPUState, spr[SPR_BOOKE_IVOR9]) },
-    { "ivor10", offsetof(CPUState, spr[SPR_BOOKE_IVOR10]) },
-    { "ivor11", offsetof(CPUState, spr[SPR_BOOKE_IVOR11]) },
-    { "ivor12", offsetof(CPUState, spr[SPR_BOOKE_IVOR12]) },
-    { "ivor13", offsetof(CPUState, spr[SPR_BOOKE_IVOR13]) },
-    { "ivor14", offsetof(CPUState, spr[SPR_BOOKE_IVOR14]) },
-    { "ivor15", offsetof(CPUState, spr[SPR_BOOKE_IVOR15]) },
-    { "ivor32", offsetof(CPUState, spr[SPR_BOOKE_IVOR32]) },
-    { "ivor33", offsetof(CPUState, spr[SPR_BOOKE_IVOR33]) },
-    { "ivor34", offsetof(CPUState, spr[SPR_BOOKE_IVOR34]) },
-    { "ivor35", offsetof(CPUState, spr[SPR_BOOKE_IVOR35]) },
-    { "ivor36", offsetof(CPUState, spr[SPR_BOOKE_IVOR36]) },
-    { "ivor37", offsetof(CPUState, spr[SPR_BOOKE_IVOR37]) },
-    { "mas0", offsetof(CPUState, spr[SPR_BOOKE_MAS0]) },
-    { "mas1", offsetof(CPUState, spr[SPR_BOOKE_MAS1]) },
-    { "mas2", offsetof(CPUState, spr[SPR_BOOKE_MAS2]) },
-    { "mas3", offsetof(CPUState, spr[SPR_BOOKE_MAS3]) },
-    { "mas4", offsetof(CPUState, spr[SPR_BOOKE_MAS4]) },
-    { "mas6", offsetof(CPUState, spr[SPR_BOOKE_MAS6]) },
-    { "mas7", offsetof(CPUState, spr[SPR_BOOKE_MAS7]) },
-    { "mmucfg", offsetof(CPUState, spr[SPR_MMUCFG]) },
-    { "tlb0cfg", offsetof(CPUState, spr[SPR_BOOKE_TLB0CFG]) },
-    { "tlb1cfg", offsetof(CPUState, spr[SPR_BOOKE_TLB1CFG]) },
-    { "epr", offsetof(CPUState, spr[SPR_BOOKE_EPR]) },
-    { "eplc", offsetof(CPUState, spr[SPR_BOOKE_EPLC]) },
-    { "epsc", offsetof(CPUState, spr[SPR_BOOKE_EPSC]) },
-    { "svr", offsetof(CPUState, spr[SPR_E500_SVR]) },
-    { "mcar", offsetof(CPUState, spr[SPR_Exxx_MCAR]) },
-    { "pid1", offsetof(CPUState, spr[SPR_BOOKE_PID1]) },
-    { "pid2", offsetof(CPUState, spr[SPR_BOOKE_PID2]) },
-    { "hid0", offsetof(CPUState, spr[SPR_HID0]) },
+    { "pvr", offsetof(CPUPPCState, spr[SPR_PVR]) },
+
+    { "srr0", offsetof(CPUPPCState, spr[SPR_SRR0]) },
+    { "srr1", offsetof(CPUPPCState, spr[SPR_SRR1]) },
+    { "sprg0", offsetof(CPUPPCState, spr[SPR_SPRG0]) },
+    { "sprg1", offsetof(CPUPPCState, spr[SPR_SPRG1]) },
+    { "sprg2", offsetof(CPUPPCState, spr[SPR_SPRG2]) },
+    { "sprg3", offsetof(CPUPPCState, spr[SPR_SPRG3]) },
+    { "sprg4", offsetof(CPUPPCState, spr[SPR_SPRG4]) },
+    { "sprg5", offsetof(CPUPPCState, spr[SPR_SPRG5]) },
+    { "sprg6", offsetof(CPUPPCState, spr[SPR_SPRG6]) },
+    { "sprg7", offsetof(CPUPPCState, spr[SPR_SPRG7]) },
+    { "pid", offsetof(CPUPPCState, spr[SPR_BOOKE_PID]) },
+    { "csrr0", offsetof(CPUPPCState, spr[SPR_BOOKE_CSRR0]) },
+    { "csrr1", offsetof(CPUPPCState, spr[SPR_BOOKE_CSRR1]) },
+    { "esr", offsetof(CPUPPCState, spr[SPR_BOOKE_ESR]) },
+    { "dear", offsetof(CPUPPCState, spr[SPR_BOOKE_DEAR]) },
+    { "mcsr", offsetof(CPUPPCState, spr[SPR_BOOKE_MCSR]) },
+    { "tsr", offsetof(CPUPPCState, spr[SPR_BOOKE_TSR]) },
+    { "tcr", offsetof(CPUPPCState, spr[SPR_BOOKE_TCR]) },
+    { "vrsave", offsetof(CPUPPCState, spr[SPR_VRSAVE]) },
+    { "pir", offsetof(CPUPPCState, spr[SPR_BOOKE_PIR]) },
+    { "mcsrr0", offsetof(CPUPPCState, spr[SPR_BOOKE_MCSRR0]) },
+    { "mcsrr1", offsetof(CPUPPCState, spr[SPR_BOOKE_MCSRR1]) },
+    { "decar", offsetof(CPUPPCState, spr[SPR_BOOKE_DECAR]) },
+    { "ivpr", offsetof(CPUPPCState, spr[SPR_BOOKE_IVPR]) },
+    { "epcr", offsetof(CPUPPCState, spr[SPR_BOOKE_EPCR]) },
+    { "sprg8", offsetof(CPUPPCState, spr[SPR_BOOKE_SPRG8]) },
+    { "ivor0", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR0]) },
+    { "ivor1", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR1]) },
+    { "ivor2", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR2]) },
+    { "ivor3", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR3]) },
+    { "ivor4", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR4]) },
+    { "ivor5", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR5]) },
+    { "ivor6", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR6]) },
+    { "ivor7", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR7]) },
+    { "ivor8", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR8]) },
+    { "ivor9", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR9]) },
+    { "ivor10", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR10]) },
+    { "ivor11", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR11]) },
+    { "ivor12", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR12]) },
+    { "ivor13", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR13]) },
+    { "ivor14", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR14]) },
+    { "ivor15", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR15]) },
+    { "ivor32", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR32]) },
+    { "ivor33", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR33]) },
+    { "ivor34", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR34]) },
+    { "ivor35", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR35]) },
+    { "ivor36", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR36]) },
+    { "ivor37", offsetof(CPUPPCState, spr[SPR_BOOKE_IVOR37]) },
+    { "mas0", offsetof(CPUPPCState, spr[SPR_BOOKE_MAS0]) },
+    { "mas1", offsetof(CPUPPCState, spr[SPR_BOOKE_MAS1]) },
+    { "mas2", offsetof(CPUPPCState, spr[SPR_BOOKE_MAS2]) },
+    { "mas3", offsetof(CPUPPCState, spr[SPR_BOOKE_MAS3]) },
+    { "mas4", offsetof(CPUPPCState, spr[SPR_BOOKE_MAS4]) },
+    { "mas6", offsetof(CPUPPCState, spr[SPR_BOOKE_MAS6]) },
+    { "mas7", offsetof(CPUPPCState, spr[SPR_BOOKE_MAS7]) },
+    { "mmucfg", offsetof(CPUPPCState, spr[SPR_MMUCFG]) },
+    { "tlb0cfg", offsetof(CPUPPCState, spr[SPR_BOOKE_TLB0CFG]) },
+    { "tlb1cfg", offsetof(CPUPPCState, spr[SPR_BOOKE_TLB1CFG]) },
+    { "epr", offsetof(CPUPPCState, spr[SPR_BOOKE_EPR]) },
+    { "eplc", offsetof(CPUPPCState, spr[SPR_BOOKE_EPLC]) },
+    { "epsc", offsetof(CPUPPCState, spr[SPR_BOOKE_EPSC]) },
+    { "svr", offsetof(CPUPPCState, spr[SPR_E500_SVR]) },
+    { "mcar", offsetof(CPUPPCState, spr[SPR_Exxx_MCAR]) },
+    { "pid1", offsetof(CPUPPCState, spr[SPR_BOOKE_PID1]) },
+    { "pid2", offsetof(CPUPPCState, spr[SPR_BOOKE_PID2]) },
+    { "hid0", offsetof(CPUPPCState, spr[SPR_HID0]) },
 
 #elif defined(TARGET_SPARC)
-    { "g0", offsetof(CPUState, gregs[0]) },
-    { "g1", offsetof(CPUState, gregs[1]) },
-    { "g2", offsetof(CPUState, gregs[2]) },
-    { "g3", offsetof(CPUState, gregs[3]) },
-    { "g4", offsetof(CPUState, gregs[4]) },
-    { "g5", offsetof(CPUState, gregs[5]) },
-    { "g6", offsetof(CPUState, gregs[6]) },
-    { "g7", offsetof(CPUState, gregs[7]) },
+    { "g0", offsetof(CPUSPARCState, gregs[0]) },
+    { "g1", offsetof(CPUSPARCState, gregs[1]) },
+    { "g2", offsetof(CPUSPARCState, gregs[2]) },
+    { "g3", offsetof(CPUSPARCState, gregs[3]) },
+    { "g4", offsetof(CPUSPARCState, gregs[4]) },
+    { "g5", offsetof(CPUSPARCState, gregs[5]) },
+    { "g6", offsetof(CPUSPARCState, gregs[6]) },
+    { "g7", offsetof(CPUSPARCState, gregs[7]) },
     { "o0", 0, monitor_get_reg },
     { "o1", 1, monitor_get_reg },
     { "o2", 2, monitor_get_reg },
@@ -2931,72 +2931,72 @@ static const MonitorDef monitor_defs[] = {
     { "i5", 21, monitor_get_reg },
     { "i6", 22, monitor_get_reg },
     { "i7", 23, monitor_get_reg },
-    { "pc", offsetof(CPUState, pc) },
-    { "npc", offsetof(CPUState, npc) },
-    { "y", offsetof(CPUState, y) },
+    { "pc", offsetof(CPUSPARCState, pc) },
+    { "npc", offsetof(CPUSPARCState, npc) },
+    { "y", offsetof(CPUSPARCState, y) },
 #ifndef TARGET_SPARC64
     { "psr", 0, &monitor_get_psr, },
-    { "wim", offsetof(CPUState, wim) },
+    { "wim", offsetof(CPUSPARCState, wim) },
 #endif
-    { "tbr", offsetof(CPUState, tbr) },
-    { "fsr", offsetof(CPUState, fsr) },
-    { "f0", offsetof(CPUState, fpr[0].l.upper) },
-    { "f1", offsetof(CPUState, fpr[0].l.lower) },
-    { "f2", offsetof(CPUState, fpr[1].l.upper) },
-    { "f3", offsetof(CPUState, fpr[1].l.lower) },
-    { "f4", offsetof(CPUState, fpr[2].l.upper) },
-    { "f5", offsetof(CPUState, fpr[2].l.lower) },
-    { "f6", offsetof(CPUState, fpr[3].l.upper) },
-    { "f7", offsetof(CPUState, fpr[3].l.lower) },
-    { "f8", offsetof(CPUState, fpr[4].l.upper) },
-    { "f9", offsetof(CPUState, fpr[4].l.lower) },
-    { "f10", offsetof(CPUState, fpr[5].l.upper) },
-    { "f11", offsetof(CPUState, fpr[5].l.lower) },
-    { "f12", offsetof(CPUState, fpr[6].l.upper) },
-    { "f13", offsetof(CPUState, fpr[6].l.lower) },
-    { "f14", offsetof(CPUState, fpr[7].l.upper) },
-    { "f15", offsetof(CPUState, fpr[7].l.lower) },
-    { "f16", offsetof(CPUState, fpr[8].l.upper) },
-    { "f17", offsetof(CPUState, fpr[8].l.lower) },
-    { "f18", offsetof(CPUState, fpr[9].l.upper) },
-    { "f19", offsetof(CPUState, fpr[9].l.lower) },
-    { "f20", offsetof(CPUState, fpr[10].l.upper) },
-    { "f21", offsetof(CPUState, fpr[10].l.lower) },
-    { "f22", offsetof(CPUState, fpr[11].l.upper) },
-    { "f23", offsetof(CPUState, fpr[11].l.lower) },
-    { "f24", offsetof(CPUState, fpr[12].l.upper) },
-    { "f25", offsetof(CPUState, fpr[12].l.lower) },
-    { "f26", offsetof(CPUState, fpr[13].l.upper) },
-    { "f27", offsetof(CPUState, fpr[13].l.lower) },
-    { "f28", offsetof(CPUState, fpr[14].l.upper) },
-    { "f29", offsetof(CPUState, fpr[14].l.lower) },
-    { "f30", offsetof(CPUState, fpr[15].l.upper) },
-    { "f31", offsetof(CPUState, fpr[15].l.lower) },
+    { "tbr", offsetof(CPUSPARCState, tbr) },
+    { "fsr", offsetof(CPUSPARCState, fsr) },
+    { "f0", offsetof(CPUSPARCState, fpr[0].l.upper) },
+    { "f1", offsetof(CPUSPARCState, fpr[0].l.lower) },
+    { "f2", offsetof(CPUSPARCState, fpr[1].l.upper) },
+    { "f3", offsetof(CPUSPARCState, fpr[1].l.lower) },
+    { "f4", offsetof(CPUSPARCState, fpr[2].l.upper) },
+    { "f5", offsetof(CPUSPARCState, fpr[2].l.lower) },
+    { "f6", offsetof(CPUSPARCState, fpr[3].l.upper) },
+    { "f7", offsetof(CPUSPARCState, fpr[3].l.lower) },
+    { "f8", offsetof(CPUSPARCState, fpr[4].l.upper) },
+    { "f9", offsetof(CPUSPARCState, fpr[4].l.lower) },
+    { "f10", offsetof(CPUSPARCState, fpr[5].l.upper) },
+    { "f11", offsetof(CPUSPARCState, fpr[5].l.lower) },
+    { "f12", offsetof(CPUSPARCState, fpr[6].l.upper) },
+    { "f13", offsetof(CPUSPARCState, fpr[6].l.lower) },
+    { "f14", offsetof(CPUSPARCState, fpr[7].l.upper) },
+    { "f15", offsetof(CPUSPARCState, fpr[7].l.lower) },
+    { "f16", offsetof(CPUSPARCState, fpr[8].l.upper) },
+    { "f17", offsetof(CPUSPARCState, fpr[8].l.lower) },
+    { "f18", offsetof(CPUSPARCState, fpr[9].l.upper) },
+    { "f19", offsetof(CPUSPARCState, fpr[9].l.lower) },
+    { "f20", offsetof(CPUSPARCState, fpr[10].l.upper) },
+    { "f21", offsetof(CPUSPARCState, fpr[10].l.lower) },
+    { "f22", offsetof(CPUSPARCState, fpr[11].l.upper) },
+    { "f23", offsetof(CPUSPARCState, fpr[11].l.lower) },
+    { "f24", offsetof(CPUSPARCState, fpr[12].l.upper) },
+    { "f25", offsetof(CPUSPARCState, fpr[12].l.lower) },
+    { "f26", offsetof(CPUSPARCState, fpr[13].l.upper) },
+    { "f27", offsetof(CPUSPARCState, fpr[13].l.lower) },
+    { "f28", offsetof(CPUSPARCState, fpr[14].l.upper) },
+    { "f29", offsetof(CPUSPARCState, fpr[14].l.lower) },
+    { "f30", offsetof(CPUSPARCState, fpr[15].l.upper) },
+    { "f31", offsetof(CPUSPARCState, fpr[15].l.lower) },
 #ifdef TARGET_SPARC64
-    { "f32", offsetof(CPUState, fpr[16]) },
-    { "f34", offsetof(CPUState, fpr[17]) },
-    { "f36", offsetof(CPUState, fpr[18]) },
-    { "f38", offsetof(CPUState, fpr[19]) },
-    { "f40", offsetof(CPUState, fpr[20]) },
-    { "f42", offsetof(CPUState, fpr[21]) },
-    { "f44", offsetof(CPUState, fpr[22]) },
-    { "f46", offsetof(CPUState, fpr[23]) },
-    { "f48", offsetof(CPUState, fpr[24]) },
-    { "f50", offsetof(CPUState, fpr[25]) },
-    { "f52", offsetof(CPUState, fpr[26]) },
-    { "f54", offsetof(CPUState, fpr[27]) },
-    { "f56", offsetof(CPUState, fpr[28]) },
-    { "f58", offsetof(CPUState, fpr[29]) },
-    { "f60", offsetof(CPUState, fpr[30]) },
-    { "f62", offsetof(CPUState, fpr[31]) },
-    { "asi", offsetof(CPUState, asi) },
-    { "pstate", offsetof(CPUState, pstate) },
-    { "cansave", offsetof(CPUState, cansave) },
-    { "canrestore", offsetof(CPUState, canrestore) },
-    { "otherwin", offsetof(CPUState, otherwin) },
-    { "wstate", offsetof(CPUState, wstate) },
-    { "cleanwin", offsetof(CPUState, cleanwin) },
-    { "fprs", offsetof(CPUState, fprs) },
+    { "f32", offsetof(CPUSPARCState, fpr[16]) },
+    { "f34", offsetof(CPUSPARCState, fpr[17]) },
+    { "f36", offsetof(CPUSPARCState, fpr[18]) },
+    { "f38", offsetof(CPUSPARCState, fpr[19]) },
+    { "f40", offsetof(CPUSPARCState, fpr[20]) },
+    { "f42", offsetof(CPUSPARCState, fpr[21]) },
+    { "f44", offsetof(CPUSPARCState, fpr[22]) },
+    { "f46", offsetof(CPUSPARCState, fpr[23]) },
+    { "f48", offsetof(CPUSPARCState, fpr[24]) },
+    { "f50", offsetof(CPUSPARCState, fpr[25]) },
+    { "f52", offsetof(CPUSPARCState, fpr[26]) },
+    { "f54", offsetof(CPUSPARCState, fpr[27]) },
+    { "f56", offsetof(CPUSPARCState, fpr[28]) },
+    { "f58", offsetof(CPUSPARCState, fpr[29]) },
+    { "f60", offsetof(CPUSPARCState, fpr[30]) },
+    { "f62", offsetof(CPUSPARCState, fpr[31]) },
+    { "asi", offsetof(CPUSPARCState, asi) },
+    { "pstate", offsetof(CPUSPARCState, pstate) },
+    { "cansave", offsetof(CPUSPARCState, cansave) },
+    { "canrestore", offsetof(CPUSPARCState, canrestore) },
+    { "otherwin", offsetof(CPUSPARCState, otherwin) },
+    { "wstate", offsetof(CPUSPARCState, wstate) },
+    { "cleanwin", offsetof(CPUSPARCState, cleanwin) },
+    { "fprs", offsetof(CPUSPARCState, fprs) },
 #endif
 #endif
     { NULL },
commit 1bba0dc932e8826a7d030df3767daf0bc339f9a2
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Feb 8 03:03:33 2012 +0100

    Rename cpu_reset() to cpu_state_reset()
    
    Frees the identifier cpu_reset for QOM CPUs (manual rename).
    
    Don't hide the parameter type behind explicit casts, use static
    functions with strongly typed argument to indirect.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/bsd-user/main.c b/bsd-user/main.c
index cdb0d0a..c3af395 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -917,7 +917,7 @@ int main(int argc, char **argv)
         exit(1);
     }
 #if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
-    cpu_reset(env);
+    cpu_state_reset(env);
 #endif
     thread_env = env;
 
diff --git a/cpu-all.h b/cpu-all.h
index f7f6e7a..e831ae0 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -433,7 +433,7 @@ void cpu_watchpoint_remove_all(CPUState *env, int mask);
 #define SSTEP_NOTIMER 0x4  /* Do not Timers while single stepping */
 
 void cpu_single_step(CPUState *env, int enabled);
-void cpu_reset(CPUState *s);
+void cpu_state_reset(CPUState *s);
 int cpu_is_stopped(CPUState *env);
 void run_on_cpu(CPUState *env, void (*func)(void *data), void *data);
 
diff --git a/cpu-exec.c b/cpu-exec.c
index 3d28053..2bf1735 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -340,7 +340,7 @@ int cpu_exec(CPUState *env)
                     }
 #elif defined(TARGET_PPC)
                     if ((interrupt_request & CPU_INTERRUPT_RESET)) {
-                        cpu_reset(env);
+                        cpu_state_reset(env);
                     }
                     if (interrupt_request & CPU_INTERRUPT_HARD) {
                         ppc_hw_interrupt(env);
diff --git a/darwin-user/main.c b/darwin-user/main.c
index e1519c7..13c1f05 100644
--- a/darwin-user/main.c
+++ b/darwin-user/main.c
@@ -858,7 +858,7 @@ int main(int argc, char **argv)
     /* NOTE: we need to init the CPU at this stage to get
        qemu_host_page_size */
     env = cpu_init(cpu_model);
-    cpu_reset(env);
+    cpu_state_reset(env);
 
     printf("Starting %s with qemu\n----------------\n", filename);
 
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index fc66910..23b3f0a 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -277,7 +277,7 @@ static void do_cpu_reset(void *opaque)
     CPUState *env = opaque;
     const struct arm_boot_info *info = env->boot_info;
 
-    cpu_reset(env);
+    cpu_state_reset(env);
     if (info) {
         if (!info->is_linux) {
             /* Jump to the entry point.  */
diff --git a/hw/armv7m.c b/hw/armv7m.c
index 6b80579..9cf96f4 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -149,7 +149,7 @@ static void armv7m_bitband_init(void)
 
 static void armv7m_reset(void *opaque)
 {
-    cpu_reset((CPUState *)opaque);
+    cpu_state_reset((CPUState *)opaque);
 }
 
 /* Init CPU and memory for a v7-M based board.
diff --git a/hw/cris-boot.c b/hw/cris-boot.c
index 37894f8..ade517d 100644
--- a/hw/cris-boot.c
+++ b/hw/cris-boot.c
@@ -34,7 +34,7 @@ static void main_cpu_reset(void *opaque)
 
     li = env->load_info;
 
-    cpu_reset(env);
+    cpu_state_reset(env);
 
     if (!li) {
         /* nothing more to do.  */
diff --git a/hw/leon3.c b/hw/leon3.c
index 71d79a6..1dc5a02 100644
--- a/hw/leon3.c
+++ b/hw/leon3.c
@@ -51,7 +51,7 @@ static void main_cpu_reset(void *opaque)
     ResetData *s   = (ResetData *)opaque;
     CPUState  *env = s->env;
 
-    cpu_reset(env);
+    cpu_state_reset(env);
 
     env->halted = 0;
     env->pc     = s->entry;
diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c
index 3cdf120..51c8a0f 100644
--- a/hw/lm32_boards.c
+++ b/hw/lm32_boards.c
@@ -56,7 +56,7 @@ static void main_cpu_reset(void *opaque)
     ResetInfo *reset_info = opaque;
     CPUState *env = reset_info->env;
 
-    cpu_reset(env);
+    cpu_state_reset(env);
 
     /* init defaults */
     env->pc = (uint32_t)reset_info->bootstrap_pc;
diff --git a/hw/microblaze_boot.c b/hw/microblaze_boot.c
index b2f96df..7ce04dc 100644
--- a/hw/microblaze_boot.c
+++ b/hw/microblaze_boot.c
@@ -45,7 +45,7 @@ static void main_cpu_reset(void *opaque)
 {
     CPUState *env = opaque;
 
-    cpu_reset(env);
+    cpu_state_reset(env);
     env->regs[5] = boot_info.cmdline;
     env->regs[7] = boot_info.fdt;
     env->sregs[SR_PC] = boot_info.bootstrap_pc;
diff --git a/hw/milkymist.c b/hw/milkymist.c
index eaef0c2..7ec6554 100644
--- a/hw/milkymist.c
+++ b/hw/milkymist.c
@@ -61,7 +61,7 @@ static void main_cpu_reset(void *opaque)
     ResetInfo *reset_info = opaque;
     CPUState *env = reset_info->env;
 
-    cpu_reset(env);
+    cpu_state_reset(env);
 
     /* init defaults */
     env->pc = reset_info->bootstrap_pc;
diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c
index efdfdc2..dae488a 100644
--- a/hw/mips_fulong2e.c
+++ b/hw/mips_fulong2e.c
@@ -200,7 +200,7 @@ static void main_cpu_reset(void *opaque)
 {
     CPUState *env = opaque;
 
-    cpu_reset(env);
+    cpu_state_reset(env);
     /* TODO: 2E reset stuff */
     if (loaderparams.kernel_filename) {
         env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index 2b4678e..d5f1b34 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -51,7 +51,7 @@ enum jazz_model_e
 static void main_cpu_reset(void *opaque)
 {
     CPUState *env = opaque;
-    cpu_reset(env);
+    cpu_state_reset(env);
 }
 
 static uint64_t rtc_read(void *opaque, target_phys_addr_t addr, unsigned size)
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 866699d..3335e11 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -745,7 +745,7 @@ static void malta_mips_config(CPUState *env)
 static void main_cpu_reset(void *opaque)
 {
     CPUState *env = opaque;
-    cpu_reset(env);
+    cpu_state_reset(env);
 
     /* The bootloader does not need to be rewritten as it is located in a
        read only location. The kernel location and the arguments table
diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
index 76c95b2..1fe4ac5 100644
--- a/hw/mips_mipssim.c
+++ b/hw/mips_mipssim.c
@@ -107,7 +107,7 @@ static void main_cpu_reset(void *opaque)
     ResetData *s = (ResetData *)opaque;
     CPUState *env = s->env;
 
-    cpu_reset(env);
+    cpu_state_reset(env);
     env->active_tc.PC = s->vector & ~(target_ulong)1;
     if (s->vector & 1) {
         env->hflags |= MIPS_HFLAG_M16;
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index 83401f0..96ad808 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -145,7 +145,7 @@ static void main_cpu_reset(void *opaque)
     ResetData *s = (ResetData *)opaque;
     CPUState *env = s->env;
 
-    cpu_reset(env);
+    cpu_state_reset(env);
     env->active_tc.PC = s->vector;
 }
 
diff --git a/hw/omap1.c b/hw/omap1.c
index 1aa5f23..5317b9b 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -3702,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_reset(mpu->env);
+    cpu_state_reset(mpu->env);
 }
 
 static const struct omap_map_s {
diff --git a/hw/omap2.c b/hw/omap2.c
index a6851b0..157defb 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -2224,7 +2224,7 @@ static void omap2_mpu_reset(void *opaque)
     omap_mcspi_reset(mpu->mcspi[1]);
     omap_i2c_reset(mpu->i2c[0]);
     omap_i2c_reset(mpu->i2c[1]);
-    cpu_reset(mpu->env);
+    cpu_state_reset(mpu->env);
 }
 
 static int omap2_validate_addr(struct omap_mpu_state_s *s,
diff --git a/hw/pc.c b/hw/pc.c
index bb9867b..aca4460 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -928,7 +928,7 @@ static void pc_cpu_reset(void *opaque)
 {
     CPUState *env = opaque;
 
-    cpu_reset(env);
+    cpu_state_reset(env);
     env->halted = !cpu_is_bsp(env);
 }
 
diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
index f86b168..835e36d 100644
--- a/hw/ppc440_bamboo.c
+++ b/hw/ppc440_bamboo.c
@@ -147,7 +147,7 @@ static void main_cpu_reset(void *opaque)
 {
     CPUState *env = opaque;
 
-    cpu_reset(env);
+    cpu_state_reset(env);
     env->gpr[1] = (16<<20) - 8;
     env->gpr[3] = FDT_ADDR;
     env->nip = entry;
diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
index 26040ac..2311162 100644
--- a/hw/ppc4xx_devs.c
+++ b/hw/ppc4xx_devs.c
@@ -38,6 +38,13 @@
 #  define LOG_UIC(...) do { } while (0)
 #endif
 
+static void ppc4xx_reset(void *opaque)
+{
+    CPUState *env = opaque;
+
+    cpu_state_reset(env);
+}
+
 /*****************************************************************************/
 /* Generic PowerPC 4xx processor instantiation */
 CPUState *ppc4xx_init (const char *cpu_model,
@@ -60,7 +67,7 @@ CPUState *ppc4xx_init (const char *cpu_model,
     tb_clk->opaque = env;
     ppc_dcr_init(env, NULL, NULL);
     /* Register qemu callbacks */
-    qemu_register_reset((QEMUResetHandler*)&cpu_reset, env);
+    qemu_register_reset(ppc4xx_reset, env);
 
     return env;
 }
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index 2fec5b4..ee50652 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -121,6 +121,13 @@ static target_phys_addr_t round_page(target_phys_addr_t addr)
     return (addr + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
 }
 
+static void ppc_core99_reset(void *opaque)
+{
+    CPUState *env = opaque;
+
+    cpu_state_reset(env);
+}
+
 /* PowerPC Mac99 hardware initialisation */
 static void ppc_core99_init (ram_addr_t ram_size,
                              const char *boot_device,
@@ -166,7 +173,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((QEMUResetHandler*)&cpu_reset, env);
+        qemu_register_reset(ppc_core99_reset, env);
     }
 
     /* allocate RAM */
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index 49c2c97..be70124 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -65,6 +65,13 @@ static target_phys_addr_t round_page(target_phys_addr_t addr)
     return (addr + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
 }
 
+static void ppc_heathrow_reset(void *opaque)
+{
+    CPUState *env = opaque;
+
+    cpu_state_reset(env);
+}
+
 static void ppc_heathrow_init (ram_addr_t ram_size,
                                const char *boot_device,
                                const char *kernel_filename,
@@ -104,7 +111,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((QEMUResetHandler*)&cpu_reset, env);
+        qemu_register_reset(ppc_heathrow_reset, env);
     }
 
     /* allocate RAM */
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index dc9edd7..6ccd6fa 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -470,6 +470,13 @@ static void cpu_request_exit(void *opaque, int irq, int level)
     }
 }
 
+static void ppc_prep_reset(void *opaque)
+{
+    CPUState *env = opaque;
+
+    cpu_state_reset(env);
+}
+
 /* PowerPC PREP hardware initialisation */
 static void ppc_prep_init (ram_addr_t ram_size,
                            const char *boot_device,
@@ -524,7 +531,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((QEMUResetHandler*)&cpu_reset, env);
+        qemu_register_reset(ppc_prep_reset, env);
     }
 
     /* allocate RAM */
diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index d69f78c..752aed9 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -198,7 +198,7 @@ static void mpc8544ds_cpu_reset_sec(void *opaque)
 {
     CPUState *env = opaque;
 
-    cpu_reset(env);
+    cpu_state_reset(env);
 
     /* Secondary CPU starts in halted state for now. Needs to change when
        implementing non-kernel boot. */
@@ -211,7 +211,7 @@ static void mpc8544ds_cpu_reset(void *opaque)
     CPUState *env = opaque;
     struct boot_info *bi = env->load_info;
 
-    cpu_reset(env);
+    cpu_state_reset(env);
 
     /* Set initial guest state. */
     env->halted = 0;
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 1ab2701..f552877 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -2045,7 +2045,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_reset(s->env);
+        cpu_state_reset(s->env);
         /* TODO: reset peripherals */
     }
 }
diff --git a/hw/r2d.c b/hw/r2d.c
index c80f9e3..ae327a7 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -201,7 +201,7 @@ static void main_cpu_reset(void *opaque)
     ResetData *s = (ResetData *)opaque;
     CPUState *env = s->env;
 
-    cpu_reset(env);
+    cpu_state_reset(env);
     env->pc = s->vector;
 }
 
diff --git a/hw/spapr.c b/hw/spapr.c
index dffb6a2..3f9d87c 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -502,6 +502,13 @@ static void spapr_reset(void *opaque)
 
 }
 
+static void spapr_cpu_reset(void *opaque)
+{
+    CPUState *env = opaque;
+
+    cpu_state_reset(env);
+}
+
 /* pSeries LPAR / sPAPR hardware init */
 static void ppc_spapr_init(ram_addr_t ram_size,
                            const char *boot_device,
@@ -560,7 +567,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((QEMUResetHandler *)&cpu_reset, env);
+        qemu_register_reset(spapr_cpu_reset, env);
 
         env->hreset_vector = 0x60;
         env->hreset_excp_prefix = 0;
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 99fb219..4045740 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -283,7 +283,7 @@ static void main_cpu_reset(void *opaque)
 {
     CPUState *env = opaque;
 
-    cpu_reset(env);
+    cpu_state_reset(env);
     env->halted = 0;
 }
 
@@ -291,7 +291,7 @@ static void secondary_cpu_reset(void *opaque)
 {
     CPUState *env = opaque;
 
-    cpu_reset(env);
+    cpu_state_reset(env);
     env->halted = 1;
 }
 
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 423108f..8b043f2 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -376,7 +376,7 @@ static void main_cpu_reset(void *opaque)
     CPUState *env = s->env;
     static unsigned int nr_resets;
 
-    cpu_reset(env);
+    cpu_state_reset(env);
 
     cpu_timer_reset(env->tick);
     cpu_timer_reset(env->stick);
diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c
index f8d2b1b..e672490 100644
--- a/hw/virtex_ml507.c
+++ b/hw/virtex_ml507.c
@@ -109,7 +109,7 @@ static void main_cpu_reset(void *opaque)
     CPUState *env = opaque;
     struct boot_info *bi = env->load_info;
 
-    cpu_reset(env);
+    cpu_state_reset(env);
     /* Linux Kernel Parameters (passing device tree):
        *   r3: pointer to the fdt
        *   r4: 0
diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c
index 26112c3..80ba4d7 100644
--- a/hw/xtensa_lx60.c
+++ b/hw/xtensa_lx60.c
@@ -146,9 +146,11 @@ static uint64_t translate_phys_addr(void *env, uint64_t addr)
     return cpu_get_phys_page_debug(env, addr);
 }
 
-static void lx60_reset(void *env)
+static void lx60_reset(void *opaque)
 {
-    cpu_reset(env);
+    CPUState *env = opaque;
+
+    cpu_state_reset(env);
 }
 
 static void lx_init(const LxBoardDesc *board,
@@ -183,7 +185,7 @@ static void lx_init(const LxBoardDesc *board,
         /* Need MMU initialized prior to ELF loading,
          * so that ELF gets loaded into virtual addresses
          */
-        cpu_reset(env);
+        cpu_state_reset(env);
     }
 
     ram = g_malloc(sizeof(*ram));
diff --git a/hw/xtensa_sim.c b/hw/xtensa_sim.c
index 104e5dc..445cfde 100644
--- a/hw/xtensa_sim.c
+++ b/hw/xtensa_sim.c
@@ -39,7 +39,7 @@ static uint64_t translate_phys_addr(void *env, uint64_t addr)
 
 static void sim_reset(void *env)
 {
-    cpu_reset(env);
+    cpu_state_reset(env);
 }
 
 static void sim_init(ram_addr_t ram_size,
diff --git a/linux-user/main.c b/linux-user/main.c
index bd47489..01129f2 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3375,7 +3375,7 @@ int main(int argc, char **argv, char **envp)
         exit(1);
     }
 #if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
-    cpu_reset(env);
+    cpu_state_reset(env);
 #endif
 
     thread_env = env;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 8a11213..29888bd 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4036,7 +4036,7 @@ static int do_fork(CPUState *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_reset(new_env);
+        cpu_state_reset(new_env);
 #endif
         /* Init regs that differ from the parent.  */
         cpu_clone_regs(new_env, newsp);
diff --git a/target-arm/helper.c b/target-arm/helper.c
index abe1c30..13ff474 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -278,7 +278,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     }
 }
 
-void cpu_reset(CPUARMState *env)
+void cpu_state_reset(CPUARMState *env)
 {
     uint32_t id;
     uint32_t tmp = 0;
@@ -416,7 +416,7 @@ CPUARMState *cpu_arm_init(const char *cpu_model)
 
     env->cpu_model_str = cpu_model;
     env->cp15.c0_cpuid = id;
-    cpu_reset(env);
+    cpu_state_reset(env);
     if (arm_feature(env, ARM_FEATURE_NEON)) {
         gdb_register_coprocessor(env, vfp_gdb_get_reg, vfp_gdb_set_reg,
                                  51, "arm-neon.xml", 0);
diff --git a/target-cris/translate.c b/target-cris/translate.c
index cbdc72c..f360c31 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3513,7 +3513,7 @@ CPUCRISState *cpu_cris_init (const char *cpu_model)
 
 	env->pregs[PR_VR] = vr_by_name(cpu_model);
 	cpu_exec_init(env);
-	cpu_reset(env);
+    cpu_state_reset(env);
 	qemu_init_vcpu(env);
 
 	if (tcg_initialized)
@@ -3573,7 +3573,7 @@ CPUCRISState *cpu_cris_init (const char *cpu_model)
 	return env;
 }
 
-void cpu_reset (CPUCRISState *env)
+void cpu_state_reset(CPUCRISState *env)
 {
 	uint32_t vr;
 
diff --git a/target-i386/helper.c b/target-i386/helper.c
index f4f3c27..140c696 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -27,7 +27,7 @@
 //#define DEBUG_MMU
 
 /* NOTE: must be called outside the CPU execute loop */
-void cpu_reset(CPUX86State *env)
+void cpu_state_reset(CPUState *env)
 {
     int i;
 
@@ -1282,7 +1282,7 @@ void do_cpu_init(CPUState *env)
     int sipi = env->interrupt_request & CPU_INTERRUPT_SIPI;
     uint64_t pat = env->pat;
 
-    cpu_reset(env);
+    cpu_state_reset(env);
     env->interrupt_request = sipi;
     env->pat = pat;
     apic_init_reset(env->apic_state);
diff --git a/target-lm32/helper.c b/target-lm32/helper.c
index 2637c03..6834401 100644
--- a/target-lm32/helper.c
+++ b/target-lm32/helper.c
@@ -212,7 +212,7 @@ CPUState *cpu_lm32_init(const char *cpu_model)
     env->flags = 0;
 
     cpu_exec_init(env);
-    cpu_reset(env);
+    cpu_state_reset(env);
     qemu_init_vcpu(env);
 
     if (!tcg_initialized) {
@@ -235,7 +235,7 @@ void cpu_lm32_set_phys_msb_ignore(CPUState *env, int value)
     }
 }
 
-void cpu_reset(CPUState *env)
+void cpu_state_reset(CPUState *env)
 {
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
         qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index fa675bf..3647366 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -143,7 +143,7 @@ static int cpu_m68k_set_model(CPUM68KState *env, const char *name)
     return 0;
 }
 
-void cpu_reset(CPUM68KState *env)
+void cpu_state_reset(CPUM68KState *env)
 {
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
         qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
@@ -181,7 +181,7 @@ CPUM68KState *cpu_m68k_init(const char *cpu_model)
         return NULL;
     }
 
-    cpu_reset(env);
+    cpu_state_reset(env);
     qemu_init_vcpu(env);
     return env;
 }
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 725c2dd..e34e88d 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1897,7 +1897,7 @@ CPUState *cpu_mb_init (const char *cpu_model)
     env = g_malloc0(sizeof(CPUState));
 
     cpu_exec_init(env);
-    cpu_reset(env);
+    cpu_state_reset(env);
     qemu_init_vcpu(env);
     set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
 
@@ -1939,7 +1939,7 @@ CPUState *cpu_mb_init (const char *cpu_model)
     return env;
 }
 
-void cpu_reset (CPUState *env)
+void cpu_state_reset(CPUState *env)
 {
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
         qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 7225616..4d1cf98 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -452,7 +452,7 @@ void do_interrupt (CPUState *env)
         set_hflags_for_handler(env);
         break;
     case EXCP_RESET:
-        cpu_reset(env);
+        cpu_state_reset(env);
         break;
     case EXCP_SRESET:
         env->CP0_Status |= (1 << CP0St_SR);
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 8361d88..5061e78 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -12708,12 +12708,12 @@ CPUMIPSState *cpu_mips_init (const char *cpu_model)
     fpu_init(env, def);
     mvp_init(env, def);
     mips_tcg_init();
-    cpu_reset(env);
+    cpu_state_reset(env);
     qemu_init_vcpu(env);
     return env;
 }
 
-void cpu_reset (CPUMIPSState *env)
+void cpu_state_reset(CPUMIPSState *env)
 {
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
         qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index bb76a8b..f4552e8 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -3136,7 +3136,7 @@ void cpu_dump_rfi (target_ulong RA, target_ulong msr)
              TARGET_FMT_lx "\n", RA, msr);
 }
 
-void cpu_reset(CPUPPCState *env)
+void cpu_state_reset(CPUPPCState *env)
 {
     target_ulong msr;
 
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index c0ec890..1a1cc0e 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -95,7 +95,7 @@ CPUS390XState *cpu_s390x_init(const char *cpu_model)
     env->cpu_model_str = cpu_model;
     env->cpu_num = cpu_num++;
     env->ext_index = -1;
-    cpu_reset(env);
+    cpu_state_reset(env);
     qemu_init_vcpu(env);
     return env;
 }
@@ -119,7 +119,7 @@ int cpu_s390x_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
 
 #endif /* CONFIG_USER_ONLY */
 
-void cpu_reset(CPUS390XState *env)
+void cpu_state_reset(CPUS390XState *env)
 {
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
         qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index dd0ee4b..c385de8 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -178,7 +178,7 @@ void cpu_dump_state(CPUState * env, FILE * f,
     }
 }
 
-void cpu_reset(CPUSH4State * env)
+void cpu_state_reset(CPUSH4State *env)
 {
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
         qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
@@ -279,7 +279,7 @@ CPUSH4State *cpu_sh4_init(const char *cpu_model)
     env->movcal_backup_tail = &(env->movcal_backup);
     sh4_translate_init();
     env->cpu_model_str = cpu_model;
-    cpu_reset(env);
+    cpu_state_reset(env);
     cpu_register(env, def);
     qemu_init_vcpu(env);
     return env;
diff --git a/target-sparc/cpu_init.c b/target-sparc/cpu_init.c
index c7269b5..bb8b761 100644
--- a/target-sparc/cpu_init.c
+++ b/target-sparc/cpu_init.c
@@ -23,7 +23,7 @@
 
 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
 
-void cpu_reset(CPUSPARCState *env)
+void cpu_state_reset(CPUSPARCState *env)
 {
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
         qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index 42a559f..077c20a 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -35,7 +35,7 @@
 
 static void reset_mmu(CPUState *env);
 
-void cpu_reset(CPUXtensaState *env)
+void cpu_state_reset(CPUXtensaState *env)
 {
     env->exception_taken = 0;
     env->pc = env->config->exception_vector[EXC_RESET];
commit fc0b2c0f1a8eb679d28763832f3223259bf37b34
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Feb 21 19:41:59 2012 +0100

    PPC: 405: Use proper CPU reset
    
    On ppc405ep there is a register that allows for software to reset the
    core, but not the whole system. Implement this reset using a reset
    interrupt.
    
    This gets rid of a bunch of #if 0'ed code.
    
    Reported-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/cpu-exec.c b/cpu-exec.c
index 2c2d24e..3d28053 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -339,11 +339,9 @@ int cpu_exec(CPUState *env)
                         }
                     }
 #elif defined(TARGET_PPC)
-#if 0
                     if ((interrupt_request & CPU_INTERRUPT_RESET)) {
                         cpu_reset(env);
                     }
-#endif
                     if (interrupt_request & CPU_INTERRUPT_HARD) {
                         ppc_hw_interrupt(env);
                         if (env->pending_interrupts == 0)
diff --git a/hw/ppc.c b/hw/ppc.c
index 59882e2..a9516f1 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -131,13 +131,7 @@ static void ppc6xx_set_irq (void *opaque, int pin, int level)
             /* Level sensitive - active low */
             if (level) {
                 LOG_IRQ("%s: reset the CPU\n", __func__);
-                env->interrupt_request |= CPU_INTERRUPT_EXITTB;
-                /* XXX: TOFIX */
-#if 0
-                cpu_reset(env);
-#else
-                qemu_system_reset_request();
-#endif
+                cpu_interrupt(env, CPU_INTERRUPT_RESET);
             }
             break;
         case PPC6xx_INPUT_SRESET:
@@ -214,10 +208,7 @@ static void ppc970_set_irq (void *opaque, int pin, int level)
         case PPC970_INPUT_HRESET:
             /* Level sensitive - active low */
             if (level) {
-#if 0 // XXX: TOFIX
-                LOG_IRQ("%s: reset the CPU\n", __func__);
-                cpu_reset(env);
-#endif
+                cpu_interrupt(env, CPU_INTERRUPT_RESET);
             }
             break;
         case PPC970_INPUT_SRESET:
diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
index 98079fa..951b389 100644
--- a/hw/ppc405_uc.c
+++ b/hw/ppc405_uc.c
@@ -1769,13 +1769,7 @@ void ppc40x_core_reset (CPUState *env)
     target_ulong dbsr;
 
     printf("Reset PowerPC core\n");
-    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
-    /* XXX: TOFIX */
-#if 0
-    cpu_reset(env);
-#else
-    qemu_system_reset_request();
-#endif
+    cpu_interrupt(env, CPU_INTERRUPT_RESET);
     dbsr = env->spr[SPR_40x_DBSR];
     dbsr &= ~0x00000300;
     dbsr |= 0x00000100;
@@ -1787,13 +1781,7 @@ void ppc40x_chip_reset (CPUState *env)
     target_ulong dbsr;
 
     printf("Reset PowerPC chip\n");
-    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
-    /* XXX: TOFIX */
-#if 0
-    cpu_reset(env);
-#else
-    qemu_system_reset_request();
-#endif
+    cpu_interrupt(env, CPU_INTERRUPT_RESET);
     /* XXX: TODO reset all internal peripherals */
     dbsr = env->spr[SPR_40x_DBSR];
     dbsr &= ~0x00000300;
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index fbcf488..ac753f3 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -2051,6 +2051,9 @@ enum {
     PPC_INTERRUPT_PERFM,          /* Performance monitor interrupt        */
 };
 
+/* CPU should be reset next, restart from scratch afterwards */
+#define CPU_INTERRUPT_RESET       CPU_INTERRUPT_TGT_INT_0
+
 /*****************************************************************************/
 
 static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
commit 418ba9e5d6849ef2e8512d8853628ce4bf37937a
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Feb 25 23:07:34 2012 +0100

    qom: Introduce object_class_get_list()
    
    This function allows to obtain a singly-linked list of classes, which
    can be sorted by the caller.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Cc: Anthony Liguori <anthony at codemonkey.ws>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/qemu/object.h b/include/qemu/object.h
index ec2d294..e8fc126 100644
--- a/include/qemu/object.h
+++ b/include/qemu/object.h
@@ -560,6 +560,17 @@ ObjectClass *object_class_by_name(const char *typename);
 void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
                           const char *implements_type, bool include_abstract,
                           void *opaque);
+
+/**
+ * object_class_get_list:
+ * @implements_type: The type to filter for, including its derivatives.
+ * @include_abstract: Whether to include abstract classes.
+ *
+ * Returns: A singly-linked list of the classes in reverse hashtable order.
+ */
+GSList *object_class_get_list(const char *implements_type,
+                              bool include_abstract);
+
 /**
  * object_ref:
  * @obj: the object
diff --git a/qom/object.c b/qom/object.c
index 664708d..9cd9506 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -584,6 +584,23 @@ void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
     g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
 }
 
+static void object_class_get_list_tramp(ObjectClass *klass, void *opaque)
+{
+    GSList **list = opaque;
+
+    *list = g_slist_prepend(*list, klass);
+}
+
+GSList *object_class_get_list(const char *implements_type,
+                              bool include_abstract)
+{
+    GSList *list = NULL;
+
+    object_class_foreach(object_class_get_list_tramp,
+                         implements_type, include_abstract, &list);
+    return list;
+}
+
 void object_ref(Object *obj)
 {
     obj->ref++;
commit ac4510337d1e461d4d56889db9691c49d3597cdb
Author: Igor Mitsyanko <i.mitsyanko at samsung.com>
Date:   Tue Feb 28 15:57:11 2012 +0400

    qom/object.c: rename type_class_init() to type_initialize()
    
    Function name type_class_init() gave us a wrong impression of separation
    of type's "class" and "object" entities initialization. Name type_initialize()
    is more appropriate for type_class_init() function (considering what operations
    it performs).
    
    Signed-off-by: Igor Mitsyanko <i.mitsyanko at samsung.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qom/object.c b/qom/object.c
index 0f87495..664708d 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -206,7 +206,7 @@ static void type_class_interface_init(TypeImpl *ti, InterfaceImpl *iface)
     g_free(name);
 }
 
-static void type_class_init(TypeImpl *ti)
+static void type_initialize(TypeImpl *ti)
 {
     size_t class_size = sizeof(ObjectClass);
     int i;
@@ -224,7 +224,7 @@ static void type_class_init(TypeImpl *ti)
     if (type_has_parent(ti)) {
         TypeImpl *parent = type_get_parent(ti);
 
-        type_class_init(parent);
+        type_initialize(parent);
 
         class_size = parent->class_size;
         g_assert(parent->class_size <= ti->class_size);
@@ -278,7 +278,7 @@ void object_initialize_with_type(void *data, TypeImpl *type)
     Object *obj = data;
 
     g_assert(type != NULL);
-    type_class_init(type);
+    type_initialize(type);
 
     g_assert(type->instance_size >= sizeof(Object));
     g_assert(type->abstract == false);
@@ -367,7 +367,7 @@ Object *object_new_with_type(Type type)
     Object *obj;
 
     g_assert(type != NULL);
-    type_class_init(type);
+    type_initialize(type);
 
     obj = g_malloc(type->instance_size);
     object_initialize_with_type(obj, type);
@@ -540,7 +540,7 @@ ObjectClass *object_class_by_name(const char *typename)
         return NULL;
     }
 
-    type_class_init(type);
+    type_initialize(type);
 
     return type->class;
 }
@@ -560,7 +560,7 @@ static void object_class_foreach_tramp(gpointer key, gpointer value,
     TypeImpl *type = value;
     ObjectClass *k;
 
-    type_class_init(type);
+    type_initialize(type);
     k = type->class;
 
     if (!data->include_abstract && type->abstract) {
commit aca59af612840772f18598363b65a25bf02bb569
Author: Igor Mitsyanko <i.mitsyanko at samsung.com>
Date:   Tue Feb 28 15:57:10 2012 +0400

    qom: if @instance_size==0, assign size of object to parent object size
    
    QOM documentation states that for objects of type with @instance_size == 0 size
    will be assigned to match parent object's size. But currently this feauture is
    not implemented and qemu asserts during creation of object with zero instance_size.
    
    Set appropriate value for type instance_size during type_class_init() call.
    object_initialize_with_type() must call type_class_init() before asserting
    type->instance_size, and object_new_with_type() must call type_class_init() before
    object allocation.
    
    Signed-off-by: Igor Mitsyanko <i.mitsyanko at samsung.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qom/object.c b/qom/object.c
index 39cbcb9..0f87495 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -177,6 +177,19 @@ static size_t type_class_get_size(TypeImpl *ti)
     return sizeof(ObjectClass);
 }
 
+static size_t type_object_get_size(TypeImpl *ti)
+{
+    if (ti->instance_size) {
+        return ti->instance_size;
+    }
+
+    if (type_has_parent(ti)) {
+        return type_object_get_size(type_get_parent(ti));
+    }
+
+    return 0;
+}
+
 static void type_class_interface_init(TypeImpl *ti, InterfaceImpl *iface)
 {
     TypeInfo info = {
@@ -203,6 +216,7 @@ static void type_class_init(TypeImpl *ti)
     }
 
     ti->class_size = type_class_get_size(ti);
+    ti->instance_size = type_object_get_size(ti);
 
     ti->class = g_malloc0(ti->class_size);
     ti->class->type = ti;
@@ -264,9 +278,9 @@ void object_initialize_with_type(void *data, TypeImpl *type)
     Object *obj = data;
 
     g_assert(type != NULL);
-    g_assert(type->instance_size >= sizeof(Object));
-
     type_class_init(type);
+
+    g_assert(type->instance_size >= sizeof(Object));
     g_assert(type->abstract == false);
 
     memset(obj, 0, type->instance_size);
@@ -353,6 +367,7 @@ Object *object_new_with_type(Type type)
     Object *obj;
 
     g_assert(type != NULL);
+    type_class_init(type);
 
     obj = g_malloc(type->instance_size);
     object_initialize_with_type(obj, type);
commit 9512e4a9edef2d9b59eb10a03184cd90a34f62d5
Author: Avi Kivity <avi at redhat.com>
Date:   Tue Mar 6 17:50:10 2012 +0200

    kvmvapic: align start address as well as size
    
    The kvmvapic code remaps a section of ROM as RAM to allow the guest to
    maintain state there.  It is careful to align the section size to a page
    boundary, to avoid creating subpages, but neglects to do the same for
    the start address.  These leads to an assert later on when the memory
    core tries to create a page which is half RAM and half ROM.
    
    Fix by aligning the start address to a page boundary.
    
    This can be triggered by running qemu-system-x86_64 -enable-kvm -vga none.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/kvmvapic.c b/hw/kvmvapic.c
index 36ccfbc..e8bfeec 100644
--- a/hw/kvmvapic.c
+++ b/hw/kvmvapic.c
@@ -578,8 +578,10 @@ static void vapic_map_rom_writable(VAPICROMState *s)
     rom_size = ram[rom_paddr + 2] * ROM_BLOCK_SIZE;
     s->rom_size = rom_size;
 
-    /* We need to round up to avoid creating subpages
+    /* We need to round to avoid creating subpages
      * from which we cannot run code. */
+    rom_size += rom_paddr & ~TARGET_PAGE_MASK;
+    rom_paddr &= TARGET_PAGE_MASK;
     rom_size = TARGET_PAGE_ALIGN(rom_size);
 
     memory_region_init_alias(&s->rom, "kvmvapic-rom", section.mr, rom_paddr,
commit 3e7ecd976b06fc9054a34bda093a70efae99588b
Merge: 684e1e0... 2d26512...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 13 13:56:13 2012 -0500

    Merge remote-tracking branch 'kiszka/queues/slirp' into staging
    
    * kiszka/queues/slirp:
      slirp: Fix compiler warning for w64
      slirp: Cleanup resources on instance removal
      slirp: Remove unneeded if_queued
      slirp: Fix queue walking in if_start
      slirp: Prevent recursion of if_start
      slirp: Keep next_m always valid

commit 684e1e047950938be259e7d02033f44c427e6ba5
Merge: ce008c1... e2854bf...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 13 13:55:02 2012 -0500

    Merge remote-tracking branch 'kraxel/usb.44' into staging
    
    * kraxel/usb.44:
      Endian fix an assertion in usb-msd
      uhci: alloc can't fail, drop check.
      uhci: new uhci_handle_td return code for tds still in flight
      uhci: renumber uhci_handle_td return codes
      uhci: use enum for uhci_handle_td return codes
      uhci: tracing support
      uhci: cancel on schedule stop.
      uhci: fix uhci_async_cancel_all
      uhci: pass addr to uhci_async_alloc
      usb: improve packet state sanity checks
      usb-ohci: DMA writeback bug fixes
      usb-ehci: drop unused isoch_pause variable
      usb: zap hw/ush-{ohic,uhci}.h + init wrappers
      usb: the big rename

commit ce008c1f10e9a7bfb0806432b899ac4390b199c3
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Mar 4 21:32:36 2012 +0100

    qom: Add QOM support to user emulators
    
    Link the Object base class and the module infrastructure for class
    registration. Introduce $(universal-obj-y) for objects that are more
    common than $(common-obj-y), so that those only get built once.
    
    Call QOM module init for type registration.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Cc: Anthony Liguori <anthony at codemonkey.ws>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile b/Makefile
index 408065e..1bc3cb0 100644
--- a/Makefile
+++ b/Makefile
@@ -98,12 +98,12 @@ ifneq ($(wildcard config-host.mak),)
 include $(SRC_PATH)/Makefile.objs
 endif
 
-$(common-obj-y): $(GENERATED_HEADERS)
+$(universal-obj-y) $(common-obj-y): $(GENERATED_HEADERS)
 subdir-libcacard: $(oslib-obj-y) $(trace-obj-y) qemu-timer-common.o
 
-$(filter %-softmmu,$(SUBDIR_RULES)): $(trace-obj-y) $(common-obj-y) subdir-libdis
+$(filter %-softmmu,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) $(common-obj-y) subdir-libdis
 
-$(filter %-user,$(SUBDIR_RULES)): $(GENERATED_HEADERS) $(trace-obj-y) subdir-libdis-user subdir-libuser
+$(filter %-user,$(SUBDIR_RULES)): $(GENERATED_HEADERS) $(universal-obj-y) $(trace-obj-y) subdir-libdis-user subdir-libuser
 
 ROMSUBDIR_RULES=$(patsubst %,romsubdir-%, $(ROMS))
 romsubdir-%:
diff --git a/Makefile.objs b/Makefile.objs
index 5f0b3f7..48bbc94 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -1,9 +1,22 @@
 #######################################################################
+# Target-independent parts used in system and user emulation
+universal-obj-y =
+
+#######################################################################
 # QObject
 qobject-obj-y = qint.o qstring.o qdict.o qlist.o qfloat.o qbool.o
 qobject-obj-y += qjson.o json-lexer.o json-streamer.o json-parser.o
 qobject-obj-y += qerror.o error.o qemu-error.o
 
+universal-obj-y += $(qobject-obj-y)
+
+#######################################################################
+# QOM
+include $(SRC_PATH)/qom/Makefile
+qom-obj-y = $(addprefix qom/, $(qom-y))
+
+universal-obj-y += $(qom-obj-y)
+
 #######################################################################
 # oslib-obj-y is code depending on the OS (win32 vs posix)
 oslib-obj-y = osdep.o
@@ -80,7 +93,6 @@ 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 += $(qobject-obj-y)
 common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX))
 common-obj-y += readline.o console.o cursor.o
 common-obj-y += $(oslib-obj-y)
@@ -128,9 +140,6 @@ 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
 
-include $(SRC_PATH)/qom/Makefile
-common-obj-y += $(addprefix qom/, $(qom-y))
-
 audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o
 audio-obj-$(CONFIG_SDL) += sdlaudio.o
 audio-obj-$(CONFIG_OSS) += ossaudio.o
@@ -186,6 +195,8 @@ user-obj-y =
 user-obj-y += envlist.o path.o
 user-obj-y += tcg-runtime.o host-utils.o
 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)
 
 ######################################################################
@@ -422,9 +433,11 @@ 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))
 
-common-obj-y += qmp-marshal.o qapi-visit.o qapi-types.o $(qapi-obj-y)
+common-obj-y += qmp-marshal.o qapi-visit.o qapi-types.o
 common-obj-y += qmp.o hmp.o
 
+universal-obj-y += $(qapi-obj-y)
+
 ######################################################################
 # guest agent
 
diff --git a/Makefile.target b/Makefile.target
index 1bd25a8..cb1532a 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -136,6 +136,7 @@ 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))
 obj-y += $(libobj-y)
@@ -163,6 +164,7 @@ 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))
 obj-y += $(libobj-y)
@@ -185,6 +187,7 @@ 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))
 obj-y += $(libobj-y)
@@ -406,6 +409,7 @@ monitor.o: hmp-commands.h qmp-commands-old.h
 
 $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y): $(GENERATED_HEADERS)
 
+obj-y += $(addprefix ../, $(universal-obj-y))
 obj-y += $(addprefix ../, $(common-obj-y))
 obj-y += $(addprefix ../libdis/, $(libdis-y))
 obj-y += $(libobj-y)
diff --git a/Makefile.user b/Makefile.user
index 2b1e4d1..b717820 100644
--- a/Makefile.user
+++ b/Makefile.user
@@ -9,6 +9,7 @@ include $(SRC_PATH)/rules.mak
 $(call set-vpath, $(SRC_PATH))
 
 QEMU_CFLAGS+=-I..
+QEMU_CFLAGS += -I$(SRC_PATH)/include
 
 include $(SRC_PATH)/Makefile.objs
 
diff --git a/bsd-user/main.c b/bsd-user/main.c
index cc7d4a3..cdb0d0a 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -748,6 +748,8 @@ int main(int argc, char **argv)
     if (argc <= 1)
         usage();
 
+    module_call_init(MODULE_INIT_QOM);
+
     if ((envlist = envlist_create()) == NULL) {
         (void) fprintf(stderr, "Unable to allocate envlist\n");
         exit(1);
diff --git a/darwin-user/main.c b/darwin-user/main.c
index 9b57c20..e1519c7 100644
--- a/darwin-user/main.c
+++ b/darwin-user/main.c
@@ -28,6 +28,7 @@
 #include <sys/mman.h>
 
 #include "qemu.h"
+#include "qemu-common.h"
 
 #define DEBUG_LOGFILE "/tmp/qemu.log"
 
@@ -749,6 +750,8 @@ int main(int argc, char **argv)
     if (argc <= 1)
         usage();
 
+    module_call_init(MODULE_INIT_QOM);
+
     optind = 1;
     for(;;) {
         if (optind >= argc)
diff --git a/linux-user/main.c b/linux-user/main.c
index 14bf5f0..bd47489 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3285,6 +3285,8 @@ int main(int argc, char **argv, char **envp)
     int i;
     int ret;
 
+    module_call_init(MODULE_INIT_QOM);
+
     qemu_cache_utils_init(envp);
 
     if ((envlist = envlist_create()) == NULL) {
diff --git a/qemu-user.c b/qemu-user.c
new file mode 100644
index 0000000..08ccb0f
--- /dev/null
+++ b/qemu-user.c
@@ -0,0 +1,37 @@
+/*
+ * Stubs for QEMU user emulation
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
+ */
+
+#include "qemu-common.h"
+#include "monitor.h"
+
+Monitor *cur_mon;
+
+int monitor_cur_is_qmp(void)
+{
+    return 0;
+}
+
+void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
+{
+}
+
+void monitor_set_error(Monitor *mon, QError *qerror)
+{
+}
commit 1b71f7c14fab6f00c2680d4489fbee7baf796e4f
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Mar 4 21:32:35 2012 +0100

    qom: Register QOM infrastructure early
    
    The constructors for QOM TYPE_INTERFACE were executed rather late in
    vl.c's main(). Call them very early so that QOM can safely be used for
    machines and CPUs.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Cc: Anthony Liguori <anthony at codemonkey.ws>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vl.c b/vl.c
index 65f11f2..bd95539 100644
--- a/vl.c
+++ b/vl.c
@@ -2299,6 +2299,8 @@ int main(int argc, char **argv, char **envp)
 #endif
     }
 
+    module_call_init(MODULE_INIT_QOM);
+
     runstate_init();
 
     init_clocks();
@@ -3466,8 +3468,6 @@ int main(int argc, char **argv, char **envp)
     if (foreach_device_config(DEV_DEBUGCON, debugcon_parse) < 0)
         exit(1);
 
-    module_call_init(MODULE_INIT_QOM);
-
     /* must be after qdev registration but before machine init */
     if (vga_model) {
         select_vgahw(vga_model);
commit 03f48b0797c9904301ee91e0081e89b3a3250f91
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Mar 4 21:32:34 2012 +0100

    kvmclock: Always register type
    
    Currently, the "kvmclock" type is only registered when kvm_enabled().
    
    This breaks when moving type registration to before command line
    parsing (so that QOM types can be used for CPU and machine).
    
    Since the QOM classes are lazy-initialized anyway and kvmclock_create()
    has another kvm_enabled() check, simply drop the KVM check in
    kvmclock_register_types().
    
    kvm-i8259, kvm-apic and kvm-ioapic do not suffer from such a check.
    
    Reviewed-by: please.
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Jan Kiszka <jan.kiszka at siemens.com>
    Cc: Marcelo Tosatti <mtosatti at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/kvm/clock.c b/hw/kvm/clock.c
index 2157340..446bd62 100644
--- a/hw/kvm/clock.c
+++ b/hw/kvm/clock.c
@@ -121,9 +121,7 @@ void kvmclock_create(void)
 
 static void kvmclock_register_types(void)
 {
-    if (kvm_enabled()) {
     type_register_static(&kvmclock_info);
-    }
 }
 
 type_init(kvmclock_register_types)
commit 2d26512b45b5236fa521c4492608fe9fb5bedf46
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Mar 10 21:20:53 2012 +0100

    slirp: Fix compiler warning for w64
    
    Casting a pointer to an integer value must use uintptr_t or intptr_t
    (not long) for portable code. MinGW-w64 requires this because
    sizeof(long) != sizeof(void *) for w64 hosts, so casting to long
    raises a compiler warning.
    
    I use uintptr_t instead of intptr_t because changing the sign does not
    matter here and casting pointers to unsigned values seems more
    reasonable (the unsigned value is a non negative offset.
    
    Cc: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>

diff --git a/slirp/cksum.c b/slirp/cksum.c
index e43867d..6328660 100644
--- a/slirp/cksum.c
+++ b/slirp/cksum.c
@@ -75,7 +75,7 @@ int cksum(struct mbuf *m, int len)
 	/*
 	 * Force to even boundary.
 	 */
-	if ((1 & (long) w) && (mlen > 0)) {
+	if ((1 & (uintptr_t)w) && (mlen > 0)) {
 		REDUCE;
 		sum <<= 8;
 		s_util.c[0] = *(uint8_t *)w;
commit a68adc220603baffc355ecea8865b3ea9707ab00
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Feb 29 19:14:23 2012 +0100

    slirp: Cleanup resources on instance removal
    
    Close & free sockets when shutting down a slirp instance, also release
    all buffers.
    
    CC: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>

diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c
index 5dbf21d..d571fd0 100644
--- a/slirp/ip_icmp.c
+++ b/slirp/ip_icmp.c
@@ -66,6 +66,13 @@ void icmp_init(Slirp *slirp)
     slirp->icmp_last_so = &slirp->icmp;
 }
 
+void icmp_cleanup(Slirp *slirp)
+{
+    while (slirp->icmp.so_next != &slirp->icmp) {
+        icmp_detach(slirp->icmp.so_next);
+    }
+}
+
 static int icmp_send(struct socket *so, struct mbuf *m, int hlen)
 {
     struct ip *ip = mtod(m, struct ip *);
diff --git a/slirp/ip_icmp.h b/slirp/ip_icmp.h
index b3da1f2..1a1af91 100644
--- a/slirp/ip_icmp.h
+++ b/slirp/ip_icmp.h
@@ -154,6 +154,7 @@ struct icmp {
 	(type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY)
 
 void icmp_init(Slirp *slirp);
+void icmp_cleanup(Slirp *slirp);
 void icmp_input(struct mbuf *, int);
 void icmp_error(struct mbuf *msrc, u_char type, u_char code, int minsize,
                 const char *message);
diff --git a/slirp/ip_input.c b/slirp/ip_input.c
index c7b3eb4..ce24faf 100644
--- a/slirp/ip_input.c
+++ b/slirp/ip_input.c
@@ -61,6 +61,13 @@ ip_init(Slirp *slirp)
     icmp_init(slirp);
 }
 
+void ip_cleanup(Slirp *slirp)
+{
+    udp_cleanup(slirp);
+    tcp_cleanup(slirp);
+    icmp_cleanup(slirp);
+}
+
 /*
  * Ip input routine.  Checksum and byte swap header.  If fragmented
  * try to reassemble.  Process options.  Pass to next level.
diff --git a/slirp/mbuf.c b/slirp/mbuf.c
index c699c75..4fefb04 100644
--- a/slirp/mbuf.c
+++ b/slirp/mbuf.c
@@ -32,6 +32,27 @@ m_init(Slirp *slirp)
     slirp->m_usedlist.m_next = slirp->m_usedlist.m_prev = &slirp->m_usedlist;
 }
 
+void m_cleanup(Slirp *slirp)
+{
+    struct mbuf *m, *next;
+
+    m = slirp->m_usedlist.m_next;
+    while (m != &slirp->m_usedlist) {
+        next = m->m_next;
+        if (m->m_flags & M_EXT) {
+            free(m->m_ext);
+        }
+        free(m);
+        m = next;
+    }
+    m = slirp->m_freelist.m_next;
+    while (m != &slirp->m_freelist) {
+        next = m->m_next;
+        free(m);
+        m = next;
+    }
+}
+
 /*
  * Get an mbuf from the free list, if there are none
  * malloc one
diff --git a/slirp/mbuf.h b/slirp/mbuf.h
index 8d7951f..3f3ab09 100644
--- a/slirp/mbuf.h
+++ b/slirp/mbuf.h
@@ -116,6 +116,7 @@ struct mbuf {
 					 * it rather than putting it on the free list */
 
 void m_init(Slirp *);
+void m_cleanup(Slirp *slirp);
 struct mbuf * m_get(Slirp *);
 void m_free(struct mbuf *);
 void m_cat(register struct mbuf *, register struct mbuf *);
diff --git a/slirp/slirp.c b/slirp/slirp.c
index bcffc34..1502830 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -246,6 +246,9 @@ void slirp_cleanup(Slirp *slirp)
 
     unregister_savevm(NULL, "slirp", slirp);
 
+    ip_cleanup(slirp);
+    m_cleanup(slirp);
+
     g_free(slirp->tftp_prefix);
     g_free(slirp->bootp_filename);
     g_free(slirp);
diff --git a/slirp/slirp.h b/slirp/slirp.h
index cbe8a3c..5033ee3 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -315,6 +315,7 @@ void if_output(struct socket *, struct mbuf *);
 
 /* ip_input.c */
 void ip_init(Slirp *);
+void ip_cleanup(Slirp *);
 void ip_input(struct mbuf *);
 void ip_slowtimo(Slirp *);
 void ip_stripoptions(register struct mbuf *, struct mbuf *);
@@ -332,6 +333,7 @@ void tcp_setpersist(register struct tcpcb *);
 
 /* tcp_subr.c */
 void tcp_init(Slirp *);
+void tcp_cleanup(Slirp *);
 void tcp_template(struct tcpcb *);
 void tcp_respond(struct tcpcb *, register struct tcpiphdr *, register struct mbuf *, tcp_seq, tcp_seq, int);
 struct tcpcb * tcp_newtcpcb(struct socket *);
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index 143a238..6f6585a 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -55,6 +55,13 @@ tcp_init(Slirp *slirp)
     slirp->tcp_last_so = &slirp->tcb;
 }
 
+void tcp_cleanup(Slirp *slirp)
+{
+    while (slirp->tcb.so_next != &slirp->tcb) {
+        tcp_close(sototcpcb(slirp->tcb.so_next));
+    }
+}
+
 /*
  * Create template to be used to send tcp packets on a connection.
  * Call after host entry created, fills
diff --git a/slirp/udp.c b/slirp/udp.c
index 5b060f3..ced5096 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -49,6 +49,14 @@ udp_init(Slirp *slirp)
     slirp->udb.so_next = slirp->udb.so_prev = &slirp->udb;
     slirp->udp_last_so = &slirp->udb;
 }
+
+void udp_cleanup(Slirp *slirp)
+{
+    while (slirp->udb.so_next != &slirp->udb) {
+        udp_detach(slirp->udb.so_next);
+    }
+}
+
 /* m->m_data  points at ip packet header
  * m->m_len   length ip packet
  * ip->ip_len length data (IPDU)
diff --git a/slirp/udp.h b/slirp/udp.h
index 9b5c3cf..9bf31fe 100644
--- a/slirp/udp.h
+++ b/slirp/udp.h
@@ -74,6 +74,7 @@ struct udpiphdr {
 struct mbuf;
 
 void udp_init(Slirp *);
+void udp_cleanup(Slirp *);
 void udp_input(register struct mbuf *, int);
 int udp_output(struct socket *, struct mbuf *, struct sockaddr_in *);
 int udp_attach(struct socket *);
commit f37343197708d90f119007ce5ecc2503be9c04c1
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Mar 6 00:02:23 2012 +0100

    slirp: Remove unneeded if_queued
    
    There is now a trivial check on entry of if_start for pending packets,
    so we can drop the additional tracking via if_queued.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>

diff --git a/slirp/if.c b/slirp/if.c
index f6e848a..096cf6f 100644
--- a/slirp/if.c
+++ b/slirp/if.c
@@ -110,8 +110,6 @@ if_output(struct socket *so, struct mbuf *ifm)
 	insque(ifm, ifq);
 
 diddit:
-	slirp->if_queued++;
-
 	if (so) {
 		/* Update *_queued */
 		so->so_queued++;
@@ -157,7 +155,6 @@ diddit:
 void if_start(Slirp *slirp)
 {
     uint64_t now = qemu_get_clock_ns(rt_clock);
-    int requeued = 0;
     bool from_batchq, next_from_batchq;
     struct mbuf *ifm, *ifm_next, *ifqt;
 
@@ -182,8 +179,7 @@ void if_start(Slirp *slirp)
     while (ifm_next) {
         /* check if we can really output */
         if (!slirp_can_output(slirp->opaque)) {
-            slirp->if_start_busy = false;
-            return;
+            break;
         }
 
         ifm = ifm_next;
@@ -200,12 +196,9 @@ void if_start(Slirp *slirp)
             ifm_next = NULL;
         }
 
-        slirp->if_queued--;
-
         /* Try to send packet unless it already expired */
         if (ifm->expiration_date >= now && !if_encap(slirp, ifm)) {
             /* Packet is delayed due to pending ARP resolution */
-            requeued++;
             continue;
         }
 
@@ -245,7 +238,5 @@ void if_start(Slirp *slirp)
         m_free(ifm);
     }
 
-    slirp->if_queued = requeued;
-
     slirp->if_start_busy = false;
 }
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 19d69eb..bcffc34 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -581,12 +581,7 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
                 }
 	}
 
-	/*
-	 * See if we can start outputting
-	 */
-	if (slirp->if_queued) {
-	    if_start(slirp);
-	}
+        if_start(slirp);
     }
 
 	/* clear global file descriptor sets.
diff --git a/slirp/slirp.h b/slirp/slirp.h
index 416d44a..cbe8a3c 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -235,7 +235,6 @@ struct Slirp {
     int mbuf_alloced;
 
     /* if states */
-    int if_queued;          /* number of packets queued so far */
     struct mbuf if_fastq;   /* fast queue (for interactive data) */
     struct mbuf if_batchq;  /* queue for non-interactive data */
     struct mbuf *next_m;    /* pointer to next mbuf to output */
commit e3078bf40a33b59fa11d077b1d0bb8796470982e
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Mar 6 00:00:07 2012 +0100

    slirp: Fix queue walking in if_start
    
    Another attempt to get this right: We need to carefully walk both the
    fastq and the batchq in if_start while trying to send packets to
    possibly not yet resolved hosts on the virtual network.
    
    So far we just requeued a delayed packet where it was and then started
    walking the queues from the top again - that couldn't work. Now we pre-
    calculate the next packet in the queue so that the current one can
    safely be removed if it was sent successfully. We also need to take into
    account that the next packet can be from the same session if the current
    one was sent and there are no other sessions.
    
    CC: Fabien Chouteau <chouteau at adacore.com>
    CC: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com>
    CC: Stefan Weil <sw at weilnetz.de>
    Tested-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>

diff --git a/slirp/if.c b/slirp/if.c
index f7aebe9..f6e848a 100644
--- a/slirp/if.c
+++ b/slirp/if.c
@@ -158,8 +158,8 @@ void if_start(Slirp *slirp)
 {
     uint64_t now = qemu_get_clock_ns(rt_clock);
     int requeued = 0;
-    bool from_batchq = false;
-    struct mbuf *ifm, *ifqt;
+    bool from_batchq, next_from_batchq;
+    struct mbuf *ifm, *ifm_next, *ifqt;
 
     DEBUG_CALL("if_start");
 
@@ -168,23 +168,36 @@ void if_start(Slirp *slirp)
     }
     slirp->if_start_busy = true;
 
-    while (slirp->if_queued) {
+    if (slirp->if_fastq.ifq_next != &slirp->if_fastq) {
+        ifm_next = slirp->if_fastq.ifq_next;
+        next_from_batchq = false;
+    } else if (slirp->next_m != &slirp->if_batchq) {
+        /* Nothing on fastq, pick up from batchq via next_m */
+        ifm_next = slirp->next_m;
+        next_from_batchq = true;
+    } else {
+        ifm_next = NULL;
+    }
+
+    while (ifm_next) {
         /* check if we can really output */
         if (!slirp_can_output(slirp->opaque)) {
             slirp->if_start_busy = false;
             return;
         }
 
-        /*
-         * See which queue to get next packet from
-         * If there's something in the fastq, select it immediately
-         */
-        if (slirp->if_fastq.ifq_next != &slirp->if_fastq) {
-            ifm = slirp->if_fastq.ifq_next;
-        } else {
-            /* Nothing on fastq, pick up from batchq via next_m */
-            ifm = slirp->next_m;
-            from_batchq = true;
+        ifm = ifm_next;
+        from_batchq = next_from_batchq;
+
+        ifm_next = ifm->ifq_next;
+        if (ifm_next == &slirp->if_fastq) {
+            /* No more packets in fastq, switch to batchq */
+            ifm_next = slirp->next_m;
+            next_from_batchq = true;
+        }
+        if (ifm_next == &slirp->if_batchq) {
+            /* end of batchq */
+            ifm_next = NULL;
         }
 
         slirp->if_queued--;
@@ -196,7 +209,7 @@ void if_start(Slirp *slirp)
             continue;
         }
 
-        if (from_batchq) {
+        if (ifm == slirp->next_m) {
             /* Set which packet to send on next iteration */
             slirp->next_m = ifm->ifq_next;
         }
@@ -207,13 +220,19 @@ void if_start(Slirp *slirp)
 
         /* If there are more packets for this session, re-queue them */
         if (ifm->ifs_next != ifm) {
-            insque(ifm->ifs_next, ifqt);
+            struct mbuf *next = ifm->ifs_next;
+
+            insque(next, ifqt);
             ifs_remque(ifm);
-            /* Set next_m if the session packet is now the only one on
-             * batchq */
-            if (ifqt == &slirp->if_batchq &&
-                slirp->next_m == &slirp->if_batchq) {
-                slirp->next_m = ifm->ifs_next;
+
+            if (!from_batchq) {
+                /* Next packet in fastq is from the same session */
+                ifm_next = next;
+                next_from_batchq = false;
+            } else if (slirp->next_m == &slirp->if_batchq) {
+                /* Set next_m and ifm_next if the session packet is now the
+                 * only one on batchq */
+                slirp->next_m = ifm_next = next;
             }
         }
 
@@ -224,7 +243,6 @@ void if_start(Slirp *slirp)
         }
 
         m_free(ifm);
-
     }
 
     slirp->if_queued = requeued;
commit 953e7f54e679cd40fff28e29189ed9e24bfb0758
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Mar 5 19:50:39 2012 +0100

    slirp: Prevent recursion of if_start
    
    if_start can be called recursively via if_encap. Avoid this as our
    scheme of dequeuing packets is not compatible with this.
    
    CC: Fabien Chouteau <chouteau at adacore.com>
    CC: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com>
    CC: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>

diff --git a/slirp/if.c b/slirp/if.c
index 14fdef1..f7aebe9 100644
--- a/slirp/if.c
+++ b/slirp/if.c
@@ -163,10 +163,17 @@ void if_start(Slirp *slirp)
 
     DEBUG_CALL("if_start");
 
+    if (slirp->if_start_busy) {
+        return;
+    }
+    slirp->if_start_busy = true;
+
     while (slirp->if_queued) {
         /* check if we can really output */
-        if (!slirp_can_output(slirp->opaque))
+        if (!slirp_can_output(slirp->opaque)) {
+            slirp->if_start_busy = false;
             return;
+        }
 
         /*
          * See which queue to get next packet from
@@ -221,4 +228,6 @@ void if_start(Slirp *slirp)
     }
 
     slirp->if_queued = requeued;
+
+    slirp->if_start_busy = false;
 }
diff --git a/slirp/slirp.h b/slirp/slirp.h
index 28a5c03..416d44a 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -239,6 +239,7 @@ struct Slirp {
     struct mbuf if_fastq;   /* fast queue (for interactive data) */
     struct mbuf if_batchq;  /* queue for non-interactive data */
     struct mbuf *next_m;    /* pointer to next mbuf to output */
+    bool if_start_busy;     /* avoid if_start recursion */
 
     /* ip states */
     struct ipq ipq;         /* ip reass. queue */
commit d6536b2c971f7323e58dfbe1e6f3b7c7c0c4edf3
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Feb 29 09:27:33 2012 +0100

    slirp: Keep next_m always valid
    
    Make sure that next_m always points to a packet if batchq is non-empty.
    This will simplify walking the queues in if_start.
    
    CC: Fabien Chouteau <chouteau at adacore.com>
    CC: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com>
    CC: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>

diff --git a/slirp/if.c b/slirp/if.c
index 33f08e1..14fdef1 100644
--- a/slirp/if.c
+++ b/slirp/if.c
@@ -96,8 +96,13 @@ if_output(struct socket *so, struct mbuf *ifm)
 			ifs_insque(ifm, ifq->ifs_prev);
 			goto diddit;
 		}
-	} else
+        } else {
 		ifq = slirp->if_batchq.ifq_prev;
+                /* Set next_m if the queue was empty so far */
+                if (slirp->next_m == &slirp->if_batchq) {
+                    slirp->next_m = ifm;
+                }
+        }
 
 	/* Create a new doubly linked list for this session */
 	ifm->ifq_so = so;
@@ -170,13 +175,8 @@ void if_start(Slirp *slirp)
         if (slirp->if_fastq.ifq_next != &slirp->if_fastq) {
             ifm = slirp->if_fastq.ifq_next;
         } else {
-            /* Nothing on fastq, see if next_m is valid */
-            if (slirp->next_m != &slirp->if_batchq) {
-                ifm = slirp->next_m;
-            } else {
-                ifm = slirp->if_batchq.ifq_next;
-            }
-
+            /* Nothing on fastq, pick up from batchq via next_m */
+            ifm = slirp->next_m;
             from_batchq = true;
         }
 
@@ -202,6 +202,12 @@ void if_start(Slirp *slirp)
         if (ifm->ifs_next != ifm) {
             insque(ifm->ifs_next, ifqt);
             ifs_remque(ifm);
+            /* Set next_m if the session packet is now the only one on
+             * batchq */
+            if (ifqt == &slirp->if_batchq &&
+                slirp->next_m == &slirp->if_batchq) {
+                slirp->next_m = ifm->ifs_next;
+            }
         }
 
         /* Update so_queued */
commit e2854bf3239f57d160cfe5230033110c0c0d2837
Author: Benjamin Herrenschmidt <benh at kernel.crashing.org>
Date:   Thu Mar 8 11:41:10 2012 +1100

    Endian fix an assertion in usb-msd
    
    This fixes a broken endian assumption in an assertion in usb-msd.
    
    Cc: Gerd Hoffman <kraxel at redhat.com>
    
    Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index 6ffaf70..bdbe7bd 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -193,9 +193,9 @@ static void usb_msd_send_status(MSDState *s, USBPacket *p)
     int len;
 
     DPRINTF("Command status %d tag 0x%x, len %zd\n",
-            s->csw.status, s->csw.tag, p->iov.size);
+            s->csw.status, le32_to_cpu(s->csw.tag), p->iov.size);
 
-    assert(s->csw.sig == 0x53425355);
+    assert(s->csw.sig == cpu_to_le32(0x53425355));
     len = MIN(sizeof(s->csw), p->iov.size);
     usb_packet_copy(p, &s->csw, len);
     memset(&s->csw, 0, sizeof(s->csw));
@@ -233,7 +233,7 @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t r
 
     s->csw.sig = cpu_to_le32(0x53425355);
     s->csw.tag = cpu_to_le32(req->tag);
-    s->csw.residue = s->residue;
+    s->csw.residue = cpu_to_le32(s->residue);
     s->csw.status = status != 0;
 
     if (s->packet) {
commit 6c60134091cb2754d810b012773754967d8bbf92
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Mar 9 11:10:48 2012 +0100

    uhci: alloc can't fail, drop check.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 8e34961..e55dad9 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -821,8 +821,6 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in
 
     /* Allocate new packet */
     async = uhci_async_alloc(uhci_queue_get(s, td), addr);
-    if (!async)
-        return TD_RESULT_NEXT_QH;
 
     /* valid needs to be large enough to handle 10 frame delay
      * for initial isochronous requests
commit 4efe4ef3b8f7530c5a62e23630ba3d439cd82ee6
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Mar 9 11:15:41 2012 +0100

    uhci: new uhci_handle_td return code for tds still in flight
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index fd50be1..8e34961 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -81,7 +81,8 @@ enum {
     TD_RESULT_STOP_FRAME = 10,
     TD_RESULT_COMPLETE,
     TD_RESULT_NEXT_QH,
-    TD_RESULT_ASYNC,
+    TD_RESULT_ASYNC_START,
+    TD_RESULT_ASYNC_CONT,
 };
 
 typedef struct UHCIState UHCIState;
@@ -812,7 +813,7 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in
         async->queue->valid = 32;
 
         if (!async->done)
-            return TD_RESULT_NEXT_QH;
+            return TD_RESULT_ASYNC_CONT;
 
         uhci_async_unlink(async);
         goto done;
@@ -860,7 +861,7 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in
  
     if (len == USB_RET_ASYNC) {
         uhci_async_link(async);
-        return TD_RESULT_ASYNC;
+        return TD_RESULT_ASYNC_START;
     }
 
     async->packet.result = len;
@@ -966,7 +967,7 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td)
         }
         trace_usb_uhci_td_queue(plink & ~0xf, ptd.ctrl, ptd.token);
         ret = uhci_handle_td(s, plink, &ptd, &int_mask);
-        assert(ret == TD_RESULT_ASYNC);
+        assert(ret == TD_RESULT_ASYNC_START);
         assert(int_mask == 0);
         plink = ptd.link;
     }
@@ -1058,11 +1059,12 @@ static void uhci_process_frame(UHCIState *s)
             goto out;
 
         case TD_RESULT_NEXT_QH:
+        case TD_RESULT_ASYNC_CONT:
             trace_usb_uhci_td_nextqh(curr_qh & ~0xf, link & ~0xf);
             link = curr_qh ? qh.link : td.link;
             continue;
 
-        case TD_RESULT_ASYNC:
+        case TD_RESULT_ASYNC_START:
             trace_usb_uhci_td_async(curr_qh & ~0xf, link & ~0xf);
             if (is_valid(td.link)) {
                 uhci_fill_queue(s, &td);
commit 0cd178ca2cabf94e7acaa64eca6714f966edaa0d
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Mar 9 11:11:46 2012 +0100

    uhci: renumber uhci_handle_td return codes
    
    Step #2 (separate for better bisectability): renumber so the silly '-1'
    goes away.  Pick a range which doesn't overlap the old values.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 25dfc2b..fd50be1 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -78,10 +78,10 @@
 #define NB_PORTS 2
 
 enum {
-    TD_RESULT_STOP_FRAME = -1,
-    TD_RESULT_COMPLETE   = 0,
-    TD_RESULT_NEXT_QH    = 1,
-    TD_RESULT_ASYNC      = 2,
+    TD_RESULT_STOP_FRAME = 10,
+    TD_RESULT_COMPLETE,
+    TD_RESULT_NEXT_QH,
+    TD_RESULT_ASYNC,
 };
 
 typedef struct UHCIState UHCIState;
commit 60e1b2a6ddf1fd9cc93ad81d8ba7d8ac4369cc78
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Mar 9 11:09:49 2012 +0100

    uhci: use enum for uhci_handle_td return codes
    
    Step #1 (separate for better bisectability): replace numbers with names.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 054ae19..25dfc2b 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -77,6 +77,13 @@
 
 #define NB_PORTS 2
 
+enum {
+    TD_RESULT_STOP_FRAME = -1,
+    TD_RESULT_COMPLETE   = 0,
+    TD_RESULT_NEXT_QH    = 1,
+    TD_RESULT_ASYNC      = 2,
+};
+
 typedef struct UHCIState UHCIState;
 typedef struct UHCIAsync UHCIAsync;
 typedef struct UHCIQueue UHCIQueue;
@@ -721,13 +728,13 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_
             /* short packet: do not update QH */
             trace_usb_uhci_packet_complete_shortxfer(async->queue->token,
                                                     async->td);
-            return 1;
+            return TD_RESULT_NEXT_QH;
         }
     }
 
     /* success */
     trace_usb_uhci_packet_complete_success(async->queue->token, async->td);
-    return 0;
+    return TD_RESULT_COMPLETE;
 
 out:
     switch(ret) {
@@ -740,7 +747,7 @@ out:
         }
         uhci_update_irq(s);
         trace_usb_uhci_packet_complete_stall(async->queue->token, async->td);
-        return 1;
+        return TD_RESULT_NEXT_QH;
 
     case USB_RET_BABBLE:
         td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL;
@@ -752,13 +759,13 @@ out:
         uhci_update_irq(s);
         /* frame interrupted */
         trace_usb_uhci_packet_complete_babble(async->queue->token, async->td);
-        return -1;
+        return TD_RESULT_STOP_FRAME;
 
     case USB_RET_NAK:
         td->ctrl |= TD_CTRL_NAK;
         if (pid == USB_TOKEN_SETUP)
             break;
-	return 1;
+        return TD_RESULT_NEXT_QH;
 
     case USB_RET_IOERROR:
     case USB_RET_NODEV:
@@ -784,7 +791,7 @@ out:
     }
     td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) |
         (err << TD_CTRL_ERROR_SHIFT);
-    return 1;
+    return TD_RESULT_NEXT_QH;
 }
 
 static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *int_mask)
@@ -797,7 +804,7 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in
 
     /* Is active ? */
     if (!(td->ctrl & TD_CTRL_ACTIVE))
-        return 1;
+        return TD_RESULT_NEXT_QH;
 
     async = uhci_async_find_td(s, addr, td);
     if (async) {
@@ -805,7 +812,7 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in
         async->queue->valid = 32;
 
         if (!async->done)
-            return 1;
+            return TD_RESULT_NEXT_QH;
 
         uhci_async_unlink(async);
         goto done;
@@ -814,7 +821,7 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in
     /* Allocate new packet */
     async = uhci_async_alloc(uhci_queue_get(s, td), addr);
     if (!async)
-        return 1;
+        return TD_RESULT_NEXT_QH;
 
     /* valid needs to be large enough to handle 10 frame delay
      * for initial isochronous requests
@@ -848,12 +855,12 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in
         uhci_async_free(async);
         s->status |= UHCI_STS_HCPERR;
         uhci_update_irq(s);
-        return -1;
+        return TD_RESULT_STOP_FRAME;
     }
  
     if (len == USB_RET_ASYNC) {
         uhci_async_link(async);
-        return 2;
+        return TD_RESULT_ASYNC;
     }
 
     async->packet.result = len;
@@ -959,7 +966,7 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td)
         }
         trace_usb_uhci_td_queue(plink & ~0xf, ptd.ctrl, ptd.token);
         ret = uhci_handle_td(s, plink, &ptd, &int_mask);
-        assert(ret == 2); /* got USB_RET_ASYNC */
+        assert(ret == TD_RESULT_ASYNC);
         assert(int_mask == 0);
         plink = ptd.link;
     }
@@ -1047,15 +1054,15 @@ static void uhci_process_frame(UHCIState *s)
         }
 
         switch (ret) {
-        case -1: /* interrupted frame */
+        case TD_RESULT_STOP_FRAME: /* interrupted frame */
             goto out;
 
-        case 1: /* goto next queue */
+        case TD_RESULT_NEXT_QH:
             trace_usb_uhci_td_nextqh(curr_qh & ~0xf, link & ~0xf);
             link = curr_qh ? qh.link : td.link;
             continue;
 
-        case 2: /* got USB_RET_ASYNC */
+        case TD_RESULT_ASYNC:
             trace_usb_uhci_td_async(curr_qh & ~0xf, link & ~0xf);
             if (is_valid(td.link)) {
                 uhci_fill_queue(s, &td);
@@ -1063,7 +1070,7 @@ static void uhci_process_frame(UHCIState *s)
             link = curr_qh ? qh.link : td.link;
             continue;
 
-        case 0: /* completed TD */
+        case TD_RESULT_COMPLETE:
             trace_usb_uhci_td_complete(curr_qh & ~0xf, link & ~0xf);
             link = td.link;
             td_count++;
commit 50dcc0f85da5d2a74760af4b67c040c4d0c8b939
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Mar 8 13:12:38 2012 +0100

    uhci: tracing support
    
    Zap DPRINTF, add tracepoints instead.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 5177e33..054ae19 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -31,6 +31,7 @@
 #include "qemu-timer.h"
 #include "iov.h"
 #include "dma.h"
+#include "trace.h"
 
 //#define DEBUG
 //#define DEBUG_DUMP_DATA
@@ -76,23 +77,6 @@
 
 #define NB_PORTS 2
 
-#ifdef DEBUG
-#define DPRINTF printf
-
-static const char *pid2str(int pid)
-{
-    switch (pid) {
-    case USB_TOKEN_SETUP: return "SETUP";
-    case USB_TOKEN_IN:    return "IN";
-    case USB_TOKEN_OUT:   return "OUT";
-    }
-    return "?";
-}
-
-#else
-#define DPRINTF(...)
-#endif
-
 typedef struct UHCIState UHCIState;
 typedef struct UHCIAsync UHCIAsync;
 typedef struct UHCIQueue UHCIQueue;
@@ -187,6 +171,7 @@ static UHCIQueue *uhci_queue_get(UHCIState *s, UHCI_TD *td)
     queue->token = token;
     QTAILQ_INIT(&queue->asyncs);
     QTAILQ_INSERT_HEAD(&s->queues, queue, next);
+    trace_usb_uhci_queue_add(queue->token);
     return queue;
 }
 
@@ -194,6 +179,7 @@ static void uhci_queue_free(UHCIQueue *queue)
 {
     UHCIState *s = queue->uhci;
 
+    trace_usb_uhci_queue_del(queue->token);
     QTAILQ_REMOVE(&s->queues, queue, next);
     g_free(queue);
 }
@@ -206,12 +192,14 @@ static UHCIAsync *uhci_async_alloc(UHCIQueue *queue, uint32_t addr)
     async->td = addr;
     usb_packet_init(&async->packet);
     pci_dma_sglist_init(&async->sgl, &queue->uhci->dev, 1);
+    trace_usb_uhci_packet_add(async->queue->token, async->td);
 
     return async;
 }
 
 static void uhci_async_free(UHCIAsync *async)
 {
+    trace_usb_uhci_packet_del(async->queue->token, async->td);
     usb_packet_cleanup(&async->packet);
     qemu_sglist_destroy(&async->sgl);
     g_free(async);
@@ -221,19 +209,19 @@ static void uhci_async_link(UHCIAsync *async)
 {
     UHCIQueue *queue = async->queue;
     QTAILQ_INSERT_TAIL(&queue->asyncs, async, next);
+    trace_usb_uhci_packet_link_async(async->queue->token, async->td);
 }
 
 static void uhci_async_unlink(UHCIAsync *async)
 {
     UHCIQueue *queue = async->queue;
     QTAILQ_REMOVE(&queue->asyncs, async, next);
+    trace_usb_uhci_packet_unlink_async(async->queue->token, async->td);
 }
 
 static void uhci_async_cancel(UHCIAsync *async)
 {
-    DPRINTF("uhci: cancel td 0x%x token 0x%x done %u\n",
-           async->td, async->token, async->done);
-
+    trace_usb_uhci_packet_cancel(async->queue->token, async->td, async->done);
     if (!async->done)
         usb_cancel_packet(&async->packet);
     uhci_async_free(async);
@@ -351,7 +339,7 @@ static void uhci_reset(void *opaque)
     int i;
     UHCIPort *port;
 
-    DPRINTF("uhci: full reset\n");
+    trace_usb_uhci_reset();
 
     pci_conf = s->dev.config;
 
@@ -451,12 +439,13 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
     UHCIState *s = opaque;
 
     addr &= 0x1f;
-    DPRINTF("uhci: writew port=0x%04x val=0x%04x\n", addr, val);
+    trace_usb_uhci_mmio_writew(addr, val);
 
     switch(addr) {
     case 0x00:
         if ((val & UHCI_CMD_RS) && !(s->cmd & UHCI_CMD_RS)) {
             /* start frame processing */
+            trace_usb_uhci_schedule_start();
             s->expire_time = qemu_get_clock_ns(vm_clock) +
                 (get_ticks_per_sec() / FRAME_TIMER_FREQ);
             qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
@@ -561,7 +550,7 @@ static uint32_t uhci_ioport_readw(void *opaque, uint32_t addr)
         break;
     }
 
-    DPRINTF("uhci: readw port=0x%04x val=0x%04x\n", addr, val);
+    trace_usb_uhci_mmio_readw(addr, val);
 
     return val;
 }
@@ -571,7 +560,7 @@ static void uhci_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
     UHCIState *s = opaque;
 
     addr &= 0x1f;
-    DPRINTF("uhci: writel port=0x%04x val=0x%08x\n", addr, val);
+    trace_usb_uhci_mmio_writel(addr, val);
 
     switch(addr) {
     case 0x08:
@@ -594,6 +583,7 @@ static uint32_t uhci_ioport_readl(void *opaque, uint32_t addr)
         val = 0xffffffff;
         break;
     }
+    trace_usb_uhci_mmio_readl(addr, val);
     return val;
 }
 
@@ -729,12 +719,14 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_
         if ((td->ctrl & TD_CTRL_SPD) && len < max_len) {
             *int_mask |= 0x02;
             /* short packet: do not update QH */
-            DPRINTF("uhci: short packet. td 0x%x token 0x%x\n", async->td, async->token);
+            trace_usb_uhci_packet_complete_shortxfer(async->queue->token,
+                                                    async->td);
             return 1;
         }
     }
 
     /* success */
+    trace_usb_uhci_packet_complete_success(async->queue->token, async->td);
     return 0;
 
 out:
@@ -747,6 +739,7 @@ out:
             *int_mask |= 0x01;
         }
         uhci_update_irq(s);
+        trace_usb_uhci_packet_complete_stall(async->queue->token, async->td);
         return 1;
 
     case USB_RET_BABBLE:
@@ -758,6 +751,7 @@ out:
         }
         uhci_update_irq(s);
         /* frame interrupted */
+        trace_usb_uhci_packet_complete_babble(async->queue->token, async->td);
         return -1;
 
     case USB_RET_NAK:
@@ -784,6 +778,8 @@ out:
             if (td->ctrl & TD_CTRL_IOC)
                 *int_mask |= 0x01;
             uhci_update_irq(s);
+            trace_usb_uhci_packet_complete_error(async->queue->token,
+                                                 async->td);
         }
     }
     td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) |
@@ -874,8 +870,6 @@ static void uhci_async_complete(USBPort *port, USBPacket *packet)
     UHCIAsync *async = container_of(packet, UHCIAsync, packet);
     UHCIState *s = async->queue->uhci;
 
-    DPRINTF("uhci: async complete. td 0x%x token 0x%x\n", async->td, async->token);
-
     if (async->isoc) {
         UHCI_TD td;
         uint32_t link = async->td;
@@ -963,6 +957,7 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td)
         if (uhci_queue_token(&ptd) != token) {
             break;
         }
+        trace_usb_uhci_td_queue(plink & ~0xf, ptd.ctrl, ptd.token);
         ret = uhci_handle_td(s, plink, &ptd, &int_mask);
         assert(ret == 2); /* got USB_RET_ASYNC */
         assert(int_mask == 0);
@@ -981,8 +976,6 @@ static void uhci_process_frame(UHCIState *s)
 
     frame_addr = s->fl_base_addr + ((s->frnum & 0x3ff) << 2);
 
-    DPRINTF("uhci: processing frame %d addr 0x%x\n" , s->frnum, frame_addr);
-
     pci_dma_read(&s->dev, frame_addr, &link, 4);
     le32_to_cpus(&link);
 
@@ -994,6 +987,7 @@ static void uhci_process_frame(UHCIState *s)
     for (cnt = FRAME_MAX_LOOPS; is_valid(link) && cnt; cnt--) {
         if (is_qh(link)) {
             /* QH */
+            trace_usb_uhci_qh_load(link & ~0xf);
 
             if (qhdb_insert(&qhdb, link)) {
                 /*
@@ -1006,14 +1000,14 @@ static void uhci_process_frame(UHCIState *s)
                  *  (b) we've reached the usb 1.1 bandwidth, which is
                  *      1280 bytes/frame.
                  */
-                DPRINTF("uhci: detected loop. qh 0x%x\n", link);
                 if (td_count == 0) {
-                    DPRINTF("uhci: no transaction last round, stop\n");
+                    trace_usb_uhci_frame_loop_stop_idle();
                     break;
                 } else if (bytes_count >= 1280) {
-                    DPRINTF("uhci: bandwidth limit reached, stop\n");
+                    trace_usb_uhci_frame_loop_stop_bandwidth();
                     break;
                 } else {
+                    trace_usb_uhci_frame_loop_continue();
                     td_count = 0;
                     qhdb_reset(&qhdb);
                     qhdb_insert(&qhdb, link);
@@ -1024,9 +1018,6 @@ static void uhci_process_frame(UHCIState *s)
             le32_to_cpus(&qh.link);
             le32_to_cpus(&qh.el_link);
 
-            DPRINTF("uhci: QH 0x%x load. link 0x%x elink 0x%x\n",
-                    link, qh.link, qh.el_link);
-
             if (!is_valid(qh.el_link)) {
                 /* QH w/o elements */
                 curr_qh = 0;
@@ -1045,9 +1036,7 @@ static void uhci_process_frame(UHCIState *s)
         le32_to_cpus(&td.ctrl);
         le32_to_cpus(&td.token);
         le32_to_cpus(&td.buffer);
-
-        DPRINTF("uhci: TD 0x%x load. link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n", 
-                link, td.link, td.ctrl, td.token, curr_qh);
+        trace_usb_uhci_td_load(curr_qh & ~0xf, link & ~0xf, td.ctrl, td.token);
 
         old_td_ctrl = td.ctrl;
         ret = uhci_handle_td(s, link, &td, &int_mask);
@@ -1062,16 +1051,12 @@ static void uhci_process_frame(UHCIState *s)
             goto out;
 
         case 1: /* goto next queue */
-            DPRINTF("uhci: TD 0x%x skip. "
-                    "link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n",
-                    link, td.link, td.ctrl, td.token, curr_qh);
+            trace_usb_uhci_td_nextqh(curr_qh & ~0xf, link & ~0xf);
             link = curr_qh ? qh.link : td.link;
             continue;
 
         case 2: /* got USB_RET_ASYNC */
-            DPRINTF("uhci: TD 0x%x async. "
-                    "link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n",
-                    link, td.link, td.ctrl, td.token, curr_qh);
+            trace_usb_uhci_td_async(curr_qh & ~0xf, link & ~0xf);
             if (is_valid(td.link)) {
                 uhci_fill_queue(s, &td);
             }
@@ -1079,10 +1064,7 @@ static void uhci_process_frame(UHCIState *s)
             continue;
 
         case 0: /* completed TD */
-            DPRINTF("uhci: TD 0x%x done. "
-                    "link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n",
-                    link, td.link, td.ctrl, td.token, curr_qh);
-
+            trace_usb_uhci_td_complete(curr_qh & ~0xf, link & ~0xf);
             link = td.link;
             td_count++;
             bytes_count += (td.ctrl & 0x7ff) + 1;
@@ -1095,10 +1077,6 @@ static void uhci_process_frame(UHCIState *s)
 
                 if (!depth_first(link)) {
                     /* done with this QH */
-
-                    DPRINTF("uhci: QH 0x%x done. link 0x%x elink 0x%x\n",
-                            curr_qh, qh.link, qh.el_link);
-
                     curr_qh = 0;
                     link    = qh.link;
                 }
@@ -1125,12 +1103,11 @@ static void uhci_frame_timer(void *opaque)
 
     if (!(s->cmd & UHCI_CMD_RS)) {
         /* Full stop */
+        trace_usb_uhci_schedule_stop();
         qemu_del_timer(s->frame_timer);
         uhci_async_cancel_all(s);
         /* set hchalted bit in status - UHCI11D 2.1.2 */
         s->status |= UHCI_STS_HCHALTED;
-
-        DPRINTF("uhci: halted\n");
         return;
     }
 
@@ -1145,7 +1122,7 @@ static void uhci_frame_timer(void *opaque)
     /* Start new frame */
     s->frnum = (s->frnum + 1) & 0x7ff;
 
-    DPRINTF("uhci: new frame #%u\n" , s->frnum);
+    trace_usb_uhci_frame_start(s->frnum);
 
     uhci_async_validate_begin(s);
 
diff --git a/trace-events b/trace-events
index 301374e..c8317a0 100644
--- a/trace-events
+++ b/trace-events
@@ -258,6 +258,37 @@ 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"
 
+# hw/usb/hcd-uhci.c
+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_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"
+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_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"
+usb_uhci_packet_link_async(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x"
+usb_uhci_packet_unlink_async(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x"
+usb_uhci_packet_cancel(uint32_t token, uint32_t addr, int done) "token 0x%x, td 0x%x, done %d"
+usb_uhci_packet_complete_success(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x"
+usb_uhci_packet_complete_shortxfer(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x"
+usb_uhci_packet_complete_stall(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x"
+usb_uhci_packet_complete_babble(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x"
+usb_uhci_packet_complete_error(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x"
+usb_uhci_packet_del(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x"
+usb_uhci_qh_load(uint32_t qh) "qh 0x%x"
+usb_uhci_td_load(uint32_t qh, uint32_t td, uint32_t ctrl, uint32_t token) "qh 0x%x, td 0x%x, ctrl 0x%x, token 0x%x"
+usb_uhci_td_queue(uint32_t td, uint32_t ctrl, uint32_t token) "td 0x%x, ctrl 0x%x, token 0x%x"
+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-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 d9a528db7f2d71d92e869e20bda37774f11fbbe1
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Mar 8 13:37:52 2012 +0100

    uhci: cancel on schedule stop.
    
    Cancel any in-flight transaction when the guest stops the uhci schedule.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 416f703..5177e33 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -1126,6 +1126,7 @@ static void uhci_frame_timer(void *opaque)
     if (!(s->cmd & UHCI_CMD_RS)) {
         /* Full stop */
         qemu_del_timer(s->frame_timer);
+        uhci_async_cancel_all(s);
         /* set hchalted bit in status - UHCI11D 2.1.2 */
         s->status |= UHCI_STS_HCHALTED;
 
commit 60f8afcb5d734b6e8a6ba6cb26254dc04e8d9f8d
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Mar 8 13:29:07 2012 +0100

    uhci: fix uhci_async_cancel_all
    
    It should also free all queues.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 476db1f..416f703 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -300,6 +300,7 @@ static void uhci_async_cancel_all(UHCIState *s)
             uhci_async_unlink(curr);
             uhci_async_cancel(curr);
         }
+        uhci_queue_free(queue);
     }
 }
 
commit 16ce543ed14acc796768a732c9d3ea1288efde24
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Mar 8 13:15:56 2012 +0100

    uhci: pass addr to uhci_async_alloc
    
    Also do async->td initialization in uhci_async_alloc now.
    Prepares for adding tracepoints.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 5c708cf..476db1f 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -198,11 +198,12 @@ static void uhci_queue_free(UHCIQueue *queue)
     g_free(queue);
 }
 
-static UHCIAsync *uhci_async_alloc(UHCIQueue *queue)
+static UHCIAsync *uhci_async_alloc(UHCIQueue *queue, uint32_t addr)
 {
     UHCIAsync *async = g_new0(UHCIAsync, 1);
 
     async->queue = queue;
+    async->td = addr;
     usb_packet_init(&async->packet);
     pci_dma_sglist_init(&async->sgl, &queue->uhci->dev, 1);
 
@@ -814,7 +815,7 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in
     }
 
     /* Allocate new packet */
-    async = uhci_async_alloc(uhci_queue_get(s, td));
+    async = uhci_async_alloc(uhci_queue_get(s, td), addr);
     if (!async)
         return 1;
 
@@ -822,7 +823,6 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in
      * for initial isochronous requests
      */
     async->queue->valid = 32;
-    async->td    = addr;
     async->isoc  = td->ctrl & TD_CTRL_IOS;
 
     max_len = ((td->token >> 21) + 1) & 0x7ff;
commit 5ac2731cf821a7ecae90786d9052891afb09dfc2
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Mar 8 12:27:47 2012 +0100

    usb: improve packet state sanity checks
    
    Add a new function to check whenever the packet state is as expected,
    log more informations in case it isn't.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb.h b/hw/usb.h
index d60d03d..e95085f 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -336,6 +336,7 @@ struct USBPacket {
 
 void usb_packet_init(USBPacket *p);
 void usb_packet_set_state(USBPacket *p, USBPacketState state);
+void usb_packet_check_state(USBPacket *p, USBPacketState expected);
 void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep);
 void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len);
 int usb_packet_map(USBPacket *p, QEMUSGList *sgl);
diff --git a/hw/usb/core.c b/hw/usb/core.c
index 494989a..a4048fe 100644
--- a/hw/usb/core.c
+++ b/hw/usb/core.c
@@ -378,7 +378,7 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
     }
     assert(dev == p->ep->dev);
     assert(dev->state == USB_STATE_DEFAULT);
-    assert(p->state == USB_PACKET_SETUP);
+    usb_packet_check_state(p, USB_PACKET_SETUP);
     assert(p->ep != NULL);
 
     if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline) {
@@ -406,7 +406,7 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p)
     USBEndpoint *ep = p->ep;
     int ret;
 
-    assert(p->state == USB_PACKET_ASYNC);
+    usb_packet_check_state(p, USB_PACKET_ASYNC);
     assert(QTAILQ_FIRST(&ep->queue) == p);
     usb_packet_set_state(p, USB_PACKET_COMPLETE);
     QTAILQ_REMOVE(&ep->queue, p, queue);
@@ -417,7 +417,7 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p)
         if (p->state == USB_PACKET_ASYNC) {
             break;
         }
-        assert(p->state == USB_PACKET_QUEUED);
+        usb_packet_check_state(p, USB_PACKET_QUEUED);
         ret = usb_process_one(p);
         if (ret == USB_RET_ASYNC) {
             usb_packet_set_state(p, USB_PACKET_ASYNC);
@@ -450,7 +450,7 @@ void usb_packet_init(USBPacket *p)
     qemu_iovec_init(&p->iov, 1);
 }
 
-void usb_packet_set_state(USBPacket *p, USBPacketState state)
+static const char *usb_packet_state_name(USBPacketState state)
 {
     static const char *name[] = {
         [USB_PACKET_UNDEFINED] = "undef",
@@ -460,11 +460,36 @@ void usb_packet_set_state(USBPacket *p, USBPacketState state)
         [USB_PACKET_COMPLETE]  = "complete",
         [USB_PACKET_CANCELED]  = "canceled",
     };
+    if (state < ARRAY_SIZE(name)) {
+        return name[state];
+    }
+    return "INVALID";
+}
+
+void usb_packet_check_state(USBPacket *p, USBPacketState expected)
+{
+    USBDevice *dev;
+    USBBus *bus;
+
+    if (p->state == expected) {
+        return;
+    }
+    dev = p->ep->dev;
+    bus = usb_bus_from_device(dev);
+    trace_usb_packet_state_fault(bus->busnr, dev->port->path, p->ep->nr, p,
+                                 usb_packet_state_name(p->state),
+                                 usb_packet_state_name(expected));
+    assert(!"usb packet state check failed");
+}
+
+void usb_packet_set_state(USBPacket *p, USBPacketState state)
+{
     USBDevice *dev = p->ep->dev;
     USBBus *bus = usb_bus_from_device(dev);
 
-    trace_usb_packet_state_change(bus->busnr, dev->port->path, p->ep->nr,
-                                  p, name[p->state], name[state]);
+    trace_usb_packet_state_change(bus->busnr, dev->port->path, p->ep->nr, p,
+                                  usb_packet_state_name(p->state),
+                                  usb_packet_state_name(state));
     p->state = state;
 }
 
diff --git a/trace-events b/trace-events
index bcfe13a..301374e 100644
--- a/trace-events
+++ b/trace-events
@@ -229,6 +229,7 @@ sun4m_iommu_bad_addr(uint64_t addr) "bad addr %"PRIx64
 
 # hw/usb/core.c
 usb_packet_state_change(int bus, const char *port, int ep, void *p, const char *o, const char *n) "bus %d, port %s, ep %d, packet %p, state %s -> %s"
+usb_packet_state_fault(int bus, const char *port, int ep, void *p, const char *o, const char *n) "bus %d, port %s, ep %d, packet %p, state %s, expected %s"
 
 # hw/usb/bus.c
 usb_port_claim(int bus, const char *port) "bus %d, port %s"
commit 86e18cae209f8101ff9a6013a1ff6ae620c06944
Author: Wei Yang <weiyang at linux.vnet.ibm.com>
Date:   Thu Mar 8 12:10:44 2012 +1100

    usb-ohci: DMA writeback bug fixes
    
    This patch fixes two bugs in the OHCI device where the device writes
    back data to system memory that should be exclusively under the
    control of the guest side driver.
    
    In OHCI specification Section 5.2.7, it mentioned "In all cases, Host
    Controller Driver is responsible for the insertion and removal of all
    Endpoint Descriptors in the various Host Controller Endpoint
    Descriptor lists".  In the ohci_frame_boundary(), ohci_put_hcca()
    writes the entire hcca back including the interrupt ED lists which
    should be under driver control. This violates the specification and
    can race with a host driver updating that list at the same time.
    
    In the OHCI Spec Section 4.6, Transfer Descriptor Queue Processing, it
    mentioned "Since the TD pointed to by TailP is not accessed by the HC,
    the Host Controller Driver can initialize that TD and link at least
    one other to it without creating a coherency or synchronization
    problem".  While the function ohci_put_ed() writes the entire endpoint
    descriptor back including the TailP which should under driver
    control. This violate the specification and can race with a host
    driver updating the TD list at the same time.
    
    In each case the solution is to make sure we don't write data which is
    under driver control.
    
    Cc: Gerd Hoffman <kraxel at redhat.com>
    
    Signed-off-by: Wei Yang <weiyang at linux.vnet.ibm.com>
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index 51fa111..1a1cc88 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -121,6 +121,11 @@ struct ohci_hcca {
     uint16_t frame, pad;
     uint32_t done;
 };
+#define HCCA_WRITEBACK_OFFSET   offsetof(struct ohci_hcca, frame)
+#define HCCA_WRITEBACK_SIZE     8 /* frame, pad, done */
+
+#define ED_WBACK_OFFSET offsetof(struct ohci_ed, head)
+#define ED_WBACK_SIZE   4
 
 static void ohci_bus_stop(OHCIState *ohci);
 static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev);
@@ -568,7 +573,13 @@ static inline int ohci_read_hcca(OHCIState *ohci,
 static inline int ohci_put_ed(OHCIState *ohci,
                               uint32_t addr, struct ohci_ed *ed)
 {
-    return put_dwords(ohci, addr, (uint32_t *)ed, sizeof(*ed) >> 2);
+    /* ed->tail is under control of the HCD.
+     * Since just ed->head is changed by HC, just write back this
+     */
+
+    return put_dwords(ohci, addr + ED_WBACK_OFFSET,
+                      (uint32_t *)((char *)ed + ED_WBACK_OFFSET),
+                      ED_WBACK_SIZE >> 2);
 }
 
 static inline int ohci_put_td(OHCIState *ohci,
@@ -587,7 +598,9 @@ static inline int ohci_put_iso_td(OHCIState *ohci,
 static inline int ohci_put_hcca(OHCIState *ohci,
                                 uint32_t addr, struct ohci_hcca *hcca)
 {
-    cpu_physical_memory_write(addr + ohci->localmem_base, hcca, sizeof(*hcca));
+    cpu_physical_memory_write(addr + ohci->localmem_base + HCCA_WRITEBACK_OFFSET,
+                              (char *)hcca + HCCA_WRITEBACK_OFFSET,
+                              HCCA_WRITEBACK_SIZE);
     return 1;
 }
 
commit fcb70eca3f14349a0ef8e74dc808360f81592026
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sun Mar 4 12:10:11 2012 +0100

    usb-ehci: drop unused isoch_pause variable
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 58811d3..60f9f5b 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -419,7 +419,6 @@ struct EHCIState {
 
     USBPacket ipacket;
     QEMUSGList isgl;
-    int isoch_pause;
 
     uint64_t last_run_ns;
 };
@@ -907,7 +906,6 @@ static void ehci_reset(void *opaque)
 
     s->astate = EST_INACTIVE;
     s->pstate = EST_INACTIVE;
-    s->isoch_pause = -1;
     s->attach_poll_counter = 0;
 
     for(i = 0; i < NB_PORTS; i++) {
@@ -2150,9 +2148,7 @@ static void ehci_frame_timer(void *opaque)
 
     for (i = 0; i < frames; i++) {
         if ( !(ehci->usbsts & USBSTS_HALT)) {
-            if (ehci->isoch_pause <= 0) {
-                ehci->frindex += 8;
-            }
+            ehci->frindex += 8;
 
             if (ehci->frindex > 0x00001fff) {
                 ehci->frindex = 0;
commit afb9a60ecb391cbccfd38e6bf400ebfcf40c5d0c
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Mar 7 15:06:32 2012 +0100

    usb: zap hw/ush-{ohic,uhci}.h + init wrappers
    
    Remove the uhci and ohci init wrappers, which all wrapped a
    pci_create_simple() one-liner.  Switch callsites to call
    pci_create_simple directly.  Remove the header files where
    the wrappers where declared.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/alpha_sys.h b/hw/alpha_sys.h
index d54b18f..f9506c6 100644
--- a/hw/alpha_sys.h
+++ b/hw/alpha_sys.h
@@ -8,7 +8,6 @@
 #include "ide.h"
 #include "net.h"
 #include "pc.h"
-#include "usb-ohci.h"
 #include "irq.h"
 
 
diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c
index e3ba9dd..efdfdc2 100644
--- a/hw/mips_fulong2e.c
+++ b/hw/mips_fulong2e.c
@@ -29,7 +29,6 @@
 #include "mips.h"
 #include "mips_cpudevs.h"
 #include "pci.h"
-#include "usb-uhci.h"
 #include "qemu-char.h"
 #include "sysemu.h"
 #include "audio/audio.h"
@@ -355,8 +354,10 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device,
     isa_bus_irqs(isa_bus, i8259);
 
     vt82c686b_ide_init(pci_bus, hd, PCI_DEVFN(FULONG2E_VIA_SLOT, 1));
-    usb_uhci_vt82c686b_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 2));
-    usb_uhci_vt82c686b_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 3));
+    pci_create_simple(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 2),
+                      "vt82c686b-usb-uhci");
+    pci_create_simple(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 3),
+                      "vt82c686b-usb-uhci");
 
     smbus = vt82c686b_pm_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 4),
                               0xeee1, NULL);
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index b1563ed..866699d 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -33,7 +33,6 @@
 #include "mips.h"
 #include "mips_cpudevs.h"
 #include "pci.h"
-#include "usb-uhci.h"
 #include "vmware_vga.h"
 #include "qemu-char.h"
 #include "sysemu.h"
@@ -965,7 +964,7 @@ void mips_malta_init (ram_addr_t ram_size,
 
     isa_bus_irqs(isa_bus, s->i8259);
     pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1);
-    usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
+    pci_create_simple(pci_bus, piix4_devfn + 2, "piix4-usb-uhci");
     smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100,
                           isa_get_irq(NULL, 9), NULL, 0);
     /* TODO: Populate SPD eeprom data.  */
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 6c5c40f..3f99f9a 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -28,8 +28,6 @@
 #include "pc.h"
 #include "apic.h"
 #include "pci.h"
-#include "usb-uhci.h"
-#include "usb-ohci.h"
 #include "net.h"
 #include "boards.h"
 #include "ide.h"
@@ -284,7 +282,7 @@ static void pc_init1(MemoryRegion *system_memory,
                  floppy, idebus[0], idebus[1], rtc_state);
 
     if (pci_enabled && usb_enabled) {
-        usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);
+        pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci");
     }
 
     if (pci_enabled && acpi_enabled) {
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index 506187b..2fec5b4 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -54,7 +54,6 @@
 #include "nvram.h"
 #include "pc.h"
 #include "pci.h"
-#include "usb-ohci.h"
 #include "net.h"
 #include "sysemu.h"
 #include "boards.h"
@@ -352,7 +351,7 @@ static void ppc_core99_init (ram_addr_t ram_size,
                dbdma_mem, cuda_mem, NULL, 3, ide_mem, escc_bar);
 
     if (usb_enabled) {
-        usb_ohci_init_pci(pci_bus, -1);
+        pci_create_simple(pci_bus, -1, "pci-ohci");
     }
 
     /* U3 needs to use USB for input because Linux doesn't support via-cuda
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index 9295a34..49c2c97 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -34,7 +34,6 @@
 #include "net.h"
 #include "isa.h"
 #include "pci.h"
-#include "usb-ohci.h"
 #include "boards.h"
 #include "fw_cfg.h"
 #include "escc.h"
@@ -278,7 +277,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
                dbdma_mem, cuda_mem, nvr, 2, ide_mem, escc_bar);
 
     if (usb_enabled) {
-        usb_ohci_init_pci(pci_bus, -1);
+        pci_create_simple(pci_bus, -1, "pci-ohci");
     }
 
     if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index eb43fb5..dc9edd7 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -30,7 +30,6 @@
 #include "isa.h"
 #include "pci.h"
 #include "pci_host.h"
-#include "usb-ohci.h"
 #include "ppc.h"
 #include "boards.h"
 #include "qemu-log.h"
@@ -688,7 +687,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
 #endif
 
     if (usb_enabled) {
-        usb_ohci_init_pci(pci_bus, -1);
+        pci_create_simple(pci_bus, -1, "pci-ohci");
     }
 
     m48t59 = m48t59_init_isa(isa_bus, 0x0074, NVRAM_SIZE, 59);
diff --git a/hw/realview.c b/hw/realview.c
index ae1bbcd..50ea67c 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -12,7 +12,6 @@
 #include "primecell.h"
 #include "devices.h"
 #include "pci.h"
-#include "usb-ohci.h"
 #include "net.h"
 #include "sysemu.h"
 #include "boards.h"
@@ -305,7 +304,7 @@ static void realview_init(ram_addr_t ram_size,
         sysbus_connect_irq(busdev, 3, pic[51]);
         pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");
         if (usb_enabled) {
-            usb_ohci_init_pci(pci_bus, -1);
+            pci_create_simple(pci_bus, -1, "pci-ohci");
         }
         n = drive_get_max_bus(IF_SCSI);
         while (n >= 0) {
diff --git a/hw/usb-ohci.h b/hw/usb-ohci.h
deleted file mode 100644
index eefcef3..0000000
--- a/hw/usb-ohci.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef QEMU_USB_OHCI_H
-#define QEMU_USB_OHCI_H
-
-#include "qemu-common.h"
-
-void usb_ohci_init_pci(struct PCIBus *bus, int devfn);
-
-#endif
-
diff --git a/hw/usb-uhci.h b/hw/usb-uhci.h
deleted file mode 100644
index 3e4d377..0000000
--- a/hw/usb-uhci.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef QEMU_USB_UHCI_H
-#define QEMU_USB_UHCI_H
-
-#include "qemu-common.h"
-
-void usb_uhci_piix3_init(PCIBus *bus, int devfn);
-void usb_uhci_piix4_init(PCIBus *bus, int devfn);
-void usb_uhci_vt82c686b_init(PCIBus *bus, int devfn);
-
-#endif
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index dd79cef..51fa111 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -30,7 +30,6 @@
 #include "qemu-timer.h"
 #include "hw/usb.h"
 #include "hw/pci.h"
-#include "hw/usb-ohci.h"
 #include "hw/sysbus.h"
 #include "hw/qdev-addr.h"
 
@@ -1815,11 +1814,6 @@ static int usb_ohci_initfn_pci(struct PCIDevice *dev)
     return 0;
 }
 
-void usb_ohci_init_pci(struct PCIBus *bus, int devfn)
-{
-    pci_create_simple(bus, devfn, "pci-ohci");
-}
-
 typedef struct {
     SysBusDevice busdev;
     OHCIState ohci;
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 7c2e9b3..5c708cf 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -29,7 +29,6 @@
 #include "hw/usb.h"
 #include "hw/pci.h"
 #include "qemu-timer.h"
-#include "hw/usb-uhci.h"
 #include "iov.h"
 #include "dma.h"
 
@@ -1391,18 +1390,3 @@ static void uhci_register_types(void)
 }
 
 type_init(uhci_register_types)
-
-void usb_uhci_piix3_init(PCIBus *bus, int devfn)
-{
-    pci_create_simple(bus, devfn, "piix3-usb-uhci");
-}
-
-void usb_uhci_piix4_init(PCIBus *bus, int devfn)
-{
-    pci_create_simple(bus, devfn, "piix4-usb-uhci");
-}
-
-void usb_uhci_vt82c686b_init(PCIBus *bus, int devfn)
-{
-    pci_create_simple(bus, devfn, "vt82c686b-usb-uhci");
-}
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index b9102f4..c1687a5 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -13,7 +13,6 @@
 #include "net.h"
 #include "sysemu.h"
 #include "pci.h"
-#include "usb-ohci.h"
 #include "boards.h"
 #include "blockdev.h"
 #include "exec-memory.h"
@@ -240,7 +239,7 @@ static void versatile_init(ram_addr_t ram_size,
         }
     }
     if (usb_enabled) {
-        usb_ohci_init_pci(pci_bus, -1);
+        pci_create_simple(pci_bus, -1, "pci-ohci");
     }
     n = drive_get_max_bus(IF_SCSI);
     while (n >= 0) {
commit f1ae32a1ecda8aaff7a355c9030c0d8c363f3a70
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Mar 7 14:55:18 2012 +0100

    usb: the big rename
    
    Reorganize usb source files.  Create a new hw/usb/ directory and move
    all usb source code to that place.  Also make filenames a bit more
    descriptive.  Host adapters are prefixed with "hch-" now, usb device
    emulations are prefixed with "dev-".  Fixup paths Makefile and include
    paths to make it compile.  No code changes.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index 5f0b3f7..1eca4a8 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -107,13 +107,15 @@ 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.o usb-hub.o usb-$(HOST_USB).o usb-hid.o usb-msd.o usb-wacom.o
-common-obj-y += usb-serial.o usb-net.o usb-bus.o usb-desc.o usb-audio.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 usb-bt.o
-common-obj-y += bt-hci-csr.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 += buffered_file.o migration.o migration-tcp.o
 common-obj-y += qemu-char.o #aio.o
 common-obj-y += msmouse.o ps2.o
@@ -194,7 +196,7 @@ user-obj-y += $(trace-obj-y)
 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-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
@@ -217,10 +219,10 @@ 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-uhci.o
-hw-obj-$(CONFIG_USB_OHCI) += usb-ohci.o
-hw-obj-$(CONFIG_USB_EHCI) += usb-ehci.o
-hw-obj-$(CONFIG_USB_XHCI) += usb-xhci.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
@@ -228,9 +230,9 @@ 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-ccid.o ccid-card-passthru.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-redir.o
+hw-obj-$(CONFIG_USB_REDIR) += usb/redirect.o
 hw-obj-$(CONFIG_I8259) += i8259_common.o i8259.o
 
 # PPC devices
diff --git a/Makefile.target b/Makefile.target
index 1bd25a8..ed76952 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -370,7 +370,7 @@ obj-arm-y += omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.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-musb.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
diff --git a/configure b/configure
index d7631ed..fe4fc4f 100755
--- a/configure
+++ b/configure
@@ -3447,6 +3447,7 @@ 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" = "arm-linux-user" -o "$target" = "armeb-linux-user" -o "$target" = "arm-bsd-user" -o "$target" = "armeb-bsd-user" ; then
@@ -3863,7 +3864,7 @@ done # for target in $targets
 DIRS="tests tests/tcg tests/tcg/cris slirp audio block net pc-bios/optionrom"
 DIRS="$DIRS pc-bios/spapr-rtas"
 DIRS="$DIRS roms/seabios roms/vgabios"
-DIRS="$DIRS fsdev ui"
+DIRS="$DIRS fsdev ui usb"
 DIRS="$DIRS qapi qapi-generated"
 DIRS="$DIRS qga trace qom"
 FILES="Makefile tests/tcg/Makefile qdict-test-data.txt"
@@ -3904,6 +3905,7 @@ for hwlib in 32 64; do
   d=libhw$hwlib
   mkdir -p $d
   mkdir -p $d/ide
+  mkdir -p $d/usb
   symlink $source_path/Makefile.hw $d/Makefile
   mkdir -p $d/9pfs
   echo "QEMU_CFLAGS+=-DTARGET_PHYS_ADDR_BITS=$hwlib" > $d/config.mak
diff --git a/hw/usb-audio.c b/hw/usb-audio.c
deleted file mode 100644
index fed1361..0000000
--- a/hw/usb-audio.c
+++ /dev/null
@@ -1,714 +0,0 @@
-/*
- * QEMU USB audio device
- *
- * written by:
- *  H. Peter Anvin <hpa at linux.intel.com>
- *  Gerd Hoffmann <kraxel at redhat.com>
- *
- * lousely based on usb net device code which is:
- *
- * Copyright (c) 2006 Thomas Sailer
- * Copyright (c) 2008 Andrzej Zaborowski
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "qemu-common.h"
-#include "usb.h"
-#include "usb-desc.h"
-#include "hw.h"
-#include "audiodev.h"
-#include "audio/audio.h"
-
-#define USBAUDIO_VENDOR_NUM     0x46f4 /* CRC16() of "QEMU" */
-#define USBAUDIO_PRODUCT_NUM    0x0002
-
-#define DEV_CONFIG_VALUE        1 /* The one and only */
-
-/* Descriptor subtypes for AC interfaces */
-#define DST_AC_HEADER           1
-#define DST_AC_INPUT_TERMINAL   2
-#define DST_AC_OUTPUT_TERMINAL  3
-#define DST_AC_FEATURE_UNIT     6
-/* Descriptor subtypes for AS interfaces */
-#define DST_AS_GENERAL          1
-#define DST_AS_FORMAT_TYPE      2
-/* Descriptor subtypes for endpoints */
-#define DST_EP_GENERAL          1
-
-enum usb_audio_strings {
-    STRING_NULL,
-    STRING_MANUFACTURER,
-    STRING_PRODUCT,
-    STRING_SERIALNUMBER,
-    STRING_CONFIG,
-    STRING_USBAUDIO_CONTROL,
-    STRING_INPUT_TERMINAL,
-    STRING_FEATURE_UNIT,
-    STRING_OUTPUT_TERMINAL,
-    STRING_NULL_STREAM,
-    STRING_REAL_STREAM,
-};
-
-static const USBDescStrings usb_audio_stringtable = {
-    [STRING_MANUFACTURER]       = "QEMU",
-    [STRING_PRODUCT]            = "QEMU USB Audio",
-    [STRING_SERIALNUMBER]       = "1",
-    [STRING_CONFIG]             = "Audio Configuration",
-    [STRING_USBAUDIO_CONTROL]   = "Audio Device",
-    [STRING_INPUT_TERMINAL]     = "Audio Output Pipe",
-    [STRING_FEATURE_UNIT]       = "Audio Output Volume Control",
-    [STRING_OUTPUT_TERMINAL]    = "Audio Output Terminal",
-    [STRING_NULL_STREAM]        = "Audio Output - Disabled",
-    [STRING_REAL_STREAM]        = "Audio Output - 48 kHz Stereo",
-};
-
-#define U16(x) ((x) & 0xff), (((x) >> 8) & 0xff)
-#define U24(x) U16(x), (((x) >> 16) & 0xff)
-#define U32(x) U24(x), (((x) >> 24) & 0xff)
-
-/*
- * A Basic Audio Device uses these specific values
- */
-#define USBAUDIO_PACKET_SIZE     192
-#define USBAUDIO_SAMPLE_RATE     48000
-#define USBAUDIO_PACKET_INTERVAL 1
-
-static const USBDescIface desc_iface[] = {
-    {
-        .bInterfaceNumber              = 0,
-        .bNumEndpoints                 = 0,
-        .bInterfaceClass               = USB_CLASS_AUDIO,
-        .bInterfaceSubClass            = USB_SUBCLASS_AUDIO_CONTROL,
-        .bInterfaceProtocol            = 0x04,
-        .iInterface                    = STRING_USBAUDIO_CONTROL,
-        .ndesc                         = 4,
-        .descs = (USBDescOther[]) {
-            {
-                /* Headphone Class-Specific AC Interface Header Descriptor */
-                .data = (uint8_t[]) {
-                    0x09,                       /*  u8  bLength */
-                    USB_DT_CS_INTERFACE,        /*  u8  bDescriptorType */
-                    DST_AC_HEADER,              /*  u8  bDescriptorSubtype */
-                    U16(0x0100),                /* u16  bcdADC */
-                    U16(0x2b),                  /* u16  wTotalLength */
-                    0x01,                       /*  u8  bInCollection */
-                    0x01,                       /*  u8  baInterfaceNr */
-                }
-            },{
-                /* Generic Stereo Input Terminal ID1 Descriptor */
-                .data = (uint8_t[]) {
-                    0x0c,                       /*  u8  bLength */
-                    USB_DT_CS_INTERFACE,        /*  u8  bDescriptorType */
-                    DST_AC_INPUT_TERMINAL,      /*  u8  bDescriptorSubtype */
-                    0x01,                       /*  u8  bTerminalID */
-                    U16(0x0101),                /* u16  wTerminalType */
-                    0x00,                       /*  u8  bAssocTerminal */
-                    0x02,                       /* u16  bNrChannels */
-                    U16(0x0003),                /* u16  wChannelConfig */
-                    0x00,                       /*  u8  iChannelNames */
-                    STRING_INPUT_TERMINAL,      /*  u8  iTerminal */
-                }
-            },{
-                /* Generic Stereo Feature Unit ID2 Descriptor */
-                .data = (uint8_t[]) {
-                    0x0d,                       /*  u8  bLength */
-                    USB_DT_CS_INTERFACE,        /*  u8  bDescriptorType */
-                    DST_AC_FEATURE_UNIT,        /*  u8  bDescriptorSubtype */
-                    0x02,                       /*  u8  bUnitID */
-                    0x01,                       /*  u8  bSourceID */
-                    0x02,                       /*  u8  bControlSize */
-                    U16(0x0001),                /* u16  bmaControls(0) */
-                    U16(0x0002),                /* u16  bmaControls(1) */
-                    U16(0x0002),                /* u16  bmaControls(2) */
-                    STRING_FEATURE_UNIT,        /*  u8  iFeature */
-                }
-            },{
-                /* Headphone Ouptut Terminal ID3 Descriptor */
-                .data = (uint8_t[]) {
-                    0x09,                       /*  u8  bLength */
-                    USB_DT_CS_INTERFACE,        /*  u8  bDescriptorType */
-                    DST_AC_OUTPUT_TERMINAL,     /*  u8  bDescriptorSubtype */
-                    0x03,                       /*  u8  bUnitID */
-                    U16(0x0301),                /* u16  wTerminalType (SPK) */
-                    0x00,                       /*  u8  bAssocTerminal */
-                    0x02,                       /*  u8  bSourceID */
-                    STRING_OUTPUT_TERMINAL,     /*  u8  iTerminal */
-                }
-            }
-        },
-    },{
-        .bInterfaceNumber              = 1,
-        .bAlternateSetting             = 0,
-        .bNumEndpoints                 = 0,
-        .bInterfaceClass               = USB_CLASS_AUDIO,
-        .bInterfaceSubClass            = USB_SUBCLASS_AUDIO_STREAMING,
-        .iInterface                    = STRING_NULL_STREAM,
-    },{
-        .bInterfaceNumber              = 1,
-        .bAlternateSetting             = 1,
-        .bNumEndpoints                 = 1,
-        .bInterfaceClass               = USB_CLASS_AUDIO,
-        .bInterfaceSubClass            = USB_SUBCLASS_AUDIO_STREAMING,
-        .iInterface                    = STRING_REAL_STREAM,
-        .ndesc                         = 2,
-        .descs = (USBDescOther[]) {
-            {
-                /* Headphone Class-specific AS General Interface Descriptor */
-                .data = (uint8_t[]) {
-                    0x07,                       /*  u8  bLength */
-                    USB_DT_CS_INTERFACE,        /*  u8  bDescriptorType */
-                    DST_AS_GENERAL,             /*  u8  bDescriptorSubtype */
-                    0x01,                       /*  u8  bTerminalLink */
-                    0x00,                       /*  u8  bDelay */
-                    0x01, 0x00,                 /* u16  wFormatTag */
-                }
-            },{
-                /* Headphone Type I Format Type Descriptor */
-                .data = (uint8_t[]) {
-                    0x0b,                       /*  u8  bLength */
-                    USB_DT_CS_INTERFACE,        /*  u8  bDescriptorType */
-                    DST_AS_FORMAT_TYPE,         /*  u8  bDescriptorSubtype */
-                    0x01,                       /*  u8  bFormatType */
-                    0x02,                       /*  u8  bNrChannels */
-                    0x02,                       /*  u8  bSubFrameSize */
-                    0x10,                       /*  u8  bBitResolution */
-                    0x01,                       /*  u8  bSamFreqType */
-                    U24(USBAUDIO_SAMPLE_RATE),  /* u24  tSamFreq */
-                }
-            }
-        },
-        .eps = (USBDescEndpoint[]) {
-            {
-                .bEndpointAddress      = USB_DIR_OUT | 0x01,
-                .bmAttributes          = 0x0d,
-                .wMaxPacketSize        = USBAUDIO_PACKET_SIZE,
-                .bInterval             = 1,
-                .is_audio              = 1,
-                /* Stereo Headphone Class-specific
-                   AS Audio Data Endpoint Descriptor */
-                .extra = (uint8_t[]) {
-                    0x07,                       /*  u8  bLength */
-                    USB_DT_CS_ENDPOINT,         /*  u8  bDescriptorType */
-                    DST_EP_GENERAL,             /*  u8  bDescriptorSubtype */
-                    0x00,                       /*  u8  bmAttributes */
-                    0x00,                       /*  u8  bLockDelayUnits */
-                    U16(0x0000),                /* u16  wLockDelay */
-                },
-            },
-        }
-    }
-};
-
-static const USBDescDevice desc_device = {
-    .bcdUSB                        = 0x0200,
-    .bMaxPacketSize0               = 64,
-    .bNumConfigurations            = 1,
-    .confs = (USBDescConfig[]) {
-        {
-            .bNumInterfaces        = 2,
-            .bConfigurationValue   = DEV_CONFIG_VALUE,
-            .iConfiguration        = STRING_CONFIG,
-            .bmAttributes          = 0xc0,
-            .bMaxPower             = 0x32,
-            .nif = ARRAY_SIZE(desc_iface),
-            .ifs = desc_iface,
-        },
-    },
-};
-
-static const USBDesc desc_audio = {
-    .id = {
-        .idVendor          = USBAUDIO_VENDOR_NUM,
-        .idProduct         = USBAUDIO_PRODUCT_NUM,
-        .bcdDevice         = 0,
-        .iManufacturer     = STRING_MANUFACTURER,
-        .iProduct          = STRING_PRODUCT,
-        .iSerialNumber     = STRING_SERIALNUMBER,
-    },
-    .full = &desc_device,
-    .str  = usb_audio_stringtable,
-};
-
-/*
- * A USB audio device supports an arbitrary number of alternate
- * interface settings for each interface.  Each corresponds to a block
- * diagram of parameterized blocks.  This can thus refer to things like
- * number of channels, data rates, or in fact completely different
- * block diagrams.  Alternative setting 0 is always the null block diagram,
- * which is used by a disabled device.
- */
-enum usb_audio_altset {
-    ALTSET_OFF  = 0x00,         /* No endpoint */
-    ALTSET_ON   = 0x01,         /* Single endpoint */
-};
-
-/*
- * Class-specific control requests
- */
-#define CR_SET_CUR      0x01
-#define CR_GET_CUR      0x81
-#define CR_SET_MIN      0x02
-#define CR_GET_MIN      0x82
-#define CR_SET_MAX      0x03
-#define CR_GET_MAX      0x83
-#define CR_SET_RES      0x04
-#define CR_GET_RES      0x84
-#define CR_SET_MEM      0x05
-#define CR_GET_MEM      0x85
-#define CR_GET_STAT     0xff
-
-/*
- * Feature Unit Control Selectors
- */
-#define MUTE_CONTROL                    0x01
-#define VOLUME_CONTROL                  0x02
-#define BASS_CONTROL                    0x03
-#define MID_CONTROL                     0x04
-#define TREBLE_CONTROL                  0x05
-#define GRAPHIC_EQUALIZER_CONTROL       0x06
-#define AUTOMATIC_GAIN_CONTROL          0x07
-#define DELAY_CONTROL                   0x08
-#define BASS_BOOST_CONTROL              0x09
-#define LOUDNESS_CONTROL                0x0a
-
-/*
- * buffering
- */
-
-struct streambuf {
-    uint8_t *data;
-    uint32_t size;
-    uint32_t prod;
-    uint32_t cons;
-};
-
-static void streambuf_init(struct streambuf *buf, uint32_t size)
-{
-    g_free(buf->data);
-    buf->size = size - (size % USBAUDIO_PACKET_SIZE);
-    buf->data = g_malloc(buf->size);
-    buf->prod = 0;
-    buf->cons = 0;
-}
-
-static void streambuf_fini(struct streambuf *buf)
-{
-    g_free(buf->data);
-    buf->data = NULL;
-}
-
-static int streambuf_put(struct streambuf *buf, USBPacket *p)
-{
-    uint32_t free = buf->size - (buf->prod - buf->cons);
-
-    if (!free) {
-        return 0;
-    }
-    assert(free >= USBAUDIO_PACKET_SIZE);
-    usb_packet_copy(p, buf->data + (buf->prod % buf->size),
-                    USBAUDIO_PACKET_SIZE);
-    buf->prod += USBAUDIO_PACKET_SIZE;
-    return USBAUDIO_PACKET_SIZE;
-}
-
-static uint8_t *streambuf_get(struct streambuf *buf)
-{
-    uint32_t used = buf->prod - buf->cons;
-    uint8_t *data;
-
-    if (!used) {
-        return NULL;
-    }
-    assert(used >= USBAUDIO_PACKET_SIZE);
-    data = buf->data + (buf->cons % buf->size);
-    buf->cons += USBAUDIO_PACKET_SIZE;
-    return data;
-}
-
-typedef struct USBAudioState {
-    /* qemu interfaces */
-    USBDevice dev;
-    QEMUSoundCard card;
-
-    /* state */
-    struct {
-        enum usb_audio_altset altset;
-        struct audsettings as;
-        SWVoiceOut *voice;
-        bool mute;
-        uint8_t vol[2];
-        struct streambuf buf;
-    } out;
-
-    /* properties */
-    uint32_t debug;
-    uint32_t buffer;
-} USBAudioState;
-
-static void output_callback(void *opaque, int avail)
-{
-    USBAudioState *s = opaque;
-    uint8_t *data;
-
-    for (;;) {
-        if (avail < USBAUDIO_PACKET_SIZE) {
-            return;
-        }
-        data = streambuf_get(&s->out.buf);
-        if (NULL == data) {
-            return;
-        }
-        AUD_write(s->out.voice, data, USBAUDIO_PACKET_SIZE);
-        avail -= USBAUDIO_PACKET_SIZE;
-    }
-}
-
-static int usb_audio_set_output_altset(USBAudioState *s, int altset)
-{
-    switch (altset) {
-    case ALTSET_OFF:
-        streambuf_init(&s->out.buf, s->buffer);
-        AUD_set_active_out(s->out.voice, false);
-        break;
-    case ALTSET_ON:
-        AUD_set_active_out(s->out.voice, true);
-        break;
-    default:
-        return -1;
-    }
-
-    if (s->debug) {
-        fprintf(stderr, "usb-audio: set interface %d\n", altset);
-    }
-    s->out.altset = altset;
-    return 0;
-}
-
-/*
- * Note: we arbitrarily map the volume control range onto -inf..+8 dB
- */
-#define ATTRIB_ID(cs, attrib, idif)     \
-    (((cs) << 24) | ((attrib) << 16) | (idif))
-
-static int usb_audio_get_control(USBAudioState *s, uint8_t attrib,
-                                 uint16_t cscn, uint16_t idif,
-                                 int length, uint8_t *data)
-{
-    uint8_t cs = cscn >> 8;
-    uint8_t cn = cscn - 1;      /* -1 for the non-present master control */
-    uint32_t aid = ATTRIB_ID(cs, attrib, idif);
-    int ret = USB_RET_STALL;
-
-    switch (aid) {
-    case ATTRIB_ID(MUTE_CONTROL, CR_GET_CUR, 0x0200):
-        data[0] = s->out.mute;
-        ret = 1;
-        break;
-    case ATTRIB_ID(VOLUME_CONTROL, CR_GET_CUR, 0x0200):
-        if (cn < 2) {
-            uint16_t vol = (s->out.vol[cn] * 0x8800 + 127) / 255 + 0x8000;
-            data[0] = vol;
-            data[1] = vol >> 8;
-            ret = 2;
-        }
-        break;
-    case ATTRIB_ID(VOLUME_CONTROL, CR_GET_MIN, 0x0200):
-        if (cn < 2) {
-            data[0] = 0x01;
-            data[1] = 0x80;
-            ret = 2;
-        }
-        break;
-    case ATTRIB_ID(VOLUME_CONTROL, CR_GET_MAX, 0x0200):
-        if (cn < 2) {
-            data[0] = 0x00;
-            data[1] = 0x08;
-            ret = 2;
-        }
-        break;
-    case ATTRIB_ID(VOLUME_CONTROL, CR_GET_RES, 0x0200):
-        if (cn < 2) {
-            data[0] = 0x88;
-            data[1] = 0x00;
-            ret = 2;
-        }
-        break;
-    }
-
-    return ret;
-}
-static int usb_audio_set_control(USBAudioState *s, uint8_t attrib,
-                                 uint16_t cscn, uint16_t idif,
-                                 int length, uint8_t *data)
-{
-    uint8_t cs = cscn >> 8;
-    uint8_t cn = cscn - 1;      /* -1 for the non-present master control */
-    uint32_t aid = ATTRIB_ID(cs, attrib, idif);
-    int ret = USB_RET_STALL;
-    bool set_vol = false;
-
-    switch (aid) {
-    case ATTRIB_ID(MUTE_CONTROL, CR_SET_CUR, 0x0200):
-        s->out.mute = data[0] & 1;
-        set_vol = true;
-        ret = 0;
-        break;
-    case ATTRIB_ID(VOLUME_CONTROL, CR_SET_CUR, 0x0200):
-        if (cn < 2) {
-            uint16_t vol = data[0] + (data[1] << 8);
-
-            if (s->debug) {
-                fprintf(stderr, "usb-audio: vol %04x\n", (uint16_t)vol);
-            }
-
-            vol -= 0x8000;
-            vol = (vol * 255 + 0x4400) / 0x8800;
-            if (vol > 255) {
-                vol = 255;
-            }
-
-            s->out.vol[cn] = vol;
-            set_vol = true;
-            ret = 0;
-        }
-        break;
-    }
-
-    if (set_vol) {
-        if (s->debug) {
-            fprintf(stderr, "usb-audio: mute %d, lvol %3d, rvol %3d\n",
-                    s->out.mute, s->out.vol[0], s->out.vol[1]);
-        }
-        AUD_set_volume_out(s->out.voice, s->out.mute,
-                           s->out.vol[0], s->out.vol[1]);
-    }
-
-    return ret;
-}
-
-static int usb_audio_handle_control(USBDevice *dev, USBPacket *p,
-                                    int request, int value, int index,
-                                    int length, uint8_t *data)
-{
-    USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
-    int ret = 0;
-
-    if (s->debug) {
-        fprintf(stderr, "usb-audio: control transaction: "
-                "request 0x%04x value 0x%04x index 0x%04x length 0x%04x\n",
-                request, value, index, length);
-    }
-
-    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
-    if (ret >= 0) {
-        return ret;
-    }
-
-    switch (request) {
-    case ClassInterfaceRequest | CR_GET_CUR:
-    case ClassInterfaceRequest | CR_GET_MIN:
-    case ClassInterfaceRequest | CR_GET_MAX:
-    case ClassInterfaceRequest | CR_GET_RES:
-        ret = usb_audio_get_control(s, request & 0xff, value, index,
-                                    length, data);
-        if (ret < 0) {
-            if (s->debug) {
-                fprintf(stderr, "usb-audio: fail: get control\n");
-            }
-            goto fail;
-        }
-        break;
-
-    case ClassInterfaceOutRequest | CR_SET_CUR:
-    case ClassInterfaceOutRequest | CR_SET_MIN:
-    case ClassInterfaceOutRequest | CR_SET_MAX:
-    case ClassInterfaceOutRequest | CR_SET_RES:
-        ret = usb_audio_set_control(s, request & 0xff, value, index,
-                                    length, data);
-        if (ret < 0) {
-            if (s->debug) {
-                fprintf(stderr, "usb-audio: fail: set control\n");
-            }
-            goto fail;
-        }
-        break;
-
-    default:
-fail:
-        if (s->debug) {
-            fprintf(stderr, "usb-audio: failed control transaction: "
-                    "request 0x%04x value 0x%04x index 0x%04x length 0x%04x\n",
-                    request, value, index, length);
-        }
-        ret = USB_RET_STALL;
-        break;
-    }
-    return ret;
-}
-
-static void usb_audio_set_interface(USBDevice *dev, int iface,
-                                    int old, int value)
-{
-    USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
-
-    if (iface == 1) {
-        usb_audio_set_output_altset(s, value);
-    }
-}
-
-static void usb_audio_handle_reset(USBDevice *dev)
-{
-    USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
-
-    if (s->debug) {
-        fprintf(stderr, "usb-audio: reset\n");
-    }
-    usb_audio_set_output_altset(s, ALTSET_OFF);
-}
-
-static int usb_audio_handle_dataout(USBAudioState *s, USBPacket *p)
-{
-    int rc;
-
-    if (s->out.altset == ALTSET_OFF) {
-        return USB_RET_STALL;
-    }
-
-    rc = streambuf_put(&s->out.buf, p);
-    if (rc < p->iov.size && s->debug > 1) {
-        fprintf(stderr, "usb-audio: output overrun (%zd bytes)\n",
-                p->iov.size - rc);
-    }
-
-    return 0;
-}
-
-static int usb_audio_handle_data(USBDevice *dev, USBPacket *p)
-{
-    USBAudioState *s = (USBAudioState *) dev;
-    int ret = 0;
-
-    switch (p->pid) {
-    case USB_TOKEN_OUT:
-        switch (p->ep->nr) {
-        case 1:
-            ret = usb_audio_handle_dataout(s, p);
-            break;
-        default:
-            goto fail;
-        }
-        break;
-
-    default:
-fail:
-        ret = USB_RET_STALL;
-        break;
-    }
-    if (ret == USB_RET_STALL && s->debug) {
-        fprintf(stderr, "usb-audio: failed data transaction: "
-                        "pid 0x%x ep 0x%x len 0x%zx\n",
-                        p->pid, p->ep->nr, p->iov.size);
-    }
-    return ret;
-}
-
-static void usb_audio_handle_destroy(USBDevice *dev)
-{
-    USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
-
-    if (s->debug) {
-        fprintf(stderr, "usb-audio: destroy\n");
-    }
-
-    usb_audio_set_output_altset(s, ALTSET_OFF);
-    AUD_close_out(&s->card, s->out.voice);
-    AUD_remove_card(&s->card);
-
-    streambuf_fini(&s->out.buf);
-}
-
-static int usb_audio_initfn(USBDevice *dev)
-{
-    USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
-
-    usb_desc_init(dev);
-    s->dev.opaque = s;
-    AUD_register_card("usb-audio", &s->card);
-
-    s->out.altset        = ALTSET_OFF;
-    s->out.mute          = false;
-    s->out.vol[0]        = 240; /* 0 dB */
-    s->out.vol[1]        = 240; /* 0 dB */
-    s->out.as.freq       = USBAUDIO_SAMPLE_RATE;
-    s->out.as.nchannels  = 2;
-    s->out.as.fmt        = AUD_FMT_S16;
-    s->out.as.endianness = 0;
-    streambuf_init(&s->out.buf, s->buffer);
-
-    s->out.voice = AUD_open_out(&s->card, s->out.voice, "usb-audio",
-                                s, output_callback, &s->out.as);
-    AUD_set_volume_out(s->out.voice, s->out.mute, s->out.vol[0], s->out.vol[1]);
-    AUD_set_active_out(s->out.voice, 0);
-    return 0;
-}
-
-static const VMStateDescription vmstate_usb_audio = {
-    .name = "usb-audio",
-    .unmigratable = 1,
-};
-
-static Property usb_audio_properties[] = {
-    DEFINE_PROP_UINT32("debug", USBAudioState, debug, 0),
-    DEFINE_PROP_UINT32("buffer", USBAudioState, buffer,
-                       8 * USBAUDIO_PACKET_SIZE),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void usb_audio_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    USBDeviceClass *k = USB_DEVICE_CLASS(klass);
-
-    dc->vmsd          = &vmstate_usb_audio;
-    dc->props         = usb_audio_properties;
-    k->product_desc   = "QEMU USB Audio Interface";
-    k->usb_desc       = &desc_audio;
-    k->init           = usb_audio_initfn;
-    k->handle_reset   = usb_audio_handle_reset;
-    k->handle_control = usb_audio_handle_control;
-    k->handle_data    = usb_audio_handle_data;
-    k->handle_destroy = usb_audio_handle_destroy;
-    k->set_interface  = usb_audio_set_interface;
-}
-
-static TypeInfo usb_audio_info = {
-    .name          = "usb-audio",
-    .parent        = TYPE_USB_DEVICE,
-    .instance_size = sizeof(USBAudioState),
-    .class_init    = usb_audio_class_init,
-};
-
-static void usb_audio_register_types(void)
-{
-    type_register_static(&usb_audio_info);
-    usb_legacy_register("usb-audio", "audio", NULL);
-}
-
-type_init(usb_audio_register_types)
diff --git a/hw/usb-bt.c b/hw/usb-bt.c
deleted file mode 100644
index 23c39ec..0000000
--- a/hw/usb-bt.c
+++ /dev/null
@@ -1,557 +0,0 @@
-/*
- * QEMU Bluetooth HCI USB Transport Layer v1.0
- *
- * Copyright (C) 2007 OpenMoko, Inc.
- * Copyright (C) 2008 Andrzej Zaborowski  <balrog at zabor.org>
- *
- * 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 or
- * (at your option) version 3 of the License.
- *
- * 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 "qemu-common.h"
-#include "usb.h"
-#include "usb-desc.h"
-#include "net.h"
-#include "bt.h"
-
-struct USBBtState {
-    USBDevice dev;
-    struct HCIInfo *hci;
-
-    int config;
-
-#define CFIFO_LEN_MASK	255
-#define DFIFO_LEN_MASK	4095
-    struct usb_hci_in_fifo_s {
-        uint8_t data[(DFIFO_LEN_MASK + 1) * 2];
-        struct {
-            uint8_t *data;
-            int len;
-        } fifo[CFIFO_LEN_MASK + 1];
-        int dstart, dlen, dsize, start, len;
-    } evt, acl, sco;
-
-    struct usb_hci_out_fifo_s {
-        uint8_t data[4096];
-	int len;
-    } outcmd, outacl, outsco;
-};
-
-#define USB_EVT_EP	1
-#define USB_ACL_EP	2
-#define USB_SCO_EP	3
-
-enum {
-    STR_MANUFACTURER = 1,
-    STR_SERIALNUMBER,
-};
-
-static const USBDescStrings desc_strings = {
-    [STR_MANUFACTURER]     = "QEMU " QEMU_VERSION,
-    [STR_SERIALNUMBER]     = "1",
-};
-
-static const USBDescIface desc_iface_bluetooth[] = {
-    {
-        .bInterfaceNumber              = 0,
-        .bNumEndpoints                 = 3,
-        .bInterfaceClass               = 0xe0, /* Wireless */
-        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
-        .bInterfaceProtocol            = 0x01, /* Bluetooth */
-        .eps = (USBDescEndpoint[]) {
-            {
-                .bEndpointAddress      = USB_DIR_IN | USB_EVT_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_INT,
-                .wMaxPacketSize        = 0x10,
-                .bInterval             = 0x02,
-            },
-            {
-                .bEndpointAddress      = USB_DIR_OUT | USB_ACL_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_BULK,
-                .wMaxPacketSize        = 0x40,
-                .bInterval             = 0x0a,
-            },
-            {
-                .bEndpointAddress      = USB_DIR_IN | USB_ACL_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_BULK,
-                .wMaxPacketSize        = 0x40,
-                .bInterval             = 0x0a,
-            },
-        },
-    },{
-        .bInterfaceNumber              = 1,
-        .bAlternateSetting             = 0,
-        .bNumEndpoints                 = 2,
-        .bInterfaceClass               = 0xe0, /* Wireless */
-        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
-        .bInterfaceProtocol            = 0x01, /* Bluetooth */
-        .eps = (USBDescEndpoint[]) {
-            {
-                .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
-                .wMaxPacketSize        = 0,
-                .bInterval             = 0x01,
-            },
-            {
-                .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
-                .wMaxPacketSize        = 0,
-                .bInterval             = 0x01,
-            },
-        },
-    },{
-        .bInterfaceNumber              = 1,
-        .bAlternateSetting             = 1,
-        .bNumEndpoints                 = 2,
-        .bInterfaceClass               = 0xe0, /* Wireless */
-        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
-        .bInterfaceProtocol            = 0x01, /* Bluetooth */
-        .eps = (USBDescEndpoint[]) {
-            {
-                .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
-                .wMaxPacketSize        = 0x09,
-                .bInterval             = 0x01,
-            },
-            {
-                .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
-                .wMaxPacketSize        = 0x09,
-                .bInterval             = 0x01,
-            },
-        },
-    },{
-        .bInterfaceNumber              = 1,
-        .bAlternateSetting             = 2,
-        .bNumEndpoints                 = 2,
-        .bInterfaceClass               = 0xe0, /* Wireless */
-        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
-        .bInterfaceProtocol            = 0x01, /* Bluetooth */
-        .eps = (USBDescEndpoint[]) {
-            {
-                .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
-                .wMaxPacketSize        = 0x11,
-                .bInterval             = 0x01,
-            },
-            {
-                .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
-                .wMaxPacketSize        = 0x11,
-                .bInterval             = 0x01,
-            },
-        },
-    },{
-        .bInterfaceNumber              = 1,
-        .bAlternateSetting             = 3,
-        .bNumEndpoints                 = 2,
-        .bInterfaceClass               = 0xe0, /* Wireless */
-        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
-        .bInterfaceProtocol            = 0x01, /* Bluetooth */
-        .eps = (USBDescEndpoint[]) {
-            {
-                .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
-                .wMaxPacketSize        = 0x19,
-                .bInterval             = 0x01,
-            },
-            {
-                .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
-                .wMaxPacketSize        = 0x19,
-                .bInterval             = 0x01,
-            },
-        },
-    },{
-        .bInterfaceNumber              = 1,
-        .bAlternateSetting             = 4,
-        .bNumEndpoints                 = 2,
-        .bInterfaceClass               = 0xe0, /* Wireless */
-        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
-        .bInterfaceProtocol            = 0x01, /* Bluetooth */
-        .eps = (USBDescEndpoint[]) {
-            {
-                .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
-                .wMaxPacketSize        = 0x21,
-                .bInterval             = 0x01,
-            },
-            {
-                .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
-                .wMaxPacketSize        = 0x21,
-                .bInterval             = 0x01,
-            },
-        },
-    },{
-        .bInterfaceNumber              = 1,
-        .bAlternateSetting             = 5,
-        .bNumEndpoints                 = 2,
-        .bInterfaceClass               = 0xe0, /* Wireless */
-        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
-        .bInterfaceProtocol            = 0x01, /* Bluetooth */
-        .eps = (USBDescEndpoint[]) {
-            {
-                .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
-                .wMaxPacketSize        = 0x31,
-                .bInterval             = 0x01,
-            },
-            {
-                .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
-                .wMaxPacketSize        = 0x31,
-                .bInterval             = 0x01,
-            },
-        },
-    }
-};
-
-static const USBDescDevice desc_device_bluetooth = {
-    .bcdUSB                        = 0x0110,
-    .bDeviceClass                  = 0xe0, /* Wireless */
-    .bDeviceSubClass               = 0x01, /* Radio Frequency */
-    .bDeviceProtocol               = 0x01, /* Bluetooth */
-    .bMaxPacketSize0               = 64,
-    .bNumConfigurations            = 1,
-    .confs = (USBDescConfig[]) {
-        {
-            .bNumInterfaces        = 2,
-            .bConfigurationValue   = 1,
-            .bmAttributes          = 0xc0,
-            .bMaxPower             = 0,
-            .nif = ARRAY_SIZE(desc_iface_bluetooth),
-            .ifs = desc_iface_bluetooth,
-        },
-    },
-};
-
-static const USBDesc desc_bluetooth = {
-    .id = {
-        .idVendor          = 0x0a12,
-        .idProduct         = 0x0001,
-        .bcdDevice         = 0x1958,
-        .iManufacturer     = STR_MANUFACTURER,
-        .iProduct          = 0,
-        .iSerialNumber     = STR_SERIALNUMBER,
-    },
-    .full = &desc_device_bluetooth,
-    .str  = desc_strings,
-};
-
-static void usb_bt_fifo_reset(struct usb_hci_in_fifo_s *fifo)
-{
-    fifo->dstart = 0;
-    fifo->dlen = 0;
-    fifo->dsize = DFIFO_LEN_MASK + 1;
-    fifo->start = 0;
-    fifo->len = 0;
-}
-
-static void usb_bt_fifo_enqueue(struct usb_hci_in_fifo_s *fifo,
-                const uint8_t *data, int len)
-{
-    int off = fifo->dstart + fifo->dlen;
-    uint8_t *buf;
-
-    fifo->dlen += len;
-    if (off <= DFIFO_LEN_MASK) {
-        if (off + len > DFIFO_LEN_MASK + 1 &&
-                        (fifo->dsize = off + len) > (DFIFO_LEN_MASK + 1) * 2) {
-            fprintf(stderr, "%s: can't alloc %i bytes\n", __FUNCTION__, len);
-            exit(-1);
-        }
-        buf = fifo->data + off;
-    } else {
-        if (fifo->dlen > fifo->dsize) {
-            fprintf(stderr, "%s: can't alloc %i bytes\n", __FUNCTION__, len);
-            exit(-1);
-        }
-        buf = fifo->data + off - fifo->dsize;
-    }
-
-    off = (fifo->start + fifo->len ++) & CFIFO_LEN_MASK;
-    fifo->fifo[off].data = memcpy(buf, data, len);
-    fifo->fifo[off].len = len;
-}
-
-static inline int usb_bt_fifo_dequeue(struct usb_hci_in_fifo_s *fifo,
-                USBPacket *p)
-{
-    int len;
-
-    if (likely(!fifo->len))
-        return USB_RET_STALL;
-
-    len = MIN(p->iov.size, fifo->fifo[fifo->start].len);
-    usb_packet_copy(p, fifo->fifo[fifo->start].data, len);
-    if (len == p->iov.size) {
-        fifo->fifo[fifo->start].len -= len;
-        fifo->fifo[fifo->start].data += len;
-    } else {
-        fifo->start ++;
-        fifo->start &= CFIFO_LEN_MASK;
-        fifo->len --;
-    }
-
-    fifo->dstart += len;
-    fifo->dlen -= len;
-    if (fifo->dstart >= fifo->dsize) {
-        fifo->dstart = 0;
-        fifo->dsize = DFIFO_LEN_MASK + 1;
-    }
-
-    return len;
-}
-
-static inline void usb_bt_fifo_out_enqueue(struct USBBtState *s,
-                struct usb_hci_out_fifo_s *fifo,
-                void (*send)(struct HCIInfo *, const uint8_t *, int),
-                int (*complete)(const uint8_t *, int),
-                USBPacket *p)
-{
-    usb_packet_copy(p, fifo->data + fifo->len, p->iov.size);
-    fifo->len += p->iov.size;
-    if (complete(fifo->data, fifo->len)) {
-        send(s->hci, fifo->data, fifo->len);
-        fifo->len = 0;
-    }
-
-    /* TODO: do we need to loop? */
-}
-
-static int usb_bt_hci_cmd_complete(const uint8_t *data, int len)
-{
-    len -= HCI_COMMAND_HDR_SIZE;
-    return len >= 0 &&
-            len >= ((struct hci_command_hdr *) data)->plen;
-}
-
-static int usb_bt_hci_acl_complete(const uint8_t *data, int len)
-{
-    len -= HCI_ACL_HDR_SIZE;
-    return len >= 0 &&
-            len >= le16_to_cpu(((struct hci_acl_hdr *) data)->dlen);
-}
-
-static int usb_bt_hci_sco_complete(const uint8_t *data, int len)
-{
-    len -= HCI_SCO_HDR_SIZE;
-    return len >= 0 &&
-            len >= ((struct hci_sco_hdr *) data)->dlen;
-}
-
-static void usb_bt_handle_reset(USBDevice *dev)
-{
-    struct USBBtState *s = (struct USBBtState *) dev->opaque;
-
-    usb_bt_fifo_reset(&s->evt);
-    usb_bt_fifo_reset(&s->acl);
-    usb_bt_fifo_reset(&s->sco);
-    s->outcmd.len = 0;
-    s->outacl.len = 0;
-    s->outsco.len = 0;
-}
-
-static int usb_bt_handle_control(USBDevice *dev, USBPacket *p,
-               int request, int value, int index, int length, uint8_t *data)
-{
-    struct USBBtState *s = (struct USBBtState *) dev->opaque;
-    int ret;
-
-    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
-    if (ret >= 0) {
-        switch (request) {
-        case DeviceRequest | USB_REQ_GET_CONFIGURATION:
-            s->config = 0;
-            break;
-        case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
-            s->config = 1;
-            usb_bt_fifo_reset(&s->evt);
-            usb_bt_fifo_reset(&s->acl);
-            usb_bt_fifo_reset(&s->sco);
-            break;
-        }
-        return ret;
-    }
-
-    ret = 0;
-    switch (request) {
-    case InterfaceRequest | USB_REQ_GET_STATUS:
-    case EndpointRequest | USB_REQ_GET_STATUS:
-        data[0] = 0x00;
-        data[1] = 0x00;
-        ret = 2;
-        break;
-    case InterfaceOutRequest | USB_REQ_CLEAR_FEATURE:
-    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
-        goto fail;
-    case InterfaceOutRequest | USB_REQ_SET_FEATURE:
-    case EndpointOutRequest | USB_REQ_SET_FEATURE:
-        goto fail;
-        break;
-    case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_DEVICE) << 8):
-        if (s->config)
-            usb_bt_fifo_out_enqueue(s, &s->outcmd, s->hci->cmd_send,
-                            usb_bt_hci_cmd_complete, p);
-        break;
-    default:
-    fail:
-        ret = USB_RET_STALL;
-        break;
-    }
-    return ret;
-}
-
-static int usb_bt_handle_data(USBDevice *dev, USBPacket *p)
-{
-    struct USBBtState *s = (struct USBBtState *) dev->opaque;
-    int ret = 0;
-
-    if (!s->config)
-        goto fail;
-
-    switch (p->pid) {
-    case USB_TOKEN_IN:
-        switch (p->ep->nr) {
-        case USB_EVT_EP:
-            ret = usb_bt_fifo_dequeue(&s->evt, p);
-            break;
-
-        case USB_ACL_EP:
-            ret = usb_bt_fifo_dequeue(&s->acl, p);
-            break;
-
-        case USB_SCO_EP:
-            ret = usb_bt_fifo_dequeue(&s->sco, p);
-            break;
-
-        default:
-            goto fail;
-        }
-        break;
-
-    case USB_TOKEN_OUT:
-        switch (p->ep->nr) {
-        case USB_ACL_EP:
-            usb_bt_fifo_out_enqueue(s, &s->outacl, s->hci->acl_send,
-                            usb_bt_hci_acl_complete, p);
-            break;
-
-        case USB_SCO_EP:
-            usb_bt_fifo_out_enqueue(s, &s->outsco, s->hci->sco_send,
-                            usb_bt_hci_sco_complete, p);
-            break;
-
-        default:
-            goto fail;
-        }
-        break;
-
-    default:
-    fail:
-        ret = USB_RET_STALL;
-        break;
-    }
-
-    return ret;
-}
-
-static void usb_bt_out_hci_packet_event(void *opaque,
-                const uint8_t *data, int len)
-{
-    struct USBBtState *s = (struct USBBtState *) opaque;
-
-    usb_bt_fifo_enqueue(&s->evt, data, len);
-}
-
-static void usb_bt_out_hci_packet_acl(void *opaque,
-                const uint8_t *data, int len)
-{
-    struct USBBtState *s = (struct USBBtState *) opaque;
-
-    usb_bt_fifo_enqueue(&s->acl, data, len);
-}
-
-static void usb_bt_handle_destroy(USBDevice *dev)
-{
-    struct USBBtState *s = (struct USBBtState *) dev->opaque;
-
-    s->hci->opaque = NULL;
-    s->hci->evt_recv = NULL;
-    s->hci->acl_recv = NULL;
-}
-
-static int usb_bt_initfn(USBDevice *dev)
-{
-    usb_desc_init(dev);
-    return 0;
-}
-
-USBDevice *usb_bt_init(USBBus *bus, HCIInfo *hci)
-{
-    USBDevice *dev;
-    struct USBBtState *s;
-
-    if (!hci)
-        return NULL;
-    dev = usb_create_simple(bus, "usb-bt-dongle");
-    if (!dev) {
-        return NULL;
-    }
-    s = DO_UPCAST(struct USBBtState, dev, dev);
-    s->dev.opaque = s;
-
-    s->hci = hci;
-    s->hci->opaque = s;
-    s->hci->evt_recv = usb_bt_out_hci_packet_event;
-    s->hci->acl_recv = usb_bt_out_hci_packet_acl;
-
-    usb_bt_handle_reset(&s->dev);
-
-    return dev;
-}
-
-static const VMStateDescription vmstate_usb_bt = {
-    .name = "usb-bt",
-    .unmigratable = 1,
-};
-
-static void usb_bt_class_initfn(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
-
-    uc->init           = usb_bt_initfn;
-    uc->product_desc   = "QEMU BT dongle";
-    uc->usb_desc       = &desc_bluetooth;
-    uc->handle_reset   = usb_bt_handle_reset;
-    uc->handle_control = usb_bt_handle_control;
-    uc->handle_data    = usb_bt_handle_data;
-    uc->handle_destroy = usb_bt_handle_destroy;
-    dc->vmsd = &vmstate_usb_bt;
-}
-
-static TypeInfo bt_info = {
-    .name          = "usb-bt-dongle",
-    .parent        = TYPE_USB_DEVICE,
-    .instance_size = sizeof(struct USBBtState),
-    .class_init    = usb_bt_class_initfn,
-};
-
-static void usb_bt_register_types(void)
-{
-    type_register_static(&bt_info);
-}
-
-type_init(usb_bt_register_types)
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
deleted file mode 100644
index 70b7ebc..0000000
--- a/hw/usb-bus.c
+++ /dev/null
@@ -1,584 +0,0 @@
-#include "hw.h"
-#include "usb.h"
-#include "qdev.h"
-#include "sysemu.h"
-#include "monitor.h"
-#include "trace.h"
-
-static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
-
-static char *usb_get_dev_path(DeviceState *dev);
-static char *usb_get_fw_dev_path(DeviceState *qdev);
-static int usb_qdev_exit(DeviceState *qdev);
-
-static struct BusInfo usb_bus_info = {
-    .name      = "USB",
-    .size      = sizeof(USBBus),
-    .print_dev = usb_bus_dev_print,
-    .get_dev_path = usb_get_dev_path,
-    .get_fw_dev_path = usb_get_fw_dev_path,
-    .props      = (Property[]) {
-        DEFINE_PROP_STRING("port", USBDevice, port_path),
-        DEFINE_PROP_END_OF_LIST()
-    },
-};
-static int next_usb_bus = 0;
-static QTAILQ_HEAD(, USBBus) busses = QTAILQ_HEAD_INITIALIZER(busses);
-
-const VMStateDescription vmstate_usb_device = {
-    .name = "USBDevice",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .fields = (VMStateField []) {
-        VMSTATE_UINT8(addr, USBDevice),
-        VMSTATE_INT32(state, USBDevice),
-        VMSTATE_INT32(remote_wakeup, USBDevice),
-        VMSTATE_INT32(setup_state, USBDevice),
-        VMSTATE_INT32(setup_len, USBDevice),
-        VMSTATE_INT32(setup_index, USBDevice),
-        VMSTATE_UINT8_ARRAY(setup_buf, USBDevice, 8),
-        VMSTATE_END_OF_LIST(),
-    }
-};
-
-void usb_bus_new(USBBus *bus, USBBusOps *ops, DeviceState *host)
-{
-    qbus_create_inplace(&bus->qbus, &usb_bus_info, host, NULL);
-    bus->ops = ops;
-    bus->busnr = next_usb_bus++;
-    bus->qbus.allow_hotplug = 1; /* Yes, we can */
-    QTAILQ_INIT(&bus->free);
-    QTAILQ_INIT(&bus->used);
-    QTAILQ_INSERT_TAIL(&busses, bus, next);
-}
-
-USBBus *usb_bus_find(int busnr)
-{
-    USBBus *bus;
-
-    if (-1 == busnr)
-        return QTAILQ_FIRST(&busses);
-    QTAILQ_FOREACH(bus, &busses, next) {
-        if (bus->busnr == busnr)
-            return bus;
-    }
-    return NULL;
-}
-
-static int usb_device_init(USBDevice *dev)
-{
-    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
-    if (klass->init) {
-        return klass->init(dev);
-    }
-    return 0;
-}
-
-USBDevice *usb_device_find_device(USBDevice *dev, uint8_t addr)
-{
-    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
-    if (klass->find_device) {
-        return klass->find_device(dev, addr);
-    }
-    return NULL;
-}
-
-static void usb_device_handle_destroy(USBDevice *dev)
-{
-    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
-    if (klass->handle_destroy) {
-        klass->handle_destroy(dev);
-    }
-}
-
-void usb_device_cancel_packet(USBDevice *dev, USBPacket *p)
-{
-    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
-    if (klass->cancel_packet) {
-        klass->cancel_packet(dev, p);
-    }
-}
-
-void usb_device_handle_attach(USBDevice *dev)
-{
-    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
-    if (klass->handle_attach) {
-        klass->handle_attach(dev);
-    }
-}
-
-void usb_device_handle_reset(USBDevice *dev)
-{
-    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
-    if (klass->handle_reset) {
-        klass->handle_reset(dev);
-    }
-}
-
-int usb_device_handle_control(USBDevice *dev, USBPacket *p, int request,
-                              int value, int index, int length, uint8_t *data)
-{
-    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
-    if (klass->handle_control) {
-        return klass->handle_control(dev, p, request, value, index, length,
-                                         data);
-    }
-    return -ENOSYS;
-}
-
-int usb_device_handle_data(USBDevice *dev, USBPacket *p)
-{
-    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
-    if (klass->handle_data) {
-        return klass->handle_data(dev, p);
-    }
-    return -ENOSYS;
-}
-
-const char *usb_device_get_product_desc(USBDevice *dev)
-{
-    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
-    return klass->product_desc;
-}
-
-const USBDesc *usb_device_get_usb_desc(USBDevice *dev)
-{
-    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
-    return klass->usb_desc;
-}
-
-void usb_device_set_interface(USBDevice *dev, int interface,
-                              int alt_old, int alt_new)
-{
-    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
-    if (klass->set_interface) {
-        klass->set_interface(dev, interface, alt_old, alt_new);
-    }
-}
-
-static int usb_qdev_init(DeviceState *qdev)
-{
-    USBDevice *dev = USB_DEVICE(qdev);
-    int rc;
-
-    pstrcpy(dev->product_desc, sizeof(dev->product_desc),
-            usb_device_get_product_desc(dev));
-    dev->auto_attach = 1;
-    QLIST_INIT(&dev->strings);
-    usb_ep_init(dev);
-    rc = usb_claim_port(dev);
-    if (rc != 0) {
-        return rc;
-    }
-    rc = usb_device_init(dev);
-    if (rc != 0) {
-        usb_release_port(dev);
-        return rc;
-    }
-    if (dev->auto_attach) {
-        rc = usb_device_attach(dev);
-        if (rc != 0) {
-            usb_qdev_exit(qdev);
-            return rc;
-        }
-    }
-    return 0;
-}
-
-static int usb_qdev_exit(DeviceState *qdev)
-{
-    USBDevice *dev = USB_DEVICE(qdev);
-
-    if (dev->attached) {
-        usb_device_detach(dev);
-    }
-    usb_device_handle_destroy(dev);
-    if (dev->port) {
-        usb_release_port(dev);
-    }
-    return 0;
-}
-
-typedef struct LegacyUSBFactory
-{
-    const char *name;
-    const char *usbdevice_name;
-    USBDevice *(*usbdevice_init)(USBBus *bus, const char *params);
-} LegacyUSBFactory;
-
-static GSList *legacy_usb_factory;
-
-void usb_legacy_register(const char *typename, const char *usbdevice_name,
-                         USBDevice *(*usbdevice_init)(USBBus *bus,
-                                                      const char *params))
-{
-    if (usbdevice_name) {
-        LegacyUSBFactory *f = g_malloc0(sizeof(*f));
-        f->name = typename;
-        f->usbdevice_name = usbdevice_name;
-        f->usbdevice_init = usbdevice_init;
-        legacy_usb_factory = g_slist_append(legacy_usb_factory, f);
-    }
-}
-
-USBDevice *usb_create(USBBus *bus, const char *name)
-{
-    DeviceState *dev;
-
-    dev = qdev_create(&bus->qbus, name);
-    return USB_DEVICE(dev);
-}
-
-USBDevice *usb_create_simple(USBBus *bus, const char *name)
-{
-    USBDevice *dev = usb_create(bus, name);
-    int rc;
-
-    if (!dev) {
-        error_report("Failed to create USB device '%s'", name);
-        return NULL;
-    }
-    rc = qdev_init(&dev->qdev);
-    if (rc < 0) {
-        error_report("Failed to initialize USB device '%s'", name);
-        return NULL;
-    }
-    return dev;
-}
-
-static void usb_fill_port(USBPort *port, void *opaque, int index,
-                          USBPortOps *ops, int speedmask)
-{
-    port->opaque = opaque;
-    port->index = index;
-    port->ops = ops;
-    port->speedmask = speedmask;
-    usb_port_location(port, NULL, index + 1);
-}
-
-void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
-                       USBPortOps *ops, int speedmask)
-{
-    usb_fill_port(port, opaque, index, ops, speedmask);
-    QTAILQ_INSERT_TAIL(&bus->free, port, next);
-    bus->nfree++;
-}
-
-int usb_register_companion(const char *masterbus, USBPort *ports[],
-                           uint32_t portcount, uint32_t firstport,
-                           void *opaque, USBPortOps *ops, int speedmask)
-{
-    USBBus *bus;
-    int i;
-
-    QTAILQ_FOREACH(bus, &busses, next) {
-        if (strcmp(bus->qbus.name, masterbus) == 0) {
-            break;
-        }
-    }
-
-    if (!bus || !bus->ops->register_companion) {
-        qerror_report(QERR_INVALID_PARAMETER_VALUE, "masterbus",
-                      "an USB masterbus");
-        if (bus) {
-            error_printf_unless_qmp(
-                "USB bus '%s' does not allow companion controllers\n",
-                masterbus);
-        }
-        return -1;
-    }
-
-    for (i = 0; i < portcount; i++) {
-        usb_fill_port(ports[i], opaque, i, ops, speedmask);
-    }
-
-    return bus->ops->register_companion(bus, ports, portcount, firstport);
-}
-
-void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr)
-{
-    if (upstream) {
-        snprintf(downstream->path, sizeof(downstream->path), "%s.%d",
-                 upstream->path, portnr);
-    } else {
-        snprintf(downstream->path, sizeof(downstream->path), "%d", portnr);
-    }
-}
-
-void usb_unregister_port(USBBus *bus, USBPort *port)
-{
-    if (port->dev)
-        qdev_free(&port->dev->qdev);
-    QTAILQ_REMOVE(&bus->free, port, next);
-    bus->nfree--;
-}
-
-int usb_claim_port(USBDevice *dev)
-{
-    USBBus *bus = usb_bus_from_device(dev);
-    USBPort *port;
-
-    assert(dev->port == NULL);
-
-    if (dev->port_path) {
-        QTAILQ_FOREACH(port, &bus->free, next) {
-            if (strcmp(port->path, dev->port_path) == 0) {
-                break;
-            }
-        }
-        if (port == NULL) {
-            error_report("Error: usb port %s (bus %s) not found (in use?)",
-                         dev->port_path, bus->qbus.name);
-            return -1;
-        }
-    } else {
-        if (bus->nfree == 1 && strcmp(object_get_typename(OBJECT(dev)), "usb-hub") != 0) {
-            /* Create a new hub and chain it on */
-            usb_create_simple(bus, "usb-hub");
-        }
-        if (bus->nfree == 0) {
-            error_report("Error: tried to attach usb device %s to a bus "
-                         "with no free ports", dev->product_desc);
-            return -1;
-        }
-        port = QTAILQ_FIRST(&bus->free);
-    }
-    trace_usb_port_claim(bus->busnr, port->path);
-
-    QTAILQ_REMOVE(&bus->free, port, next);
-    bus->nfree--;
-
-    dev->port = port;
-    port->dev = dev;
-
-    QTAILQ_INSERT_TAIL(&bus->used, port, next);
-    bus->nused++;
-    return 0;
-}
-
-void usb_release_port(USBDevice *dev)
-{
-    USBBus *bus = usb_bus_from_device(dev);
-    USBPort *port = dev->port;
-
-    assert(port != NULL);
-    trace_usb_port_release(bus->busnr, port->path);
-
-    QTAILQ_REMOVE(&bus->used, port, next);
-    bus->nused--;
-
-    dev->port = NULL;
-    port->dev = NULL;
-
-    QTAILQ_INSERT_TAIL(&bus->free, port, next);
-    bus->nfree++;
-}
-
-int usb_device_attach(USBDevice *dev)
-{
-    USBBus *bus = usb_bus_from_device(dev);
-    USBPort *port = dev->port;
-
-    assert(port != NULL);
-    assert(!dev->attached);
-    trace_usb_port_attach(bus->busnr, port->path);
-
-    if (!(port->speedmask & dev->speedmask)) {
-        error_report("Warning: speed mismatch trying to attach "
-                     "usb device %s to bus %s",
-                     dev->product_desc, bus->qbus.name);
-        return -1;
-    }
-
-    dev->attached++;
-    usb_attach(port);
-
-    return 0;
-}
-
-int usb_device_detach(USBDevice *dev)
-{
-    USBBus *bus = usb_bus_from_device(dev);
-    USBPort *port = dev->port;
-
-    assert(port != NULL);
-    assert(dev->attached);
-    trace_usb_port_detach(bus->busnr, port->path);
-
-    usb_detach(port);
-    dev->attached--;
-    return 0;
-}
-
-int usb_device_delete_addr(int busnr, int addr)
-{
-    USBBus *bus;
-    USBPort *port;
-    USBDevice *dev;
-
-    bus = usb_bus_find(busnr);
-    if (!bus)
-        return -1;
-
-    QTAILQ_FOREACH(port, &bus->used, next) {
-        if (port->dev->addr == addr)
-            break;
-    }
-    if (!port)
-        return -1;
-    dev = port->dev;
-
-    qdev_free(&dev->qdev);
-    return 0;
-}
-
-static const char *usb_speed(unsigned int speed)
-{
-    static const char *txt[] = {
-        [ USB_SPEED_LOW  ] = "1.5",
-        [ USB_SPEED_FULL ] = "12",
-        [ USB_SPEED_HIGH ] = "480",
-        [ USB_SPEED_SUPER ] = "5000",
-    };
-    if (speed >= ARRAY_SIZE(txt))
-        return "?";
-    return txt[speed];
-}
-
-static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
-{
-    USBDevice *dev = USB_DEVICE(qdev);
-    USBBus *bus = usb_bus_from_device(dev);
-
-    monitor_printf(mon, "%*saddr %d.%d, port %s, speed %s, name %s%s\n",
-                   indent, "", bus->busnr, dev->addr,
-                   dev->port ? dev->port->path : "-",
-                   usb_speed(dev->speed), dev->product_desc,
-                   dev->attached ? ", attached" : "");
-}
-
-static char *usb_get_dev_path(DeviceState *qdev)
-{
-    USBDevice *dev = USB_DEVICE(qdev);
-    return g_strdup(dev->port->path);
-}
-
-static char *usb_get_fw_dev_path(DeviceState *qdev)
-{
-    USBDevice *dev = USB_DEVICE(qdev);
-    char *fw_path, *in;
-    ssize_t pos = 0, fw_len;
-    long nr;
-
-    fw_len = 32 + strlen(dev->port->path) * 6;
-    fw_path = g_malloc(fw_len);
-    in = dev->port->path;
-    while (fw_len - pos > 0) {
-        nr = strtol(in, &in, 10);
-        if (in[0] == '.') {
-            /* some hub between root port and device */
-            pos += snprintf(fw_path + pos, fw_len - pos, "hub@%ld/", nr);
-            in++;
-        } else {
-            /* the device itself */
-            pos += snprintf(fw_path + pos, fw_len - pos, "%s@%ld",
-                            qdev_fw_name(qdev), nr);
-            break;
-        }
-    }
-    return fw_path;
-}
-
-void usb_info(Monitor *mon)
-{
-    USBBus *bus;
-    USBDevice *dev;
-    USBPort *port;
-
-    if (QTAILQ_EMPTY(&busses)) {
-        monitor_printf(mon, "USB support not enabled\n");
-        return;
-    }
-
-    QTAILQ_FOREACH(bus, &busses, next) {
-        QTAILQ_FOREACH(port, &bus->used, next) {
-            dev = port->dev;
-            if (!dev)
-                continue;
-            monitor_printf(mon, "  Device %d.%d, Port %s, Speed %s Mb/s, Product %s\n",
-                           bus->busnr, dev->addr, port->path, usb_speed(dev->speed),
-                           dev->product_desc);
-        }
-    }
-}
-
-/* handle legacy -usbdevice cmd line option */
-USBDevice *usbdevice_create(const char *cmdline)
-{
-    USBBus *bus = usb_bus_find(-1 /* any */);
-    LegacyUSBFactory *f = NULL;
-    GSList *i;
-    char driver[32];
-    const char *params;
-    int len;
-
-    params = strchr(cmdline,':');
-    if (params) {
-        params++;
-        len = params - cmdline;
-        if (len > sizeof(driver))
-            len = sizeof(driver);
-        pstrcpy(driver, len, cmdline);
-    } else {
-        params = "";
-        pstrcpy(driver, sizeof(driver), cmdline);
-    }
-
-    for (i = legacy_usb_factory; i; i = i->next) {
-        f = i->data;
-        if (strcmp(f->usbdevice_name, driver) == 0) {
-            break;
-        }
-    }
-    if (i == NULL) {
-#if 0
-        /* no error because some drivers are not converted (yet) */
-        error_report("usbdevice %s not found", driver);
-#endif
-        return NULL;
-    }
-
-    if (!f->usbdevice_init) {
-        if (*params) {
-            error_report("usbdevice %s accepts no params", driver);
-            return NULL;
-        }
-        return usb_create_simple(bus, f->name);
-    }
-    return f->usbdevice_init(bus, params);
-}
-
-static void usb_device_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *k = DEVICE_CLASS(klass);
-    k->bus_info = &usb_bus_info;
-    k->init     = usb_qdev_init;
-    k->unplug   = qdev_simple_unplug_cb;
-    k->exit     = usb_qdev_exit;
-}
-
-static TypeInfo usb_device_type_info = {
-    .name = TYPE_USB_DEVICE,
-    .parent = TYPE_DEVICE,
-    .instance_size = sizeof(USBDevice),
-    .abstract = true,
-    .class_size = sizeof(USBDeviceClass),
-    .class_init = usb_device_class_init,
-};
-
-static void usb_register_types(void)
-{
-    type_register_static(&usb_device_type_info);
-}
-
-type_init(usb_register_types)
diff --git a/hw/usb-ccid.c b/hw/usb-ccid.c
deleted file mode 100644
index ced687f..0000000
--- a/hw/usb-ccid.c
+++ /dev/null
@@ -1,1365 +0,0 @@
-/*
- * Copyright (C) 2011 Red Hat, Inc.
- *
- * CCID Device emulation
- *
- * Written by Alon Levy, with contributions from Robert Relyea.
- *
- * Based on usb-serial.c, see its copyright and attributions below.
- *
- * This work is licensed under the terms of the GNU GPL, version 2.1 or later.
- * See the COPYING file in the top-level directory.
- * ------- (original copyright & attribution for usb-serial.c below) --------
- * Copyright (c) 2006 CodeSourcery.
- * Copyright (c) 2008 Samuel Thibault <samuel.thibault at ens-lyon.org>
- * Written by Paul Brook, reused for FTDI by Samuel Thibault,
- */
-
-/*
- * References:
- *
- * CCID Specification Revision 1.1 April 22nd 2005
- *  "Universal Serial Bus, Device Class: Smart Card"
- *  Specification for Integrated Circuit(s) Cards Interface Devices
- *
- * Endianness note: from the spec (1.3)
- *  "Fields that are larger than a byte are stored in little endian"
- *
- * KNOWN BUGS
- * 1. remove/insert can sometimes result in removed state instead of inserted.
- * This is a result of the following:
- *  symptom: dmesg shows ERMOTEIO (-121), pcscd shows -99. This can happen
- *  when a short packet is sent, as seen in uhci-usb.c, resulting from a urb
- *  from the guest requesting SPD and us returning a smaller packet.
- *  Not sure which messages trigger this.
- */
-
-#include "qemu-common.h"
-#include "qemu-error.h"
-#include "usb.h"
-#include "usb-desc.h"
-#include "monitor.h"
-
-#include "hw/ccid.h"
-
-#define DPRINTF(s, lvl, fmt, ...) \
-do { \
-    if (lvl <= s->debug) { \
-        printf("usb-ccid: " fmt , ## __VA_ARGS__); \
-    } \
-} while (0)
-
-#define D_WARN 1
-#define D_INFO 2
-#define D_MORE_INFO 3
-#define D_VERBOSE 4
-
-#define CCID_DEV_NAME "usb-ccid"
-
-/*
- * The two options for variable sized buffers:
- * make them constant size, for large enough constant,
- * or handle the migration complexity - VMState doesn't handle this case.
- * sizes are expected never to be exceeded, unless guest misbehaves.
- */
-#define BULK_OUT_DATA_SIZE 65536
-#define PENDING_ANSWERS_NUM 128
-
-#define BULK_IN_BUF_SIZE 384
-#define BULK_IN_PENDING_NUM 8
-
-#define InterfaceOutClass \
-    ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)<<8)
-
-#define InterfaceInClass  \
-    ((USB_DIR_IN  | USB_TYPE_CLASS | USB_RECIP_INTERFACE)<<8)
-
-#define CCID_MAX_PACKET_SIZE                64
-
-#define CCID_CONTROL_ABORT                  0x1
-#define CCID_CONTROL_GET_CLOCK_FREQUENCIES  0x2
-#define CCID_CONTROL_GET_DATA_RATES         0x3
-
-#define CCID_PRODUCT_DESCRIPTION        "QEMU USB CCID"
-#define CCID_VENDOR_DESCRIPTION         "QEMU " QEMU_VERSION
-#define CCID_INTERFACE_NAME             "CCID Interface"
-#define CCID_SERIAL_NUMBER_STRING       "1"
-/*
- * Using Gemplus Vendor and Product id
- * Effect on various drivers:
- *  usbccid.sys (winxp, others untested) is a class driver so it doesn't care.
- *  linux has a number of class drivers, but openct filters based on
- *   vendor/product (/etc/openct.conf under fedora), hence Gemplus.
- */
-#define CCID_VENDOR_ID                  0x08e6
-#define CCID_PRODUCT_ID                 0x4433
-#define CCID_DEVICE_VERSION             0x0000
-
-/*
- * BULK_OUT messages from PC to Reader
- * Defined in CCID Rev 1.1 6.1 (page 26)
- */
-#define CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn              0x62
-#define CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff             0x63
-#define CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus           0x65
-#define CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock                0x6f
-#define CCID_MESSAGE_TYPE_PC_to_RDR_GetParameters           0x6c
-#define CCID_MESSAGE_TYPE_PC_to_RDR_ResetParameters         0x6d
-#define CCID_MESSAGE_TYPE_PC_to_RDR_SetParameters           0x61
-#define CCID_MESSAGE_TYPE_PC_to_RDR_Escape                  0x6b
-#define CCID_MESSAGE_TYPE_PC_to_RDR_IccClock                0x6e
-#define CCID_MESSAGE_TYPE_PC_to_RDR_T0APDU                  0x6a
-#define CCID_MESSAGE_TYPE_PC_to_RDR_Secure                  0x69
-#define CCID_MESSAGE_TYPE_PC_to_RDR_Mechanical              0x71
-#define CCID_MESSAGE_TYPE_PC_to_RDR_Abort                   0x72
-#define CCID_MESSAGE_TYPE_PC_to_RDR_SetDataRateAndClockFrequency 0x73
-
-/*
- * BULK_IN messages from Reader to PC
- * Defined in CCID Rev 1.1 6.2 (page 48)
- */
-#define CCID_MESSAGE_TYPE_RDR_to_PC_DataBlock               0x80
-#define CCID_MESSAGE_TYPE_RDR_to_PC_SlotStatus              0x81
-#define CCID_MESSAGE_TYPE_RDR_to_PC_Parameters              0x82
-#define CCID_MESSAGE_TYPE_RDR_to_PC_Escape                  0x83
-#define CCID_MESSAGE_TYPE_RDR_to_PC_DataRateAndClockFrequency 0x84
-
-/*
- * INTERRUPT_IN messages from Reader to PC
- * Defined in CCID Rev 1.1 6.3 (page 56)
- */
-#define CCID_MESSAGE_TYPE_RDR_to_PC_NotifySlotChange        0x50
-#define CCID_MESSAGE_TYPE_RDR_to_PC_HardwareError           0x51
-
-/*
- * Endpoints for CCID - addresses are up to us to decide.
- * To support slot insertion and removal we must have an interrupt in ep
- * in addition we need a bulk in and bulk out ep
- * 5.2, page 20
- */
-#define CCID_INT_IN_EP       1
-#define CCID_BULK_IN_EP      2
-#define CCID_BULK_OUT_EP     3
-
-/* bmSlotICCState masks */
-#define SLOT_0_STATE_MASK    1
-#define SLOT_0_CHANGED_MASK  2
-
-/* Status codes that go in bStatus (see 6.2.6) */
-enum {
-    ICC_STATUS_PRESENT_ACTIVE = 0,
-    ICC_STATUS_PRESENT_INACTIVE,
-    ICC_STATUS_NOT_PRESENT
-};
-
-enum {
-    COMMAND_STATUS_NO_ERROR = 0,
-    COMMAND_STATUS_FAILED,
-    COMMAND_STATUS_TIME_EXTENSION_REQUIRED
-};
-
-/* Error codes that go in bError (see 6.2.6) */
-enum {
-    ERROR_CMD_NOT_SUPPORTED = 0,
-    ERROR_CMD_ABORTED       = -1,
-    ERROR_ICC_MUTE          = -2,
-    ERROR_XFR_PARITY_ERROR  = -3,
-    ERROR_XFR_OVERRUN       = -4,
-    ERROR_HW_ERROR          = -5,
-};
-
-/* 6.2.6 RDR_to_PC_SlotStatus definitions */
-enum {
-    CLOCK_STATUS_RUNNING = 0,
-    /*
-     * 0 - Clock Running, 1 - Clock stopped in State L, 2 - H,
-     * 3 - unknown state. rest are RFU
-     */
-};
-
-typedef struct QEMU_PACKED CCID_Header {
-    uint8_t     bMessageType;
-    uint32_t    dwLength;
-    uint8_t     bSlot;
-    uint8_t     bSeq;
-} CCID_Header;
-
-typedef struct QEMU_PACKED CCID_BULK_IN {
-    CCID_Header hdr;
-    uint8_t     bStatus;        /* Only used in BULK_IN */
-    uint8_t     bError;         /* Only used in BULK_IN */
-} CCID_BULK_IN;
-
-typedef struct QEMU_PACKED CCID_SlotStatus {
-    CCID_BULK_IN b;
-    uint8_t     bClockStatus;
-} CCID_SlotStatus;
-
-typedef struct QEMU_PACKED CCID_Parameter {
-    CCID_BULK_IN b;
-    uint8_t     bProtocolNum;
-    uint8_t     abProtocolDataStructure[0];
-} CCID_Parameter;
-
-typedef struct QEMU_PACKED CCID_DataBlock {
-    CCID_BULK_IN b;
-    uint8_t      bChainParameter;
-    uint8_t      abData[0];
-} CCID_DataBlock;
-
-/* 6.1.4 PC_to_RDR_XfrBlock */
-typedef struct QEMU_PACKED CCID_XferBlock {
-    CCID_Header  hdr;
-    uint8_t      bBWI; /* Block Waiting Timeout */
-    uint16_t     wLevelParameter; /* XXX currently unused */
-    uint8_t      abData[0];
-} CCID_XferBlock;
-
-typedef struct QEMU_PACKED CCID_IccPowerOn {
-    CCID_Header hdr;
-    uint8_t     bPowerSelect;
-    uint16_t    abRFU;
-} CCID_IccPowerOn;
-
-typedef struct QEMU_PACKED CCID_IccPowerOff {
-    CCID_Header hdr;
-    uint16_t    abRFU;
-} CCID_IccPowerOff;
-
-typedef struct QEMU_PACKED CCID_SetParameters {
-    CCID_Header hdr;
-    uint8_t     bProtocolNum;
-    uint16_t   abRFU;
-    uint8_t    abProtocolDataStructure[0];
-} CCID_SetParameters;
-
-typedef struct CCID_Notify_Slot_Change {
-    uint8_t     bMessageType; /* CCID_MESSAGE_TYPE_RDR_to_PC_NotifySlotChange */
-    uint8_t     bmSlotICCState;
-} CCID_Notify_Slot_Change;
-
-/* used for DataBlock response to XferBlock */
-typedef struct Answer {
-    uint8_t slot;
-    uint8_t seq;
-} Answer;
-
-/* pending BULK_IN messages */
-typedef struct BulkIn {
-    uint8_t  data[BULK_IN_BUF_SIZE];
-    uint32_t len;
-    uint32_t pos;
-} BulkIn;
-
-enum {
-    MIGRATION_NONE,
-    MIGRATION_MIGRATED,
-};
-
-typedef struct CCIDBus {
-    BusState qbus;
-} CCIDBus;
-
-#define MAX_PROTOCOL_SIZE   7
-
-/*
- * powered - defaults to true, changed by PowerOn/PowerOff messages
- */
-typedef struct USBCCIDState {
-    USBDevice dev;
-    USBEndpoint *intr;
-    CCIDBus bus;
-    CCIDCardState *card;
-    BulkIn bulk_in_pending[BULK_IN_PENDING_NUM]; /* circular */
-    uint32_t bulk_in_pending_start;
-    uint32_t bulk_in_pending_end; /* first free */
-    uint32_t bulk_in_pending_num;
-    BulkIn *current_bulk_in;
-    uint8_t  bulk_out_data[BULK_OUT_DATA_SIZE];
-    uint32_t bulk_out_pos;
-    uint64_t last_answer_error;
-    Answer pending_answers[PENDING_ANSWERS_NUM];
-    uint32_t pending_answers_start;
-    uint32_t pending_answers_end;
-    uint32_t pending_answers_num;
-    uint8_t  bError;
-    uint8_t  bmCommandStatus;
-    uint8_t  bProtocolNum;
-    uint8_t  abProtocolDataStructure[MAX_PROTOCOL_SIZE];
-    uint32_t ulProtocolDataStructureSize;
-    uint32_t state_vmstate;
-    uint32_t migration_target_ip;
-    uint16_t migration_target_port;
-    uint8_t  migration_state;
-    uint8_t  bmSlotICCState;
-    uint8_t  powered;
-    uint8_t  notify_slot_change;
-    uint8_t  debug;
-} USBCCIDState;
-
-/*
- * CCID Spec chapter 4: CCID uses a standard device descriptor per Chapter 9,
- * "USB Device Framework", section 9.6.1, in the Universal Serial Bus
- * Specification.
- *
- * This device implemented based on the spec and with an Athena Smart Card
- * Reader as reference:
- *   0dc3:1004 Athena Smartcard Solutions, Inc.
- */
-
-static const uint8_t qemu_ccid_descriptor[] = {
-        /* Smart Card Device Class Descriptor */
-        0x36,       /* u8  bLength; */
-        0x21,       /* u8  bDescriptorType; Functional */
-        0x10, 0x01, /* u16 bcdCCID; CCID Specification Release Number. */
-        0x00,       /*
-                     * u8  bMaxSlotIndex; The index of the highest available
-                     * slot on this device. All slots are consecutive starting
-                     * at 00h.
-                     */
-        0x07,       /* u8  bVoltageSupport; 01h - 5.0v, 02h - 3.0, 03 - 1.8 */
-
-        0x03, 0x00, /* u32 dwProtocols; RRRR PPPP. RRRR = 0000h.*/
-        0x00, 0x00, /* PPPP: 0001h = Protocol T=0, 0002h = Protocol T=1 */
-                    /* u32 dwDefaultClock; in kHZ (0x0fa0 is 4 MHz) */
-        0xa0, 0x0f, 0x00, 0x00,
-                    /* u32 dwMaximumClock; */
-        0x00, 0x00, 0x01, 0x00,
-        0x00,       /* u8 bNumClockSupported;                 *
-                     *    0 means just the default and max.   */
-                    /* u32 dwDataRate ;bps. 9600 == 00002580h */
-        0x80, 0x25, 0x00, 0x00,
-                    /* u32 dwMaxDataRate ; 11520 bps == 0001C200h */
-        0x00, 0xC2, 0x01, 0x00,
-        0x00,       /* u8  bNumDataRatesSupported; 00 means all rates between
-                     *     default and max */
-                    /* u32 dwMaxIFSD;                                  *
-                     *     maximum IFSD supported by CCID for protocol *
-                     *     T=1 (Maximum seen from various cards)       */
-        0xfe, 0x00, 0x00, 0x00,
-                    /* u32 dwSyncProtocols; 1 - 2-wire, 2 - 3-wire, 4 - I2C */
-        0x00, 0x00, 0x00, 0x00,
-                    /* u32 dwMechanical;  0 - no special characteristics. */
-        0x00, 0x00, 0x00, 0x00,
-                    /*
-                     * u32 dwFeatures;
-                     * 0 - No special characteristics
-                     * + 2 Automatic parameter configuration based on ATR data
-                     * + 4 Automatic activation of ICC on inserting
-                     * + 8 Automatic ICC voltage selection
-                     * + 10 Automatic ICC clock frequency change
-                     * + 20 Automatic baud rate change
-                     * + 40 Automatic parameters negotiation made by the CCID
-                     * + 80 automatic PPS made by the CCID
-                     * 100 CCID can set ICC in clock stop mode
-                     * 200 NAD value other then 00 accepted (T=1 protocol)
-                     * + 400 Automatic IFSD exchange as first exchange (T=1)
-                     * One of the following only:
-                     * + 10000 TPDU level exchanges with CCID
-                     * 20000 Short APDU level exchange with CCID
-                     * 40000 Short and Extended APDU level exchange with CCID
-                     *
-                     * + 100000 USB Wake up signaling supported on card
-                     * insertion and removal. Must set bit 5 in bmAttributes
-                     * in Configuration descriptor if 100000 is set.
-                     */
-        0xfe, 0x04, 0x11, 0x00,
-                    /*
-                     * u32 dwMaxCCIDMessageLength; For extended APDU in
-                     * [261 + 10 , 65544 + 10]. Otherwise the minimum is
-                     * wMaxPacketSize of the Bulk-OUT endpoint
-                     */
-        0x12, 0x00, 0x01, 0x00,
-        0xFF,       /*
-                     * u8  bClassGetResponse; Significant only for CCID that
-                     * offers an APDU level for exchanges. Indicates the
-                     * default class value used by the CCID when it sends a
-                     * Get Response command to perform the transportation of
-                     * an APDU by T=0 protocol
-                     * FFh indicates that the CCID echos the class of the APDU.
-                     */
-        0xFF,       /*
-                     * u8  bClassEnvelope; EAPDU only. Envelope command for
-                     * T=0
-                     */
-        0x00, 0x00, /*
-                     * u16 wLcdLayout; XXYY Number of lines (XX) and chars per
-                     * line for LCD display used for PIN entry. 0000 - no LCD
-                     */
-        0x01,       /*
-                     * u8  bPINSupport; 01h PIN Verification,
-                     *                  02h PIN Modification
-                     */
-        0x01,       /* u8  bMaxCCIDBusySlots; */
-};
-
-enum {
-    STR_MANUFACTURER = 1,
-    STR_PRODUCT,
-    STR_SERIALNUMBER,
-    STR_INTERFACE,
-};
-
-static const USBDescStrings desc_strings = {
-    [STR_MANUFACTURER]  = "QEMU " QEMU_VERSION,
-    [STR_PRODUCT]       = "QEMU USB CCID",
-    [STR_SERIALNUMBER]  = "1",
-    [STR_INTERFACE]     = "CCID Interface",
-};
-
-static const USBDescIface desc_iface0 = {
-    .bInterfaceNumber              = 0,
-    .bNumEndpoints                 = 3,
-    .bInterfaceClass               = 0x0b,
-    .bInterfaceSubClass            = 0x00,
-    .bInterfaceProtocol            = 0x00,
-    .iInterface                    = STR_INTERFACE,
-    .ndesc                         = 1,
-    .descs = (USBDescOther[]) {
-        {
-            /* smartcard descriptor */
-            .data = qemu_ccid_descriptor,
-        },
-    },
-    .eps = (USBDescEndpoint[]) {
-        {
-            .bEndpointAddress      = USB_DIR_IN | CCID_INT_IN_EP,
-            .bmAttributes          = USB_ENDPOINT_XFER_INT,
-            .bInterval             = 255,
-            .wMaxPacketSize        = 64,
-        },{
-            .bEndpointAddress      = USB_DIR_IN | CCID_BULK_IN_EP,
-            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
-            .wMaxPacketSize        = 64,
-        },{
-            .bEndpointAddress      = USB_DIR_OUT | CCID_BULK_OUT_EP,
-            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
-            .wMaxPacketSize        = 64,
-        },
-    }
-};
-
-static const USBDescDevice desc_device = {
-    .bcdUSB                        = 0x0110,
-    .bMaxPacketSize0               = 64,
-    .bNumConfigurations            = 1,
-    .confs = (USBDescConfig[]) {
-        {
-            .bNumInterfaces        = 1,
-            .bConfigurationValue   = 1,
-            .bmAttributes          = 0xe0,
-            .bMaxPower             = 50,
-            .nif = 1,
-            .ifs = &desc_iface0,
-        },
-    },
-};
-
-static const USBDesc desc_ccid = {
-    .id = {
-        .idVendor          = CCID_VENDOR_ID,
-        .idProduct         = CCID_PRODUCT_ID,
-        .bcdDevice         = CCID_DEVICE_VERSION,
-        .iManufacturer     = STR_MANUFACTURER,
-        .iProduct          = STR_PRODUCT,
-        .iSerialNumber     = STR_SERIALNUMBER,
-    },
-    .full = &desc_device,
-    .str  = desc_strings,
-};
-
-static const uint8_t *ccid_card_get_atr(CCIDCardState *card, uint32_t *len)
-{
-    CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
-    if (cc->get_atr) {
-        return cc->get_atr(card, len);
-    }
-    return NULL;
-}
-
-static void ccid_card_apdu_from_guest(CCIDCardState *card,
-                                      const uint8_t *apdu,
-                                      uint32_t len)
-{
-    CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
-    if (cc->apdu_from_guest) {
-        cc->apdu_from_guest(card, apdu, len);
-    }
-}
-
-static int ccid_card_exitfn(CCIDCardState *card)
-{
-    CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
-    if (cc->exitfn) {
-        return cc->exitfn(card);
-    }
-    return 0;
-}
-
-static int ccid_card_initfn(CCIDCardState *card)
-{
-    CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
-    if (cc->initfn) {
-        return cc->initfn(card);
-    }
-    return 0;
-}
-
-static bool ccid_has_pending_answers(USBCCIDState *s)
-{
-    return s->pending_answers_num > 0;
-}
-
-static void ccid_clear_pending_answers(USBCCIDState *s)
-{
-    s->pending_answers_num = 0;
-    s->pending_answers_start = 0;
-    s->pending_answers_end = 0;
-}
-
-static void ccid_print_pending_answers(USBCCIDState *s)
-{
-    Answer *answer;
-    int i, count;
-
-    DPRINTF(s, D_VERBOSE, "usb-ccid: pending answers:");
-    if (!ccid_has_pending_answers(s)) {
-        DPRINTF(s, D_VERBOSE, " empty\n");
-        return;
-    }
-    for (i = s->pending_answers_start, count = s->pending_answers_num ;
-         count > 0; count--, i++) {
-        answer = &s->pending_answers[i % PENDING_ANSWERS_NUM];
-        if (count == 1) {
-            DPRINTF(s, D_VERBOSE, "%d:%d\n", answer->slot, answer->seq);
-        } else {
-            DPRINTF(s, D_VERBOSE, "%d:%d,", answer->slot, answer->seq);
-        }
-    }
-}
-
-static void ccid_add_pending_answer(USBCCIDState *s, CCID_Header *hdr)
-{
-    Answer *answer;
-
-    assert(s->pending_answers_num < PENDING_ANSWERS_NUM);
-    s->pending_answers_num++;
-    answer =
-        &s->pending_answers[(s->pending_answers_end++) % PENDING_ANSWERS_NUM];
-    answer->slot = hdr->bSlot;
-    answer->seq = hdr->bSeq;
-    ccid_print_pending_answers(s);
-}
-
-static void ccid_remove_pending_answer(USBCCIDState *s,
-    uint8_t *slot, uint8_t *seq)
-{
-    Answer *answer;
-
-    assert(s->pending_answers_num > 0);
-    s->pending_answers_num--;
-    answer =
-        &s->pending_answers[(s->pending_answers_start++) % PENDING_ANSWERS_NUM];
-    *slot = answer->slot;
-    *seq = answer->seq;
-    ccid_print_pending_answers(s);
-}
-
-static void ccid_bulk_in_clear(USBCCIDState *s)
-{
-    s->bulk_in_pending_start = 0;
-    s->bulk_in_pending_end = 0;
-    s->bulk_in_pending_num = 0;
-}
-
-static void ccid_bulk_in_release(USBCCIDState *s)
-{
-    assert(s->current_bulk_in != NULL);
-    s->current_bulk_in->pos = 0;
-    s->current_bulk_in = NULL;
-}
-
-static void ccid_bulk_in_get(USBCCIDState *s)
-{
-    if (s->current_bulk_in != NULL || s->bulk_in_pending_num == 0) {
-        return;
-    }
-    assert(s->bulk_in_pending_num > 0);
-    s->bulk_in_pending_num--;
-    s->current_bulk_in =
-        &s->bulk_in_pending[(s->bulk_in_pending_start++) % BULK_IN_PENDING_NUM];
-}
-
-static void *ccid_reserve_recv_buf(USBCCIDState *s, uint16_t len)
-{
-    BulkIn *bulk_in;
-
-    DPRINTF(s, D_VERBOSE, "%s: QUEUE: reserve %d bytes\n", __func__, len);
-
-    /* look for an existing element */
-    if (len > BULK_IN_BUF_SIZE) {
-        DPRINTF(s, D_WARN, "usb-ccid.c: %s: len larger then max (%d>%d). "
-                           "discarding message.\n",
-                           __func__, len, BULK_IN_BUF_SIZE);
-        return NULL;
-    }
-    if (s->bulk_in_pending_num >= BULK_IN_PENDING_NUM) {
-        DPRINTF(s, D_WARN, "usb-ccid.c: %s: No free bulk_in buffers. "
-                           "discarding message.\n", __func__);
-        return NULL;
-    }
-    bulk_in =
-        &s->bulk_in_pending[(s->bulk_in_pending_end++) % BULK_IN_PENDING_NUM];
-    s->bulk_in_pending_num++;
-    bulk_in->len = len;
-    return bulk_in->data;
-}
-
-static void ccid_reset(USBCCIDState *s)
-{
-    ccid_bulk_in_clear(s);
-    ccid_clear_pending_answers(s);
-}
-
-static void ccid_detach(USBCCIDState *s)
-{
-    ccid_reset(s);
-}
-
-static void ccid_handle_reset(USBDevice *dev)
-{
-    USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
-
-    DPRINTF(s, 1, "Reset\n");
-
-    ccid_reset(s);
-}
-
-static int ccid_handle_control(USBDevice *dev, USBPacket *p, int request,
-                               int value, int index, int length, uint8_t *data)
-{
-    USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
-    int ret = 0;
-
-    DPRINTF(s, 1, "got control %x, value %x\n", request, value);
-    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
-    if (ret >= 0) {
-        return ret;
-    }
-
-    switch (request) {
-        /* Class specific requests.  */
-    case InterfaceOutClass | CCID_CONTROL_ABORT:
-        DPRINTF(s, 1, "ccid_control abort UNIMPLEMENTED\n");
-        ret = USB_RET_STALL;
-        break;
-    case InterfaceInClass | CCID_CONTROL_GET_CLOCK_FREQUENCIES:
-        DPRINTF(s, 1, "ccid_control get clock frequencies UNIMPLEMENTED\n");
-        ret = USB_RET_STALL;
-        break;
-    case InterfaceInClass | CCID_CONTROL_GET_DATA_RATES:
-        DPRINTF(s, 1, "ccid_control get data rates UNIMPLEMENTED\n");
-        ret = USB_RET_STALL;
-        break;
-    default:
-        DPRINTF(s, 1, "got unsupported/bogus control %x, value %x\n",
-                request, value);
-        ret = USB_RET_STALL;
-        break;
-    }
-    return ret;
-}
-
-static bool ccid_card_inserted(USBCCIDState *s)
-{
-    return s->bmSlotICCState & SLOT_0_STATE_MASK;
-}
-
-static uint8_t ccid_card_status(USBCCIDState *s)
-{
-    return ccid_card_inserted(s)
-            ? (s->powered ?
-                ICC_STATUS_PRESENT_ACTIVE
-              : ICC_STATUS_PRESENT_INACTIVE
-              )
-            : ICC_STATUS_NOT_PRESENT;
-}
-
-static uint8_t ccid_calc_status(USBCCIDState *s)
-{
-    /*
-     * page 55, 6.2.6, calculation of bStatus from bmICCStatus and
-     * bmCommandStatus
-     */
-    uint8_t ret = ccid_card_status(s) | (s->bmCommandStatus << 6);
-    DPRINTF(s, D_VERBOSE, "status = %d\n", ret);
-    return ret;
-}
-
-static void ccid_reset_error_status(USBCCIDState *s)
-{
-    s->bError = ERROR_CMD_NOT_SUPPORTED;
-    s->bmCommandStatus = COMMAND_STATUS_NO_ERROR;
-}
-
-static void ccid_write_slot_status(USBCCIDState *s, CCID_Header *recv)
-{
-    CCID_SlotStatus *h = ccid_reserve_recv_buf(s, sizeof(CCID_SlotStatus));
-    if (h == NULL) {
-        return;
-    }
-    h->b.hdr.bMessageType = CCID_MESSAGE_TYPE_RDR_to_PC_SlotStatus;
-    h->b.hdr.dwLength = 0;
-    h->b.hdr.bSlot = recv->bSlot;
-    h->b.hdr.bSeq = recv->bSeq;
-    h->b.bStatus = ccid_calc_status(s);
-    h->b.bError = s->bError;
-    h->bClockStatus = CLOCK_STATUS_RUNNING;
-    ccid_reset_error_status(s);
-}
-
-static void ccid_write_parameters(USBCCIDState *s, CCID_Header *recv)
-{
-    CCID_Parameter *h;
-    uint32_t len = s->ulProtocolDataStructureSize;
-
-    h = ccid_reserve_recv_buf(s, sizeof(CCID_Parameter) + len);
-    if (h == NULL) {
-        return;
-    }
-    h->b.hdr.bMessageType = CCID_MESSAGE_TYPE_RDR_to_PC_Parameters;
-    h->b.hdr.dwLength = 0;
-    h->b.hdr.bSlot = recv->bSlot;
-    h->b.hdr.bSeq = recv->bSeq;
-    h->b.bStatus = ccid_calc_status(s);
-    h->b.bError = s->bError;
-    h->bProtocolNum = s->bProtocolNum;
-    memcpy(h->abProtocolDataStructure, s->abProtocolDataStructure, len);
-    ccid_reset_error_status(s);
-}
-
-static void ccid_write_data_block(USBCCIDState *s, uint8_t slot, uint8_t seq,
-                                  const uint8_t *data, uint32_t len)
-{
-    CCID_DataBlock *p = ccid_reserve_recv_buf(s, sizeof(*p) + len);
-
-    if (p == NULL) {
-        return;
-    }
-    p->b.hdr.bMessageType = CCID_MESSAGE_TYPE_RDR_to_PC_DataBlock;
-    p->b.hdr.dwLength = cpu_to_le32(len);
-    p->b.hdr.bSlot = slot;
-    p->b.hdr.bSeq = seq;
-    p->b.bStatus = ccid_calc_status(s);
-    p->b.bError = s->bError;
-    if (p->b.bError) {
-        DPRINTF(s, D_VERBOSE, "error %d", p->b.bError);
-    }
-    memcpy(p->abData, data, len);
-    ccid_reset_error_status(s);
-}
-
-static void ccid_write_data_block_answer(USBCCIDState *s,
-    const uint8_t *data, uint32_t len)
-{
-    uint8_t seq;
-    uint8_t slot;
-
-    if (!ccid_has_pending_answers(s)) {
-        abort();
-    }
-    ccid_remove_pending_answer(s, &slot, &seq);
-    ccid_write_data_block(s, slot, seq, data, len);
-}
-
-static void ccid_write_data_block_atr(USBCCIDState *s, CCID_Header *recv)
-{
-    const uint8_t *atr = NULL;
-    uint32_t len = 0;
-
-    if (s->card) {
-        atr = ccid_card_get_atr(s->card, &len);
-    }
-    ccid_write_data_block(s, recv->bSlot, recv->bSeq, atr, len);
-}
-
-static void ccid_set_parameters(USBCCIDState *s, CCID_Header *recv)
-{
-    CCID_SetParameters *ph = (CCID_SetParameters *) recv;
-    uint32_t len = 0;
-    if ((ph->bProtocolNum & 3) == 0) {
-        len = 5;
-    }
-    if ((ph->bProtocolNum & 3) == 1) {
-        len = 7;
-    }
-    if (len == 0) {
-        s->bmCommandStatus = COMMAND_STATUS_FAILED;
-        s->bError = 7; /* Protocol invalid or not supported */
-        return;
-    }
-    s->bProtocolNum = ph->bProtocolNum;
-    memcpy(s->abProtocolDataStructure, ph->abProtocolDataStructure, len);
-    s->ulProtocolDataStructureSize = len;
-    DPRINTF(s, 1, "%s: using len %d\n", __func__, len);
-}
-
-/*
- * must be 5 bytes for T=0, 7 bytes for T=1
- * See page 52
- */
-static const uint8_t abDefaultProtocolDataStructure[7] = {
-    0x77, 0x00, 0x00, 0x00, 0x00, 0xfe /*IFSC*/, 0x00 /*NAD*/ };
-
-static void ccid_reset_parameters(USBCCIDState *s)
-{
-   uint32_t len = sizeof(abDefaultProtocolDataStructure);
-
-   s->bProtocolNum = 1; /* T=1 */
-   s->ulProtocolDataStructureSize = len;
-   memcpy(s->abProtocolDataStructure, abDefaultProtocolDataStructure, len);
-}
-
-static void ccid_report_error_failed(USBCCIDState *s, uint8_t error)
-{
-    s->bmCommandStatus = COMMAND_STATUS_FAILED;
-    s->bError = error;
-}
-
-/* NOTE: only a single slot is supported (SLOT_0) */
-static void ccid_on_slot_change(USBCCIDState *s, bool full)
-{
-    /* RDR_to_PC_NotifySlotChange, 6.3.1 page 56 */
-    uint8_t current = s->bmSlotICCState;
-    if (full) {
-        s->bmSlotICCState |= SLOT_0_STATE_MASK;
-    } else {
-        s->bmSlotICCState &= ~SLOT_0_STATE_MASK;
-    }
-    if (current != s->bmSlotICCState) {
-        s->bmSlotICCState |= SLOT_0_CHANGED_MASK;
-    }
-    s->notify_slot_change = true;
-    usb_wakeup(s->intr);
-}
-
-static void ccid_write_data_block_error(
-    USBCCIDState *s, uint8_t slot, uint8_t seq)
-{
-    ccid_write_data_block(s, slot, seq, NULL, 0);
-}
-
-static void ccid_on_apdu_from_guest(USBCCIDState *s, CCID_XferBlock *recv)
-{
-    uint32_t len;
-
-    if (ccid_card_status(s) != ICC_STATUS_PRESENT_ACTIVE) {
-        DPRINTF(s, 1,
-                "usb-ccid: not sending apdu to client, no card connected\n");
-        ccid_write_data_block_error(s, recv->hdr.bSlot, recv->hdr.bSeq);
-        return;
-    }
-    len = le32_to_cpu(recv->hdr.dwLength);
-    DPRINTF(s, 1, "%s: seq %d, len %d\n", __func__,
-                recv->hdr.bSeq, len);
-    ccid_add_pending_answer(s, (CCID_Header *)recv);
-    if (s->card) {
-        ccid_card_apdu_from_guest(s->card, recv->abData, len);
-    } else {
-        DPRINTF(s, D_WARN, "warning: discarded apdu\n");
-    }
-}
-
-/*
- * Handle a single USB_TOKEN_OUT, return value returned to guest.
- * Return value:
- *  0             - all ok
- *  USB_RET_STALL - failed to handle packet
- */
-static int ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
-{
-    CCID_Header *ccid_header;
-
-    if (p->iov.size + s->bulk_out_pos > BULK_OUT_DATA_SIZE) {
-        return USB_RET_STALL;
-    }
-    ccid_header = (CCID_Header *)s->bulk_out_data;
-    usb_packet_copy(p, s->bulk_out_data + s->bulk_out_pos, p->iov.size);
-    s->bulk_out_pos += p->iov.size;
-    if (p->iov.size == CCID_MAX_PACKET_SIZE) {
-        DPRINTF(s, D_VERBOSE,
-            "usb-ccid: bulk_in: expecting more packets (%zd/%d)\n",
-            p->iov.size, ccid_header->dwLength);
-        return 0;
-    }
-    if (s->bulk_out_pos < 10) {
-        DPRINTF(s, 1,
-                "%s: bad USB_TOKEN_OUT length, should be at least 10 bytes\n",
-                __func__);
-    } else {
-        DPRINTF(s, D_MORE_INFO, "%s %x\n", __func__, ccid_header->bMessageType);
-        switch (ccid_header->bMessageType) {
-        case CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus:
-            ccid_write_slot_status(s, ccid_header);
-            break;
-        case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn:
-            DPRINTF(s, 1, "PowerOn: %d\n",
-                ((CCID_IccPowerOn *)(ccid_header))->bPowerSelect);
-            s->powered = true;
-            if (!ccid_card_inserted(s)) {
-                ccid_report_error_failed(s, ERROR_ICC_MUTE);
-            }
-            /* atr is written regardless of error. */
-            ccid_write_data_block_atr(s, ccid_header);
-            break;
-        case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff:
-            DPRINTF(s, 1, "PowerOff\n");
-            ccid_reset_error_status(s);
-            s->powered = false;
-            ccid_write_slot_status(s, ccid_header);
-            break;
-        case CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock:
-            ccid_on_apdu_from_guest(s, (CCID_XferBlock *)s->bulk_out_data);
-            break;
-        case CCID_MESSAGE_TYPE_PC_to_RDR_SetParameters:
-            ccid_reset_error_status(s);
-            ccid_set_parameters(s, ccid_header);
-            ccid_write_parameters(s, ccid_header);
-            break;
-        case CCID_MESSAGE_TYPE_PC_to_RDR_ResetParameters:
-            ccid_reset_error_status(s);
-            ccid_reset_parameters(s);
-            ccid_write_parameters(s, ccid_header);
-            break;
-        case CCID_MESSAGE_TYPE_PC_to_RDR_GetParameters:
-            ccid_reset_error_status(s);
-            ccid_write_parameters(s, ccid_header);
-            break;
-        default:
-            DPRINTF(s, 1,
-                "handle_data: ERROR: unhandled message type %Xh\n",
-                ccid_header->bMessageType);
-            /*
-             * The caller is expecting the device to respond, tell it we
-             * don't support the operation.
-             */
-            ccid_report_error_failed(s, ERROR_CMD_NOT_SUPPORTED);
-            ccid_write_slot_status(s, ccid_header);
-            break;
-        }
-    }
-    s->bulk_out_pos = 0;
-    return 0;
-}
-
-static int ccid_bulk_in_copy_to_guest(USBCCIDState *s, USBPacket *p)
-{
-    int ret = 0;
-
-    assert(p->iov.size > 0);
-    ccid_bulk_in_get(s);
-    if (s->current_bulk_in != NULL) {
-        ret = MIN(s->current_bulk_in->len - s->current_bulk_in->pos,
-                  p->iov.size);
-        usb_packet_copy(p, s->current_bulk_in->data +
-                        s->current_bulk_in->pos, ret);
-        s->current_bulk_in->pos += ret;
-        if (s->current_bulk_in->pos == s->current_bulk_in->len) {
-            ccid_bulk_in_release(s);
-        }
-    } else {
-        /* return when device has no data - usb 2.0 spec Table 8-4 */
-        ret = USB_RET_NAK;
-    }
-    if (ret > 0) {
-        DPRINTF(s, D_MORE_INFO,
-                "%s: %zd/%d req/act to guest (BULK_IN)\n",
-                __func__, p->iov.size, ret);
-    }
-    if (ret != USB_RET_NAK && ret < p->iov.size) {
-        DPRINTF(s, 1,
-                "%s: returning short (EREMOTEIO) %d < %zd\n",
-                __func__, ret, p->iov.size);
-    }
-    return ret;
-}
-
-static int ccid_handle_data(USBDevice *dev, USBPacket *p)
-{
-    USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
-    int ret = 0;
-    uint8_t buf[2];
-
-    switch (p->pid) {
-    case USB_TOKEN_OUT:
-        ret = ccid_handle_bulk_out(s, p);
-        break;
-
-    case USB_TOKEN_IN:
-        switch (p->ep->nr) {
-        case CCID_BULK_IN_EP:
-            if (!p->iov.size) {
-                ret = USB_RET_NAK;
-            } else {
-                ret = ccid_bulk_in_copy_to_guest(s, p);
-            }
-            break;
-        case CCID_INT_IN_EP:
-            if (s->notify_slot_change) {
-                /* page 56, RDR_to_PC_NotifySlotChange */
-                buf[0] = CCID_MESSAGE_TYPE_RDR_to_PC_NotifySlotChange;
-                buf[1] = s->bmSlotICCState;
-                usb_packet_copy(p, buf, 2);
-                ret = 2;
-                s->notify_slot_change = false;
-                s->bmSlotICCState &= ~SLOT_0_CHANGED_MASK;
-                DPRINTF(s, D_INFO,
-                        "handle_data: int_in: notify_slot_change %X, "
-                        "requested len %zd\n",
-                        s->bmSlotICCState, p->iov.size);
-            }
-            break;
-        default:
-            DPRINTF(s, 1, "Bad endpoint\n");
-            ret = USB_RET_STALL;
-            break;
-        }
-        break;
-    default:
-        DPRINTF(s, 1, "Bad token\n");
-        ret = USB_RET_STALL;
-        break;
-    }
-
-    return ret;
-}
-
-static void ccid_handle_destroy(USBDevice *dev)
-{
-    USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
-
-    ccid_bulk_in_clear(s);
-}
-
-static void ccid_flush_pending_answers(USBCCIDState *s)
-{
-    while (ccid_has_pending_answers(s)) {
-        ccid_write_data_block_answer(s, NULL, 0);
-    }
-}
-
-static Answer *ccid_peek_next_answer(USBCCIDState *s)
-{
-    return s->pending_answers_num == 0
-        ? NULL
-        : &s->pending_answers[s->pending_answers_start % PENDING_ANSWERS_NUM];
-}
-
-static struct BusInfo ccid_bus_info = {
-    .name = "ccid-bus",
-    .size = sizeof(CCIDBus),
-    .props = (Property[]) {
-        DEFINE_PROP_UINT32("slot", struct CCIDCardState, slot, 0),
-        DEFINE_PROP_END_OF_LIST(),
-    }
-};
-
-void ccid_card_send_apdu_to_guest(CCIDCardState *card,
-                                  uint8_t *apdu, uint32_t len)
-{
-    USBCCIDState *s = DO_UPCAST(USBCCIDState, dev.qdev,
-                                card->qdev.parent_bus->parent);
-    Answer *answer;
-
-    if (!ccid_has_pending_answers(s)) {
-        DPRINTF(s, 1, "CCID ERROR: got an APDU without pending answers\n");
-        return;
-    }
-    s->bmCommandStatus = COMMAND_STATUS_NO_ERROR;
-    answer = ccid_peek_next_answer(s);
-    if (answer == NULL) {
-        abort();
-    }
-    DPRINTF(s, 1, "APDU returned to guest %d (answer seq %d, slot %d)\n",
-        len, answer->seq, answer->slot);
-    ccid_write_data_block_answer(s, apdu, len);
-}
-
-void ccid_card_card_removed(CCIDCardState *card)
-{
-    USBCCIDState *s =
-        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
-
-    ccid_on_slot_change(s, false);
-    ccid_flush_pending_answers(s);
-    ccid_reset(s);
-}
-
-int ccid_card_ccid_attach(CCIDCardState *card)
-{
-    USBCCIDState *s =
-        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
-
-    DPRINTF(s, 1, "CCID Attach\n");
-    if (s->migration_state == MIGRATION_MIGRATED) {
-        s->migration_state = MIGRATION_NONE;
-    }
-    return 0;
-}
-
-void ccid_card_ccid_detach(CCIDCardState *card)
-{
-    USBCCIDState *s =
-        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
-
-    DPRINTF(s, 1, "CCID Detach\n");
-    if (ccid_card_inserted(s)) {
-        ccid_on_slot_change(s, false);
-    }
-    ccid_detach(s);
-}
-
-void ccid_card_card_error(CCIDCardState *card, uint64_t error)
-{
-    USBCCIDState *s =
-        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
-
-    s->bmCommandStatus = COMMAND_STATUS_FAILED;
-    s->last_answer_error = error;
-    DPRINTF(s, 1, "VSC_Error: %" PRIX64 "\n", s->last_answer_error);
-    /* TODO: these errors should be more verbose and propagated to the guest.*/
-    /*
-     * We flush all pending answers on CardRemove message in ccid-card-passthru,
-     * so check that first to not trigger abort
-     */
-    if (ccid_has_pending_answers(s)) {
-        ccid_write_data_block_answer(s, NULL, 0);
-    }
-}
-
-void ccid_card_card_inserted(CCIDCardState *card)
-{
-    USBCCIDState *s =
-        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
-
-    s->bmCommandStatus = COMMAND_STATUS_NO_ERROR;
-    ccid_flush_pending_answers(s);
-    ccid_on_slot_change(s, true);
-}
-
-static int ccid_card_exit(DeviceState *qdev)
-{
-    int ret = 0;
-    CCIDCardState *card = CCID_CARD(qdev);
-    USBCCIDState *s =
-        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
-
-    if (ccid_card_inserted(s)) {
-        ccid_card_card_removed(card);
-    }
-    ret = ccid_card_exitfn(card);
-    s->card = NULL;
-    return ret;
-}
-
-static int ccid_card_init(DeviceState *qdev)
-{
-    CCIDCardState *card = CCID_CARD(qdev);
-    USBCCIDState *s =
-        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
-    int ret = 0;
-
-    if (card->slot != 0) {
-        error_report("Warning: usb-ccid supports one slot, can't add %d",
-                card->slot);
-        return -1;
-    }
-    if (s->card != NULL) {
-        error_report("Warning: usb-ccid card already full, not adding");
-        return -1;
-    }
-    ret = ccid_card_initfn(card);
-    if (ret == 0) {
-        s->card = card;
-    }
-    return ret;
-}
-
-static int ccid_initfn(USBDevice *dev)
-{
-    USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
-
-    usb_desc_init(dev);
-    qbus_create_inplace(&s->bus.qbus, &ccid_bus_info, &dev->qdev, NULL);
-    s->intr = usb_ep_get(dev, USB_TOKEN_IN, CCID_INT_IN_EP);
-    s->bus.qbus.allow_hotplug = 1;
-    s->card = NULL;
-    s->migration_state = MIGRATION_NONE;
-    s->migration_target_ip = 0;
-    s->migration_target_port = 0;
-    s->dev.speed = USB_SPEED_FULL;
-    s->dev.speedmask = USB_SPEED_MASK_FULL;
-    s->notify_slot_change = false;
-    s->powered = true;
-    s->pending_answers_num = 0;
-    s->last_answer_error = 0;
-    s->bulk_in_pending_start = 0;
-    s->bulk_in_pending_end = 0;
-    s->current_bulk_in = NULL;
-    ccid_reset_error_status(s);
-    s->bulk_out_pos = 0;
-    ccid_reset_parameters(s);
-    ccid_reset(s);
-    return 0;
-}
-
-static int ccid_post_load(void *opaque, int version_id)
-{
-    USBCCIDState *s = opaque;
-
-    /*
-     * This must be done after usb_device_attach, which sets state to ATTACHED,
-     * while it must be DEFAULT in order to accept packets (like it is after
-     * reset, but reset will reset our addr and call our reset handler which
-     * may change state, and we don't want to do that when migrating).
-     */
-    s->dev.state = s->state_vmstate;
-    return 0;
-}
-
-static void ccid_pre_save(void *opaque)
-{
-    USBCCIDState *s = opaque;
-
-    s->state_vmstate = s->dev.state;
-    if (s->dev.attached) {
-        /*
-         * Migrating an open device, ignore reconnection CHR_EVENT to avoid an
-         * erroneous detach.
-         */
-        s->migration_state = MIGRATION_MIGRATED;
-    }
-}
-
-static VMStateDescription bulk_in_vmstate = {
-    .name = "CCID BulkIn state",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_BUFFER(data, BulkIn),
-        VMSTATE_UINT32(len, BulkIn),
-        VMSTATE_UINT32(pos, BulkIn),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static VMStateDescription answer_vmstate = {
-    .name = "CCID Answer state",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT8(slot, Answer),
-        VMSTATE_UINT8(seq, Answer),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static VMStateDescription usb_device_vmstate = {
-    .name = "usb_device",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT8(addr, USBDevice),
-        VMSTATE_BUFFER(setup_buf, USBDevice),
-        VMSTATE_BUFFER(data_buf, USBDevice),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static VMStateDescription ccid_vmstate = {
-    .name = CCID_DEV_NAME,
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .post_load = ccid_post_load,
-    .pre_save = ccid_pre_save,
-    .fields = (VMStateField[]) {
-        VMSTATE_STRUCT(dev, USBCCIDState, 1, usb_device_vmstate, USBDevice),
-        VMSTATE_UINT8(debug, USBCCIDState),
-        VMSTATE_BUFFER(bulk_out_data, USBCCIDState),
-        VMSTATE_UINT32(bulk_out_pos, USBCCIDState),
-        VMSTATE_UINT8(bmSlotICCState, USBCCIDState),
-        VMSTATE_UINT8(powered, USBCCIDState),
-        VMSTATE_UINT8(notify_slot_change, USBCCIDState),
-        VMSTATE_UINT64(last_answer_error, USBCCIDState),
-        VMSTATE_UINT8(bError, USBCCIDState),
-        VMSTATE_UINT8(bmCommandStatus, USBCCIDState),
-        VMSTATE_UINT8(bProtocolNum, USBCCIDState),
-        VMSTATE_BUFFER(abProtocolDataStructure, USBCCIDState),
-        VMSTATE_UINT32(ulProtocolDataStructureSize, USBCCIDState),
-        VMSTATE_STRUCT_ARRAY(bulk_in_pending, USBCCIDState,
-                       BULK_IN_PENDING_NUM, 1, bulk_in_vmstate, BulkIn),
-        VMSTATE_UINT32(bulk_in_pending_start, USBCCIDState),
-        VMSTATE_UINT32(bulk_in_pending_end, USBCCIDState),
-        VMSTATE_STRUCT_ARRAY(pending_answers, USBCCIDState,
-                        PENDING_ANSWERS_NUM, 1, answer_vmstate, Answer),
-        VMSTATE_UINT32(pending_answers_num, USBCCIDState),
-        VMSTATE_UINT8(migration_state, USBCCIDState),
-        VMSTATE_UINT32(state_vmstate, USBCCIDState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static Property ccid_properties[] = {
-    DEFINE_PROP_UINT8("debug", USBCCIDState, debug, 0),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void ccid_class_initfn(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
-
-    uc->init           = ccid_initfn;
-    uc->product_desc   = "QEMU USB CCID";
-    uc->usb_desc       = &desc_ccid;
-    uc->handle_reset   = ccid_handle_reset;
-    uc->handle_control = ccid_handle_control;
-    uc->handle_data    = ccid_handle_data;
-    uc->handle_destroy = ccid_handle_destroy;
-    dc->desc = "CCID Rev 1.1 smartcard reader";
-    dc->vmsd = &ccid_vmstate;
-    dc->props = ccid_properties;
-}
-
-static TypeInfo ccid_info = {
-    .name          = CCID_DEV_NAME,
-    .parent        = TYPE_USB_DEVICE,
-    .instance_size = sizeof(USBCCIDState),
-    .class_init    = ccid_class_initfn,
-};
-
-static void ccid_card_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *k = DEVICE_CLASS(klass);
-    k->bus_info = &ccid_bus_info;
-    k->init = ccid_card_init;
-    k->exit = ccid_card_exit;
-}
-
-static TypeInfo ccid_card_type_info = {
-    .name = TYPE_CCID_CARD,
-    .parent = TYPE_DEVICE,
-    .instance_size = sizeof(CCIDCardState),
-    .abstract = true,
-    .class_size = sizeof(CCIDCardClass),
-    .class_init = ccid_card_class_init,
-};
-
-static void ccid_register_types(void)
-{
-    type_register_static(&ccid_card_type_info);
-    type_register_static(&ccid_info);
-    usb_legacy_register(CCID_DEV_NAME, "ccid", NULL);
-}
-
-type_init(ccid_register_types)
diff --git a/hw/usb-desc.c b/hw/usb-desc.c
deleted file mode 100644
index ccf85ad..0000000
--- a/hw/usb-desc.c
+++ /dev/null
@@ -1,601 +0,0 @@
-#include "usb.h"
-#include "usb-desc.h"
-#include "trace.h"
-
-/* ------------------------------------------------------------------ */
-
-static uint8_t usb_lo(uint16_t val)
-{
-    return val & 0xff;
-}
-
-static uint8_t usb_hi(uint16_t val)
-{
-    return (val >> 8) & 0xff;
-}
-
-int usb_desc_device(const USBDescID *id, const USBDescDevice *dev,
-                    uint8_t *dest, size_t len)
-{
-    uint8_t bLength = 0x12;
-
-    if (len < bLength) {
-        return -1;
-    }
-
-    dest[0x00] = bLength;
-    dest[0x01] = USB_DT_DEVICE;
-
-    dest[0x02] = usb_lo(dev->bcdUSB);
-    dest[0x03] = usb_hi(dev->bcdUSB);
-    dest[0x04] = dev->bDeviceClass;
-    dest[0x05] = dev->bDeviceSubClass;
-    dest[0x06] = dev->bDeviceProtocol;
-    dest[0x07] = dev->bMaxPacketSize0;
-
-    dest[0x08] = usb_lo(id->idVendor);
-    dest[0x09] = usb_hi(id->idVendor);
-    dest[0x0a] = usb_lo(id->idProduct);
-    dest[0x0b] = usb_hi(id->idProduct);
-    dest[0x0c] = usb_lo(id->bcdDevice);
-    dest[0x0d] = usb_hi(id->bcdDevice);
-    dest[0x0e] = id->iManufacturer;
-    dest[0x0f] = id->iProduct;
-    dest[0x10] = id->iSerialNumber;
-
-    dest[0x11] = dev->bNumConfigurations;
-
-    return bLength;
-}
-
-int usb_desc_device_qualifier(const USBDescDevice *dev,
-                              uint8_t *dest, size_t len)
-{
-    uint8_t bLength = 0x0a;
-
-    if (len < bLength) {
-        return -1;
-    }
-
-    dest[0x00] = bLength;
-    dest[0x01] = USB_DT_DEVICE_QUALIFIER;
-
-    dest[0x02] = usb_lo(dev->bcdUSB);
-    dest[0x03] = usb_hi(dev->bcdUSB);
-    dest[0x04] = dev->bDeviceClass;
-    dest[0x05] = dev->bDeviceSubClass;
-    dest[0x06] = dev->bDeviceProtocol;
-    dest[0x07] = dev->bMaxPacketSize0;
-    dest[0x08] = dev->bNumConfigurations;
-    dest[0x09] = 0; /* reserved */
-
-    return bLength;
-}
-
-int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len)
-{
-    uint8_t  bLength = 0x09;
-    uint16_t wTotalLength = 0;
-    int i, rc;
-
-    if (len < bLength) {
-        return -1;
-    }
-
-    dest[0x00] = bLength;
-    dest[0x01] = USB_DT_CONFIG;
-    dest[0x04] = conf->bNumInterfaces;
-    dest[0x05] = conf->bConfigurationValue;
-    dest[0x06] = conf->iConfiguration;
-    dest[0x07] = conf->bmAttributes;
-    dest[0x08] = conf->bMaxPower;
-    wTotalLength += bLength;
-
-    /* handle grouped interfaces if any*/
-    for (i = 0; i < conf->nif_groups; i++) {
-        rc = usb_desc_iface_group(&(conf->if_groups[i]),
-                                  dest + wTotalLength,
-                                  len - wTotalLength);
-        if (rc < 0) {
-            return rc;
-        }
-        wTotalLength += rc;
-    }
-
-    /* handle normal (ungrouped / no IAD) interfaces if any */
-    for (i = 0; i < conf->nif; i++) {
-        rc = usb_desc_iface(conf->ifs + i, dest + wTotalLength, len - wTotalLength);
-        if (rc < 0) {
-            return rc;
-        }
-        wTotalLength += rc;
-    }
-
-    dest[0x02] = usb_lo(wTotalLength);
-    dest[0x03] = usb_hi(wTotalLength);
-    return wTotalLength;
-}
-
-int usb_desc_iface_group(const USBDescIfaceAssoc *iad, uint8_t *dest,
-                         size_t len)
-{
-    int pos = 0;
-    int i = 0;
-
-    /* handle interface association descriptor */
-    uint8_t bLength = 0x08;
-
-    if (len < bLength) {
-        return -1;
-    }
-
-    dest[0x00] = bLength;
-    dest[0x01] = USB_DT_INTERFACE_ASSOC;
-    dest[0x02] = iad->bFirstInterface;
-    dest[0x03] = iad->bInterfaceCount;
-    dest[0x04] = iad->bFunctionClass;
-    dest[0x05] = iad->bFunctionSubClass;
-    dest[0x06] = iad->bFunctionProtocol;
-    dest[0x07] = iad->iFunction;
-    pos += bLength;
-
-    /* handle associated interfaces in this group */
-    for (i = 0; i < iad->nif; i++) {
-        int rc = usb_desc_iface(&(iad->ifs[i]), dest + pos, len - pos);
-        if (rc < 0) {
-            return rc;
-        }
-        pos += rc;
-    }
-
-    return pos;
-}
-
-int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len)
-{
-    uint8_t bLength = 0x09;
-    int i, rc, pos = 0;
-
-    if (len < bLength) {
-        return -1;
-    }
-
-    dest[0x00] = bLength;
-    dest[0x01] = USB_DT_INTERFACE;
-    dest[0x02] = iface->bInterfaceNumber;
-    dest[0x03] = iface->bAlternateSetting;
-    dest[0x04] = iface->bNumEndpoints;
-    dest[0x05] = iface->bInterfaceClass;
-    dest[0x06] = iface->bInterfaceSubClass;
-    dest[0x07] = iface->bInterfaceProtocol;
-    dest[0x08] = iface->iInterface;
-    pos += bLength;
-
-    for (i = 0; i < iface->ndesc; i++) {
-        rc = usb_desc_other(iface->descs + i, dest + pos, len - pos);
-        if (rc < 0) {
-            return rc;
-        }
-        pos += rc;
-    }
-
-    for (i = 0; i < iface->bNumEndpoints; i++) {
-        rc = usb_desc_endpoint(iface->eps + i, dest + pos, len - pos);
-        if (rc < 0) {
-            return rc;
-        }
-        pos += rc;
-    }
-
-    return pos;
-}
-
-int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len)
-{
-    uint8_t bLength = ep->is_audio ? 0x09 : 0x07;
-    uint8_t extralen = ep->extra ? ep->extra[0] : 0;
-
-    if (len < bLength + extralen) {
-        return -1;
-    }
-
-    dest[0x00] = bLength;
-    dest[0x01] = USB_DT_ENDPOINT;
-    dest[0x02] = ep->bEndpointAddress;
-    dest[0x03] = ep->bmAttributes;
-    dest[0x04] = usb_lo(ep->wMaxPacketSize);
-    dest[0x05] = usb_hi(ep->wMaxPacketSize);
-    dest[0x06] = ep->bInterval;
-    if (ep->is_audio) {
-        dest[0x07] = ep->bRefresh;
-        dest[0x08] = ep->bSynchAddress;
-    }
-    if (ep->extra) {
-        memcpy(dest + bLength, ep->extra, extralen);
-    }
-
-    return bLength + extralen;
-}
-
-int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
-{
-    int bLength = desc->length ? desc->length : desc->data[0];
-
-    if (len < bLength) {
-        return -1;
-    }
-
-    memcpy(dest, desc->data, bLength);
-    return bLength;
-}
-
-/* ------------------------------------------------------------------ */
-
-static void usb_desc_ep_init(USBDevice *dev)
-{
-    const USBDescIface *iface;
-    int i, e, pid, ep;
-
-    usb_ep_init(dev);
-    for (i = 0; i < dev->ninterfaces; i++) {
-        iface = dev->ifaces[i];
-        if (iface == NULL) {
-            continue;
-        }
-        for (e = 0; e < iface->bNumEndpoints; e++) {
-            pid = (iface->eps[e].bEndpointAddress & USB_DIR_IN) ?
-                USB_TOKEN_IN : USB_TOKEN_OUT;
-            ep = iface->eps[e].bEndpointAddress & 0x0f;
-            usb_ep_set_type(dev, pid, ep, iface->eps[e].bmAttributes & 0x03);
-            usb_ep_set_ifnum(dev, pid, ep, iface->bInterfaceNumber);
-            usb_ep_set_max_packet_size(dev, pid, ep,
-                                       iface->eps[e].wMaxPacketSize);
-        }
-    }
-}
-
-static const USBDescIface *usb_desc_find_interface(USBDevice *dev,
-                                                   int nif, int alt)
-{
-    const USBDescIface *iface;
-    int g, i;
-
-    if (!dev->config) {
-        return NULL;
-    }
-    for (g = 0; g < dev->config->nif_groups; g++) {
-        for (i = 0; i < dev->config->if_groups[g].nif; i++) {
-            iface = &dev->config->if_groups[g].ifs[i];
-            if (iface->bInterfaceNumber == nif &&
-                iface->bAlternateSetting == alt) {
-                return iface;
-            }
-        }
-    }
-    for (i = 0; i < dev->config->nif; i++) {
-        iface = &dev->config->ifs[i];
-        if (iface->bInterfaceNumber == nif &&
-            iface->bAlternateSetting == alt) {
-            return iface;
-        }
-    }
-    return NULL;
-}
-
-static int usb_desc_set_interface(USBDevice *dev, int index, int value)
-{
-    const USBDescIface *iface;
-    int old;
-
-    iface = usb_desc_find_interface(dev, index, value);
-    if (iface == NULL) {
-        return -1;
-    }
-
-    old = dev->altsetting[index];
-    dev->altsetting[index] = value;
-    dev->ifaces[index] = iface;
-    usb_desc_ep_init(dev);
-
-    if (old != value) {
-        usb_device_set_interface(dev, index, old, value);
-    }
-    return 0;
-}
-
-static int usb_desc_set_config(USBDevice *dev, int value)
-{
-    int i;
-
-    if (value == 0) {
-        dev->configuration = 0;
-        dev->ninterfaces   = 0;
-        dev->config = NULL;
-    } else {
-        for (i = 0; i < dev->device->bNumConfigurations; i++) {
-            if (dev->device->confs[i].bConfigurationValue == value) {
-                dev->configuration = value;
-                dev->ninterfaces   = dev->device->confs[i].bNumInterfaces;
-                dev->config = dev->device->confs + i;
-                assert(dev->ninterfaces <= USB_MAX_INTERFACES);
-            }
-        }
-        if (i < dev->device->bNumConfigurations) {
-            return -1;
-        }
-    }
-
-    for (i = 0; i < dev->ninterfaces; i++) {
-        usb_desc_set_interface(dev, i, 0);
-    }
-    for (; i < USB_MAX_INTERFACES; i++) {
-        dev->altsetting[i] = 0;
-        dev->ifaces[i] = NULL;
-    }
-
-    return 0;
-}
-
-static void usb_desc_setdefaults(USBDevice *dev)
-{
-    const USBDesc *desc = usb_device_get_usb_desc(dev);
-
-    assert(desc != NULL);
-    switch (dev->speed) {
-    case USB_SPEED_LOW:
-    case USB_SPEED_FULL:
-        dev->device = desc->full;
-        break;
-    case USB_SPEED_HIGH:
-        dev->device = desc->high;
-        break;
-    }
-    usb_desc_set_config(dev, 0);
-}
-
-void usb_desc_init(USBDevice *dev)
-{
-    const USBDesc *desc = usb_device_get_usb_desc(dev);
-
-    assert(desc != NULL);
-    dev->speed = USB_SPEED_FULL;
-    dev->speedmask = 0;
-    if (desc->full) {
-        dev->speedmask |= USB_SPEED_MASK_FULL;
-    }
-    if (desc->high) {
-        dev->speedmask |= USB_SPEED_MASK_HIGH;
-    }
-    usb_desc_setdefaults(dev);
-}
-
-void usb_desc_attach(USBDevice *dev)
-{
-    const USBDesc *desc = usb_device_get_usb_desc(dev);
-
-    assert(desc != NULL);
-    if (desc->high && (dev->port->speedmask & USB_SPEED_MASK_HIGH)) {
-        dev->speed = USB_SPEED_HIGH;
-    } else if (desc->full && (dev->port->speedmask & USB_SPEED_MASK_FULL)) {
-        dev->speed = USB_SPEED_FULL;
-    } else {
-        fprintf(stderr, "usb: port/device speed mismatch for \"%s\"\n",
-                usb_device_get_product_desc(dev));
-        return;
-    }
-    usb_desc_setdefaults(dev);
-}
-
-void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str)
-{
-    USBDescString *s;
-
-    QLIST_FOREACH(s, &dev->strings, next) {
-        if (s->index == index) {
-            break;
-        }
-    }
-    if (s == NULL) {
-        s = g_malloc0(sizeof(*s));
-        s->index = index;
-        QLIST_INSERT_HEAD(&dev->strings, s, next);
-    }
-    g_free(s->str);
-    s->str = g_strdup(str);
-}
-
-const char *usb_desc_get_string(USBDevice *dev, uint8_t index)
-{
-    USBDescString *s;
-
-    QLIST_FOREACH(s, &dev->strings, next) {
-        if (s->index == index) {
-            return s->str;
-        }
-    }
-    return NULL;
-}
-
-int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len)
-{
-    uint8_t bLength, pos, i;
-    const char *str;
-
-    if (len < 4) {
-        return -1;
-    }
-
-    if (index == 0) {
-        /* language ids */
-        dest[0] = 4;
-        dest[1] = USB_DT_STRING;
-        dest[2] = 0x09;
-        dest[3] = 0x04;
-        return 4;
-    }
-
-    str = usb_desc_get_string(dev, index);
-    if (str == NULL) {
-        str = usb_device_get_usb_desc(dev)->str[index];
-        if (str == NULL) {
-            return 0;
-        }
-    }
-
-    bLength = strlen(str) * 2 + 2;
-    dest[0] = bLength;
-    dest[1] = USB_DT_STRING;
-    i = 0; pos = 2;
-    while (pos+1 < bLength && pos+1 < len) {
-        dest[pos++] = str[i++];
-        dest[pos++] = 0;
-    }
-    return pos;
-}
-
-int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len)
-{
-    const USBDesc *desc = usb_device_get_usb_desc(dev);
-    const USBDescDevice *other_dev;
-    uint8_t buf[256];
-    uint8_t type = value >> 8;
-    uint8_t index = value & 0xff;
-    int ret = -1;
-
-    if (dev->speed == USB_SPEED_HIGH) {
-        other_dev = usb_device_get_usb_desc(dev)->full;
-    } else {
-        other_dev = usb_device_get_usb_desc(dev)->high;
-    }
-
-    switch(type) {
-    case USB_DT_DEVICE:
-        ret = usb_desc_device(&desc->id, dev->device, buf, sizeof(buf));
-        trace_usb_desc_device(dev->addr, len, ret);
-        break;
-    case USB_DT_CONFIG:
-        if (index < dev->device->bNumConfigurations) {
-            ret = usb_desc_config(dev->device->confs + index, buf, sizeof(buf));
-        }
-        trace_usb_desc_config(dev->addr, index, len, ret);
-        break;
-    case USB_DT_STRING:
-        ret = usb_desc_string(dev, index, buf, sizeof(buf));
-        trace_usb_desc_string(dev->addr, index, len, ret);
-        break;
-
-    case USB_DT_DEVICE_QUALIFIER:
-        if (other_dev != NULL) {
-            ret = usb_desc_device_qualifier(other_dev, buf, sizeof(buf));
-        }
-        trace_usb_desc_device_qualifier(dev->addr, len, ret);
-        break;
-    case USB_DT_OTHER_SPEED_CONFIG:
-        if (other_dev != NULL && index < other_dev->bNumConfigurations) {
-            ret = usb_desc_config(other_dev->confs + index, buf, sizeof(buf));
-            buf[0x01] = USB_DT_OTHER_SPEED_CONFIG;
-        }
-        trace_usb_desc_other_speed_config(dev->addr, index, len, ret);
-        break;
-
-    case USB_DT_DEBUG:
-        /* ignore silently */
-        break;
-
-    default:
-        fprintf(stderr, "%s: %d unknown type %d (len %zd)\n", __FUNCTION__,
-                dev->addr, type, len);
-        break;
-    }
-
-    if (ret > 0) {
-        if (ret > len) {
-            ret = len;
-        }
-        memcpy(dest, buf, ret);
-    }
-    return ret;
-}
-
-int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
-        int request, int value, int index, int length, uint8_t *data)
-{
-    const USBDesc *desc = usb_device_get_usb_desc(dev);
-    int ret = -1;
-
-    assert(desc != NULL);
-    switch(request) {
-    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
-        dev->addr = value;
-        trace_usb_set_addr(dev->addr);
-        ret = 0;
-        break;
-
-    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
-        ret = usb_desc_get_descriptor(dev, value, data, length);
-        break;
-
-    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
-        /*
-         * 9.4.2: 0 should be returned if the device is unconfigured, otherwise
-         * the non zero value of bConfigurationValue.
-         */
-        data[0] = dev->config ? dev->config->bConfigurationValue : 0;
-        ret = 1;
-        break;
-    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
-        ret = usb_desc_set_config(dev, value);
-        trace_usb_set_config(dev->addr, value, ret);
-        break;
-
-    case DeviceRequest | USB_REQ_GET_STATUS: {
-        const USBDescConfig *config = dev->config ?
-            dev->config : &dev->device->confs[0];
-
-        data[0] = 0;
-        /*
-         * Default state: Device behavior when this request is received while
-         *                the device is in the Default state is not specified.
-         * We return the same value that a configured device would return if
-         * it used the first configuration.
-         */
-        if (config->bmAttributes & 0x40) {
-            data[0] |= 1 << USB_DEVICE_SELF_POWERED;
-        }
-        if (dev->remote_wakeup) {
-            data[0] |= 1 << USB_DEVICE_REMOTE_WAKEUP;
-        }
-        data[1] = 0x00;
-        ret = 2;
-        break;
-    }
-    case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
-        if (value == USB_DEVICE_REMOTE_WAKEUP) {
-            dev->remote_wakeup = 0;
-            ret = 0;
-        }
-        trace_usb_clear_device_feature(dev->addr, value, ret);
-        break;
-    case DeviceOutRequest | USB_REQ_SET_FEATURE:
-        if (value == USB_DEVICE_REMOTE_WAKEUP) {
-            dev->remote_wakeup = 1;
-            ret = 0;
-        }
-        trace_usb_set_device_feature(dev->addr, value, ret);
-        break;
-
-    case InterfaceRequest | USB_REQ_GET_INTERFACE:
-        if (index < 0 || index >= dev->ninterfaces) {
-            break;
-        }
-        data[0] = dev->altsetting[index];
-        ret = 1;
-        break;
-    case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
-        ret = usb_desc_set_interface(dev, index, value);
-        trace_usb_set_interface(dev->addr, index, value, ret);
-        break;
-
-    }
-    return ret;
-}
diff --git a/hw/usb-desc.h b/hw/usb-desc.h
deleted file mode 100644
index d6e07ea..0000000
--- a/hw/usb-desc.h
+++ /dev/null
@@ -1,117 +0,0 @@
-#ifndef QEMU_HW_USB_DESC_H
-#define QEMU_HW_USB_DESC_H
-
-#include <inttypes.h>
-
-struct USBDescID {
-    uint16_t                  idVendor;
-    uint16_t                  idProduct;
-    uint16_t                  bcdDevice;
-    uint8_t                   iManufacturer;
-    uint8_t                   iProduct;
-    uint8_t                   iSerialNumber;
-};
-
-struct USBDescDevice {
-    uint16_t                  bcdUSB;
-    uint8_t                   bDeviceClass;
-    uint8_t                   bDeviceSubClass;
-    uint8_t                   bDeviceProtocol;
-    uint8_t                   bMaxPacketSize0;
-    uint8_t                   bNumConfigurations;
-
-    const USBDescConfig       *confs;
-};
-
-struct USBDescConfig {
-    uint8_t                   bNumInterfaces;
-    uint8_t                   bConfigurationValue;
-    uint8_t                   iConfiguration;
-    uint8_t                   bmAttributes;
-    uint8_t                   bMaxPower;
-
-    /* grouped interfaces */
-    uint8_t                   nif_groups;
-    const USBDescIfaceAssoc   *if_groups;
-
-    /* "normal" interfaces */
-    uint8_t                   nif;
-    const USBDescIface        *ifs;
-};
-
-/* conceptually an Interface Association Descriptor, and releated interfaces */
-struct USBDescIfaceAssoc {
-    uint8_t                   bFirstInterface;
-    uint8_t                   bInterfaceCount;
-    uint8_t                   bFunctionClass;
-    uint8_t                   bFunctionSubClass;
-    uint8_t                   bFunctionProtocol;
-    uint8_t                   iFunction;
-
-    uint8_t                   nif;
-    const USBDescIface        *ifs;
-};
-
-struct USBDescIface {
-    uint8_t                   bInterfaceNumber;
-    uint8_t                   bAlternateSetting;
-    uint8_t                   bNumEndpoints;
-    uint8_t                   bInterfaceClass;
-    uint8_t                   bInterfaceSubClass;
-    uint8_t                   bInterfaceProtocol;
-    uint8_t                   iInterface;
-
-    uint8_t                   ndesc;
-    USBDescOther              *descs;
-    USBDescEndpoint           *eps;
-};
-
-struct USBDescEndpoint {
-    uint8_t                   bEndpointAddress;
-    uint8_t                   bmAttributes;
-    uint16_t                  wMaxPacketSize;
-    uint8_t                   bInterval;
-    uint8_t                   bRefresh;
-    uint8_t                   bSynchAddress;
-
-    uint8_t                   is_audio; /* has bRefresh + bSynchAddress */
-    uint8_t                   *extra;
-};
-
-struct USBDescOther {
-    uint8_t                   length;
-    const uint8_t             *data;
-};
-
-typedef const char *USBDescStrings[256];
-
-struct USBDesc {
-    USBDescID                 id;
-    const USBDescDevice       *full;
-    const USBDescDevice       *high;
-    const char* const         *str;
-};
-
-/* generate usb packages from structs */
-int usb_desc_device(const USBDescID *id, const USBDescDevice *dev,
-                    uint8_t *dest, size_t len);
-int usb_desc_device_qualifier(const USBDescDevice *dev,
-                              uint8_t *dest, size_t len);
-int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len);
-int usb_desc_iface_group(const USBDescIfaceAssoc *iad, uint8_t *dest,
-                         size_t len);
-int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len);
-int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len);
-int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len);
-
-/* control message emulation helpers */
-void usb_desc_init(USBDevice *dev);
-void usb_desc_attach(USBDevice *dev);
-void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str);
-const char *usb_desc_get_string(USBDevice *dev, uint8_t index);
-int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len);
-int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len);
-int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
-        int request, int value, int index, int length, uint8_t *data);
-
-#endif /* QEMU_HW_USB_DESC_H */
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
deleted file mode 100644
index df742f7..0000000
--- a/hw/usb-ehci.c
+++ /dev/null
@@ -1,2345 +0,0 @@
-/*
- * QEMU USB EHCI Emulation
- *
- * Copyright(c) 2008  Emutex Ltd. (address at hidden)
- *
- * EHCI project was started by Mark Burkley, with contributions by
- * Niels de Vos.  David S. Ahern continued working on it.  Kevin Wolf,
- * Jan Kiszka and Vincent Palatin contributed bugfixes.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or(at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "hw.h"
-#include "qemu-timer.h"
-#include "usb.h"
-#include "pci.h"
-#include "monitor.h"
-#include "trace.h"
-#include "dma.h"
-
-#define EHCI_DEBUG   0
-
-#if EHCI_DEBUG
-#define DPRINTF printf
-#else
-#define DPRINTF(...)
-#endif
-
-/* internal processing - reset HC to try and recover */
-#define USB_RET_PROCERR   (-99)
-
-#define MMIO_SIZE        0x1000
-
-/* Capability Registers Base Address - section 2.2 */
-#define CAPREGBASE       0x0000
-#define CAPLENGTH        CAPREGBASE + 0x0000  // 1-byte, 0x0001 reserved
-#define HCIVERSION       CAPREGBASE + 0x0002  // 2-bytes, i/f version #
-#define HCSPARAMS        CAPREGBASE + 0x0004  // 4-bytes, structural params
-#define HCCPARAMS        CAPREGBASE + 0x0008  // 4-bytes, capability params
-#define EECP             HCCPARAMS + 1
-#define HCSPPORTROUTE1   CAPREGBASE + 0x000c
-#define HCSPPORTROUTE2   CAPREGBASE + 0x0010
-
-#define OPREGBASE        0x0020        // Operational Registers Base Address
-
-#define USBCMD           OPREGBASE + 0x0000
-#define USBCMD_RUNSTOP   (1 << 0)      // run / Stop
-#define USBCMD_HCRESET   (1 << 1)      // HC Reset
-#define USBCMD_FLS       (3 << 2)      // Frame List Size
-#define USBCMD_FLS_SH    2             // Frame List Size Shift
-#define USBCMD_PSE       (1 << 4)      // Periodic Schedule Enable
-#define USBCMD_ASE       (1 << 5)      // Asynch Schedule Enable
-#define USBCMD_IAAD      (1 << 6)      // Int Asynch Advance Doorbell
-#define USBCMD_LHCR      (1 << 7)      // Light Host Controller Reset
-#define USBCMD_ASPMC     (3 << 8)      // Async Sched Park Mode Count
-#define USBCMD_ASPME     (1 << 11)     // Async Sched Park Mode Enable
-#define USBCMD_ITC       (0x7f << 16)  // Int Threshold Control
-#define USBCMD_ITC_SH    16            // Int Threshold Control Shift
-
-#define USBSTS           OPREGBASE + 0x0004
-#define USBSTS_RO_MASK   0x0000003f
-#define USBSTS_INT       (1 << 0)      // USB Interrupt
-#define USBSTS_ERRINT    (1 << 1)      // Error Interrupt
-#define USBSTS_PCD       (1 << 2)      // Port Change Detect
-#define USBSTS_FLR       (1 << 3)      // Frame List Rollover
-#define USBSTS_HSE       (1 << 4)      // Host System Error
-#define USBSTS_IAA       (1 << 5)      // Interrupt on Async Advance
-#define USBSTS_HALT      (1 << 12)     // HC Halted
-#define USBSTS_REC       (1 << 13)     // Reclamation
-#define USBSTS_PSS       (1 << 14)     // Periodic Schedule Status
-#define USBSTS_ASS       (1 << 15)     // Asynchronous Schedule Status
-
-/*
- *  Interrupt enable bits correspond to the interrupt active bits in USBSTS
- *  so no need to redefine here.
- */
-#define USBINTR              OPREGBASE + 0x0008
-#define USBINTR_MASK         0x0000003f
-
-#define FRINDEX              OPREGBASE + 0x000c
-#define CTRLDSSEGMENT        OPREGBASE + 0x0010
-#define PERIODICLISTBASE     OPREGBASE + 0x0014
-#define ASYNCLISTADDR        OPREGBASE + 0x0018
-#define ASYNCLISTADDR_MASK   0xffffffe0
-
-#define CONFIGFLAG           OPREGBASE + 0x0040
-
-#define PORTSC               (OPREGBASE + 0x0044)
-#define PORTSC_BEGIN         PORTSC
-#define PORTSC_END           (PORTSC + 4 * NB_PORTS)
-/*
- * Bits that are reserved or are read-only are masked out of values
- * written to us by software
- */
-#define PORTSC_RO_MASK       0x007001c0
-#define PORTSC_RWC_MASK      0x0000002a
-#define PORTSC_WKOC_E        (1 << 22)    // Wake on Over Current Enable
-#define PORTSC_WKDS_E        (1 << 21)    // Wake on Disconnect Enable
-#define PORTSC_WKCN_E        (1 << 20)    // Wake on Connect Enable
-#define PORTSC_PTC           (15 << 16)   // Port Test Control
-#define PORTSC_PTC_SH        16           // Port Test Control shift
-#define PORTSC_PIC           (3 << 14)    // Port Indicator Control
-#define PORTSC_PIC_SH        14           // Port Indicator Control Shift
-#define PORTSC_POWNER        (1 << 13)    // Port Owner
-#define PORTSC_PPOWER        (1 << 12)    // Port Power
-#define PORTSC_LINESTAT      (3 << 10)    // Port Line Status
-#define PORTSC_LINESTAT_SH   10           // Port Line Status Shift
-#define PORTSC_PRESET        (1 << 8)     // Port Reset
-#define PORTSC_SUSPEND       (1 << 7)     // Port Suspend
-#define PORTSC_FPRES         (1 << 6)     // Force Port Resume
-#define PORTSC_OCC           (1 << 5)     // Over Current Change
-#define PORTSC_OCA           (1 << 4)     // Over Current Active
-#define PORTSC_PEDC          (1 << 3)     // Port Enable/Disable Change
-#define PORTSC_PED           (1 << 2)     // Port Enable/Disable
-#define PORTSC_CSC           (1 << 1)     // Connect Status Change
-#define PORTSC_CONNECT       (1 << 0)     // Current Connect Status
-
-#define FRAME_TIMER_FREQ 1000
-#define FRAME_TIMER_NS   (1000000000 / FRAME_TIMER_FREQ)
-
-#define NB_MAXINTRATE    8        // Max rate at which controller issues ints
-#define NB_PORTS         6        // Number of downstream ports
-#define BUFF_SIZE        5*4096   // Max bytes to transfer per transaction
-#define MAX_ITERATIONS   20       // Max number of QH before we break the loop
-#define MAX_QH           100      // Max allowable queue heads in a chain
-
-/*  Internal periodic / asynchronous schedule state machine states
- */
-typedef enum {
-    EST_INACTIVE = 1000,
-    EST_ACTIVE,
-    EST_EXECUTING,
-    EST_SLEEPING,
-    /*  The following states are internal to the state machine function
-    */
-    EST_WAITLISTHEAD,
-    EST_FETCHENTRY,
-    EST_FETCHQH,
-    EST_FETCHITD,
-    EST_FETCHSITD,
-    EST_ADVANCEQUEUE,
-    EST_FETCHQTD,
-    EST_EXECUTE,
-    EST_WRITEBACK,
-    EST_HORIZONTALQH
-} EHCI_STATES;
-
-/* macros for accessing fields within next link pointer entry */
-#define NLPTR_GET(x)             ((x) & 0xffffffe0)
-#define NLPTR_TYPE_GET(x)        (((x) >> 1) & 3)
-#define NLPTR_TBIT(x)            ((x) & 1)  // 1=invalid, 0=valid
-
-/* link pointer types */
-#define NLPTR_TYPE_ITD           0     // isoc xfer descriptor
-#define NLPTR_TYPE_QH            1     // queue head
-#define NLPTR_TYPE_STITD         2     // split xaction, isoc xfer descriptor
-#define NLPTR_TYPE_FSTN          3     // frame span traversal node
-
-
-/*  EHCI spec version 1.0 Section 3.3
- */
-typedef struct EHCIitd {
-    uint32_t next;
-
-    uint32_t transact[8];
-#define ITD_XACT_ACTIVE          (1 << 31)
-#define ITD_XACT_DBERROR         (1 << 30)
-#define ITD_XACT_BABBLE          (1 << 29)
-#define ITD_XACT_XACTERR         (1 << 28)
-#define ITD_XACT_LENGTH_MASK     0x0fff0000
-#define ITD_XACT_LENGTH_SH       16
-#define ITD_XACT_IOC             (1 << 15)
-#define ITD_XACT_PGSEL_MASK      0x00007000
-#define ITD_XACT_PGSEL_SH        12
-#define ITD_XACT_OFFSET_MASK     0x00000fff
-
-    uint32_t bufptr[7];
-#define ITD_BUFPTR_MASK          0xfffff000
-#define ITD_BUFPTR_SH            12
-#define ITD_BUFPTR_EP_MASK       0x00000f00
-#define ITD_BUFPTR_EP_SH         8
-#define ITD_BUFPTR_DEVADDR_MASK  0x0000007f
-#define ITD_BUFPTR_DEVADDR_SH    0
-#define ITD_BUFPTR_DIRECTION     (1 << 11)
-#define ITD_BUFPTR_MAXPKT_MASK   0x000007ff
-#define ITD_BUFPTR_MAXPKT_SH     0
-#define ITD_BUFPTR_MULT_MASK     0x00000003
-#define ITD_BUFPTR_MULT_SH       0
-} EHCIitd;
-
-/*  EHCI spec version 1.0 Section 3.4
- */
-typedef struct EHCIsitd {
-    uint32_t next;                  // Standard next link pointer
-    uint32_t epchar;
-#define SITD_EPCHAR_IO              (1 << 31)
-#define SITD_EPCHAR_PORTNUM_MASK    0x7f000000
-#define SITD_EPCHAR_PORTNUM_SH      24
-#define SITD_EPCHAR_HUBADD_MASK     0x007f0000
-#define SITD_EPCHAR_HUBADDR_SH      16
-#define SITD_EPCHAR_EPNUM_MASK      0x00000f00
-#define SITD_EPCHAR_EPNUM_SH        8
-#define SITD_EPCHAR_DEVADDR_MASK    0x0000007f
-
-    uint32_t uframe;
-#define SITD_UFRAME_CMASK_MASK      0x0000ff00
-#define SITD_UFRAME_CMASK_SH        8
-#define SITD_UFRAME_SMASK_MASK      0x000000ff
-
-    uint32_t results;
-#define SITD_RESULTS_IOC              (1 << 31)
-#define SITD_RESULTS_PGSEL            (1 << 30)
-#define SITD_RESULTS_TBYTES_MASK      0x03ff0000
-#define SITD_RESULTS_TYBYTES_SH       16
-#define SITD_RESULTS_CPROGMASK_MASK   0x0000ff00
-#define SITD_RESULTS_CPROGMASK_SH     8
-#define SITD_RESULTS_ACTIVE           (1 << 7)
-#define SITD_RESULTS_ERR              (1 << 6)
-#define SITD_RESULTS_DBERR            (1 << 5)
-#define SITD_RESULTS_BABBLE           (1 << 4)
-#define SITD_RESULTS_XACTERR          (1 << 3)
-#define SITD_RESULTS_MISSEDUF         (1 << 2)
-#define SITD_RESULTS_SPLITXSTATE      (1 << 1)
-
-    uint32_t bufptr[2];
-#define SITD_BUFPTR_MASK              0xfffff000
-#define SITD_BUFPTR_CURROFF_MASK      0x00000fff
-#define SITD_BUFPTR_TPOS_MASK         0x00000018
-#define SITD_BUFPTR_TPOS_SH           3
-#define SITD_BUFPTR_TCNT_MASK         0x00000007
-
-    uint32_t backptr;                 // Standard next link pointer
-} EHCIsitd;
-
-/*  EHCI spec version 1.0 Section 3.5
- */
-typedef struct EHCIqtd {
-    uint32_t next;                    // Standard next link pointer
-    uint32_t altnext;                 // Standard next link pointer
-    uint32_t token;
-#define QTD_TOKEN_DTOGGLE             (1 << 31)
-#define QTD_TOKEN_TBYTES_MASK         0x7fff0000
-#define QTD_TOKEN_TBYTES_SH           16
-#define QTD_TOKEN_IOC                 (1 << 15)
-#define QTD_TOKEN_CPAGE_MASK          0x00007000
-#define QTD_TOKEN_CPAGE_SH            12
-#define QTD_TOKEN_CERR_MASK           0x00000c00
-#define QTD_TOKEN_CERR_SH             10
-#define QTD_TOKEN_PID_MASK            0x00000300
-#define QTD_TOKEN_PID_SH              8
-#define QTD_TOKEN_ACTIVE              (1 << 7)
-#define QTD_TOKEN_HALT                (1 << 6)
-#define QTD_TOKEN_DBERR               (1 << 5)
-#define QTD_TOKEN_BABBLE              (1 << 4)
-#define QTD_TOKEN_XACTERR             (1 << 3)
-#define QTD_TOKEN_MISSEDUF            (1 << 2)
-#define QTD_TOKEN_SPLITXSTATE         (1 << 1)
-#define QTD_TOKEN_PING                (1 << 0)
-
-    uint32_t bufptr[5];               // Standard buffer pointer
-#define QTD_BUFPTR_MASK               0xfffff000
-#define QTD_BUFPTR_SH                 12
-} EHCIqtd;
-
-/*  EHCI spec version 1.0 Section 3.6
- */
-typedef struct EHCIqh {
-    uint32_t next;                    // Standard next link pointer
-
-    /* endpoint characteristics */
-    uint32_t epchar;
-#define QH_EPCHAR_RL_MASK             0xf0000000
-#define QH_EPCHAR_RL_SH               28
-#define QH_EPCHAR_C                   (1 << 27)
-#define QH_EPCHAR_MPLEN_MASK          0x07FF0000
-#define QH_EPCHAR_MPLEN_SH            16
-#define QH_EPCHAR_H                   (1 << 15)
-#define QH_EPCHAR_DTC                 (1 << 14)
-#define QH_EPCHAR_EPS_MASK            0x00003000
-#define QH_EPCHAR_EPS_SH              12
-#define EHCI_QH_EPS_FULL              0
-#define EHCI_QH_EPS_LOW               1
-#define EHCI_QH_EPS_HIGH              2
-#define EHCI_QH_EPS_RESERVED          3
-
-#define QH_EPCHAR_EP_MASK             0x00000f00
-#define QH_EPCHAR_EP_SH               8
-#define QH_EPCHAR_I                   (1 << 7)
-#define QH_EPCHAR_DEVADDR_MASK        0x0000007f
-#define QH_EPCHAR_DEVADDR_SH          0
-
-    /* endpoint capabilities */
-    uint32_t epcap;
-#define QH_EPCAP_MULT_MASK            0xc0000000
-#define QH_EPCAP_MULT_SH              30
-#define QH_EPCAP_PORTNUM_MASK         0x3f800000
-#define QH_EPCAP_PORTNUM_SH           23
-#define QH_EPCAP_HUBADDR_MASK         0x007f0000
-#define QH_EPCAP_HUBADDR_SH           16
-#define QH_EPCAP_CMASK_MASK           0x0000ff00
-#define QH_EPCAP_CMASK_SH             8
-#define QH_EPCAP_SMASK_MASK           0x000000ff
-#define QH_EPCAP_SMASK_SH             0
-
-    uint32_t current_qtd;             // Standard next link pointer
-    uint32_t next_qtd;                // Standard next link pointer
-    uint32_t altnext_qtd;
-#define QH_ALTNEXT_NAKCNT_MASK        0x0000001e
-#define QH_ALTNEXT_NAKCNT_SH          1
-
-    uint32_t token;                   // Same as QTD token
-    uint32_t bufptr[5];               // Standard buffer pointer
-#define BUFPTR_CPROGMASK_MASK         0x000000ff
-#define BUFPTR_FRAMETAG_MASK          0x0000001f
-#define BUFPTR_SBYTES_MASK            0x00000fe0
-#define BUFPTR_SBYTES_SH              5
-} EHCIqh;
-
-/*  EHCI spec version 1.0 Section 3.7
- */
-typedef struct EHCIfstn {
-    uint32_t next;                    // Standard next link pointer
-    uint32_t backptr;                 // Standard next link pointer
-} EHCIfstn;
-
-typedef struct EHCIQueue EHCIQueue;
-typedef struct EHCIState EHCIState;
-
-enum async_state {
-    EHCI_ASYNC_NONE = 0,
-    EHCI_ASYNC_INFLIGHT,
-    EHCI_ASYNC_FINISHED,
-};
-
-struct EHCIQueue {
-    EHCIState *ehci;
-    QTAILQ_ENTRY(EHCIQueue) next;
-    uint32_t seen;
-    uint64_t ts;
-
-    /* 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;
-};
-
-typedef QTAILQ_HEAD(EHCIQueueHead, EHCIQueue) EHCIQueueHead;
-
-struct EHCIState {
-    PCIDevice dev;
-    USBBus bus;
-    qemu_irq irq;
-    MemoryRegion mem;
-    int companion_count;
-
-    /* properties */
-    uint32_t freq;
-    uint32_t maxframes;
-
-    /*
-     *  EHCI spec version 1.0 Section 2.3
-     *  Host Controller Operational Registers
-     */
-    union {
-        uint8_t mmio[MMIO_SIZE];
-        struct {
-            uint8_t cap[OPREGBASE];
-            uint32_t usbcmd;
-            uint32_t usbsts;
-            uint32_t usbintr;
-            uint32_t frindex;
-            uint32_t ctrldssegment;
-            uint32_t periodiclistbase;
-            uint32_t asynclistaddr;
-            uint32_t notused[9];
-            uint32_t configflag;
-            uint32_t portsc[NB_PORTS];
-        };
-    };
-
-    /*
-     *  Internal states, shadow registers, etc
-     */
-    uint32_t sofv;
-    QEMUTimer *frame_timer;
-    int attach_poll_counter;
-    int astate;                        // Current state in asynchronous schedule
-    int pstate;                        // Current state in periodic schedule
-    USBPort ports[NB_PORTS];
-    USBPort *companion_ports[NB_PORTS];
-    uint32_t usbsts_pending;
-    EHCIQueueHead aqueues;
-    EHCIQueueHead pqueues;
-
-    uint32_t a_fetch_addr;   // which address to look at next
-    uint32_t p_fetch_addr;   // which address to look at next
-
-    USBPacket ipacket;
-    QEMUSGList isgl;
-    int isoch_pause;
-
-    uint64_t last_run_ns;
-};
-
-#define SET_LAST_RUN_CLOCK(s) \
-    (s)->last_run_ns = qemu_get_clock_ns(vm_clock);
-
-/* nifty macros from Arnon's EHCI version  */
-#define get_field(data, field) \
-    (((data) & field##_MASK) >> field##_SH)
-
-#define set_field(data, newval, field) do { \
-    uint32_t val = *data; \
-    val &= ~ field##_MASK; \
-    val |= ((newval) << field##_SH) & field##_MASK; \
-    *data = val; \
-    } while(0)
-
-static const char *ehci_state_names[] = {
-    [EST_INACTIVE]     = "INACTIVE",
-    [EST_ACTIVE]       = "ACTIVE",
-    [EST_EXECUTING]    = "EXECUTING",
-    [EST_SLEEPING]     = "SLEEPING",
-    [EST_WAITLISTHEAD] = "WAITLISTHEAD",
-    [EST_FETCHENTRY]   = "FETCH ENTRY",
-    [EST_FETCHQH]      = "FETCH QH",
-    [EST_FETCHITD]     = "FETCH ITD",
-    [EST_ADVANCEQUEUE] = "ADVANCEQUEUE",
-    [EST_FETCHQTD]     = "FETCH QTD",
-    [EST_EXECUTE]      = "EXECUTE",
-    [EST_WRITEBACK]    = "WRITEBACK",
-    [EST_HORIZONTALQH] = "HORIZONTALQH",
-};
-
-static const char *ehci_mmio_names[] = {
-    [CAPLENGTH]         = "CAPLENGTH",
-    [HCIVERSION]        = "HCIVERSION",
-    [HCSPARAMS]         = "HCSPARAMS",
-    [HCCPARAMS]         = "HCCPARAMS",
-    [USBCMD]            = "USBCMD",
-    [USBSTS]            = "USBSTS",
-    [USBINTR]           = "USBINTR",
-    [FRINDEX]           = "FRINDEX",
-    [PERIODICLISTBASE]  = "P-LIST BASE",
-    [ASYNCLISTADDR]     = "A-LIST ADDR",
-    [PORTSC_BEGIN]      = "PORTSC #0",
-    [PORTSC_BEGIN + 4]  = "PORTSC #1",
-    [PORTSC_BEGIN + 8]  = "PORTSC #2",
-    [PORTSC_BEGIN + 12] = "PORTSC #3",
-    [PORTSC_BEGIN + 16] = "PORTSC #4",
-    [PORTSC_BEGIN + 20] = "PORTSC #5",
-    [CONFIGFLAG]        = "CONFIGFLAG",
-};
-
-static const char *nr2str(const char **n, size_t len, uint32_t nr)
-{
-    if (nr < len && n[nr] != NULL) {
-        return n[nr];
-    } else {
-        return "unknown";
-    }
-}
-
-static const char *state2str(uint32_t state)
-{
-    return nr2str(ehci_state_names, ARRAY_SIZE(ehci_state_names), state);
-}
-
-static const char *addr2str(target_phys_addr_t addr)
-{
-    return nr2str(ehci_mmio_names, ARRAY_SIZE(ehci_mmio_names), addr);
-}
-
-static void ehci_trace_usbsts(uint32_t mask, int state)
-{
-    /* interrupts */
-    if (mask & USBSTS_INT) {
-        trace_usb_ehci_usbsts("INT", state);
-    }
-    if (mask & USBSTS_ERRINT) {
-        trace_usb_ehci_usbsts("ERRINT", state);
-    }
-    if (mask & USBSTS_PCD) {
-        trace_usb_ehci_usbsts("PCD", state);
-    }
-    if (mask & USBSTS_FLR) {
-        trace_usb_ehci_usbsts("FLR", state);
-    }
-    if (mask & USBSTS_HSE) {
-        trace_usb_ehci_usbsts("HSE", state);
-    }
-    if (mask & USBSTS_IAA) {
-        trace_usb_ehci_usbsts("IAA", state);
-    }
-
-    /* status */
-    if (mask & USBSTS_HALT) {
-        trace_usb_ehci_usbsts("HALT", state);
-    }
-    if (mask & USBSTS_REC) {
-        trace_usb_ehci_usbsts("REC", state);
-    }
-    if (mask & USBSTS_PSS) {
-        trace_usb_ehci_usbsts("PSS", state);
-    }
-    if (mask & USBSTS_ASS) {
-        trace_usb_ehci_usbsts("ASS", state);
-    }
-}
-
-static inline void ehci_set_usbsts(EHCIState *s, int mask)
-{
-    if ((s->usbsts & mask) == mask) {
-        return;
-    }
-    ehci_trace_usbsts(mask, 1);
-    s->usbsts |= mask;
-}
-
-static inline void ehci_clear_usbsts(EHCIState *s, int mask)
-{
-    if ((s->usbsts & mask) == 0) {
-        return;
-    }
-    ehci_trace_usbsts(mask, 0);
-    s->usbsts &= ~mask;
-}
-
-static inline void ehci_set_interrupt(EHCIState *s, int intr)
-{
-    int level = 0;
-
-    // TODO honour interrupt threshold requests
-
-    ehci_set_usbsts(s, intr);
-
-    if ((s->usbsts & USBINTR_MASK) & s->usbintr) {
-        level = 1;
-    }
-
-    qemu_set_irq(s->irq, level);
-}
-
-static inline void ehci_record_interrupt(EHCIState *s, int intr)
-{
-    s->usbsts_pending |= intr;
-}
-
-static inline void ehci_commit_interrupt(EHCIState *s)
-{
-    if (!s->usbsts_pending) {
-        return;
-    }
-    ehci_set_interrupt(s, s->usbsts_pending);
-    s->usbsts_pending = 0;
-}
-
-static void ehci_set_state(EHCIState *s, int async, int state)
-{
-    if (async) {
-        trace_usb_ehci_state("async", state2str(state));
-        s->astate = state;
-    } else {
-        trace_usb_ehci_state("periodic", state2str(state));
-        s->pstate = state;
-    }
-}
-
-static int ehci_get_state(EHCIState *s, int async)
-{
-    return async ? s->astate : s->pstate;
-}
-
-static void ehci_set_fetch_addr(EHCIState *s, int async, uint32_t addr)
-{
-    if (async) {
-        s->a_fetch_addr = addr;
-    } else {
-        s->p_fetch_addr = addr;
-    }
-}
-
-static int ehci_get_fetch_addr(EHCIState *s, int async)
-{
-    return async ? s->a_fetch_addr : s->p_fetch_addr;
-}
-
-static void ehci_trace_qh(EHCIQueue *q, target_phys_addr_t addr, EHCIqh *qh)
-{
-    /* need three here due to argument count limits */
-    trace_usb_ehci_qh_ptrs(q, addr, qh->next,
-                           qh->current_qtd, qh->next_qtd, qh->altnext_qtd);
-    trace_usb_ehci_qh_fields(addr,
-                             get_field(qh->epchar, QH_EPCHAR_RL),
-                             get_field(qh->epchar, QH_EPCHAR_MPLEN),
-                             get_field(qh->epchar, QH_EPCHAR_EPS),
-                             get_field(qh->epchar, QH_EPCHAR_EP),
-                             get_field(qh->epchar, QH_EPCHAR_DEVADDR));
-    trace_usb_ehci_qh_bits(addr,
-                           (bool)(qh->epchar & QH_EPCHAR_C),
-                           (bool)(qh->epchar & QH_EPCHAR_H),
-                           (bool)(qh->epchar & QH_EPCHAR_DTC),
-                           (bool)(qh->epchar & QH_EPCHAR_I));
-}
-
-static void ehci_trace_qtd(EHCIQueue *q, target_phys_addr_t addr, EHCIqtd *qtd)
-{
-    /* need three here due to argument count limits */
-    trace_usb_ehci_qtd_ptrs(q, addr, qtd->next, qtd->altnext);
-    trace_usb_ehci_qtd_fields(addr,
-                              get_field(qtd->token, QTD_TOKEN_TBYTES),
-                              get_field(qtd->token, QTD_TOKEN_CPAGE),
-                              get_field(qtd->token, QTD_TOKEN_CERR),
-                              get_field(qtd->token, QTD_TOKEN_PID));
-    trace_usb_ehci_qtd_bits(addr,
-                            (bool)(qtd->token & QTD_TOKEN_IOC),
-                            (bool)(qtd->token & QTD_TOKEN_ACTIVE),
-                            (bool)(qtd->token & QTD_TOKEN_HALT),
-                            (bool)(qtd->token & QTD_TOKEN_BABBLE),
-                            (bool)(qtd->token & QTD_TOKEN_XACTERR));
-}
-
-static void ehci_trace_itd(EHCIState *s, target_phys_addr_t addr, EHCIitd *itd)
-{
-    trace_usb_ehci_itd(addr, itd->next,
-                       get_field(itd->bufptr[1], ITD_BUFPTR_MAXPKT),
-                       get_field(itd->bufptr[2], ITD_BUFPTR_MULT),
-                       get_field(itd->bufptr[0], ITD_BUFPTR_EP),
-                       get_field(itd->bufptr[0], ITD_BUFPTR_DEVADDR));
-}
-
-static void ehci_trace_sitd(EHCIState *s, target_phys_addr_t addr,
-                            EHCIsitd *sitd)
-{
-    trace_usb_ehci_sitd(addr, sitd->next,
-                        (bool)(sitd->results & SITD_RESULTS_ACTIVE));
-}
-
-/* queue management */
-
-static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async)
-{
-    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
-    EHCIQueue *q;
-
-    q = g_malloc0(sizeof(*q));
-    q->ehci = ehci;
-    QTAILQ_INSERT_HEAD(head, q, next);
-    trace_usb_ehci_queue_action(q, "alloc");
-    return q;
-}
-
-static void ehci_free_queue(EHCIQueue *q, int async)
-{
-    EHCIQueueHead *head = async ? &q->ehci->aqueues : &q->ehci->pqueues;
-    trace_usb_ehci_queue_action(q, "free");
-    if (q->async == EHCI_ASYNC_INFLIGHT) {
-        usb_cancel_packet(&q->packet);
-    }
-    QTAILQ_REMOVE(head, q, next);
-    g_free(q);
-}
-
-static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr,
-                                        int async)
-{
-    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
-    EHCIQueue *q;
-
-    QTAILQ_FOREACH(q, head, next) {
-        if (addr == q->qhaddr) {
-            return q;
-        }
-    }
-    return NULL;
-}
-
-static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
-{
-    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
-    EHCIQueue *q, *tmp;
-
-    QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
-        if (q->seen) {
-            q->seen = 0;
-            q->ts = ehci->last_run_ns;
-            continue;
-        }
-        if (!flush && ehci->last_run_ns < q->ts + 250000000) {
-            /* allow 0.25 sec idle */
-            continue;
-        }
-        ehci_free_queue(q, async);
-    }
-}
-
-static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async)
-{
-    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
-    EHCIQueue *q, *tmp;
-
-    QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
-        if (!usb_packet_is_inflight(&q->packet) ||
-            q->packet.ep->dev != dev) {
-            continue;
-        }
-        ehci_free_queue(q, async);
-    }
-}
-
-static void ehci_queues_rip_all(EHCIState *ehci, int async)
-{
-    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
-    EHCIQueue *q, *tmp;
-
-    QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
-        ehci_free_queue(q, async);
-    }
-}
-
-/* Attach or detach a device on root hub */
-
-static void ehci_attach(USBPort *port)
-{
-    EHCIState *s = port->opaque;
-    uint32_t *portsc = &s->portsc[port->index];
-
-    trace_usb_ehci_port_attach(port->index, port->dev->product_desc);
-
-    if (*portsc & PORTSC_POWNER) {
-        USBPort *companion = s->companion_ports[port->index];
-        companion->dev = port->dev;
-        companion->ops->attach(companion);
-        return;
-    }
-
-    *portsc |= PORTSC_CONNECT;
-    *portsc |= PORTSC_CSC;
-
-    ehci_set_interrupt(s, USBSTS_PCD);
-}
-
-static void ehci_detach(USBPort *port)
-{
-    EHCIState *s = port->opaque;
-    uint32_t *portsc = &s->portsc[port->index];
-
-    trace_usb_ehci_port_detach(port->index);
-
-    if (*portsc & PORTSC_POWNER) {
-        USBPort *companion = s->companion_ports[port->index];
-        companion->ops->detach(companion);
-        companion->dev = NULL;
-        /*
-         * EHCI spec 4.2.2: "When a disconnect occurs... On the event,
-         * the port ownership is returned immediately to the EHCI controller."
-         */
-        *portsc &= ~PORTSC_POWNER;
-        return;
-    }
-
-    ehci_queues_rip_device(s, port->dev, 0);
-    ehci_queues_rip_device(s, port->dev, 1);
-
-    *portsc &= ~(PORTSC_CONNECT|PORTSC_PED);
-    *portsc |= PORTSC_CSC;
-
-    ehci_set_interrupt(s, USBSTS_PCD);
-}
-
-static void ehci_child_detach(USBPort *port, USBDevice *child)
-{
-    EHCIState *s = port->opaque;
-    uint32_t portsc = s->portsc[port->index];
-
-    if (portsc & PORTSC_POWNER) {
-        USBPort *companion = s->companion_ports[port->index];
-        companion->ops->child_detach(companion, child);
-        companion->dev = NULL;
-        return;
-    }
-
-    ehci_queues_rip_device(s, child, 0);
-    ehci_queues_rip_device(s, child, 1);
-}
-
-static void ehci_wakeup(USBPort *port)
-{
-    EHCIState *s = port->opaque;
-    uint32_t portsc = s->portsc[port->index];
-
-    if (portsc & PORTSC_POWNER) {
-        USBPort *companion = s->companion_ports[port->index];
-        if (companion->ops->wakeup) {
-            companion->ops->wakeup(companion);
-        }
-    }
-}
-
-static int ehci_register_companion(USBBus *bus, USBPort *ports[],
-                                   uint32_t portcount, uint32_t firstport)
-{
-    EHCIState *s = container_of(bus, EHCIState, bus);
-    uint32_t i;
-
-    if (firstport + portcount > NB_PORTS) {
-        qerror_report(QERR_INVALID_PARAMETER_VALUE, "firstport",
-                      "firstport on masterbus");
-        error_printf_unless_qmp(
-            "firstport value of %u makes companion take ports %u - %u, which "
-            "is outside of the valid range of 0 - %u\n", firstport, firstport,
-            firstport + portcount - 1, NB_PORTS - 1);
-        return -1;
-    }
-
-    for (i = 0; i < portcount; i++) {
-        if (s->companion_ports[firstport + i]) {
-            qerror_report(QERR_INVALID_PARAMETER_VALUE, "masterbus",
-                          "an USB masterbus");
-            error_printf_unless_qmp(
-                "port %u on masterbus %s already has a companion assigned\n",
-                firstport + i, bus->qbus.name);
-            return -1;
-        }
-    }
-
-    for (i = 0; i < portcount; i++) {
-        s->companion_ports[firstport + i] = ports[i];
-        s->ports[firstport + i].speedmask |=
-            USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL;
-        /* Ensure devs attached before the initial reset go to the companion */
-        s->portsc[firstport + i] = PORTSC_POWNER;
-    }
-
-    s->companion_count++;
-    s->mmio[0x05] = (s->companion_count << 4) | portcount;
-
-    return 0;
-}
-
-static USBDevice *ehci_find_device(EHCIState *ehci, uint8_t addr)
-{
-    USBDevice *dev;
-    USBPort *port;
-    int i;
-
-    for (i = 0; i < NB_PORTS; i++) {
-        port = &ehci->ports[i];
-        if (!(ehci->portsc[i] & PORTSC_PED)) {
-            DPRINTF("Port %d not enabled\n", i);
-            continue;
-        }
-        dev = usb_find_device(port, addr);
-        if (dev != NULL) {
-            return dev;
-        }
-    }
-    return NULL;
-}
-
-/* 4.1 host controller initialization */
-static void ehci_reset(void *opaque)
-{
-    EHCIState *s = opaque;
-    int i;
-    USBDevice *devs[NB_PORTS];
-
-    trace_usb_ehci_reset();
-
-    /*
-     * Do the detach before touching portsc, so that it correctly gets send to
-     * us or to our companion based on PORTSC_POWNER before the reset.
-     */
-    for(i = 0; i < NB_PORTS; i++) {
-        devs[i] = s->ports[i].dev;
-        if (devs[i] && devs[i]->attached) {
-            usb_detach(&s->ports[i]);
-        }
-    }
-
-    memset(&s->mmio[OPREGBASE], 0x00, MMIO_SIZE - OPREGBASE);
-
-    s->usbcmd = NB_MAXINTRATE << USBCMD_ITC_SH;
-    s->usbsts = USBSTS_HALT;
-
-    s->astate = EST_INACTIVE;
-    s->pstate = EST_INACTIVE;
-    s->isoch_pause = -1;
-    s->attach_poll_counter = 0;
-
-    for(i = 0; i < NB_PORTS; i++) {
-        if (s->companion_ports[i]) {
-            s->portsc[i] = PORTSC_POWNER | PORTSC_PPOWER;
-        } else {
-            s->portsc[i] = PORTSC_PPOWER;
-        }
-        if (devs[i] && devs[i]->attached) {
-            usb_attach(&s->ports[i]);
-            usb_device_reset(devs[i]);
-        }
-    }
-    ehci_queues_rip_all(s, 0);
-    ehci_queues_rip_all(s, 1);
-    qemu_del_timer(s->frame_timer);
-}
-
-static uint32_t ehci_mem_readb(void *ptr, target_phys_addr_t addr)
-{
-    EHCIState *s = ptr;
-    uint32_t val;
-
-    val = s->mmio[addr];
-
-    return val;
-}
-
-static uint32_t ehci_mem_readw(void *ptr, target_phys_addr_t addr)
-{
-    EHCIState *s = ptr;
-    uint32_t val;
-
-    val = s->mmio[addr] | (s->mmio[addr+1] << 8);
-
-    return val;
-}
-
-static uint32_t ehci_mem_readl(void *ptr, target_phys_addr_t addr)
-{
-    EHCIState *s = ptr;
-    uint32_t val;
-
-    val = s->mmio[addr] | (s->mmio[addr+1] << 8) |
-          (s->mmio[addr+2] << 16) | (s->mmio[addr+3] << 24);
-
-    trace_usb_ehci_mmio_readl(addr, addr2str(addr), val);
-    return val;
-}
-
-static void ehci_mem_writeb(void *ptr, target_phys_addr_t addr, uint32_t val)
-{
-    fprintf(stderr, "EHCI doesn't handle byte writes to MMIO\n");
-    exit(1);
-}
-
-static void ehci_mem_writew(void *ptr, target_phys_addr_t addr, uint32_t val)
-{
-    fprintf(stderr, "EHCI doesn't handle 16-bit writes to MMIO\n");
-    exit(1);
-}
-
-static void handle_port_owner_write(EHCIState *s, int port, uint32_t owner)
-{
-    USBDevice *dev = s->ports[port].dev;
-    uint32_t *portsc = &s->portsc[port];
-    uint32_t orig;
-
-    if (s->companion_ports[port] == NULL)
-        return;
-
-    owner = owner & PORTSC_POWNER;
-    orig  = *portsc & PORTSC_POWNER;
-
-    if (!(owner ^ orig)) {
-        return;
-    }
-
-    if (dev && dev->attached) {
-        usb_detach(&s->ports[port]);
-    }
-
-    *portsc &= ~PORTSC_POWNER;
-    *portsc |= owner;
-
-    if (dev && dev->attached) {
-        usb_attach(&s->ports[port]);
-    }
-}
-
-static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
-{
-    uint32_t *portsc = &s->portsc[port];
-    USBDevice *dev = s->ports[port].dev;
-
-    /* Clear rwc bits */
-    *portsc &= ~(val & PORTSC_RWC_MASK);
-    /* The guest may clear, but not set the PED bit */
-    *portsc &= val | ~PORTSC_PED;
-    /* POWNER is masked out by RO_MASK as it is RO when we've no companion */
-    handle_port_owner_write(s, port, val);
-    /* And finally apply RO_MASK */
-    val &= PORTSC_RO_MASK;
-
-    if ((val & PORTSC_PRESET) && !(*portsc & PORTSC_PRESET)) {
-        trace_usb_ehci_port_reset(port, 1);
-    }
-
-    if (!(val & PORTSC_PRESET) &&(*portsc & PORTSC_PRESET)) {
-        trace_usb_ehci_port_reset(port, 0);
-        if (dev && dev->attached) {
-            usb_port_reset(&s->ports[port]);
-            *portsc &= ~PORTSC_CSC;
-        }
-
-        /*
-         *  Table 2.16 Set the enable bit(and enable bit change) to indicate
-         *  to SW that this port has a high speed device attached
-         */
-        if (dev && dev->attached && (dev->speedmask & USB_SPEED_MASK_HIGH)) {
-            val |= PORTSC_PED;
-        }
-    }
-
-    *portsc &= ~PORTSC_RO_MASK;
-    *portsc |= val;
-}
-
-static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
-{
-    EHCIState *s = ptr;
-    uint32_t *mmio = (uint32_t *)(&s->mmio[addr]);
-    uint32_t old = *mmio;
-    int i;
-
-    trace_usb_ehci_mmio_writel(addr, addr2str(addr), val);
-
-    /* Only aligned reads are allowed on OHCI */
-    if (addr & 3) {
-        fprintf(stderr, "usb-ehci: Mis-aligned write to addr 0x"
-                TARGET_FMT_plx "\n", addr);
-        return;
-    }
-
-    if (addr >= PORTSC && addr < PORTSC + 4 * NB_PORTS) {
-        handle_port_status_write(s, (addr-PORTSC)/4, val);
-        trace_usb_ehci_mmio_change(addr, addr2str(addr), *mmio, old);
-        return;
-    }
-
-    if (addr < OPREGBASE) {
-        fprintf(stderr, "usb-ehci: write attempt to read-only register"
-                TARGET_FMT_plx "\n", addr);
-        return;
-    }
-
-
-    /* Do any register specific pre-write processing here.  */
-    switch(addr) {
-    case USBCMD:
-        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);
-            ehci_queues_rip_all(s, 0);
-            ehci_queues_rip_all(s, 1);
-            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)) {
-            fprintf(stderr, "attempt to set frame list size -- value %d\n",
-                    val & USBCMD_FLS);
-            val &= ~USBCMD_FLS;
-        }
-        break;
-
-    case USBSTS:
-        val &= USBSTS_RO_MASK;              // bits 6 thru 31 are RO
-        ehci_clear_usbsts(s, val);          // bits 0 thru 5 are R/WC
-        val = s->usbsts;
-        ehci_set_interrupt(s, 0);
-        break;
-
-    case USBINTR:
-        val &= USBINTR_MASK;
-        break;
-
-    case FRINDEX:
-        s->sofv = val >> 3;
-        break;
-
-    case CONFIGFLAG:
-        val &= 0x1;
-        if (val) {
-            for(i = 0; i < NB_PORTS; i++)
-                handle_port_owner_write(s, i, 0);
-        }
-        break;
-
-    case PERIODICLISTBASE:
-        if ((s->usbcmd & USBCMD_PSE) && (s->usbcmd & USBCMD_RUNSTOP)) {
-            fprintf(stderr,
-              "ehci: PERIODIC list base register set while periodic schedule\n"
-              "      is enabled and HC is enabled\n");
-        }
-        break;
-
-    case ASYNCLISTADDR:
-        if ((s->usbcmd & USBCMD_ASE) && (s->usbcmd & USBCMD_RUNSTOP)) {
-            fprintf(stderr,
-              "ehci: ASYNC list address register set while async schedule\n"
-              "      is enabled and HC is enabled\n");
-        }
-        break;
-    }
-
-    *mmio = val;
-    trace_usb_ehci_mmio_change(addr, addr2str(addr), *mmio, old);
-}
-
-
-// TODO : Put in common header file, duplication from usb-ohci.c
-
-/* Get an array of dwords from main memory */
-static inline int get_dwords(EHCIState *ehci, uint32_t addr,
-                             uint32_t *buf, int num)
-{
-    int i;
-
-    for(i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
-        pci_dma_read(&ehci->dev, addr, buf, sizeof(*buf));
-        *buf = le32_to_cpu(*buf);
-    }
-
-    return 1;
-}
-
-/* Put an array of dwords in to main memory */
-static inline int put_dwords(EHCIState *ehci, uint32_t addr,
-                             uint32_t *buf, int num)
-{
-    int i;
-
-    for(i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
-        uint32_t tmp = cpu_to_le32(*buf);
-        pci_dma_write(&ehci->dev, addr, &tmp, sizeof(tmp));
-    }
-
-    return 1;
-}
-
-// 4.10.2
-
-static int ehci_qh_do_overlay(EHCIQueue *q)
-{
-    int i;
-    int dtoggle;
-    int ping;
-    int eps;
-    int reload;
-
-    // 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;
-
-
-    eps = get_field(q->qh.epchar, QH_EPCHAR_EPS);
-    if (eps == EHCI_QH_EPS_HIGH) {
-        q->qh.token &= ~QTD_TOKEN_PING;
-        q->qh.token |= ping;
-    }
-
-    reload = get_field(q->qh.epchar, QH_EPCHAR_RL);
-    set_field(&q->qh.altnext_qtd, reload, QH_ALTNEXT_NAKCNT);
-
-    for (i = 0; i < 5; i++) {
-        q->qh.bufptr[i] = q->qtd.bufptr[i];
-    }
-
-    if (!(q->qh.epchar & QH_EPCHAR_DTC)) {
-        // preserve QH DT bit
-        q->qh.token &= ~QTD_TOKEN_DTOGGLE;
-        q->qh.token |= dtoggle;
-    }
-
-    q->qh.bufptr[1] &= ~BUFPTR_CPROGMASK_MASK;
-    q->qh.bufptr[2] &= ~BUFPTR_FRAMETAG_MASK;
-
-    put_dwords(q->ehci, NLPTR_GET(q->qhaddr), (uint32_t *) &q->qh,
-               sizeof(EHCIqh) >> 2);
-
-    return 0;
-}
-
-static int ehci_init_transfer(EHCIQueue *q)
-{
-    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);
-
-    while (bytes > 0) {
-        if (cpage > 4) {
-            fprintf(stderr, "cpage out of range (%d)\n", cpage);
-            return USB_RET_PROCERR;
-        }
-
-        page  = q->qh.bufptr[cpage] & QTD_BUFPTR_MASK;
-        page += offset;
-        plen  = bytes;
-        if (plen > 4096 - offset) {
-            plen = 4096 - offset;
-            offset = 0;
-            cpage++;
-        }
-
-        qemu_sglist_add(&q->sgl, page, plen);
-        bytes -= plen;
-    }
-    return 0;
-}
-
-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);
-        offset = q->qh.bufptr[0] & ~QTD_BUFPTR_MASK;
-
-        offset += status;
-        cpage  += offset >> QTD_BUFPTR_SH;
-        offset &= ~QTD_BUFPTR_MASK;
-
-        set_field(&q->qh.token, cpage, QTD_TOKEN_CPAGE);
-        q->qh.bufptr[0] &= QTD_BUFPTR_MASK;
-        q->qh.bufptr[0] |= offset;
-    }
-}
-
-static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
-{
-    EHCIQueue *q;
-    EHCIState *s = port->opaque;
-    uint32_t portsc = s->portsc[port->index];
-
-    if (portsc & PORTSC_POWNER) {
-        USBPort *companion = s->companion_ports[port->index];
-        companion->ops->complete(companion, 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;
-}
-
-static void ehci_execute_complete(EHCIQueue *q)
-{
-    assert(q->async != EHCI_ASYNC_INFLIGHT);
-    q->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) {
-        case USB_RET_IOERROR:
-        case USB_RET_NODEV:
-            q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_XACTERR);
-            set_field(&q->qh.token, 0, QTD_TOKEN_CERR);
-            ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
-            break;
-        case USB_RET_STALL:
-            q->qh.token |= QTD_TOKEN_HALT;
-            ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
-            break;
-        case USB_RET_NAK:
-            set_field(&q->qh.altnext_qtd, 0, QH_ALTNEXT_NAKCNT);
-            return; /* We're not done yet with this transaction */
-        case USB_RET_BABBLE:
-            q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_BABBLE);
-            ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
-            break;
-        default:
-            /* should not be triggerable */
-            fprintf(stderr, "USB invalid response %d to handle\n", q->usb_status);
-            assert(0);
-            break;
-        }
-    } else if ((q->usb_status > q->tbytes) && (q->pid == USB_TOKEN_IN)) {
-        q->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;
-        } else {
-            q->tbytes = 0;
-        }
-
-        DPRINTF("updating tbytes to %d\n", q->tbytes);
-        set_field(&q->qh.token, q->tbytes, QTD_TOKEN_TBYTES);
-    }
-    ehci_finish_transfer(q, q->usb_status);
-    usb_packet_unmap(&q->packet);
-
-    q->qh.token ^= QTD_TOKEN_DTOGGLE;
-    q->qh.token &= ~QTD_TOKEN_ACTIVE;
-
-    if (q->qh.token & QTD_TOKEN_IOC) {
-        ehci_record_interrupt(q->ehci, USBSTS_INT);
-    }
-}
-
-// 4.10.3
-
-static int ehci_execute(EHCIQueue *q)
-{
-    USBDevice *dev;
-    USBEndpoint *ep;
-    int ret;
-    int endp;
-    int devadr;
-
-    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) {
-        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;
-    }
-
-    if (ehci_init_transfer(q) != 0) {
-        return USB_RET_PROCERR;
-    }
-
-    endp = get_field(q->qh.epchar, QH_EPCHAR_EP);
-    devadr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR);
-
-    /* TODO: associating device with ehci port */
-    dev = ehci_find_device(q->ehci, devadr);
-    ep = usb_ep_get(dev, q->pid, endp);
-
-    usb_packet_setup(&q->packet, q->pid, ep);
-    usb_packet_map(&q->packet, &q->sgl);
-
-    ret = usb_handle_packet(dev, &q->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,
-            q->packet.iov.size, q->tbytes, endp, ret);
-
-    if (ret > BUFF_SIZE) {
-        fprintf(stderr, "ret from usb_handle_packet > BUFF_SIZE\n");
-        return USB_RET_PROCERR;
-    }
-
-    return ret;
-}
-
-/*  4.7.2
- */
-
-static int ehci_process_itd(EHCIState *ehci,
-                            EHCIitd *itd)
-{
-    USBDevice *dev;
-    USBEndpoint *ep;
-    int ret;
-    uint32_t i, len, pid, dir, devaddr, endp;
-    uint32_t pg, off, ptr1, ptr2, max, mult;
-
-    dir =(itd->bufptr[1] & ITD_BUFPTR_DIRECTION);
-    devaddr = get_field(itd->bufptr[0], ITD_BUFPTR_DEVADDR);
-    endp = get_field(itd->bufptr[0], ITD_BUFPTR_EP);
-    max = get_field(itd->bufptr[1], ITD_BUFPTR_MAXPKT);
-    mult = get_field(itd->bufptr[2], ITD_BUFPTR_MULT);
-
-    for(i = 0; i < 8; i++) {
-        if (itd->transact[i] & ITD_XACT_ACTIVE) {
-            pg   = get_field(itd->transact[i], ITD_XACT_PGSEL);
-            off  = itd->transact[i] & ITD_XACT_OFFSET_MASK;
-            ptr1 = (itd->bufptr[pg] & ITD_BUFPTR_MASK);
-            ptr2 = (itd->bufptr[pg+1] & ITD_BUFPTR_MASK);
-            len  = get_field(itd->transact[i], ITD_XACT_LENGTH);
-
-            if (len > max * mult) {
-                len = max * mult;
-            }
-
-            if (len > BUFF_SIZE) {
-                return USB_RET_PROCERR;
-            }
-
-            pci_dma_sglist_init(&ehci->isgl, &ehci->dev, 2);
-            if (off + len > 4096) {
-                /* transfer crosses page border */
-                uint32_t len2 = off + len - 4096;
-                uint32_t len1 = len - len2;
-                qemu_sglist_add(&ehci->isgl, ptr1 + off, len1);
-                qemu_sglist_add(&ehci->isgl, ptr2, len2);
-            } else {
-                qemu_sglist_add(&ehci->isgl, ptr1 + off, len);
-            }
-
-            pid = dir ? USB_TOKEN_IN : USB_TOKEN_OUT;
-
-            dev = ehci_find_device(ehci, devaddr);
-            ep = usb_ep_get(dev, pid, endp);
-            if (ep->type == USB_ENDPOINT_XFER_ISOC) {
-                usb_packet_setup(&ehci->ipacket, pid, ep);
-                usb_packet_map(&ehci->ipacket, &ehci->isgl);
-                ret = usb_handle_packet(dev, &ehci->ipacket);
-                assert(ret != USB_RET_ASYNC);
-                usb_packet_unmap(&ehci->ipacket);
-            } else {
-                DPRINTF("ISOCH: attempt to addess non-iso endpoint\n");
-                ret = USB_RET_NAK;
-            }
-            qemu_sglist_destroy(&ehci->isgl);
-
-            if (ret < 0) {
-                switch (ret) {
-                default:
-                    fprintf(stderr, "Unexpected iso usb result: %d\n", ret);
-                    /* Fall through */
-                case USB_RET_IOERROR:
-                case USB_RET_NODEV:
-                    /* 3.3.2: XACTERR is only allowed on IN transactions */
-                    if (dir) {
-                        itd->transact[i] |= ITD_XACT_XACTERR;
-                        ehci_record_interrupt(ehci, USBSTS_ERRINT);
-                    }
-                    break;
-                case USB_RET_BABBLE:
-                    itd->transact[i] |= ITD_XACT_BABBLE;
-                    ehci_record_interrupt(ehci, USBSTS_ERRINT);
-                    break;
-                case USB_RET_NAK:
-                    /* no data for us, so do a zero-length transfer */
-                    ret = 0;
-                    break;
-                }
-            }
-            if (ret >= 0) {
-                if (!dir) {
-                    /* OUT */
-                    set_field(&itd->transact[i], len - ret, ITD_XACT_LENGTH);
-                } else {
-                    /* IN */
-                    set_field(&itd->transact[i], ret, ITD_XACT_LENGTH);
-                }
-            }
-            if (itd->transact[i] & ITD_XACT_IOC) {
-                ehci_record_interrupt(ehci, USBSTS_INT);
-            }
-            itd->transact[i] &= ~ITD_XACT_ACTIVE;
-        }
-    }
-    return 0;
-}
-
-/*  This state is the entry point for asynchronous schedule
- *  processing.  Entry here consitutes a EHCI start event state (4.8.5)
- */
-static int ehci_state_waitlisthead(EHCIState *ehci,  int async)
-{
-    EHCIqh qh;
-    int i = 0;
-    int again = 0;
-    uint32_t entry = ehci->asynclistaddr;
-
-    /* set reclamation flag at start event (4.8.6) */
-    if (async) {
-        ehci_set_usbsts(ehci, USBSTS_REC);
-    }
-
-    ehci_queues_rip_unused(ehci, async, 0);
-
-    /*  Find the head of the list (4.9.1.1) */
-    for(i = 0; i < MAX_QH; i++) {
-        get_dwords(ehci, NLPTR_GET(entry), (uint32_t *) &qh,
-                   sizeof(EHCIqh) >> 2);
-        ehci_trace_qh(NULL, NLPTR_GET(entry), &qh);
-
-        if (qh.epchar & QH_EPCHAR_H) {
-            if (async) {
-                entry |= (NLPTR_TYPE_QH << 1);
-            }
-
-            ehci_set_fetch_addr(ehci, async, entry);
-            ehci_set_state(ehci, async, EST_FETCHENTRY);
-            again = 1;
-            goto out;
-        }
-
-        entry = qh.next;
-        if (entry == ehci->asynclistaddr) {
-            break;
-        }
-    }
-
-    /* no head found for list. */
-
-    ehci_set_state(ehci, async, EST_ACTIVE);
-
-out:
-    return again;
-}
-
-
-/*  This state is the entry point for periodic schedule processing as
- *  well as being a continuation state for async processing.
- */
-static int ehci_state_fetchentry(EHCIState *ehci, int async)
-{
-    int again = 0;
-    uint32_t entry = ehci_get_fetch_addr(ehci, async);
-
-    if (NLPTR_TBIT(entry)) {
-        ehci_set_state(ehci, async, EST_ACTIVE);
-        goto out;
-    }
-
-    /* section 4.8, only QH in async schedule */
-    if (async && (NLPTR_TYPE_GET(entry) != NLPTR_TYPE_QH)) {
-        fprintf(stderr, "non queue head request in async schedule\n");
-        return -1;
-    }
-
-    switch (NLPTR_TYPE_GET(entry)) {
-    case NLPTR_TYPE_QH:
-        ehci_set_state(ehci, async, EST_FETCHQH);
-        again = 1;
-        break;
-
-    case NLPTR_TYPE_ITD:
-        ehci_set_state(ehci, async, EST_FETCHITD);
-        again = 1;
-        break;
-
-    case NLPTR_TYPE_STITD:
-        ehci_set_state(ehci, async, EST_FETCHSITD);
-        again = 1;
-        break;
-
-    default:
-        /* TODO: handle FSTN type */
-        fprintf(stderr, "FETCHENTRY: entry at %X is of type %d "
-                "which is not supported yet\n", entry, NLPTR_TYPE_GET(entry));
-        return -1;
-    }
-
-out:
-    return again;
-}
-
-static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
-{
-    uint32_t entry;
-    EHCIQueue *q;
-
-    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->qhaddr = entry;
-    q->seen++;
-
-    if (q->seen > 1) {
-        /* we are going in circles -- stop processing */
-        ehci_set_state(ehci, async, EST_ACTIVE);
-        q = NULL;
-        goto out;
-    }
-
-    get_dwords(ehci, NLPTR_GET(q->qhaddr),
-               (uint32_t *) &q->qh, sizeof(EHCIqh) >> 2);
-    ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &q->qh);
-
-    if (q->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) {
-        /* I/O finished -- continue processing queue */
-        trace_usb_ehci_queue_action(q, "resume");
-        ehci_set_state(ehci, async, EST_EXECUTING);
-        goto out;
-    }
-
-    if (async && (q->qh.epchar & QH_EPCHAR_H)) {
-
-        /*  EHCI spec version 1.0 Section 4.8.3 & 4.10.1 */
-        if (ehci->usbsts & USBSTS_REC) {
-            ehci_clear_usbsts(ehci, USBSTS_REC);
-        } else {
-            DPRINTF("FETCHQH:  QH 0x%08x. H-bit set, reclamation status reset"
-                       " - done processing\n", q->qhaddr);
-            ehci_set_state(ehci, async, EST_ACTIVE);
-            q = NULL;
-            goto out;
-        }
-    }
-
-#if EHCI_DEBUG
-    if (q->qhaddr != q->qh.next) {
-    DPRINTF("FETCHQH:  QH 0x%08x (h %x halt %x active %x) next 0x%08x\n",
-               q->qhaddr,
-               q->qh.epchar & QH_EPCHAR_H,
-               q->qh.token & QTD_TOKEN_HALT,
-               q->qh.token & QTD_TOKEN_ACTIVE,
-               q->qh.next);
-    }
-#endif
-
-    if (q->qh.token & QTD_TOKEN_HALT) {
-        ehci_set_state(ehci, async, EST_HORIZONTALQH);
-
-    } else if ((q->qh.token & QTD_TOKEN_ACTIVE) &&
-               (NLPTR_TBIT(q->qh.current_qtd) == 0)) {
-        q->qtdaddr = q->qh.current_qtd;
-        ehci_set_state(ehci, async, EST_FETCHQTD);
-
-    } else {
-        /*  EHCI spec version 1.0 Section 4.10.2 */
-        ehci_set_state(ehci, async, EST_ADVANCEQUEUE);
-    }
-
-out:
-    return q;
-}
-
-static int ehci_state_fetchitd(EHCIState *ehci, int async)
-{
-    uint32_t entry;
-    EHCIitd itd;
-
-    assert(!async);
-    entry = ehci_get_fetch_addr(ehci, async);
-
-    get_dwords(ehci, NLPTR_GET(entry), (uint32_t *) &itd,
-               sizeof(EHCIitd) >> 2);
-    ehci_trace_itd(ehci, entry, &itd);
-
-    if (ehci_process_itd(ehci, &itd) != 0) {
-        return -1;
-    }
-
-    put_dwords(ehci, NLPTR_GET(entry), (uint32_t *) &itd,
-               sizeof(EHCIitd) >> 2);
-    ehci_set_fetch_addr(ehci, async, itd.next);
-    ehci_set_state(ehci, async, EST_FETCHENTRY);
-
-    return 1;
-}
-
-static int ehci_state_fetchsitd(EHCIState *ehci, int async)
-{
-    uint32_t entry;
-    EHCIsitd sitd;
-
-    assert(!async);
-    entry = ehci_get_fetch_addr(ehci, async);
-
-    get_dwords(ehci, NLPTR_GET(entry), (uint32_t *)&sitd,
-               sizeof(EHCIsitd) >> 2);
-    ehci_trace_sitd(ehci, entry, &sitd);
-
-    if (!(sitd.results & SITD_RESULTS_ACTIVE)) {
-        /* siTD is not active, nothing to do */;
-    } else {
-        /* TODO: split transfers are not implemented */
-        fprintf(stderr, "WARNING: Skipping active siTD\n");
-    }
-
-    ehci_set_fetch_addr(ehci, async, sitd.next);
-    ehci_set_state(ehci, async, EST_FETCHENTRY);
-    return 1;
-}
-
-/* Section 4.10.2 - paragraph 3 */
-static int ehci_state_advqueue(EHCIQueue *q, int async)
-{
-#if 0
-    /* TO-DO: 4.10.2 - paragraph 2
-     * if I-bit is set to 1 and QH is not active
-     * go to horizontal QH
-     */
-    if (I-bit set) {
-        ehci_set_state(ehci, async, EST_HORIZONTALQH);
-        goto out;
-    }
-#endif
-
-    /*
-     * want data and alt-next qTD is valid
-     */
-    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);
-
-    /*
-     *  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);
-
-    /*
-     *  no valid qTD, try next QH
-     */
-    } else {
-        ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
-    }
-
-    return 1;
-}
-
-/* Section 4.10.2 - paragraph 4 */
-static int ehci_state_fetchqtd(EHCIQueue *q, int async)
-{
-    int again = 0;
-
-    get_dwords(q->ehci, NLPTR_GET(q->qtdaddr), (uint32_t *) &q->qtd,
-               sizeof(EHCIqtd) >> 2);
-    ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), &q->qtd);
-
-    if (q->qtd.token & QTD_TOKEN_ACTIVE) {
-        ehci_set_state(q->ehci, async, EST_EXECUTE);
-        again = 1;
-    } else {
-        ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
-        again = 1;
-    }
-
-    return again;
-}
-
-static int ehci_state_horizqh(EHCIQueue *q, int async)
-{
-    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);
-        again = 1;
-    } else {
-        ehci_set_state(q->ehci, async, EST_ACTIVE);
-    }
-
-    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)
-{
-    int again = 0;
-
-    if (ehci_qh_do_overlay(q) != 0) {
-        return -1;
-    }
-
-    // TODO verify enough time remains in the uframe as in 4.4.1.1
-    // 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) {
-        int transactCtr = get_field(q->qh.epcap, QH_EPCAP_MULT);
-        if (!transactCtr) {
-            ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
-            again = 1;
-            goto out;
-        }
-    }
-
-    if (async) {
-        ehci_set_usbsts(q->ehci, USBSTS_REC);
-    }
-
-    q->usb_status = ehci_execute(q);
-    if (q->usb_status == USB_RET_PROCERR) {
-        again = -1;
-        goto out;
-    }
-    if (q->usb_status == USB_RET_ASYNC) {
-        ehci_flush_qh(q);
-        trace_usb_ehci_queue_action(q, "suspend");
-        q->async = EHCI_ASYNC_INFLIGHT;
-        ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
-        again = 1;
-        goto out;
-    }
-
-    ehci_set_state(q->ehci, async, EST_EXECUTING);
-    again = 1;
-
-out:
-    return again;
-}
-
-static int ehci_state_executing(EHCIQueue *q, int async)
-{
-    int again = 0;
-
-    ehci_execute_complete(q);
-    if (q->usb_status == USB_RET_ASYNC) {
-        goto out;
-    }
-    if (q->usb_status == USB_RET_PROCERR) {
-        again = -1;
-        goto out;
-    }
-
-    // 4.10.3
-    if (!async) {
-        int transactCtr = get_field(q->qh.epcap, QH_EPCAP_MULT);
-        transactCtr--;
-        set_field(&q->qh.epcap, transactCtr, QH_EPCAP_MULT);
-        // 4.10.3, bottom of page 82, should exit this state when transaction
-        // counter decrements to 0
-    }
-
-    /* 4.10.5 */
-    if (q->usb_status == USB_RET_NAK) {
-        ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
-    } else {
-        ehci_set_state(q->ehci, async, EST_WRITEBACK);
-    }
-
-    again = 1;
-
-out:
-    ehci_flush_qh(q);
-    return again;
-}
-
-
-static int ehci_state_writeback(EHCIQueue *q, int async)
-{
-    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,
-               sizeof(EHCIqtd) >> 2);
-
-    /*
-     * EHCI specs say go horizontal here.
-     *
-     * We can also advance the queue here for performance reasons.  We
-     * need to take care to only take that shortcut in case we've
-     * processed the qtd just written back without errors, i.e. halt
-     * bit is clear.
-     */
-    if (q->qh.token & QTD_TOKEN_HALT) {
-        ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
-        again = 1;
-    } else {
-        ehci_set_state(q->ehci, async, EST_ADVANCEQUEUE);
-        again = 1;
-    }
-    return again;
-}
-
-/*
- * This is the state machine that is common to both async and periodic
- */
-
-static void ehci_advance_state(EHCIState *ehci,
-                               int async)
-{
-    EHCIQueue *q = NULL;
-    int again;
-    int iter = 0;
-
-    do {
-        if (ehci_get_state(ehci, async) == EST_FETCHQH) {
-            iter++;
-            /* if we are roaming a lot of QH without executing a qTD
-             * something is wrong with the linked list. TO-DO: why is
-             * this hack needed?
-             */
-            assert(iter < MAX_ITERATIONS);
-#if 0
-            if (iter > MAX_ITERATIONS) {
-                DPRINTF("\n*** advance_state: bailing on MAX ITERATIONS***\n");
-                ehci_set_state(ehci, async, EST_ACTIVE);
-                break;
-            }
-#endif
-        }
-        switch(ehci_get_state(ehci, async)) {
-        case EST_WAITLISTHEAD:
-            again = ehci_state_waitlisthead(ehci, async);
-            break;
-
-        case EST_FETCHENTRY:
-            again = ehci_state_fetchentry(ehci, async);
-            break;
-
-        case EST_FETCHQH:
-            q = ehci_state_fetchqh(ehci, async);
-            again = q ? 1 : 0;
-            break;
-
-        case EST_FETCHITD:
-            again = ehci_state_fetchitd(ehci, async);
-            break;
-
-        case EST_FETCHSITD:
-            again = ehci_state_fetchsitd(ehci, async);
-            break;
-
-        case EST_ADVANCEQUEUE:
-            again = ehci_state_advqueue(q, async);
-            break;
-
-        case EST_FETCHQTD:
-            again = ehci_state_fetchqtd(q, async);
-            break;
-
-        case EST_HORIZONTALQH:
-            again = ehci_state_horizqh(q, async);
-            break;
-
-        case EST_EXECUTE:
-            iter = 0;
-            again = ehci_state_execute(q, async);
-            break;
-
-        case EST_EXECUTING:
-            assert(q != NULL);
-            again = ehci_state_executing(q, async);
-            break;
-
-        case EST_WRITEBACK:
-            assert(q != NULL);
-            again = ehci_state_writeback(q, async);
-            break;
-
-        default:
-            fprintf(stderr, "Bad state!\n");
-            again = -1;
-            assert(0);
-            break;
-        }
-
-        if (again < 0) {
-            fprintf(stderr, "processing error - resetting ehci HC\n");
-            ehci_reset(ehci);
-            again = 0;
-            assert(0);
-        }
-    }
-    while (again);
-
-    ehci_commit_interrupt(ehci);
-}
-
-static void ehci_advance_async_state(EHCIState *ehci)
-{
-    const int async = 1;
-
-    switch(ehci_get_state(ehci, async)) {
-    case EST_INACTIVE:
-        if (!(ehci->usbcmd & USBCMD_ASE)) {
-            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->usbcmd & USBCMD_ASE)) {
-            ehci_queues_rip_all(ehci, async);
-            ehci_clear_usbsts(ehci, USBSTS_ASS);
-            ehci_set_state(ehci, async, EST_INACTIVE);
-            break;
-        }
-
-        /* make sure guest has acknowledged the doorbell interrupt */
-        /* TO-DO: is this really needed? */
-        if (ehci->usbsts & USBSTS_IAA) {
-            DPRINTF("IAA status bit still set.\n");
-            break;
-        }
-
-        /* check that address register has been set */
-        if (ehci->asynclistaddr == 0) {
-            break;
-        }
-
-        ehci_set_state(ehci, async, EST_WAITLISTHEAD);
-        ehci_advance_state(ehci, async);
-
-        /* If the doorbell is set, the guest wants to make a change to the
-         * schedule. The host controller needs to release cached data.
-         * (section 4.8.2)
-         */
-        if (ehci->usbcmd & USBCMD_IAAD) {
-            /* Remove all unseen qhs from the async qhs queue */
-            ehci_queues_rip_unused(ehci, async, 1);
-            DPRINTF("ASYNC: doorbell request acknowledged\n");
-            ehci->usbcmd &= ~USBCMD_IAAD;
-            ehci_set_interrupt(ehci, USBSTS_IAA);
-        }
-        break;
-
-    default:
-        /* this should only be due to a developer mistake */
-        fprintf(stderr, "ehci: Bad asynchronous state %d. "
-                "Resetting to active\n", ehci->astate);
-        assert(0);
-    }
-}
-
-static void ehci_advance_periodic_state(EHCIState *ehci)
-{
-    uint32_t entry;
-    uint32_t list;
-    const int async = 0;
-
-    // 4.6
-
-    switch(ehci_get_state(ehci, async)) {
-    case EST_INACTIVE:
-        if ( !(ehci->frindex & 7) && (ehci->usbcmd & USBCMD_PSE)) {
-            ehci_set_usbsts(ehci, USBSTS_PSS);
-            ehci_set_state(ehci, async, EST_ACTIVE);
-            // No break, fall through to ACTIVE
-        } else
-            break;
-
-    case EST_ACTIVE:
-        if ( !(ehci->frindex & 7) && !(ehci->usbcmd & USBCMD_PSE)) {
-            ehci_queues_rip_all(ehci, async);
-            ehci_clear_usbsts(ehci, USBSTS_PSS);
-            ehci_set_state(ehci, async, EST_INACTIVE);
-            break;
-        }
-
-        list = ehci->periodiclistbase & 0xfffff000;
-        /* check that register has been set */
-        if (list == 0) {
-            break;
-        }
-        list |= ((ehci->frindex & 0x1ff8) >> 1);
-
-        pci_dma_read(&ehci->dev, list, &entry, sizeof entry);
-        entry = le32_to_cpu(entry);
-
-        DPRINTF("PERIODIC state adv fr=%d.  [%08X] -> %08X\n",
-                ehci->frindex / 8, list, entry);
-        ehci_set_fetch_addr(ehci, async,entry);
-        ehci_set_state(ehci, async, EST_FETCHENTRY);
-        ehci_advance_state(ehci, async);
-        ehci_queues_rip_unused(ehci, async, 0);
-        break;
-
-    default:
-        /* this should only be due to a developer mistake */
-        fprintf(stderr, "ehci: Bad periodic state %d. "
-                "Resetting to active\n", ehci->pstate);
-        assert(0);
-    }
-}
-
-static void ehci_frame_timer(void *opaque)
-{
-    EHCIState *ehci = opaque;
-    int64_t expire_time, t_now;
-    uint64_t ns_elapsed;
-    int frames;
-    int i;
-    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++) {
-        if ( !(ehci->usbsts & USBSTS_HALT)) {
-            if (ehci->isoch_pause <= 0) {
-                ehci->frindex += 8;
-            }
-
-            if (ehci->frindex > 0x00001fff) {
-                ehci->frindex = 0;
-                ehci_set_interrupt(ehci, USBSTS_FLR);
-            }
-
-            ehci->sofv = (ehci->frindex - 1) >> 3;
-            ehci->sofv &= 0x000003ff;
-        }
-
-        if (frames - i > ehci->maxframes) {
-            skipped_frames++;
-        } else {
-            ehci_advance_periodic_state(ehci);
-        }
-
-        ehci->last_run_ns += FRAME_TIMER_NS;
-    }
-
-#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
-     */
-    ehci_advance_async_state(ehci);
-
-    qemu_mod_timer(ehci->frame_timer, expire_time);
-}
-
-
-static const MemoryRegionOps ehci_mem_ops = {
-    .old_mmio = {
-        .read = { ehci_mem_readb, ehci_mem_readw, ehci_mem_readl },
-        .write = { ehci_mem_writeb, ehci_mem_writew, ehci_mem_writel },
-    },
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static int usb_ehci_initfn(PCIDevice *dev);
-
-static USBPortOps ehci_port_ops = {
-    .attach = ehci_attach,
-    .detach = ehci_detach,
-    .child_detach = ehci_child_detach,
-    .wakeup = ehci_wakeup,
-    .complete = ehci_async_complete_packet,
-};
-
-static USBBusOps ehci_bus_ops = {
-    .register_companion = ehci_register_companion,
-};
-
-static const VMStateDescription vmstate_ehci = {
-    .name = "ehci",
-    .unmigratable = 1,
-};
-
-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(),
-};
-
-static void ehci_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = usb_ehci_initfn;
-    k->vendor_id = PCI_VENDOR_ID_INTEL;
-    k->device_id = PCI_DEVICE_ID_INTEL_82801D; /* ich4 */
-    k->revision = 0x10;
-    k->class_id = PCI_CLASS_SERIAL_USB;
-    dc->vmsd = &vmstate_ehci;
-    dc->props = ehci_properties;
-}
-
-static TypeInfo ehci_info = {
-    .name          = "usb-ehci",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(EHCIState),
-    .class_init    = ehci_class_init,
-};
-
-static void ich9_ehci_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = usb_ehci_initfn;
-    k->vendor_id = PCI_VENDOR_ID_INTEL;
-    k->device_id = PCI_DEVICE_ID_INTEL_82801I_EHCI1;
-    k->revision = 0x03;
-    k->class_id = PCI_CLASS_SERIAL_USB;
-    dc->vmsd = &vmstate_ehci;
-    dc->props = ehci_properties;
-}
-
-static TypeInfo ich9_ehci_info = {
-    .name          = "ich9-usb-ehci1",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(EHCIState),
-    .class_init    = ich9_ehci_class_init,
-};
-
-static int usb_ehci_initfn(PCIDevice *dev)
-{
-    EHCIState *s = DO_UPCAST(EHCIState, dev, dev);
-    uint8_t *pci_conf = s->dev.config;
-    int i;
-
-    pci_set_byte(&pci_conf[PCI_CLASS_PROG], 0x20);
-
-    /* capabilities pointer */
-    pci_set_byte(&pci_conf[PCI_CAPABILITY_LIST], 0x00);
-    //pci_set_byte(&pci_conf[PCI_CAPABILITY_LIST], 0x50);
-
-    pci_set_byte(&pci_conf[PCI_INTERRUPT_PIN], 4); /* interrupt pin D */
-    pci_set_byte(&pci_conf[PCI_MIN_GNT], 0);
-    pci_set_byte(&pci_conf[PCI_MAX_LAT], 0);
-
-    // pci_conf[0x50] = 0x01; // power management caps
-
-    pci_set_byte(&pci_conf[USB_SBRN], USB_RELEASE_2); // release number (2.1.4)
-    pci_set_byte(&pci_conf[0x61], 0x20);  // frame length adjustment (2.1.5)
-    pci_set_word(&pci_conf[0x62], 0x00);  // port wake up capability (2.1.6)
-
-    pci_conf[0x64] = 0x00;
-    pci_conf[0x65] = 0x00;
-    pci_conf[0x66] = 0x00;
-    pci_conf[0x67] = 0x00;
-    pci_conf[0x68] = 0x01;
-    pci_conf[0x69] = 0x00;
-    pci_conf[0x6a] = 0x00;
-    pci_conf[0x6b] = 0x00;  // USBLEGSUP
-    pci_conf[0x6c] = 0x00;
-    pci_conf[0x6d] = 0x00;
-    pci_conf[0x6e] = 0x00;
-    pci_conf[0x6f] = 0xc0;  // USBLEFCTLSTS
-
-    // 2.2 host controller interface version
-    s->mmio[0x00] = (uint8_t) OPREGBASE;
-    s->mmio[0x01] = 0x00;
-    s->mmio[0x02] = 0x00;
-    s->mmio[0x03] = 0x01;        // HC version
-    s->mmio[0x04] = NB_PORTS;    // Number of downstream ports
-    s->mmio[0x05] = 0x00;        // No companion ports at present
-    s->mmio[0x06] = 0x00;
-    s->mmio[0x07] = 0x00;
-    s->mmio[0x08] = 0x80;        // We can cache whole frame, not 64-bit capable
-    s->mmio[0x09] = 0x68;        // EECP
-    s->mmio[0x0a] = 0x00;
-    s->mmio[0x0b] = 0x00;
-
-    s->irq = s->dev.irq[3];
-
-    usb_bus_new(&s->bus, &ehci_bus_ops, &s->dev.qdev);
-    for(i = 0; i < NB_PORTS; i++) {
-        usb_register_port(&s->bus, &s->ports[i], s, i, &ehci_port_ops,
-                          USB_SPEED_MASK_HIGH);
-        s->ports[i].dev = 0;
-    }
-
-    s->frame_timer = qemu_new_timer_ns(vm_clock, ehci_frame_timer, s);
-    QTAILQ_INIT(&s->aqueues);
-    QTAILQ_INIT(&s->pqueues);
-
-    qemu_register_reset(ehci_reset, s);
-
-    memory_region_init_io(&s->mem, &ehci_mem_ops, s, "ehci", MMIO_SIZE);
-    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem);
-
-    return 0;
-}
-
-static void ehci_register_types(void)
-{
-    type_register_static(&ehci_info);
-    type_register_static(&ich9_ehci_info);
-}
-
-type_init(ehci_register_types)
-
-/*
- * vim: expandtab ts=4
- */
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
deleted file mode 100644
index 37bca78..0000000
--- a/hw/usb-hid.c
+++ /dev/null
@@ -1,638 +0,0 @@
-/*
- * QEMU USB HID devices
- *
- * Copyright (c) 2005 Fabrice Bellard
- * Copyright (c) 2007 OpenMoko, Inc.  (andrew at openedhand.com)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "hw.h"
-#include "console.h"
-#include "usb.h"
-#include "usb-desc.h"
-#include "qemu-timer.h"
-#include "hid.h"
-
-/* HID interface requests */
-#define GET_REPORT   0xa101
-#define GET_IDLE     0xa102
-#define GET_PROTOCOL 0xa103
-#define SET_REPORT   0x2109
-#define SET_IDLE     0x210a
-#define SET_PROTOCOL 0x210b
-
-/* HID descriptor types */
-#define USB_DT_HID    0x21
-#define USB_DT_REPORT 0x22
-#define USB_DT_PHY    0x23
-
-typedef struct USBHIDState {
-    USBDevice dev;
-    USBEndpoint *intr;
-    HIDState hid;
-} USBHIDState;
-
-enum {
-    STR_MANUFACTURER = 1,
-    STR_PRODUCT_MOUSE,
-    STR_PRODUCT_TABLET,
-    STR_PRODUCT_KEYBOARD,
-    STR_SERIALNUMBER,
-    STR_CONFIG_MOUSE,
-    STR_CONFIG_TABLET,
-    STR_CONFIG_KEYBOARD,
-};
-
-static const USBDescStrings desc_strings = {
-    [STR_MANUFACTURER]     = "QEMU " QEMU_VERSION,
-    [STR_PRODUCT_MOUSE]    = "QEMU USB Mouse",
-    [STR_PRODUCT_TABLET]   = "QEMU USB Tablet",
-    [STR_PRODUCT_KEYBOARD] = "QEMU USB Keyboard",
-    [STR_SERIALNUMBER]     = "42", /* == remote wakeup works */
-    [STR_CONFIG_MOUSE]     = "HID Mouse",
-    [STR_CONFIG_TABLET]    = "HID Tablet",
-    [STR_CONFIG_KEYBOARD]  = "HID Keyboard",
-};
-
-static const USBDescIface desc_iface_mouse = {
-    .bInterfaceNumber              = 0,
-    .bNumEndpoints                 = 1,
-    .bInterfaceClass               = USB_CLASS_HID,
-    .bInterfaceSubClass            = 0x01, /* boot */
-    .bInterfaceProtocol            = 0x02,
-    .ndesc                         = 1,
-    .descs = (USBDescOther[]) {
-        {
-            /* HID descriptor */
-            .data = (uint8_t[]) {
-                0x09,          /*  u8  bLength */
-                USB_DT_HID,    /*  u8  bDescriptorType */
-                0x01, 0x00,    /*  u16 HID_class */
-                0x00,          /*  u8  country_code */
-                0x01,          /*  u8  num_descriptors */
-                USB_DT_REPORT, /*  u8  type: Report */
-                52, 0,         /*  u16 len */
-            },
-        },
-    },
-    .eps = (USBDescEndpoint[]) {
-        {
-            .bEndpointAddress      = USB_DIR_IN | 0x01,
-            .bmAttributes          = USB_ENDPOINT_XFER_INT,
-            .wMaxPacketSize        = 4,
-            .bInterval             = 0x0a,
-        },
-    },
-};
-
-static const USBDescIface desc_iface_tablet = {
-    .bInterfaceNumber              = 0,
-    .bNumEndpoints                 = 1,
-    .bInterfaceClass               = USB_CLASS_HID,
-    .bInterfaceProtocol            = 0x02,
-    .ndesc                         = 1,
-    .descs = (USBDescOther[]) {
-        {
-            /* HID descriptor */
-            .data = (uint8_t[]) {
-                0x09,          /*  u8  bLength */
-                USB_DT_HID,    /*  u8  bDescriptorType */
-                0x01, 0x00,    /*  u16 HID_class */
-                0x00,          /*  u8  country_code */
-                0x01,          /*  u8  num_descriptors */
-                USB_DT_REPORT, /*  u8  type: Report */
-                74, 0,         /*  u16 len */
-            },
-        },
-    },
-    .eps = (USBDescEndpoint[]) {
-        {
-            .bEndpointAddress      = USB_DIR_IN | 0x01,
-            .bmAttributes          = USB_ENDPOINT_XFER_INT,
-            .wMaxPacketSize        = 8,
-            .bInterval             = 0x0a,
-        },
-    },
-};
-
-static const USBDescIface desc_iface_keyboard = {
-    .bInterfaceNumber              = 0,
-    .bNumEndpoints                 = 1,
-    .bInterfaceClass               = USB_CLASS_HID,
-    .bInterfaceSubClass            = 0x01, /* boot */
-    .bInterfaceProtocol            = 0x01, /* keyboard */
-    .ndesc                         = 1,
-    .descs = (USBDescOther[]) {
-        {
-            /* HID descriptor */
-            .data = (uint8_t[]) {
-                0x09,          /*  u8  bLength */
-                USB_DT_HID,    /*  u8  bDescriptorType */
-                0x11, 0x01,    /*  u16 HID_class */
-                0x00,          /*  u8  country_code */
-                0x01,          /*  u8  num_descriptors */
-                USB_DT_REPORT, /*  u8  type: Report */
-                0x3f, 0,       /*  u16 len */
-            },
-        },
-    },
-    .eps = (USBDescEndpoint[]) {
-        {
-            .bEndpointAddress      = USB_DIR_IN | 0x01,
-            .bmAttributes          = USB_ENDPOINT_XFER_INT,
-            .wMaxPacketSize        = 8,
-            .bInterval             = 0x0a,
-        },
-    },
-};
-
-static const USBDescDevice desc_device_mouse = {
-    .bcdUSB                        = 0x0100,
-    .bMaxPacketSize0               = 8,
-    .bNumConfigurations            = 1,
-    .confs = (USBDescConfig[]) {
-        {
-            .bNumInterfaces        = 1,
-            .bConfigurationValue   = 1,
-            .iConfiguration        = STR_CONFIG_MOUSE,
-            .bmAttributes          = 0xa0,
-            .bMaxPower             = 50,
-            .nif = 1,
-            .ifs = &desc_iface_mouse,
-        },
-    },
-};
-
-static const USBDescDevice desc_device_tablet = {
-    .bcdUSB                        = 0x0100,
-    .bMaxPacketSize0               = 8,
-    .bNumConfigurations            = 1,
-    .confs = (USBDescConfig[]) {
-        {
-            .bNumInterfaces        = 1,
-            .bConfigurationValue   = 1,
-            .iConfiguration        = STR_CONFIG_TABLET,
-            .bmAttributes          = 0xa0,
-            .bMaxPower             = 50,
-            .nif = 1,
-            .ifs = &desc_iface_tablet,
-        },
-    },
-};
-
-static const USBDescDevice desc_device_keyboard = {
-    .bcdUSB                        = 0x0100,
-    .bMaxPacketSize0               = 8,
-    .bNumConfigurations            = 1,
-    .confs = (USBDescConfig[]) {
-        {
-            .bNumInterfaces        = 1,
-            .bConfigurationValue   = 1,
-            .iConfiguration        = STR_CONFIG_KEYBOARD,
-            .bmAttributes          = 0xa0,
-            .bMaxPower             = 50,
-            .nif = 1,
-            .ifs = &desc_iface_keyboard,
-        },
-    },
-};
-
-static const USBDesc desc_mouse = {
-    .id = {
-        .idVendor          = 0x0627,
-        .idProduct         = 0x0001,
-        .bcdDevice         = 0,
-        .iManufacturer     = STR_MANUFACTURER,
-        .iProduct          = STR_PRODUCT_MOUSE,
-        .iSerialNumber     = STR_SERIALNUMBER,
-    },
-    .full = &desc_device_mouse,
-    .str  = desc_strings,
-};
-
-static const USBDesc desc_tablet = {
-    .id = {
-        .idVendor          = 0x0627,
-        .idProduct         = 0x0001,
-        .bcdDevice         = 0,
-        .iManufacturer     = STR_MANUFACTURER,
-        .iProduct          = STR_PRODUCT_TABLET,
-        .iSerialNumber     = STR_SERIALNUMBER,
-    },
-    .full = &desc_device_tablet,
-    .str  = desc_strings,
-};
-
-static const USBDesc desc_keyboard = {
-    .id = {
-        .idVendor          = 0x0627,
-        .idProduct         = 0x0001,
-        .bcdDevice         = 0,
-        .iManufacturer     = STR_MANUFACTURER,
-        .iProduct          = STR_PRODUCT_KEYBOARD,
-        .iSerialNumber     = STR_SERIALNUMBER,
-    },
-    .full = &desc_device_keyboard,
-    .str  = desc_strings,
-};
-
-static const uint8_t qemu_mouse_hid_report_descriptor[] = {
-    0x05, 0x01,		/* Usage Page (Generic Desktop) */
-    0x09, 0x02,		/* Usage (Mouse) */
-    0xa1, 0x01,		/* Collection (Application) */
-    0x09, 0x01,		/*   Usage (Pointer) */
-    0xa1, 0x00,		/*   Collection (Physical) */
-    0x05, 0x09,		/*     Usage Page (Button) */
-    0x19, 0x01,		/*     Usage Minimum (1) */
-    0x29, 0x03,		/*     Usage Maximum (3) */
-    0x15, 0x00,		/*     Logical Minimum (0) */
-    0x25, 0x01,		/*     Logical Maximum (1) */
-    0x95, 0x03,		/*     Report Count (3) */
-    0x75, 0x01,		/*     Report Size (1) */
-    0x81, 0x02,		/*     Input (Data, Variable, Absolute) */
-    0x95, 0x01,		/*     Report Count (1) */
-    0x75, 0x05,		/*     Report Size (5) */
-    0x81, 0x01,		/*     Input (Constant) */
-    0x05, 0x01,		/*     Usage Page (Generic Desktop) */
-    0x09, 0x30,		/*     Usage (X) */
-    0x09, 0x31,		/*     Usage (Y) */
-    0x09, 0x38,		/*     Usage (Wheel) */
-    0x15, 0x81,		/*     Logical Minimum (-0x7f) */
-    0x25, 0x7f,		/*     Logical Maximum (0x7f) */
-    0x75, 0x08,		/*     Report Size (8) */
-    0x95, 0x03,		/*     Report Count (3) */
-    0x81, 0x06,		/*     Input (Data, Variable, Relative) */
-    0xc0,		/*   End Collection */
-    0xc0,		/* End Collection */
-};
-
-static const uint8_t qemu_tablet_hid_report_descriptor[] = {
-    0x05, 0x01,		/* Usage Page (Generic Desktop) */
-    0x09, 0x01,		/* Usage (Pointer) */
-    0xa1, 0x01,		/* Collection (Application) */
-    0x09, 0x01,		/*   Usage (Pointer) */
-    0xa1, 0x00,		/*   Collection (Physical) */
-    0x05, 0x09,		/*     Usage Page (Button) */
-    0x19, 0x01,		/*     Usage Minimum (1) */
-    0x29, 0x03,		/*     Usage Maximum (3) */
-    0x15, 0x00,		/*     Logical Minimum (0) */
-    0x25, 0x01,		/*     Logical Maximum (1) */
-    0x95, 0x03,		/*     Report Count (3) */
-    0x75, 0x01,		/*     Report Size (1) */
-    0x81, 0x02,		/*     Input (Data, Variable, Absolute) */
-    0x95, 0x01,		/*     Report Count (1) */
-    0x75, 0x05,		/*     Report Size (5) */
-    0x81, 0x01,		/*     Input (Constant) */
-    0x05, 0x01,		/*     Usage Page (Generic Desktop) */
-    0x09, 0x30,		/*     Usage (X) */
-    0x09, 0x31,		/*     Usage (Y) */
-    0x15, 0x00,		/*     Logical Minimum (0) */
-    0x26, 0xff, 0x7f,	/*     Logical Maximum (0x7fff) */
-    0x35, 0x00,		/*     Physical Minimum (0) */
-    0x46, 0xff, 0x7f,	/*     Physical Maximum (0x7fff) */
-    0x75, 0x10,		/*     Report Size (16) */
-    0x95, 0x02,		/*     Report Count (2) */
-    0x81, 0x02,		/*     Input (Data, Variable, Absolute) */
-    0x05, 0x01,		/*     Usage Page (Generic Desktop) */
-    0x09, 0x38,		/*     Usage (Wheel) */
-    0x15, 0x81,		/*     Logical Minimum (-0x7f) */
-    0x25, 0x7f,		/*     Logical Maximum (0x7f) */
-    0x35, 0x00,		/*     Physical Minimum (same as logical) */
-    0x45, 0x00,		/*     Physical Maximum (same as logical) */
-    0x75, 0x08,		/*     Report Size (8) */
-    0x95, 0x01,		/*     Report Count (1) */
-    0x81, 0x06,		/*     Input (Data, Variable, Relative) */
-    0xc0,		/*   End Collection */
-    0xc0,		/* End Collection */
-};
-
-static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
-    0x05, 0x01,		/* Usage Page (Generic Desktop) */
-    0x09, 0x06,		/* Usage (Keyboard) */
-    0xa1, 0x01,		/* Collection (Application) */
-    0x75, 0x01,		/*   Report Size (1) */
-    0x95, 0x08,		/*   Report Count (8) */
-    0x05, 0x07,		/*   Usage Page (Key Codes) */
-    0x19, 0xe0,		/*   Usage Minimum (224) */
-    0x29, 0xe7,		/*   Usage Maximum (231) */
-    0x15, 0x00,		/*   Logical Minimum (0) */
-    0x25, 0x01,		/*   Logical Maximum (1) */
-    0x81, 0x02,		/*   Input (Data, Variable, Absolute) */
-    0x95, 0x01,		/*   Report Count (1) */
-    0x75, 0x08,		/*   Report Size (8) */
-    0x81, 0x01,		/*   Input (Constant) */
-    0x95, 0x05,		/*   Report Count (5) */
-    0x75, 0x01,		/*   Report Size (1) */
-    0x05, 0x08,		/*   Usage Page (LEDs) */
-    0x19, 0x01,		/*   Usage Minimum (1) */
-    0x29, 0x05,		/*   Usage Maximum (5) */
-    0x91, 0x02,		/*   Output (Data, Variable, Absolute) */
-    0x95, 0x01,		/*   Report Count (1) */
-    0x75, 0x03,		/*   Report Size (3) */
-    0x91, 0x01,		/*   Output (Constant) */
-    0x95, 0x06,		/*   Report Count (6) */
-    0x75, 0x08,		/*   Report Size (8) */
-    0x15, 0x00,		/*   Logical Minimum (0) */
-    0x25, 0xff,		/*   Logical Maximum (255) */
-    0x05, 0x07,		/*   Usage Page (Key Codes) */
-    0x19, 0x00,		/*   Usage Minimum (0) */
-    0x29, 0xff,		/*   Usage Maximum (255) */
-    0x81, 0x00,		/*   Input (Data, Array) */
-    0xc0,		/* End Collection */
-};
-
-static void usb_hid_changed(HIDState *hs)
-{
-    USBHIDState *us = container_of(hs, USBHIDState, hid);
-
-    usb_wakeup(us->intr);
-}
-
-static void usb_hid_handle_reset(USBDevice *dev)
-{
-    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
-
-    hid_reset(&us->hid);
-}
-
-static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
-               int request, int value, int index, int length, uint8_t *data)
-{
-    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
-    HIDState *hs = &us->hid;
-    int ret;
-
-    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
-    if (ret >= 0) {
-        return ret;
-    }
-
-    ret = 0;
-    switch (request) {
-        /* hid specific requests */
-    case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
-        switch (value >> 8) {
-        case 0x22:
-            if (hs->kind == HID_MOUSE) {
-		memcpy(data, qemu_mouse_hid_report_descriptor,
-		       sizeof(qemu_mouse_hid_report_descriptor));
-		ret = sizeof(qemu_mouse_hid_report_descriptor);
-            } else if (hs->kind == HID_TABLET) {
-                memcpy(data, qemu_tablet_hid_report_descriptor,
-		       sizeof(qemu_tablet_hid_report_descriptor));
-		ret = sizeof(qemu_tablet_hid_report_descriptor);
-            } else if (hs->kind == HID_KEYBOARD) {
-                memcpy(data, qemu_keyboard_hid_report_descriptor,
-                       sizeof(qemu_keyboard_hid_report_descriptor));
-                ret = sizeof(qemu_keyboard_hid_report_descriptor);
-            }
-            break;
-        default:
-            goto fail;
-        }
-        break;
-    case GET_REPORT:
-        if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
-            ret = hid_pointer_poll(hs, data, length);
-        } else if (hs->kind == HID_KEYBOARD) {
-            ret = hid_keyboard_poll(hs, data, length);
-        }
-        break;
-    case SET_REPORT:
-        if (hs->kind == HID_KEYBOARD) {
-            ret = hid_keyboard_write(hs, data, length);
-        } else {
-            goto fail;
-        }
-        break;
-    case GET_PROTOCOL:
-        if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
-            goto fail;
-        }
-        ret = 1;
-        data[0] = hs->protocol;
-        break;
-    case SET_PROTOCOL:
-        if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
-            goto fail;
-        }
-        ret = 0;
-        hs->protocol = value;
-        break;
-    case GET_IDLE:
-        ret = 1;
-        data[0] = hs->idle;
-        break;
-    case SET_IDLE:
-        hs->idle = (uint8_t) (value >> 8);
-        hid_set_next_idle(hs, qemu_get_clock_ns(vm_clock));
-        if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
-            hid_pointer_activate(hs);
-        }
-        ret = 0;
-        break;
-    default:
-    fail:
-        ret = USB_RET_STALL;
-        break;
-    }
-    return ret;
-}
-
-static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
-{
-    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
-    HIDState *hs = &us->hid;
-    uint8_t buf[p->iov.size];
-    int ret = 0;
-
-    switch (p->pid) {
-    case USB_TOKEN_IN:
-        if (p->ep->nr == 1) {
-            int64_t curtime = qemu_get_clock_ns(vm_clock);
-            if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
-                hid_pointer_activate(hs);
-            }
-            if (!hid_has_events(hs) &&
-                (!hs->idle || hs->next_idle_clock - curtime > 0)) {
-                return USB_RET_NAK;
-            }
-            hid_set_next_idle(hs, curtime);
-            if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
-                ret = hid_pointer_poll(hs, buf, p->iov.size);
-            } else if (hs->kind == HID_KEYBOARD) {
-                ret = hid_keyboard_poll(hs, buf, p->iov.size);
-            }
-            usb_packet_copy(p, buf, ret);
-        } else {
-            goto fail;
-        }
-        break;
-    case USB_TOKEN_OUT:
-    default:
-    fail:
-        ret = USB_RET_STALL;
-        break;
-    }
-    return ret;
-}
-
-static void usb_hid_handle_destroy(USBDevice *dev)
-{
-    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
-
-    hid_free(&us->hid);
-}
-
-static int usb_hid_initfn(USBDevice *dev, int kind)
-{
-    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
-
-    usb_desc_init(dev);
-    us->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
-    hid_init(&us->hid, kind, usb_hid_changed);
-    return 0;
-}
-
-static int usb_tablet_initfn(USBDevice *dev)
-{
-    return usb_hid_initfn(dev, HID_TABLET);
-}
-
-static int usb_mouse_initfn(USBDevice *dev)
-{
-    return usb_hid_initfn(dev, HID_MOUSE);
-}
-
-static int usb_keyboard_initfn(USBDevice *dev)
-{
-    return usb_hid_initfn(dev, HID_KEYBOARD);
-}
-
-static int usb_ptr_post_load(void *opaque, int version_id)
-{
-    USBHIDState *s = opaque;
-
-    if (s->dev.remote_wakeup) {
-        hid_pointer_activate(&s->hid);
-    }
-    return 0;
-}
-
-static const VMStateDescription vmstate_usb_ptr = {
-    .name = "usb-ptr",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .post_load = usb_ptr_post_load,
-    .fields = (VMStateField []) {
-        VMSTATE_USB_DEVICE(dev, USBHIDState),
-        VMSTATE_HID_POINTER_DEVICE(hid, USBHIDState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static const VMStateDescription vmstate_usb_kbd = {
-    .name = "usb-kbd",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .fields = (VMStateField []) {
-        VMSTATE_USB_DEVICE(dev, USBHIDState),
-        VMSTATE_HID_KEYBOARD_DEVICE(hid, USBHIDState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void usb_hid_class_initfn(ObjectClass *klass, void *data)
-{
-    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
-
-    uc->handle_reset   = usb_hid_handle_reset;
-    uc->handle_control = usb_hid_handle_control;
-    uc->handle_data    = usb_hid_handle_data;
-    uc->handle_destroy = usb_hid_handle_destroy;
-}
-
-static void usb_tablet_class_initfn(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
-
-    usb_hid_class_initfn(klass, data);
-    uc->init           = usb_tablet_initfn;
-    uc->product_desc   = "QEMU USB Tablet";
-    uc->usb_desc       = &desc_tablet;
-    dc->vmsd = &vmstate_usb_ptr;
-}
-
-static TypeInfo usb_tablet_info = {
-    .name          = "usb-tablet",
-    .parent        = TYPE_USB_DEVICE,
-    .instance_size = sizeof(USBHIDState),
-    .class_init    = usb_tablet_class_initfn,
-};
-
-static void usb_mouse_class_initfn(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
-
-    usb_hid_class_initfn(klass, data);
-    uc->init           = usb_mouse_initfn;
-    uc->product_desc   = "QEMU USB Mouse";
-    uc->usb_desc       = &desc_mouse;
-    dc->vmsd = &vmstate_usb_ptr;
-}
-
-static TypeInfo usb_mouse_info = {
-    .name          = "usb-mouse",
-    .parent        = TYPE_USB_DEVICE,
-    .instance_size = sizeof(USBHIDState),
-    .class_init    = usb_mouse_class_initfn,
-};
-
-static void usb_keyboard_class_initfn(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
-
-    usb_hid_class_initfn(klass, data);
-    uc->init           = usb_keyboard_initfn;
-    uc->product_desc   = "QEMU USB Keyboard";
-    uc->usb_desc       = &desc_keyboard;
-    dc->vmsd = &vmstate_usb_kbd;
-}
-
-static TypeInfo usb_keyboard_info = {
-    .name          = "usb-kbd",
-    .parent        = TYPE_USB_DEVICE,
-    .instance_size = sizeof(USBHIDState),
-    .class_init    = usb_keyboard_class_initfn,
-};
-
-static void usb_hid_register_types(void)
-{
-    type_register_static(&usb_tablet_info);
-    usb_legacy_register("usb-tablet", "tablet", NULL);
-    type_register_static(&usb_mouse_info);
-    usb_legacy_register("usb-mouse", "mouse", NULL);
-    type_register_static(&usb_keyboard_info);
-    usb_legacy_register("usb-kbd", "keyboard", NULL);
-}
-
-type_init(usb_hid_register_types)
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
deleted file mode 100644
index a12856e..0000000
--- a/hw/usb-hub.c
+++ /dev/null
@@ -1,549 +0,0 @@
-/*
- * QEMU USB HUB emulation
- *
- * Copyright (c) 2005 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "qemu-common.h"
-#include "usb.h"
-#include "usb-desc.h"
-
-//#define DEBUG
-
-#define NUM_PORTS 8
-
-typedef struct USBHubPort {
-    USBPort port;
-    uint16_t wPortStatus;
-    uint16_t wPortChange;
-} USBHubPort;
-
-typedef struct USBHubState {
-    USBDevice dev;
-    USBEndpoint *intr;
-    USBHubPort ports[NUM_PORTS];
-} USBHubState;
-
-#define ClearHubFeature		(0x2000 | USB_REQ_CLEAR_FEATURE)
-#define ClearPortFeature	(0x2300 | USB_REQ_CLEAR_FEATURE)
-#define GetHubDescriptor	(0xa000 | USB_REQ_GET_DESCRIPTOR)
-#define GetHubStatus		(0xa000 | USB_REQ_GET_STATUS)
-#define GetPortStatus		(0xa300 | USB_REQ_GET_STATUS)
-#define SetHubFeature		(0x2000 | USB_REQ_SET_FEATURE)
-#define SetPortFeature		(0x2300 | USB_REQ_SET_FEATURE)
-
-#define PORT_STAT_CONNECTION	0x0001
-#define PORT_STAT_ENABLE	0x0002
-#define PORT_STAT_SUSPEND	0x0004
-#define PORT_STAT_OVERCURRENT	0x0008
-#define PORT_STAT_RESET		0x0010
-#define PORT_STAT_POWER		0x0100
-#define PORT_STAT_LOW_SPEED	0x0200
-#define PORT_STAT_HIGH_SPEED    0x0400
-#define PORT_STAT_TEST          0x0800
-#define PORT_STAT_INDICATOR     0x1000
-
-#define PORT_STAT_C_CONNECTION	0x0001
-#define PORT_STAT_C_ENABLE	0x0002
-#define PORT_STAT_C_SUSPEND	0x0004
-#define PORT_STAT_C_OVERCURRENT	0x0008
-#define PORT_STAT_C_RESET	0x0010
-
-#define PORT_CONNECTION	        0
-#define PORT_ENABLE		1
-#define PORT_SUSPEND		2
-#define PORT_OVERCURRENT	3
-#define PORT_RESET		4
-#define PORT_POWER		8
-#define PORT_LOWSPEED		9
-#define PORT_HIGHSPEED		10
-#define PORT_C_CONNECTION	16
-#define PORT_C_ENABLE		17
-#define PORT_C_SUSPEND		18
-#define PORT_C_OVERCURRENT	19
-#define PORT_C_RESET		20
-#define PORT_TEST               21
-#define PORT_INDICATOR          22
-
-/* same as Linux kernel root hubs */
-
-enum {
-    STR_MANUFACTURER = 1,
-    STR_PRODUCT,
-    STR_SERIALNUMBER,
-};
-
-static const USBDescStrings desc_strings = {
-    [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
-    [STR_PRODUCT]      = "QEMU USB Hub",
-    [STR_SERIALNUMBER] = "314159",
-};
-
-static const USBDescIface desc_iface_hub = {
-    .bInterfaceNumber              = 0,
-    .bNumEndpoints                 = 1,
-    .bInterfaceClass               = USB_CLASS_HUB,
-    .eps = (USBDescEndpoint[]) {
-        {
-            .bEndpointAddress      = USB_DIR_IN | 0x01,
-            .bmAttributes          = USB_ENDPOINT_XFER_INT,
-            .wMaxPacketSize        = 1 + (NUM_PORTS + 7) / 8,
-            .bInterval             = 0xff,
-        },
-    }
-};
-
-static const USBDescDevice desc_device_hub = {
-    .bcdUSB                        = 0x0110,
-    .bDeviceClass                  = USB_CLASS_HUB,
-    .bMaxPacketSize0               = 8,
-    .bNumConfigurations            = 1,
-    .confs = (USBDescConfig[]) {
-        {
-            .bNumInterfaces        = 1,
-            .bConfigurationValue   = 1,
-            .bmAttributes          = 0xe0,
-            .nif = 1,
-            .ifs = &desc_iface_hub,
-        },
-    },
-};
-
-static const USBDesc desc_hub = {
-    .id = {
-        .idVendor          = 0x0409,
-        .idProduct         = 0x55aa,
-        .bcdDevice         = 0x0101,
-        .iManufacturer     = STR_MANUFACTURER,
-        .iProduct          = STR_PRODUCT,
-        .iSerialNumber     = STR_SERIALNUMBER,
-    },
-    .full = &desc_device_hub,
-    .str  = desc_strings,
-};
-
-static const uint8_t qemu_hub_hub_descriptor[] =
-{
-	0x00,			/*  u8  bLength; patched in later */
-	0x29,			/*  u8  bDescriptorType; Hub-descriptor */
-	0x00,			/*  u8  bNbrPorts; (patched later) */
-	0x0a,			/* u16  wHubCharacteristics; */
-	0x00,			/*   (per-port OC, no power switching) */
-	0x01,			/*  u8  bPwrOn2pwrGood; 2ms */
-	0x00			/*  u8  bHubContrCurrent; 0 mA */
-
-        /* DeviceRemovable and PortPwrCtrlMask patched in later */
-};
-
-static void usb_hub_attach(USBPort *port1)
-{
-    USBHubState *s = port1->opaque;
-    USBHubPort *port = &s->ports[port1->index];
-
-    port->wPortStatus |= PORT_STAT_CONNECTION;
-    port->wPortChange |= PORT_STAT_C_CONNECTION;
-    if (port->port.dev->speed == USB_SPEED_LOW) {
-        port->wPortStatus |= PORT_STAT_LOW_SPEED;
-    } else {
-        port->wPortStatus &= ~PORT_STAT_LOW_SPEED;
-    }
-    usb_wakeup(s->intr);
-}
-
-static void usb_hub_detach(USBPort *port1)
-{
-    USBHubState *s = port1->opaque;
-    USBHubPort *port = &s->ports[port1->index];
-
-    usb_wakeup(s->intr);
-
-    /* Let upstream know the device on this port is gone */
-    s->dev.port->ops->child_detach(s->dev.port, port1->dev);
-
-    port->wPortStatus &= ~PORT_STAT_CONNECTION;
-    port->wPortChange |= PORT_STAT_C_CONNECTION;
-    if (port->wPortStatus & PORT_STAT_ENABLE) {
-        port->wPortStatus &= ~PORT_STAT_ENABLE;
-        port->wPortChange |= PORT_STAT_C_ENABLE;
-    }
-}
-
-static void usb_hub_child_detach(USBPort *port1, USBDevice *child)
-{
-    USBHubState *s = port1->opaque;
-
-    /* Pass along upstream */
-    s->dev.port->ops->child_detach(s->dev.port, child);
-}
-
-static void usb_hub_wakeup(USBPort *port1)
-{
-    USBHubState *s = port1->opaque;
-    USBHubPort *port = &s->ports[port1->index];
-
-    if (port->wPortStatus & PORT_STAT_SUSPEND) {
-        port->wPortChange |= PORT_STAT_C_SUSPEND;
-        usb_wakeup(s->intr);
-    }
-}
-
-static void usb_hub_complete(USBPort *port, USBPacket *packet)
-{
-    USBHubState *s = port->opaque;
-
-    /*
-     * Just pass it along upstream for now.
-     *
-     * If we ever implement usb 2.0 split transactions this will
-     * become a little more complicated ...
-     *
-     * Can't use usb_packet_complete() here because packet->owner is
-     * cleared already, go call the ->complete() callback directly
-     * instead.
-     */
-    s->dev.port->ops->complete(s->dev.port, packet);
-}
-
-static USBDevice *usb_hub_find_device(USBDevice *dev, uint8_t addr)
-{
-    USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
-    USBHubPort *port;
-    USBDevice *downstream;
-    int i;
-
-    for (i = 0; i < NUM_PORTS; i++) {
-        port = &s->ports[i];
-        if (!(port->wPortStatus & PORT_STAT_ENABLE)) {
-            continue;
-        }
-        downstream = usb_find_device(&port->port, addr);
-        if (downstream != NULL) {
-            return downstream;
-        }
-    }
-    return NULL;
-}
-
-static void usb_hub_handle_reset(USBDevice *dev)
-{
-    USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
-    USBHubPort *port;
-    int i;
-
-    for (i = 0; i < NUM_PORTS; i++) {
-        port = s->ports + i;
-        port->wPortStatus = PORT_STAT_POWER;
-        port->wPortChange = 0;
-        if (port->port.dev && port->port.dev->attached) {
-            port->wPortStatus |= PORT_STAT_CONNECTION;
-            port->wPortChange |= PORT_STAT_C_CONNECTION;
-            if (port->port.dev->speed == USB_SPEED_LOW) {
-                port->wPortStatus |= PORT_STAT_LOW_SPEED;
-            }
-        }
-    }
-}
-
-static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
-               int request, int value, int index, int length, uint8_t *data)
-{
-    USBHubState *s = (USBHubState *)dev;
-    int ret;
-
-    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
-    if (ret >= 0) {
-        return ret;
-    }
-
-    switch(request) {
-    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
-        if (value == 0 && index != 0x81) { /* clear ep halt */
-            goto fail;
-        }
-        ret = 0;
-        break;
-        /* usb specific requests */
-    case GetHubStatus:
-        data[0] = 0;
-        data[1] = 0;
-        data[2] = 0;
-        data[3] = 0;
-        ret = 4;
-        break;
-    case GetPortStatus:
-        {
-            unsigned int n = index - 1;
-            USBHubPort *port;
-            if (n >= NUM_PORTS) {
-                goto fail;
-            }
-            port = &s->ports[n];
-            data[0] = port->wPortStatus;
-            data[1] = port->wPortStatus >> 8;
-            data[2] = port->wPortChange;
-            data[3] = port->wPortChange >> 8;
-            ret = 4;
-        }
-        break;
-    case SetHubFeature:
-    case ClearHubFeature:
-        if (value == 0 || value == 1) {
-        } else {
-            goto fail;
-        }
-        ret = 0;
-        break;
-    case SetPortFeature:
-        {
-            unsigned int n = index - 1;
-            USBHubPort *port;
-            USBDevice *dev;
-            if (n >= NUM_PORTS) {
-                goto fail;
-            }
-            port = &s->ports[n];
-            dev = port->port.dev;
-            switch(value) {
-            case PORT_SUSPEND:
-                port->wPortStatus |= PORT_STAT_SUSPEND;
-                break;
-            case PORT_RESET:
-                if (dev && dev->attached) {
-                    usb_device_reset(dev);
-                    port->wPortChange |= PORT_STAT_C_RESET;
-                    /* set enable bit */
-                    port->wPortStatus |= PORT_STAT_ENABLE;
-                }
-                break;
-            case PORT_POWER:
-                break;
-            default:
-                goto fail;
-            }
-            ret = 0;
-        }
-        break;
-    case ClearPortFeature:
-        {
-            unsigned int n = index - 1;
-            USBHubPort *port;
-
-            if (n >= NUM_PORTS) {
-                goto fail;
-            }
-            port = &s->ports[n];
-            switch(value) {
-            case PORT_ENABLE:
-                port->wPortStatus &= ~PORT_STAT_ENABLE;
-                break;
-            case PORT_C_ENABLE:
-                port->wPortChange &= ~PORT_STAT_C_ENABLE;
-                break;
-            case PORT_SUSPEND:
-                port->wPortStatus &= ~PORT_STAT_SUSPEND;
-                break;
-            case PORT_C_SUSPEND:
-                port->wPortChange &= ~PORT_STAT_C_SUSPEND;
-                break;
-            case PORT_C_CONNECTION:
-                port->wPortChange &= ~PORT_STAT_C_CONNECTION;
-                break;
-            case PORT_C_OVERCURRENT:
-                port->wPortChange &= ~PORT_STAT_C_OVERCURRENT;
-                break;
-            case PORT_C_RESET:
-                port->wPortChange &= ~PORT_STAT_C_RESET;
-                break;
-            default:
-                goto fail;
-            }
-            ret = 0;
-        }
-        break;
-    case GetHubDescriptor:
-        {
-            unsigned int n, limit, var_hub_size = 0;
-            memcpy(data, qemu_hub_hub_descriptor,
-                   sizeof(qemu_hub_hub_descriptor));
-            data[2] = NUM_PORTS;
-
-            /* fill DeviceRemovable bits */
-            limit = ((NUM_PORTS + 1 + 7) / 8) + 7;
-            for (n = 7; n < limit; n++) {
-                data[n] = 0x00;
-                var_hub_size++;
-            }
-
-            /* fill PortPwrCtrlMask bits */
-            limit = limit + ((NUM_PORTS + 7) / 8);
-            for (;n < limit; n++) {
-                data[n] = 0xff;
-                var_hub_size++;
-            }
-
-            ret = sizeof(qemu_hub_hub_descriptor) + var_hub_size;
-            data[0] = ret;
-            break;
-        }
-    default:
-    fail:
-        ret = USB_RET_STALL;
-        break;
-    }
-    return ret;
-}
-
-static int usb_hub_handle_data(USBDevice *dev, USBPacket *p)
-{
-    USBHubState *s = (USBHubState *)dev;
-    int ret;
-
-    switch(p->pid) {
-    case USB_TOKEN_IN:
-        if (p->ep->nr == 1) {
-            USBHubPort *port;
-            unsigned int status;
-            uint8_t buf[4];
-            int i, n;
-            n = (NUM_PORTS + 1 + 7) / 8;
-            if (p->iov.size == 1) { /* FreeBSD workaround */
-                n = 1;
-            } else if (n > p->iov.size) {
-                return USB_RET_BABBLE;
-            }
-            status = 0;
-            for(i = 0; i < NUM_PORTS; i++) {
-                port = &s->ports[i];
-                if (port->wPortChange)
-                    status |= (1 << (i + 1));
-            }
-            if (status != 0) {
-                for(i = 0; i < n; i++) {
-                    buf[i] = status >> (8 * i);
-                }
-                usb_packet_copy(p, buf, n);
-                ret = n;
-            } else {
-                ret = USB_RET_NAK; /* usb11 11.13.1 */
-            }
-        } else {
-            goto fail;
-        }
-        break;
-    case USB_TOKEN_OUT:
-    default:
-    fail:
-        ret = USB_RET_STALL;
-        break;
-    }
-    return ret;
-}
-
-static void usb_hub_handle_destroy(USBDevice *dev)
-{
-    USBHubState *s = (USBHubState *)dev;
-    int i;
-
-    for (i = 0; i < NUM_PORTS; i++) {
-        usb_unregister_port(usb_bus_from_device(dev),
-                            &s->ports[i].port);
-    }
-}
-
-static USBPortOps usb_hub_port_ops = {
-    .attach = usb_hub_attach,
-    .detach = usb_hub_detach,
-    .child_detach = usb_hub_child_detach,
-    .wakeup = usb_hub_wakeup,
-    .complete = usb_hub_complete,
-};
-
-static int usb_hub_initfn(USBDevice *dev)
-{
-    USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
-    USBHubPort *port;
-    int i;
-
-    usb_desc_init(dev);
-    s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
-    for (i = 0; i < NUM_PORTS; i++) {
-        port = &s->ports[i];
-        usb_register_port(usb_bus_from_device(dev),
-                          &port->port, s, i, &usb_hub_port_ops,
-                          USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
-        usb_port_location(&port->port, dev->port, i+1);
-    }
-    usb_hub_handle_reset(dev);
-    return 0;
-}
-
-static const VMStateDescription vmstate_usb_hub_port = {
-    .name = "usb-hub-port",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .fields = (VMStateField []) {
-        VMSTATE_UINT16(wPortStatus, USBHubPort),
-        VMSTATE_UINT16(wPortChange, USBHubPort),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static const VMStateDescription vmstate_usb_hub = {
-    .name = "usb-hub",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .fields = (VMStateField []) {
-        VMSTATE_USB_DEVICE(dev, USBHubState),
-        VMSTATE_STRUCT_ARRAY(ports, USBHubState, NUM_PORTS, 0,
-                             vmstate_usb_hub_port, USBHubPort),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void usb_hub_class_initfn(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
-
-    uc->init           = usb_hub_initfn;
-    uc->product_desc   = "QEMU USB Hub";
-    uc->usb_desc       = &desc_hub;
-    uc->find_device    = usb_hub_find_device;
-    uc->handle_reset   = usb_hub_handle_reset;
-    uc->handle_control = usb_hub_handle_control;
-    uc->handle_data    = usb_hub_handle_data;
-    uc->handle_destroy = usb_hub_handle_destroy;
-    dc->fw_name = "hub";
-    dc->vmsd = &vmstate_usb_hub;
-}
-
-static TypeInfo hub_info = {
-    .name          = "usb-hub",
-    .parent        = TYPE_USB_DEVICE,
-    .instance_size = sizeof(USBHubState),
-    .class_init    = usb_hub_class_initfn,
-};
-
-static void usb_hub_register_types(void)
-{
-    type_register_static(&hub_info);
-}
-
-type_init(usb_hub_register_types)
diff --git a/hw/usb-libhw.c b/hw/usb-libhw.c
deleted file mode 100644
index 162b42b..0000000
--- a/hw/usb-libhw.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * QEMU USB emulation, libhw bits.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "qemu-common.h"
-#include "cpu-common.h"
-#include "usb.h"
-#include "dma.h"
-
-int usb_packet_map(USBPacket *p, QEMUSGList *sgl)
-{
-    int is_write = (p->pid == USB_TOKEN_IN);
-    target_phys_addr_t len;
-    void *mem;
-    int i;
-
-    for (i = 0; i < sgl->nsg; i++) {
-        len = sgl->sg[i].len;
-        mem = cpu_physical_memory_map(sgl->sg[i].base, &len,
-                                      is_write);
-        if (!mem) {
-            goto err;
-        }
-        qemu_iovec_add(&p->iov, mem, len);
-        if (len != sgl->sg[i].len) {
-            goto err;
-        }
-    }
-    return 0;
-
-err:
-    usb_packet_unmap(p);
-    return -1;
-}
-
-void usb_packet_unmap(USBPacket *p)
-{
-    int is_write = (p->pid == USB_TOKEN_IN);
-    int i;
-
-    for (i = 0; i < p->iov.niov; i++) {
-        cpu_physical_memory_unmap(p->iov.iov[i].iov_base,
-                                  p->iov.iov[i].iov_len, is_write,
-                                  p->iov.iov[i].iov_len);
-    }
-}
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
deleted file mode 100644
index c6f08a0..0000000
--- a/hw/usb-msd.c
+++ /dev/null
@@ -1,677 +0,0 @@
-/*
- * USB Mass Storage Device emulation
- *
- * Copyright (c) 2006 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licensed under the LGPL.
- */
-
-#include "qemu-common.h"
-#include "qemu-option.h"
-#include "qemu-config.h"
-#include "usb.h"
-#include "usb-desc.h"
-#include "scsi.h"
-#include "console.h"
-#include "monitor.h"
-#include "sysemu.h"
-#include "blockdev.h"
-
-//#define DEBUG_MSD
-
-#ifdef DEBUG_MSD
-#define DPRINTF(fmt, ...) \
-do { printf("usb-msd: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while(0)
-#endif
-
-/* USB requests.  */
-#define MassStorageReset  0xff
-#define GetMaxLun         0xfe
-
-enum USBMSDMode {
-    USB_MSDM_CBW, /* Command Block.  */
-    USB_MSDM_DATAOUT, /* Transfer data to device.  */
-    USB_MSDM_DATAIN, /* Transfer data from device.  */
-    USB_MSDM_CSW /* Command Status.  */
-};
-
-struct usb_msd_csw {
-    uint32_t sig;
-    uint32_t tag;
-    uint32_t residue;
-    uint8_t status;
-};
-
-typedef struct {
-    USBDevice dev;
-    enum USBMSDMode mode;
-    uint32_t scsi_len;
-    uint8_t *scsi_buf;
-    uint32_t data_len;
-    uint32_t residue;
-    struct usb_msd_csw csw;
-    SCSIRequest *req;
-    SCSIBus bus;
-    BlockConf conf;
-    char *serial;
-    SCSIDevice *scsi_dev;
-    uint32_t removable;
-    /* For async completion.  */
-    USBPacket *packet;
-} MSDState;
-
-struct usb_msd_cbw {
-    uint32_t sig;
-    uint32_t tag;
-    uint32_t data_len;
-    uint8_t flags;
-    uint8_t lun;
-    uint8_t cmd_len;
-    uint8_t cmd[16];
-};
-
-enum {
-    STR_MANUFACTURER = 1,
-    STR_PRODUCT,
-    STR_SERIALNUMBER,
-    STR_CONFIG_FULL,
-    STR_CONFIG_HIGH,
-};
-
-static const USBDescStrings desc_strings = {
-    [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
-    [STR_PRODUCT]      = "QEMU USB HARDDRIVE",
-    [STR_SERIALNUMBER] = "1",
-    [STR_CONFIG_FULL]  = "Full speed config (usb 1.1)",
-    [STR_CONFIG_HIGH]  = "High speed config (usb 2.0)",
-};
-
-static const USBDescIface desc_iface_full = {
-    .bInterfaceNumber              = 0,
-    .bNumEndpoints                 = 2,
-    .bInterfaceClass               = USB_CLASS_MASS_STORAGE,
-    .bInterfaceSubClass            = 0x06, /* SCSI */
-    .bInterfaceProtocol            = 0x50, /* Bulk */
-    .eps = (USBDescEndpoint[]) {
-        {
-            .bEndpointAddress      = USB_DIR_IN | 0x01,
-            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
-            .wMaxPacketSize        = 64,
-        },{
-            .bEndpointAddress      = USB_DIR_OUT | 0x02,
-            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
-            .wMaxPacketSize        = 64,
-        },
-    }
-};
-
-static const USBDescDevice desc_device_full = {
-    .bcdUSB                        = 0x0200,
-    .bMaxPacketSize0               = 8,
-    .bNumConfigurations            = 1,
-    .confs = (USBDescConfig[]) {
-        {
-            .bNumInterfaces        = 1,
-            .bConfigurationValue   = 1,
-            .iConfiguration        = STR_CONFIG_FULL,
-            .bmAttributes          = 0xc0,
-            .nif = 1,
-            .ifs = &desc_iface_full,
-        },
-    },
-};
-
-static const USBDescIface desc_iface_high = {
-    .bInterfaceNumber              = 0,
-    .bNumEndpoints                 = 2,
-    .bInterfaceClass               = USB_CLASS_MASS_STORAGE,
-    .bInterfaceSubClass            = 0x06, /* SCSI */
-    .bInterfaceProtocol            = 0x50, /* Bulk */
-    .eps = (USBDescEndpoint[]) {
-        {
-            .bEndpointAddress      = USB_DIR_IN | 0x01,
-            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
-            .wMaxPacketSize        = 512,
-        },{
-            .bEndpointAddress      = USB_DIR_OUT | 0x02,
-            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
-            .wMaxPacketSize        = 512,
-        },
-    }
-};
-
-static const USBDescDevice desc_device_high = {
-    .bcdUSB                        = 0x0200,
-    .bMaxPacketSize0               = 64,
-    .bNumConfigurations            = 1,
-    .confs = (USBDescConfig[]) {
-        {
-            .bNumInterfaces        = 1,
-            .bConfigurationValue   = 1,
-            .iConfiguration        = STR_CONFIG_HIGH,
-            .bmAttributes          = 0xc0,
-            .nif = 1,
-            .ifs = &desc_iface_high,
-        },
-    },
-};
-
-static const USBDesc desc = {
-    .id = {
-        .idVendor          = 0x46f4, /* CRC16() of "QEMU" */
-        .idProduct         = 0x0001,
-        .bcdDevice         = 0,
-        .iManufacturer     = STR_MANUFACTURER,
-        .iProduct          = STR_PRODUCT,
-        .iSerialNumber     = STR_SERIALNUMBER,
-    },
-    .full = &desc_device_full,
-    .high = &desc_device_high,
-    .str  = desc_strings,
-};
-
-static void usb_msd_copy_data(MSDState *s, USBPacket *p)
-{
-    uint32_t len;
-    len = p->iov.size - p->result;
-    if (len > s->scsi_len)
-        len = s->scsi_len;
-    usb_packet_copy(p, s->scsi_buf, len);
-    s->scsi_len -= len;
-    s->scsi_buf += len;
-    s->data_len -= len;
-    if (s->scsi_len == 0 || s->data_len == 0) {
-        scsi_req_continue(s->req);
-    }
-}
-
-static void usb_msd_send_status(MSDState *s, USBPacket *p)
-{
-    int len;
-
-    DPRINTF("Command status %d tag 0x%x, len %zd\n",
-            s->csw.status, s->csw.tag, p->iov.size);
-
-    assert(s->csw.sig == 0x53425355);
-    len = MIN(sizeof(s->csw), p->iov.size);
-    usb_packet_copy(p, &s->csw, len);
-    memset(&s->csw, 0, sizeof(s->csw));
-}
-
-static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
-{
-    MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
-    USBPacket *p = s->packet;
-
-    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);
-    if (p) {
-        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);
-        }
-    }
-}
-
-static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t resid)
-{
-    MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
-    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 = s->residue;
-    s->csw.status = status != 0;
-
-    if (s->packet) {
-        if (s->data_len == 0 && s->mode == USB_MSDM_DATAOUT) {
-            /* A deferred packet with no write data remaining must be
-               the status read packet.  */
-            usb_msd_send_status(s, p);
-            s->mode = USB_MSDM_CBW;
-        } else {
-            if (s->data_len) {
-                int len = (p->iov.size - p->result);
-                usb_packet_skip(p, len);
-                s->data_len -= len;
-            }
-            if (s->data_len == 0) {
-                s->mode = USB_MSDM_CSW;
-            }
-        }
-        s->packet = NULL;
-        usb_packet_complete(&s->dev, p);
-    } else if (s->data_len == 0) {
-        s->mode = USB_MSDM_CSW;
-    }
-    scsi_req_unref(req);
-    s->req = NULL;
-}
-
-static void usb_msd_request_cancelled(SCSIRequest *req)
-{
-    MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
-
-    if (req == s->req) {
-        scsi_req_unref(s->req);
-        s->req = NULL;
-        s->packet = NULL;
-        s->scsi_len = 0;
-    }
-}
-
-static void usb_msd_handle_reset(USBDevice *dev)
-{
-    MSDState *s = (MSDState *)dev;
-
-    DPRINTF("Reset\n");
-    if (s->req) {
-        scsi_req_cancel(s->req);
-    }
-    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->mode = USB_MSDM_CBW;
-}
-
-static int usb_msd_handle_control(USBDevice *dev, USBPacket *p,
-               int request, int value, int index, int length, uint8_t *data)
-{
-    MSDState *s = (MSDState *)dev;
-    int ret;
-
-    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
-    if (ret >= 0) {
-        return ret;
-    }
-
-    ret = 0;
-    switch (request) {
-    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
-        ret = 0;
-        break;
-        /* Class specific requests.  */
-    case ClassInterfaceOutRequest | MassStorageReset:
-        /* Reset state ready for the next CBW.  */
-        s->mode = USB_MSDM_CBW;
-        ret = 0;
-        break;
-    case ClassInterfaceRequest | GetMaxLun:
-        data[0] = 0;
-        ret = 1;
-        break;
-    default:
-        ret = USB_RET_STALL;
-        break;
-    }
-    return ret;
-}
-
-static void usb_msd_cancel_io(USBDevice *dev, USBPacket *p)
-{
-    MSDState *s = DO_UPCAST(MSDState, dev, dev);
-
-    if (s->req) {
-        scsi_req_cancel(s->req);
-    }
-}
-
-static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
-{
-    MSDState *s = (MSDState *)dev;
-    uint32_t tag;
-    int ret = 0;
-    struct usb_msd_cbw cbw;
-    uint8_t devep = p->ep->nr;
-
-    switch (p->pid) {
-    case USB_TOKEN_OUT:
-        if (devep != 2)
-            goto fail;
-
-        switch (s->mode) {
-        case USB_MSDM_CBW:
-            if (p->iov.size != 31) {
-                fprintf(stderr, "usb-msd: Bad CBW size");
-                goto fail;
-            }
-            usb_packet_copy(p, &cbw, 31);
-            if (le32_to_cpu(cbw.sig) != 0x43425355) {
-                fprintf(stderr, "usb-msd: Bad signature %08x\n",
-                        le32_to_cpu(cbw.sig));
-                goto fail;
-            }
-            DPRINTF("Command on LUN %d\n", cbw.lun);
-            if (cbw.lun != 0) {
-                fprintf(stderr, "usb-msd: Bad LUN %d\n", cbw.lun);
-                goto fail;
-            }
-            tag = le32_to_cpu(cbw.tag);
-            s->data_len = le32_to_cpu(cbw.data_len);
-            if (s->data_len == 0) {
-                s->mode = USB_MSDM_CSW;
-            } else if (cbw.flags & 0x80) {
-                s->mode = USB_MSDM_DATAIN;
-            } else {
-                s->mode = USB_MSDM_DATAOUT;
-            }
-            DPRINTF("Command tag 0x%x flags %08x len %d data %d\n",
-                    tag, cbw.flags, cbw.cmd_len, s->data_len);
-            s->residue = 0;
-            s->scsi_len = 0;
-            s->req = scsi_req_new(s->scsi_dev, tag, 0, cbw.cmd, NULL);
-            scsi_req_enqueue(s->req);
-            if (s->req && s->req->cmd.xfer != SCSI_XFER_NONE) {
-                scsi_req_continue(s->req);
-            }
-            ret = p->result;
-            break;
-
-        case USB_MSDM_DATAOUT:
-            DPRINTF("Data out %zd/%d\n", p->iov.size, s->data_len);
-            if (p->iov.size > s->data_len) {
-                goto fail;
-            }
-
-            if (s->scsi_len) {
-                usb_msd_copy_data(s, p);
-            }
-            if (s->residue) {
-                int len = p->iov.size - p->result;
-                if (len) {
-                    usb_packet_skip(p, len);
-                    s->data_len -= len;
-                    if (s->data_len == 0) {
-                        s->mode = USB_MSDM_CSW;
-                    }
-                }
-            }
-            if (p->result < p->iov.size) {
-                DPRINTF("Deferring packet %p\n", p);
-                s->packet = p;
-                ret = USB_RET_ASYNC;
-            } else {
-                ret = p->result;
-            }
-            break;
-
-        default:
-            DPRINTF("Unexpected write (len %zd)\n", p->iov.size);
-            goto fail;
-        }
-        break;
-
-    case USB_TOKEN_IN:
-        if (devep != 1)
-            goto fail;
-
-        switch (s->mode) {
-        case USB_MSDM_DATAOUT:
-            if (s->data_len != 0 || p->iov.size < 13) {
-                goto fail;
-            }
-            /* Waiting for SCSI write to complete.  */
-            s->packet = p;
-            ret = USB_RET_ASYNC;
-            break;
-
-        case USB_MSDM_CSW:
-            if (p->iov.size < 13) {
-                goto fail;
-            }
-
-            if (s->req) {
-                /* still in flight */
-                s->packet = p;
-                ret = USB_RET_ASYNC;
-            } else {
-                usb_msd_send_status(s, p);
-                s->mode = USB_MSDM_CBW;
-                ret = 13;
-            }
-            break;
-
-        case USB_MSDM_DATAIN:
-            DPRINTF("Data in %zd/%d, scsi_len %d\n",
-                    p->iov.size, s->data_len, s->scsi_len);
-            if (s->scsi_len) {
-                usb_msd_copy_data(s, p);
-            }
-            if (s->residue) {
-                int len = p->iov.size - p->result;
-                if (len) {
-                    usb_packet_skip(p, len);
-                    s->data_len -= len;
-                    if (s->data_len == 0) {
-                        s->mode = USB_MSDM_CSW;
-                    }
-                }
-            }
-            if (p->result < p->iov.size) {
-                DPRINTF("Deferring packet %p\n", p);
-                s->packet = p;
-                ret = USB_RET_ASYNC;
-            } else {
-                ret = p->result;
-            }
-            break;
-
-        default:
-            DPRINTF("Unexpected read (len %zd)\n", p->iov.size);
-            goto fail;
-        }
-        break;
-
-    default:
-        DPRINTF("Bad token\n");
-    fail:
-        ret = USB_RET_STALL;
-        break;
-    }
-
-    return ret;
-}
-
-static void usb_msd_password_cb(void *opaque, int err)
-{
-    MSDState *s = opaque;
-
-    if (!err)
-        err = usb_device_attach(&s->dev);
-
-    if (err)
-        qdev_unplug(&s->dev.qdev);
-}
-
-static const struct SCSIBusInfo usb_msd_scsi_info = {
-    .tcq = false,
-    .max_target = 0,
-    .max_lun = 0,
-
-    .transfer_data = usb_msd_transfer_data,
-    .complete = usb_msd_command_complete,
-    .cancel = usb_msd_request_cancelled
-};
-
-static int usb_msd_initfn(USBDevice *dev)
-{
-    MSDState *s = DO_UPCAST(MSDState, dev, dev);
-    BlockDriverState *bs = s->conf.bs;
-    DriveInfo *dinfo;
-
-    if (!bs) {
-        error_report("drive property not set");
-        return -1;
-    }
-
-    /*
-     * Hack alert: this pretends to be a block device, but it's really
-     * a SCSI bus that can serve only a single device, which it
-     * creates automatically.  But first it needs to detach from its
-     * blockdev, or else scsi_bus_legacy_add_drive() dies when it
-     * attaches again.
-     *
-     * The hack is probably a bad idea.
-     */
-    bdrv_detach_dev(bs, &s->dev.qdev);
-    s->conf.bs = NULL;
-
-    if (!s->serial) {
-        /* try to fall back to value set with legacy -drive serial=... */
-        dinfo = drive_get_by_blockdev(bs);
-        if (*dinfo->serial) {
-            s->serial = strdup(dinfo->serial);
-        }
-    }
-    if (s->serial) {
-        usb_desc_set_string(dev, STR_SERIALNUMBER, s->serial);
-    }
-
-    usb_desc_init(dev);
-    scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info);
-    s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable,
-                                            s->conf.bootindex);
-    if (!s->scsi_dev) {
-        return -1;
-    }
-    s->bus.qbus.allow_hotplug = 0;
-    usb_msd_handle_reset(dev);
-
-    if (bdrv_key_required(bs)) {
-        if (cur_mon) {
-            monitor_read_bdrv_key_start(cur_mon, bs, usb_msd_password_cb, s);
-            s->dev.auto_attach = 0;
-        } else {
-            autostart = 0;
-        }
-    }
-
-    return 0;
-}
-
-static USBDevice *usb_msd_init(USBBus *bus, const char *filename)
-{
-    static int nr=0;
-    char id[8];
-    QemuOpts *opts;
-    DriveInfo *dinfo;
-    USBDevice *dev;
-    const char *p1;
-    char fmt[32];
-
-    /* parse -usbdevice disk: syntax into drive opts */
-    snprintf(id, sizeof(id), "usb%d", nr++);
-    opts = qemu_opts_create(qemu_find_opts("drive"), id, 0);
-
-    p1 = strchr(filename, ':');
-    if (p1++) {
-        const char *p2;
-
-        if (strstart(filename, "format=", &p2)) {
-            int len = MIN(p1 - p2, sizeof(fmt));
-            pstrcpy(fmt, len, p2);
-            qemu_opt_set(opts, "format", fmt);
-        } else if (*filename != ':') {
-            printf("unrecognized USB mass-storage option %s\n", filename);
-            return NULL;
-        }
-        filename = p1;
-    }
-    if (!*filename) {
-        printf("block device specification needed\n");
-        return NULL;
-    }
-    qemu_opt_set(opts, "file", filename);
-    qemu_opt_set(opts, "if", "none");
-
-    /* create host drive */
-    dinfo = drive_init(opts, 0);
-    if (!dinfo) {
-        qemu_opts_del(opts);
-        return NULL;
-    }
-
-    /* create guest device */
-    dev = usb_create(bus, "usb-storage");
-    if (!dev) {
-        return NULL;
-    }
-    if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
-        qdev_free(&dev->qdev);
-        return NULL;
-    }
-    if (qdev_init(&dev->qdev) < 0)
-        return NULL;
-
-    return dev;
-}
-
-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_END_OF_LIST()
-    }
-};
-
-static Property msd_properties[] = {
-    DEFINE_BLOCK_PROPERTIES(MSDState, conf),
-    DEFINE_PROP_STRING("serial", MSDState, serial),
-    DEFINE_PROP_BIT("removable", MSDState, removable, 0, false),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void usb_msd_class_initfn(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
-
-    uc->init           = usb_msd_initfn;
-    uc->product_desc   = "QEMU USB MSD";
-    uc->usb_desc       = &desc;
-    uc->cancel_packet  = usb_msd_cancel_io;
-    uc->handle_attach  = usb_desc_attach;
-    uc->handle_reset   = usb_msd_handle_reset;
-    uc->handle_control = usb_msd_handle_control;
-    uc->handle_data    = usb_msd_handle_data;
-    dc->fw_name = "storage";
-    dc->vmsd = &vmstate_usb_msd;
-    dc->props = msd_properties;
-}
-
-static TypeInfo msd_info = {
-    .name          = "usb-storage",
-    .parent        = TYPE_USB_DEVICE,
-    .instance_size = sizeof(MSDState),
-    .class_init    = usb_msd_class_initfn,
-};
-
-static void usb_msd_register_types(void)
-{
-    type_register_static(&msd_info);
-    usb_legacy_register("usb-storage", "disk", usb_msd_init);
-}
-
-type_init(usb_msd_register_types)
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
deleted file mode 100644
index 820907a..0000000
--- a/hw/usb-musb.c
+++ /dev/null
@@ -1,1544 +0,0 @@
-/*
- * "Inventra" High-speed Dual-Role Controller (MUSB-HDRC), Mentor Graphics,
- * USB2.0 OTG compliant core used in various chips.
- *
- * Copyright (C) 2008 Nokia Corporation
- * Written by Andrzej Zaborowski <andrew at openedhand.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
- *
- * 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/>.
- *
- * Only host-mode and non-DMA accesses are currently supported.
- */
-#include "qemu-common.h"
-#include "qemu-timer.h"
-#include "usb.h"
-#include "irq.h"
-#include "hw.h"
-
-/* Common USB registers */
-#define MUSB_HDRC_FADDR		0x00	/* 8-bit */
-#define MUSB_HDRC_POWER		0x01	/* 8-bit */
-
-#define MUSB_HDRC_INTRTX	0x02	/* 16-bit */
-#define MUSB_HDRC_INTRRX	0x04
-#define MUSB_HDRC_INTRTXE	0x06  
-#define MUSB_HDRC_INTRRXE	0x08  
-#define MUSB_HDRC_INTRUSB	0x0a	/* 8 bit */
-#define MUSB_HDRC_INTRUSBE	0x0b	/* 8 bit */
-#define MUSB_HDRC_FRAME		0x0c	/* 16-bit */
-#define MUSB_HDRC_INDEX		0x0e	/* 8 bit */
-#define MUSB_HDRC_TESTMODE	0x0f	/* 8 bit */
-
-/* Per-EP registers in indexed mode */
-#define MUSB_HDRC_EP_IDX	0x10	/* 8-bit */
-
-/* EP FIFOs */
-#define MUSB_HDRC_FIFO		0x20
-
-/* Additional Control Registers */
-#define	MUSB_HDRC_DEVCTL	0x60	/* 8 bit */
-
-/* These are indexed */
-#define MUSB_HDRC_TXFIFOSZ	0x62	/* 8 bit (see masks) */
-#define MUSB_HDRC_RXFIFOSZ	0x63	/* 8 bit (see masks) */
-#define MUSB_HDRC_TXFIFOADDR	0x64	/* 16 bit offset shifted right 3 */
-#define MUSB_HDRC_RXFIFOADDR	0x66	/* 16 bit offset shifted right 3 */
-
-/* Some more registers */
-#define MUSB_HDRC_VCTRL		0x68	/* 8 bit */
-#define MUSB_HDRC_HWVERS	0x6c	/* 8 bit */
-
-/* Added in HDRC 1.9(?) & MHDRC 1.4 */
-/* ULPI pass-through */
-#define MUSB_HDRC_ULPI_VBUSCTL	0x70
-#define MUSB_HDRC_ULPI_REGDATA	0x74
-#define MUSB_HDRC_ULPI_REGADDR	0x75
-#define MUSB_HDRC_ULPI_REGCTL	0x76
-
-/* Extended config & PHY control */
-#define MUSB_HDRC_ENDCOUNT	0x78	/* 8 bit */
-#define MUSB_HDRC_DMARAMCFG	0x79	/* 8 bit */
-#define MUSB_HDRC_PHYWAIT	0x7a	/* 8 bit */
-#define MUSB_HDRC_PHYVPLEN	0x7b	/* 8 bit */
-#define MUSB_HDRC_HS_EOF1	0x7c	/* 8 bit, units of 546.1 us */
-#define MUSB_HDRC_FS_EOF1	0x7d	/* 8 bit, units of 533.3 ns */
-#define MUSB_HDRC_LS_EOF1	0x7e	/* 8 bit, units of 1.067 us */
-
-/* Per-EP BUSCTL registers */
-#define MUSB_HDRC_BUSCTL	0x80
-
-/* Per-EP registers in flat mode */
-#define MUSB_HDRC_EP		0x100
-
-/* offsets to registers in flat model */
-#define MUSB_HDRC_TXMAXP	0x00	/* 16 bit apparently */
-#define MUSB_HDRC_TXCSR		0x02	/* 16 bit apparently */
-#define MUSB_HDRC_CSR0		MUSB_HDRC_TXCSR		/* re-used for EP0 */
-#define MUSB_HDRC_RXMAXP	0x04	/* 16 bit apparently */
-#define MUSB_HDRC_RXCSR		0x06	/* 16 bit apparently */
-#define MUSB_HDRC_RXCOUNT	0x08	/* 16 bit apparently */
-#define MUSB_HDRC_COUNT0	MUSB_HDRC_RXCOUNT	/* re-used for EP0 */
-#define MUSB_HDRC_TXTYPE	0x0a	/* 8 bit apparently */
-#define MUSB_HDRC_TYPE0		MUSB_HDRC_TXTYPE	/* re-used for EP0 */
-#define MUSB_HDRC_TXINTERVAL	0x0b	/* 8 bit apparently */
-#define MUSB_HDRC_NAKLIMIT0	MUSB_HDRC_TXINTERVAL	/* re-used for EP0 */
-#define MUSB_HDRC_RXTYPE	0x0c	/* 8 bit apparently */
-#define MUSB_HDRC_RXINTERVAL	0x0d	/* 8 bit apparently */
-#define MUSB_HDRC_FIFOSIZE	0x0f	/* 8 bit apparently */
-#define MUSB_HDRC_CONFIGDATA	MGC_O_HDRC_FIFOSIZE	/* re-used for EP0 */
-
-/* "Bus control" registers */
-#define MUSB_HDRC_TXFUNCADDR	0x00
-#define MUSB_HDRC_TXHUBADDR	0x02
-#define MUSB_HDRC_TXHUBPORT	0x03
-
-#define MUSB_HDRC_RXFUNCADDR	0x04
-#define MUSB_HDRC_RXHUBADDR	0x06
-#define MUSB_HDRC_RXHUBPORT	0x07
-
-/*
- * MUSBHDRC Register bit masks
- */
-
-/* POWER */
-#define MGC_M_POWER_ISOUPDATE		0x80 
-#define	MGC_M_POWER_SOFTCONN		0x40
-#define	MGC_M_POWER_HSENAB		0x20
-#define	MGC_M_POWER_HSMODE		0x10
-#define MGC_M_POWER_RESET		0x08
-#define MGC_M_POWER_RESUME		0x04
-#define MGC_M_POWER_SUSPENDM		0x02
-#define MGC_M_POWER_ENSUSPEND		0x01
-
-/* INTRUSB */
-#define MGC_M_INTR_SUSPEND		0x01
-#define MGC_M_INTR_RESUME		0x02
-#define MGC_M_INTR_RESET		0x04
-#define MGC_M_INTR_BABBLE		0x04
-#define MGC_M_INTR_SOF			0x08 
-#define MGC_M_INTR_CONNECT		0x10
-#define MGC_M_INTR_DISCONNECT		0x20
-#define MGC_M_INTR_SESSREQ		0x40
-#define MGC_M_INTR_VBUSERROR		0x80	/* FOR SESSION END */
-#define MGC_M_INTR_EP0			0x01	/* FOR EP0 INTERRUPT */
-
-/* DEVCTL */
-#define MGC_M_DEVCTL_BDEVICE		0x80   
-#define MGC_M_DEVCTL_FSDEV		0x40
-#define MGC_M_DEVCTL_LSDEV		0x20
-#define MGC_M_DEVCTL_VBUS		0x18
-#define MGC_S_DEVCTL_VBUS		3
-#define MGC_M_DEVCTL_HM			0x04
-#define MGC_M_DEVCTL_HR			0x02
-#define MGC_M_DEVCTL_SESSION		0x01
-
-/* TESTMODE */
-#define MGC_M_TEST_FORCE_HOST		0x80
-#define MGC_M_TEST_FIFO_ACCESS		0x40
-#define MGC_M_TEST_FORCE_FS		0x20
-#define MGC_M_TEST_FORCE_HS		0x10
-#define MGC_M_TEST_PACKET		0x08
-#define MGC_M_TEST_K			0x04
-#define MGC_M_TEST_J			0x02
-#define MGC_M_TEST_SE0_NAK		0x01
-
-/* CSR0 */
-#define	MGC_M_CSR0_FLUSHFIFO		0x0100
-#define MGC_M_CSR0_TXPKTRDY		0x0002
-#define MGC_M_CSR0_RXPKTRDY		0x0001
-
-/* CSR0 in Peripheral mode */
-#define MGC_M_CSR0_P_SVDSETUPEND	0x0080
-#define MGC_M_CSR0_P_SVDRXPKTRDY	0x0040
-#define MGC_M_CSR0_P_SENDSTALL		0x0020
-#define MGC_M_CSR0_P_SETUPEND		0x0010
-#define MGC_M_CSR0_P_DATAEND		0x0008
-#define MGC_M_CSR0_P_SENTSTALL		0x0004
-
-/* CSR0 in Host mode */
-#define MGC_M_CSR0_H_NO_PING		0x0800
-#define MGC_M_CSR0_H_WR_DATATOGGLE	0x0400	/* set to allow setting: */
-#define MGC_M_CSR0_H_DATATOGGLE		0x0200	/* data toggle control */
-#define	MGC_M_CSR0_H_NAKTIMEOUT		0x0080
-#define MGC_M_CSR0_H_STATUSPKT		0x0040
-#define MGC_M_CSR0_H_REQPKT		0x0020
-#define MGC_M_CSR0_H_ERROR		0x0010
-#define MGC_M_CSR0_H_SETUPPKT		0x0008
-#define MGC_M_CSR0_H_RXSTALL		0x0004
-
-/* CONFIGDATA */
-#define MGC_M_CONFIGDATA_MPRXE		0x80	/* auto bulk pkt combining */
-#define MGC_M_CONFIGDATA_MPTXE		0x40	/* auto bulk pkt splitting */
-#define MGC_M_CONFIGDATA_BIGENDIAN	0x20
-#define MGC_M_CONFIGDATA_HBRXE		0x10	/* HB-ISO for RX */
-#define MGC_M_CONFIGDATA_HBTXE		0x08	/* HB-ISO for TX */
-#define MGC_M_CONFIGDATA_DYNFIFO	0x04	/* dynamic FIFO sizing */
-#define MGC_M_CONFIGDATA_SOFTCONE	0x02	/* SoftConnect */
-#define MGC_M_CONFIGDATA_UTMIDW		0x01	/* Width, 0 => 8b, 1 => 16b */
-
-/* TXCSR in Peripheral and Host mode */
-#define MGC_M_TXCSR_AUTOSET		0x8000
-#define MGC_M_TXCSR_ISO			0x4000
-#define MGC_M_TXCSR_MODE		0x2000
-#define MGC_M_TXCSR_DMAENAB		0x1000
-#define MGC_M_TXCSR_FRCDATATOG		0x0800
-#define MGC_M_TXCSR_DMAMODE		0x0400
-#define MGC_M_TXCSR_CLRDATATOG		0x0040
-#define MGC_M_TXCSR_FLUSHFIFO		0x0008
-#define MGC_M_TXCSR_FIFONOTEMPTY	0x0002
-#define MGC_M_TXCSR_TXPKTRDY		0x0001
-
-/* TXCSR in Peripheral mode */
-#define MGC_M_TXCSR_P_INCOMPTX		0x0080
-#define MGC_M_TXCSR_P_SENTSTALL		0x0020
-#define MGC_M_TXCSR_P_SENDSTALL		0x0010
-#define MGC_M_TXCSR_P_UNDERRUN		0x0004
-
-/* TXCSR in Host mode */
-#define MGC_M_TXCSR_H_WR_DATATOGGLE	0x0200
-#define MGC_M_TXCSR_H_DATATOGGLE	0x0100
-#define MGC_M_TXCSR_H_NAKTIMEOUT	0x0080
-#define MGC_M_TXCSR_H_RXSTALL		0x0020
-#define MGC_M_TXCSR_H_ERROR		0x0004
-
-/* RXCSR in Peripheral and Host mode */
-#define MGC_M_RXCSR_AUTOCLEAR		0x8000
-#define MGC_M_RXCSR_DMAENAB		0x2000
-#define MGC_M_RXCSR_DISNYET		0x1000
-#define MGC_M_RXCSR_DMAMODE		0x0800
-#define MGC_M_RXCSR_INCOMPRX		0x0100
-#define MGC_M_RXCSR_CLRDATATOG		0x0080
-#define MGC_M_RXCSR_FLUSHFIFO		0x0010
-#define MGC_M_RXCSR_DATAERROR		0x0008
-#define MGC_M_RXCSR_FIFOFULL		0x0002
-#define MGC_M_RXCSR_RXPKTRDY		0x0001
-
-/* RXCSR in Peripheral mode */
-#define MGC_M_RXCSR_P_ISO		0x4000
-#define MGC_M_RXCSR_P_SENTSTALL		0x0040
-#define MGC_M_RXCSR_P_SENDSTALL		0x0020
-#define MGC_M_RXCSR_P_OVERRUN		0x0004
-
-/* RXCSR in Host mode */
-#define MGC_M_RXCSR_H_AUTOREQ		0x4000
-#define MGC_M_RXCSR_H_WR_DATATOGGLE	0x0400
-#define MGC_M_RXCSR_H_DATATOGGLE	0x0200
-#define MGC_M_RXCSR_H_RXSTALL		0x0040
-#define MGC_M_RXCSR_H_REQPKT		0x0020
-#define MGC_M_RXCSR_H_ERROR		0x0004
-
-/* HUBADDR */
-#define MGC_M_HUBADDR_MULTI_TT		0x80
-
-/* ULPI: Added in HDRC 1.9(?) & MHDRC 1.4 */
-#define MGC_M_ULPI_VBCTL_USEEXTVBUSIND	0x02
-#define MGC_M_ULPI_VBCTL_USEEXTVBUS	0x01
-#define MGC_M_ULPI_REGCTL_INT_ENABLE	0x08
-#define MGC_M_ULPI_REGCTL_READNOTWRITE	0x04
-#define MGC_M_ULPI_REGCTL_COMPLETE	0x02
-#define MGC_M_ULPI_REGCTL_REG		0x01
-
-/* #define MUSB_DEBUG */
-
-#ifdef MUSB_DEBUG
-#define TRACE(fmt,...) fprintf(stderr, "%s@%d: " fmt "\n", __FUNCTION__, \
-                               __LINE__, ##__VA_ARGS__)
-#else
-#define TRACE(...)
-#endif
-
-
-static void musb_attach(USBPort *port);
-static void musb_detach(USBPort *port);
-static void musb_child_detach(USBPort *port, USBDevice *child);
-static void musb_schedule_cb(USBPort *port, USBPacket *p);
-static void musb_async_cancel_device(MUSBState *s, USBDevice *dev);
-
-static USBPortOps musb_port_ops = {
-    .attach = musb_attach,
-    .detach = musb_detach,
-    .child_detach = musb_child_detach,
-    .complete = musb_schedule_cb,
-};
-
-static USBBusOps musb_bus_ops = {
-};
-
-typedef struct MUSBPacket MUSBPacket;
-typedef struct MUSBEndPoint MUSBEndPoint;
-
-struct MUSBPacket {
-    USBPacket p;
-    MUSBEndPoint *ep;
-    int dir;
-};
-
-struct MUSBEndPoint {
-    uint16_t faddr[2];
-    uint8_t haddr[2];
-    uint8_t hport[2];
-    uint16_t csr[2];
-    uint16_t maxp[2];
-    uint16_t rxcount;
-    uint8_t type[2];
-    uint8_t interval[2];
-    uint8_t config;
-    uint8_t fifosize;
-    int timeout[2];	/* Always in microframes */
-
-    uint8_t *buf[2];
-    int fifolen[2];
-    int fifostart[2];
-    int fifoaddr[2];
-    MUSBPacket packey[2];
-    int status[2];
-    int ext_size[2];
-
-    /* For callbacks' use */
-    int epnum;
-    int interrupt[2];
-    MUSBState *musb;
-    USBCallback *delayed_cb[2];
-    QEMUTimer *intv_timer[2];
-};
-
-struct MUSBState {
-    qemu_irq irqs[musb_irq_max];
-    USBBus bus;
-    USBPort port;
-
-    int idx;
-    uint8_t devctl;
-    uint8_t power;
-    uint8_t faddr;
-
-    uint8_t intr;
-    uint8_t mask;
-    uint16_t tx_intr;
-    uint16_t tx_mask;
-    uint16_t rx_intr;
-    uint16_t rx_mask;
-
-    int setup_len;
-    int session;
-
-    uint8_t buf[0x8000];
-
-        /* Duplicating the world since 2008!...  probably we should have 32
-         * logical, single endpoints instead.  */
-    MUSBEndPoint ep[16];
-};
-
-void musb_reset(MUSBState *s)
-{
-    int i;
-
-    s->faddr = 0x00;
-    s->devctl = 0;
-    s->power = MGC_M_POWER_HSENAB;
-    s->tx_intr = 0x0000;
-    s->rx_intr = 0x0000;
-    s->tx_mask = 0xffff;
-    s->rx_mask = 0xffff;
-    s->intr = 0x00;
-    s->mask = 0x06;
-    s->idx = 0;
-
-    s->setup_len = 0;
-    s->session = 0;
-    memset(s->buf, 0, sizeof(s->buf));
-
-    /* TODO: _DW */
-    s->ep[0].config = MGC_M_CONFIGDATA_SOFTCONE | MGC_M_CONFIGDATA_DYNFIFO;
-    for (i = 0; i < 16; i ++) {
-        s->ep[i].fifosize = 64;
-        s->ep[i].maxp[0] = 0x40;
-        s->ep[i].maxp[1] = 0x40;
-        s->ep[i].musb = s;
-        s->ep[i].epnum = i;
-        usb_packet_init(&s->ep[i].packey[0].p);
-        usb_packet_init(&s->ep[i].packey[1].p);
-    }
-}
-
-struct MUSBState *musb_init(DeviceState *parent_device, int gpio_base)
-{
-    MUSBState *s = g_malloc0(sizeof(*s));
-    int i;
-
-    for (i = 0; i < musb_irq_max; i++) {
-        s->irqs[i] = qdev_get_gpio_in(parent_device, gpio_base + i);
-    }
-
-    musb_reset(s);
-
-    usb_bus_new(&s->bus, &musb_bus_ops, parent_device);
-    usb_register_port(&s->bus, &s->port, s, 0, &musb_port_ops,
-                      USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
-
-    return s;
-}
-
-static void musb_vbus_set(MUSBState *s, int level)
-{
-    if (level)
-        s->devctl |= 3 << MGC_S_DEVCTL_VBUS;
-    else
-        s->devctl &= ~MGC_M_DEVCTL_VBUS;
-
-    qemu_set_irq(s->irqs[musb_set_vbus], level);
-}
-
-static void musb_intr_set(MUSBState *s, int line, int level)
-{
-    if (!level) {
-        s->intr &= ~(1 << line);
-        qemu_irq_lower(s->irqs[line]);
-    } else if (s->mask & (1 << line)) {
-        s->intr |= 1 << line;
-        qemu_irq_raise(s->irqs[line]);
-    }
-}
-
-static void musb_tx_intr_set(MUSBState *s, int line, int level)
-{
-    if (!level) {
-        s->tx_intr &= ~(1 << line);
-        if (!s->tx_intr)
-            qemu_irq_lower(s->irqs[musb_irq_tx]);
-    } else if (s->tx_mask & (1 << line)) {
-        s->tx_intr |= 1 << line;
-        qemu_irq_raise(s->irqs[musb_irq_tx]);
-    }
-}
-
-static void musb_rx_intr_set(MUSBState *s, int line, int level)
-{
-    if (line) {
-        if (!level) {
-            s->rx_intr &= ~(1 << line);
-            if (!s->rx_intr)
-                qemu_irq_lower(s->irqs[musb_irq_rx]);
-        } else if (s->rx_mask & (1 << line)) {
-            s->rx_intr |= 1 << line;
-            qemu_irq_raise(s->irqs[musb_irq_rx]);
-        }
-    } else
-        musb_tx_intr_set(s, line, level);
-}
-
-uint32_t musb_core_intr_get(MUSBState *s)
-{
-    return (s->rx_intr << 15) | s->tx_intr;
-}
-
-void musb_core_intr_clear(MUSBState *s, uint32_t mask)
-{
-    if (s->rx_intr) {
-        s->rx_intr &= mask >> 15;
-        if (!s->rx_intr)
-            qemu_irq_lower(s->irqs[musb_irq_rx]);
-    }
-
-    if (s->tx_intr) {
-        s->tx_intr &= mask & 0xffff;
-        if (!s->tx_intr)
-            qemu_irq_lower(s->irqs[musb_irq_tx]);
-    }
-}
-
-void musb_set_size(MUSBState *s, int epnum, int size, int is_tx)
-{
-    s->ep[epnum].ext_size[!is_tx] = size;
-    s->ep[epnum].fifostart[0] = 0;
-    s->ep[epnum].fifostart[1] = 0;
-    s->ep[epnum].fifolen[0] = 0;
-    s->ep[epnum].fifolen[1] = 0;
-}
-
-static void musb_session_update(MUSBState *s, int prev_dev, int prev_sess)
-{
-    int detect_prev = prev_dev && prev_sess;
-    int detect = !!s->port.dev && s->session;
-
-    if (detect && !detect_prev) {
-        /* Let's skip the ID pin sense and VBUS sense formalities and
-         * and signal a successful SRP directly.  This should work at least
-         * for the Linux driver stack.  */
-        musb_intr_set(s, musb_irq_connect, 1);
-
-        if (s->port.dev->speed == USB_SPEED_LOW) {
-            s->devctl &= ~MGC_M_DEVCTL_FSDEV;
-            s->devctl |= MGC_M_DEVCTL_LSDEV;
-        } else {
-            s->devctl |= MGC_M_DEVCTL_FSDEV;
-            s->devctl &= ~MGC_M_DEVCTL_LSDEV;
-        }
-
-        /* A-mode?  */
-        s->devctl &= ~MGC_M_DEVCTL_BDEVICE;
-
-        /* Host-mode bit?  */
-        s->devctl |= MGC_M_DEVCTL_HM;
-#if 1
-        musb_vbus_set(s, 1);
-#endif
-    } else if (!detect && detect_prev) {
-#if 1
-        musb_vbus_set(s, 0);
-#endif
-    }
-}
-
-/* Attach or detach a device on our only port.  */
-static void musb_attach(USBPort *port)
-{
-    MUSBState *s = (MUSBState *) port->opaque;
-
-    musb_intr_set(s, musb_irq_vbus_request, 1);
-    musb_session_update(s, 0, s->session);
-}
-
-static void musb_detach(USBPort *port)
-{
-    MUSBState *s = (MUSBState *) port->opaque;
-
-    musb_async_cancel_device(s, port->dev);
-
-    musb_intr_set(s, musb_irq_disconnect, 1);
-    musb_session_update(s, 1, s->session);
-}
-
-static void musb_child_detach(USBPort *port, USBDevice *child)
-{
-    MUSBState *s = (MUSBState *) port->opaque;
-
-    musb_async_cancel_device(s, child);
-}
-
-static void musb_cb_tick0(void *opaque)
-{
-    MUSBEndPoint *ep = (MUSBEndPoint *) opaque;
-
-    ep->delayed_cb[0](&ep->packey[0].p, opaque);
-}
-
-static void musb_cb_tick1(void *opaque)
-{
-    MUSBEndPoint *ep = (MUSBEndPoint *) opaque;
-
-    ep->delayed_cb[1](&ep->packey[1].p, opaque);
-}
-
-#define musb_cb_tick	(dir ? musb_cb_tick1 : musb_cb_tick0)
-
-static void musb_schedule_cb(USBPort *port, USBPacket *packey)
-{
-    MUSBPacket *p = container_of(packey, MUSBPacket, p);
-    MUSBEndPoint *ep = p->ep;
-    int dir = p->dir;
-    int timeout = 0;
-
-    if (ep->status[dir] == USB_RET_NAK)
-        timeout = ep->timeout[dir];
-    else if (ep->interrupt[dir])
-        timeout = 8;
-    else
-        return musb_cb_tick(ep);
-
-    if (!ep->intv_timer[dir])
-        ep->intv_timer[dir] = qemu_new_timer_ns(vm_clock, musb_cb_tick, ep);
-
-    qemu_mod_timer(ep->intv_timer[dir], qemu_get_clock_ns(vm_clock) +
-                   muldiv64(timeout, get_ticks_per_sec(), 8000));
-}
-
-static int musb_timeout(int ttype, int speed, int val)
-{
-#if 1
-    return val << 3;
-#endif
-
-    switch (ttype) {
-    case USB_ENDPOINT_XFER_CONTROL:
-        if (val < 2)
-            return 0;
-        else if (speed == USB_SPEED_HIGH)
-            return 1 << (val - 1);
-        else
-            return 8 << (val - 1);
-
-    case USB_ENDPOINT_XFER_INT:
-        if (speed == USB_SPEED_HIGH)
-            if (val < 2)
-                return 0;
-            else
-                return 1 << (val - 1);
-        else
-            return val << 3;
-
-    case USB_ENDPOINT_XFER_BULK:
-    case USB_ENDPOINT_XFER_ISOC:
-        if (val < 2)
-            return 0;
-        else if (speed == USB_SPEED_HIGH)
-            return 1 << (val - 1);
-        else
-            return 8 << (val - 1);
-        /* TODO: what with low-speed Bulk and Isochronous?  */
-    }
-
-    hw_error("bad interval\n");
-}
-
-static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
-                int epnum, int pid, int len, USBCallback cb, int dir)
-{
-    USBDevice *dev;
-    USBEndpoint *uep;
-    int ret;
-    int idx = epnum && dir;
-    int ttype;
-
-    /* ep->type[0,1] contains:
-     * in bits 7:6 the speed (0 - invalid, 1 - high, 2 - full, 3 - slow)
-     * in bits 5:4 the transfer type (BULK / INT)
-     * in bits 3:0 the EP num
-     */
-    ttype = epnum ? (ep->type[idx] >> 4) & 3 : 0;
-
-    ep->timeout[dir] = musb_timeout(ttype,
-                    ep->type[idx] >> 6, ep->interval[idx]);
-    ep->interrupt[dir] = ttype == USB_ENDPOINT_XFER_INT;
-    ep->delayed_cb[dir] = cb;
-
-    /* A wild guess on the FADDR semantics... */
-    dev = usb_find_device(&s->port, ep->faddr[idx]);
-    uep = usb_ep_get(dev, pid, ep->type[idx] & 0xf);
-    usb_packet_setup(&ep->packey[dir].p, pid, uep);
-    usb_packet_addbuf(&ep->packey[dir].p, ep->buf[idx], len);
-    ep->packey[dir].ep = ep;
-    ep->packey[dir].dir = dir;
-
-    ret = usb_handle_packet(dev, &ep->packey[dir].p);
-
-    if (ret == USB_RET_ASYNC) {
-        ep->status[dir] = len;
-        return;
-    }
-
-    ep->status[dir] = ret;
-    musb_schedule_cb(&s->port, &ep->packey[dir].p);
-}
-
-static void musb_tx_packet_complete(USBPacket *packey, void *opaque)
-{
-    /* Unfortunately we can't use packey->devep because that's the remote
-     * endpoint number and may be different than our local.  */
-    MUSBEndPoint *ep = (MUSBEndPoint *) opaque;
-    int epnum = ep->epnum;
-    MUSBState *s = ep->musb;
-
-    ep->fifostart[0] = 0;
-    ep->fifolen[0] = 0;
-#ifdef CLEAR_NAK
-    if (ep->status[0] != USB_RET_NAK) {
-#endif
-        if (epnum)
-            ep->csr[0] &= ~(MGC_M_TXCSR_FIFONOTEMPTY | MGC_M_TXCSR_TXPKTRDY);
-        else
-            ep->csr[0] &= ~MGC_M_CSR0_TXPKTRDY;
-#ifdef CLEAR_NAK
-    }
-#endif
-
-    /* Clear all of the error bits first */
-    if (epnum)
-        ep->csr[0] &= ~(MGC_M_TXCSR_H_ERROR | MGC_M_TXCSR_H_RXSTALL |
-                        MGC_M_TXCSR_H_NAKTIMEOUT);
-    else
-        ep->csr[0] &= ~(MGC_M_CSR0_H_ERROR | MGC_M_CSR0_H_RXSTALL |
-                        MGC_M_CSR0_H_NAKTIMEOUT | MGC_M_CSR0_H_NO_PING);
-
-    if (ep->status[0] == USB_RET_STALL) {
-        /* Command not supported by target! */
-        ep->status[0] = 0;
-
-        if (epnum)
-            ep->csr[0] |= MGC_M_TXCSR_H_RXSTALL;
-        else
-            ep->csr[0] |= MGC_M_CSR0_H_RXSTALL;
-    }
-
-    if (ep->status[0] == USB_RET_NAK) {
-        ep->status[0] = 0;
-
-        /* NAK timeouts are only generated in Bulk transfers and
-         * Data-errors in Isochronous.  */
-        if (ep->interrupt[0]) {
-            return;
-        }
-
-        if (epnum)
-            ep->csr[0] |= MGC_M_TXCSR_H_NAKTIMEOUT;
-        else
-            ep->csr[0] |= MGC_M_CSR0_H_NAKTIMEOUT;
-    }
-
-    if (ep->status[0] < 0) {
-        if (ep->status[0] == USB_RET_BABBLE)
-            musb_intr_set(s, musb_irq_rst_babble, 1);
-
-        /* Pretend we've tried three times already and failed (in
-         * case of USB_TOKEN_SETUP).  */
-        if (epnum)
-            ep->csr[0] |= MGC_M_TXCSR_H_ERROR;
-        else
-            ep->csr[0] |= MGC_M_CSR0_H_ERROR;
-
-        musb_tx_intr_set(s, epnum, 1);
-        return;
-    }
-    /* TODO: check len for over/underruns of an OUT packet?  */
-
-#ifdef SETUPLEN_HACK
-    if (!epnum && ep->packey[0].pid == USB_TOKEN_SETUP)
-        s->setup_len = ep->packey[0].data[6];
-#endif
-
-    /* In DMA mode: if no error, assert DMA request for this EP,
-     * and skip the interrupt.  */
-    musb_tx_intr_set(s, epnum, 1);
-}
-
-static void musb_rx_packet_complete(USBPacket *packey, void *opaque)
-{
-    /* Unfortunately we can't use packey->devep because that's the remote
-     * endpoint number and may be different than our local.  */
-    MUSBEndPoint *ep = (MUSBEndPoint *) opaque;
-    int epnum = ep->epnum;
-    MUSBState *s = ep->musb;
-
-    ep->fifostart[1] = 0;
-    ep->fifolen[1] = 0;
-
-#ifdef CLEAR_NAK
-    if (ep->status[1] != USB_RET_NAK) {
-#endif
-        ep->csr[1] &= ~MGC_M_RXCSR_H_REQPKT;
-        if (!epnum)
-            ep->csr[0] &= ~MGC_M_CSR0_H_REQPKT;
-#ifdef CLEAR_NAK
-    }
-#endif
-
-    /* Clear all of the imaginable error bits first */
-    ep->csr[1] &= ~(MGC_M_RXCSR_H_ERROR | MGC_M_RXCSR_H_RXSTALL |
-                    MGC_M_RXCSR_DATAERROR);
-    if (!epnum)
-        ep->csr[0] &= ~(MGC_M_CSR0_H_ERROR | MGC_M_CSR0_H_RXSTALL |
-                        MGC_M_CSR0_H_NAKTIMEOUT | MGC_M_CSR0_H_NO_PING);
-
-    if (ep->status[1] == USB_RET_STALL) {
-        ep->status[1] = 0;
-        packey->result = 0;
-
-        ep->csr[1] |= MGC_M_RXCSR_H_RXSTALL;
-        if (!epnum)
-            ep->csr[0] |= MGC_M_CSR0_H_RXSTALL;
-    }
-
-    if (ep->status[1] == USB_RET_NAK) {
-        ep->status[1] = 0;
-
-        /* NAK timeouts are only generated in Bulk transfers and
-         * Data-errors in Isochronous.  */
-        if (ep->interrupt[1])
-            return musb_packet(s, ep, epnum, USB_TOKEN_IN,
-                            packey->iov.size, musb_rx_packet_complete, 1);
-
-        ep->csr[1] |= MGC_M_RXCSR_DATAERROR;
-        if (!epnum)
-            ep->csr[0] |= MGC_M_CSR0_H_NAKTIMEOUT;
-    }
-
-    if (ep->status[1] < 0) {
-        if (ep->status[1] == USB_RET_BABBLE) {
-            musb_intr_set(s, musb_irq_rst_babble, 1);
-            return;
-        }
-
-        /* Pretend we've tried three times already and failed (in
-         * case of a control transfer).  */
-        ep->csr[1] |= MGC_M_RXCSR_H_ERROR;
-        if (!epnum)
-            ep->csr[0] |= MGC_M_CSR0_H_ERROR;
-
-        musb_rx_intr_set(s, epnum, 1);
-        return;
-    }
-    /* TODO: check len for over/underruns of an OUT packet?  */
-    /* TODO: perhaps make use of e->ext_size[1] here.  */
-
-    packey->result = ep->status[1];
-
-    if (!(ep->csr[1] & (MGC_M_RXCSR_H_RXSTALL | MGC_M_RXCSR_DATAERROR))) {
-        ep->csr[1] |= MGC_M_RXCSR_FIFOFULL | MGC_M_RXCSR_RXPKTRDY;
-        if (!epnum)
-            ep->csr[0] |= MGC_M_CSR0_RXPKTRDY;
-
-        ep->rxcount = packey->result; /* XXX: MIN(packey->len, ep->maxp[1]); */
-        /* In DMA mode: assert DMA request for this EP */
-    }
-
-    /* Only if DMA has not been asserted */
-    musb_rx_intr_set(s, epnum, 1);
-}
-
-static void musb_async_cancel_device(MUSBState *s, USBDevice *dev)
-{
-    int ep, dir;
-
-    for (ep = 0; ep < 16; ep++) {
-        for (dir = 0; dir < 2; dir++) {
-            if (!usb_packet_is_inflight(&s->ep[ep].packey[dir].p) ||
-                s->ep[ep].packey[dir].p.ep->dev != dev) {
-                continue;
-            }
-            usb_cancel_packet(&s->ep[ep].packey[dir].p);
-            /* status updates needed here? */
-        }
-    }
-}
-
-static void musb_tx_rdy(MUSBState *s, int epnum)
-{
-    MUSBEndPoint *ep = s->ep + epnum;
-    int pid;
-    int total, valid = 0;
-    TRACE("start %d, len %d",  ep->fifostart[0], ep->fifolen[0] );
-    ep->fifostart[0] += ep->fifolen[0];
-    ep->fifolen[0] = 0;
-
-    /* XXX: how's the total size of the packet retrieved exactly in
-     * the generic case?  */
-    total = ep->maxp[0] & 0x3ff;
-
-    if (ep->ext_size[0]) {
-        total = ep->ext_size[0];
-        ep->ext_size[0] = 0;
-        valid = 1;
-    }
-
-    /* If the packet is not fully ready yet, wait for a next segment.  */
-    if (epnum && (ep->fifostart[0]) < total)
-        return;
-
-    if (!valid)
-        total = ep->fifostart[0];
-
-    pid = USB_TOKEN_OUT;
-    if (!epnum && (ep->csr[0] & MGC_M_CSR0_H_SETUPPKT)) {
-        pid = USB_TOKEN_SETUP;
-        if (total != 8) {
-            TRACE("illegal SETUPPKT length of %i bytes", total);
-        }
-        /* Controller should retry SETUP packets three times on errors
-         * but it doesn't make sense for us to do that.  */
-    }
-
-    return musb_packet(s, ep, epnum, pid,
-                    total, musb_tx_packet_complete, 0);
-}
-
-static void musb_rx_req(MUSBState *s, int epnum)
-{
-    MUSBEndPoint *ep = s->ep + epnum;
-    int total;
-
-    /* If we already have a packet, which didn't fit into the
-     * 64 bytes of the FIFO, only move the FIFO start and return. (Obsolete) */
-    if (ep->packey[1].p.pid == USB_TOKEN_IN && ep->status[1] >= 0 &&
-                    (ep->fifostart[1]) + ep->rxcount <
-                    ep->packey[1].p.iov.size) {
-        TRACE("0x%08x, %d",  ep->fifostart[1], ep->rxcount );
-        ep->fifostart[1] += ep->rxcount;
-        ep->fifolen[1] = 0;
-
-        ep->rxcount = MIN(ep->packey[0].p.iov.size - (ep->fifostart[1]),
-                        ep->maxp[1]);
-
-        ep->csr[1] &= ~MGC_M_RXCSR_H_REQPKT;
-        if (!epnum)
-            ep->csr[0] &= ~MGC_M_CSR0_H_REQPKT;
-
-        /* Clear all of the error bits first */
-        ep->csr[1] &= ~(MGC_M_RXCSR_H_ERROR | MGC_M_RXCSR_H_RXSTALL |
-                        MGC_M_RXCSR_DATAERROR);
-        if (!epnum)
-            ep->csr[0] &= ~(MGC_M_CSR0_H_ERROR | MGC_M_CSR0_H_RXSTALL |
-                            MGC_M_CSR0_H_NAKTIMEOUT | MGC_M_CSR0_H_NO_PING);
-
-        ep->csr[1] |= MGC_M_RXCSR_FIFOFULL | MGC_M_RXCSR_RXPKTRDY;
-        if (!epnum)
-            ep->csr[0] |= MGC_M_CSR0_RXPKTRDY;
-        musb_rx_intr_set(s, epnum, 1);
-        return;
-    }
-
-    /* The driver sets maxp[1] to 64 or less because it knows the hardware
-     * FIFO is this deep.  Bigger packets get split in
-     * usb_generic_handle_packet but we can also do the splitting locally
-     * for performance.  It turns out we can also have a bigger FIFO and
-     * ignore the limit set in ep->maxp[1].  The Linux MUSB driver deals
-     * OK with single packets of even 32KB and we avoid splitting, however
-     * usb_msd.c sometimes sends a packet bigger than what Linux expects
-     * (e.g. 8192 bytes instead of 4096) and we get an OVERRUN.  Splitting
-     * hides this overrun from Linux.  Up to 4096 everything is fine
-     * though.  Currently this is disabled.
-     *
-     * XXX: mind ep->fifosize.  */
-    total = MIN(ep->maxp[1] & 0x3ff, sizeof(s->buf));
-
-#ifdef SETUPLEN_HACK
-    /* Why should *we* do that instead of Linux?  */
-    if (!epnum) {
-        if (ep->packey[0].p.devaddr == 2) {
-            total = MIN(s->setup_len, 8);
-        } else {
-            total = MIN(s->setup_len, 64);
-        }
-        s->setup_len -= total;
-    }
-#endif
-
-    return musb_packet(s, ep, epnum, USB_TOKEN_IN,
-                    total, musb_rx_packet_complete, 1);
-}
-
-static uint8_t musb_read_fifo(MUSBEndPoint *ep)
-{
-    uint8_t value;
-    if (ep->fifolen[1] >= 64) {
-        /* We have a FIFO underrun */
-        TRACE("EP%d FIFO is now empty, stop reading", ep->epnum);
-        return 0x00000000;
-    }
-    /* In DMA mode clear RXPKTRDY and set REQPKT automatically
-     * (if AUTOREQ is set) */
-
-    ep->csr[1] &= ~MGC_M_RXCSR_FIFOFULL;
-    value=ep->buf[1][ep->fifostart[1] + ep->fifolen[1] ++];
-    TRACE("EP%d 0x%02x, %d", ep->epnum, value, ep->fifolen[1] );
-    return value;
-}
-
-static void musb_write_fifo(MUSBEndPoint *ep, uint8_t value)
-{
-    TRACE("EP%d = %02x", ep->epnum, value);
-    if (ep->fifolen[0] >= 64) {
-        /* We have a FIFO overrun */
-        TRACE("EP%d FIFO exceeded 64 bytes, stop feeding data", ep->epnum);
-        return;
-     }
-
-     ep->buf[0][ep->fifostart[0] + ep->fifolen[0] ++] = value;
-     ep->csr[0] |= MGC_M_TXCSR_FIFONOTEMPTY;
-}
-
-static void musb_ep_frame_cancel(MUSBEndPoint *ep, int dir)
-{
-    if (ep->intv_timer[dir])
-        qemu_del_timer(ep->intv_timer[dir]);
-}
-
-/* Bus control */
-static uint8_t musb_busctl_readb(void *opaque, int ep, int addr)
-{
-    MUSBState *s = (MUSBState *) opaque;
-
-    switch (addr) {
-    /* For USB2.0 HS hubs only */
-    case MUSB_HDRC_TXHUBADDR:
-        return s->ep[ep].haddr[0];
-    case MUSB_HDRC_TXHUBPORT:
-        return s->ep[ep].hport[0];
-    case MUSB_HDRC_RXHUBADDR:
-        return s->ep[ep].haddr[1];
-    case MUSB_HDRC_RXHUBPORT:
-        return s->ep[ep].hport[1];
-
-    default:
-        TRACE("unknown register 0x%02x", addr);
-        return 0x00;
-    };
-}
-
-static void musb_busctl_writeb(void *opaque, int ep, int addr, uint8_t value)
-{
-    MUSBState *s = (MUSBState *) opaque;
-
-    switch (addr) {
-    case MUSB_HDRC_TXFUNCADDR:
-        s->ep[ep].faddr[0] = value;
-        break;
-    case MUSB_HDRC_RXFUNCADDR:
-        s->ep[ep].faddr[1] = value;
-        break;
-    case MUSB_HDRC_TXHUBADDR:
-        s->ep[ep].haddr[0] = value;
-        break;
-    case MUSB_HDRC_TXHUBPORT:
-        s->ep[ep].hport[0] = value;
-        break;
-    case MUSB_HDRC_RXHUBADDR:
-        s->ep[ep].haddr[1] = value;
-        break;
-    case MUSB_HDRC_RXHUBPORT:
-        s->ep[ep].hport[1] = value;
-        break;
-
-    default:
-        TRACE("unknown register 0x%02x", addr);
-        break;
-    };
-}
-
-static uint16_t musb_busctl_readh(void *opaque, int ep, int addr)
-{
-    MUSBState *s = (MUSBState *) opaque;
-
-    switch (addr) {
-    case MUSB_HDRC_TXFUNCADDR:
-        return s->ep[ep].faddr[0];
-    case MUSB_HDRC_RXFUNCADDR:
-        return s->ep[ep].faddr[1];
-
-    default:
-        return musb_busctl_readb(s, ep, addr) |
-                (musb_busctl_readb(s, ep, addr | 1) << 8);
-    };
-}
-
-static void musb_busctl_writeh(void *opaque, int ep, int addr, uint16_t value)
-{
-    MUSBState *s = (MUSBState *) opaque;
-
-    switch (addr) {
-    case MUSB_HDRC_TXFUNCADDR:
-        s->ep[ep].faddr[0] = value;
-        break;
-    case MUSB_HDRC_RXFUNCADDR:
-        s->ep[ep].faddr[1] = value;
-        break;
-
-    default:
-        musb_busctl_writeb(s, ep, addr, value & 0xff);
-        musb_busctl_writeb(s, ep, addr | 1, value >> 8);
-    };
-}
-
-/* Endpoint control */
-static uint8_t musb_ep_readb(void *opaque, int ep, int addr)
-{
-    MUSBState *s = (MUSBState *) opaque;
-
-    switch (addr) {
-    case MUSB_HDRC_TXTYPE:
-        return s->ep[ep].type[0];
-    case MUSB_HDRC_TXINTERVAL:
-        return s->ep[ep].interval[0];
-    case MUSB_HDRC_RXTYPE:
-        return s->ep[ep].type[1];
-    case MUSB_HDRC_RXINTERVAL:
-        return s->ep[ep].interval[1];
-    case (MUSB_HDRC_FIFOSIZE & ~1):
-        return 0x00;
-    case MUSB_HDRC_FIFOSIZE:
-        return ep ? s->ep[ep].fifosize : s->ep[ep].config;
-    case MUSB_HDRC_RXCOUNT:
-        return s->ep[ep].rxcount;
-
-    default:
-        TRACE("unknown register 0x%02x", addr);
-        return 0x00;
-    };
-}
-
-static void musb_ep_writeb(void *opaque, int ep, int addr, uint8_t value)
-{
-    MUSBState *s = (MUSBState *) opaque;
-
-    switch (addr) {
-    case MUSB_HDRC_TXTYPE:
-        s->ep[ep].type[0] = value;
-        break;
-    case MUSB_HDRC_TXINTERVAL:
-        s->ep[ep].interval[0] = value;
-        musb_ep_frame_cancel(&s->ep[ep], 0);
-        break;
-    case MUSB_HDRC_RXTYPE:
-        s->ep[ep].type[1] = value;
-        break;
-    case MUSB_HDRC_RXINTERVAL:
-        s->ep[ep].interval[1] = value;
-        musb_ep_frame_cancel(&s->ep[ep], 1);
-        break;
-    case (MUSB_HDRC_FIFOSIZE & ~1):
-        break;
-    case MUSB_HDRC_FIFOSIZE:
-        TRACE("somebody messes with fifosize (now %i bytes)", value);
-        s->ep[ep].fifosize = value;
-        break;
-    default:
-        TRACE("unknown register 0x%02x", addr);
-        break;
-    };
-}
-
-static uint16_t musb_ep_readh(void *opaque, int ep, int addr)
-{
-    MUSBState *s = (MUSBState *) opaque;
-    uint16_t ret;
-
-    switch (addr) {
-    case MUSB_HDRC_TXMAXP:
-        return s->ep[ep].maxp[0];
-    case MUSB_HDRC_TXCSR:
-        return s->ep[ep].csr[0];
-    case MUSB_HDRC_RXMAXP:
-        return s->ep[ep].maxp[1];
-    case MUSB_HDRC_RXCSR:
-        ret = s->ep[ep].csr[1];
-
-        /* TODO: This and other bits probably depend on
-         * ep->csr[1] & MGC_M_RXCSR_AUTOCLEAR.  */
-        if (s->ep[ep].csr[1] & MGC_M_RXCSR_AUTOCLEAR)
-            s->ep[ep].csr[1] &= ~MGC_M_RXCSR_RXPKTRDY;
-
-        return ret;
-    case MUSB_HDRC_RXCOUNT:
-        return s->ep[ep].rxcount;
-
-    default:
-        return musb_ep_readb(s, ep, addr) |
-                (musb_ep_readb(s, ep, addr | 1) << 8);
-    };
-}
-
-static void musb_ep_writeh(void *opaque, int ep, int addr, uint16_t value)
-{
-    MUSBState *s = (MUSBState *) opaque;
-
-    switch (addr) {
-    case MUSB_HDRC_TXMAXP:
-        s->ep[ep].maxp[0] = value;
-        break;
-    case MUSB_HDRC_TXCSR:
-        if (ep) {
-            s->ep[ep].csr[0] &= value & 0xa6;
-            s->ep[ep].csr[0] |= value & 0xff59;
-        } else {
-            s->ep[ep].csr[0] &= value & 0x85;
-            s->ep[ep].csr[0] |= value & 0xf7a;
-        }
-
-        musb_ep_frame_cancel(&s->ep[ep], 0);
-
-        if ((ep && (value & MGC_M_TXCSR_FLUSHFIFO)) ||
-                        (!ep && (value & MGC_M_CSR0_FLUSHFIFO))) {
-            s->ep[ep].fifolen[0] = 0;
-            s->ep[ep].fifostart[0] = 0;
-            if (ep)
-                s->ep[ep].csr[0] &=
-                        ~(MGC_M_TXCSR_FIFONOTEMPTY | MGC_M_TXCSR_TXPKTRDY);
-            else
-                s->ep[ep].csr[0] &=
-                        ~(MGC_M_CSR0_TXPKTRDY | MGC_M_CSR0_RXPKTRDY);
-        }
-        if (
-                        (ep &&
-#ifdef CLEAR_NAK
-                         (value & MGC_M_TXCSR_TXPKTRDY) &&
-                         !(value & MGC_M_TXCSR_H_NAKTIMEOUT)) ||
-#else
-                         (value & MGC_M_TXCSR_TXPKTRDY)) ||
-#endif
-                        (!ep &&
-#ifdef CLEAR_NAK
-                         (value & MGC_M_CSR0_TXPKTRDY) &&
-                         !(value & MGC_M_CSR0_H_NAKTIMEOUT)))
-#else
-                         (value & MGC_M_CSR0_TXPKTRDY)))
-#endif
-            musb_tx_rdy(s, ep);
-        if (!ep &&
-                        (value & MGC_M_CSR0_H_REQPKT) &&
-#ifdef CLEAR_NAK
-                        !(value & (MGC_M_CSR0_H_NAKTIMEOUT |
-                                        MGC_M_CSR0_RXPKTRDY)))
-#else
-                        !(value & MGC_M_CSR0_RXPKTRDY))
-#endif
-            musb_rx_req(s, ep);
-        break;
-
-    case MUSB_HDRC_RXMAXP:
-        s->ep[ep].maxp[1] = value;
-        break;
-    case MUSB_HDRC_RXCSR:
-        /* (DMA mode only) */
-        if (
-                (value & MGC_M_RXCSR_H_AUTOREQ) &&
-                !(value & MGC_M_RXCSR_RXPKTRDY) &&
-                (s->ep[ep].csr[1] & MGC_M_RXCSR_RXPKTRDY))
-            value |= MGC_M_RXCSR_H_REQPKT;
-
-        s->ep[ep].csr[1] &= 0x102 | (value & 0x4d);
-        s->ep[ep].csr[1] |= value & 0xfeb0;
-
-        musb_ep_frame_cancel(&s->ep[ep], 1);
-
-        if (value & MGC_M_RXCSR_FLUSHFIFO) {
-            s->ep[ep].fifolen[1] = 0;
-            s->ep[ep].fifostart[1] = 0;
-            s->ep[ep].csr[1] &= ~(MGC_M_RXCSR_FIFOFULL | MGC_M_RXCSR_RXPKTRDY);
-            /* If double buffering and we have two packets ready, flush
-             * only the first one and set up the fifo at the second packet.  */
-        }
-#ifdef CLEAR_NAK
-        if ((value & MGC_M_RXCSR_H_REQPKT) && !(value & MGC_M_RXCSR_DATAERROR))
-#else
-        if (value & MGC_M_RXCSR_H_REQPKT)
-#endif
-            musb_rx_req(s, ep);
-        break;
-    case MUSB_HDRC_RXCOUNT:
-        s->ep[ep].rxcount = value;
-        break;
-
-    default:
-        musb_ep_writeb(s, ep, addr, value & 0xff);
-        musb_ep_writeb(s, ep, addr | 1, value >> 8);
-    };
-}
-
-/* Generic control */
-static uint32_t musb_readb(void *opaque, target_phys_addr_t addr)
-{
-    MUSBState *s = (MUSBState *) opaque;
-    int ep, i;
-    uint8_t ret;
-
-    switch (addr) {
-    case MUSB_HDRC_FADDR:
-        return s->faddr;
-    case MUSB_HDRC_POWER:
-        return s->power;
-    case MUSB_HDRC_INTRUSB:
-        ret = s->intr;
-        for (i = 0; i < sizeof(ret) * 8; i ++)
-            if (ret & (1 << i))
-                musb_intr_set(s, i, 0);
-        return ret;
-    case MUSB_HDRC_INTRUSBE:
-        return s->mask;
-    case MUSB_HDRC_INDEX:
-        return s->idx;
-    case MUSB_HDRC_TESTMODE:
-        return 0x00;
-
-    case MUSB_HDRC_EP_IDX ... (MUSB_HDRC_EP_IDX + 0xf):
-        return musb_ep_readb(s, s->idx, addr & 0xf);
-
-    case MUSB_HDRC_DEVCTL:
-        return s->devctl;
-
-    case MUSB_HDRC_TXFIFOSZ:
-    case MUSB_HDRC_RXFIFOSZ:
-    case MUSB_HDRC_VCTRL:
-        /* TODO */
-        return 0x00;
-
-    case MUSB_HDRC_HWVERS:
-        return (1 << 10) | 400;
-
-    case (MUSB_HDRC_VCTRL | 1):
-    case (MUSB_HDRC_HWVERS | 1):
-    case (MUSB_HDRC_DEVCTL | 1):
-        return 0x00;
-
-    case MUSB_HDRC_BUSCTL ... (MUSB_HDRC_BUSCTL + 0x7f):
-        ep = (addr >> 3) & 0xf;
-        return musb_busctl_readb(s, ep, addr & 0x7);
-
-    case MUSB_HDRC_EP ... (MUSB_HDRC_EP + 0xff):
-        ep = (addr >> 4) & 0xf;
-        return musb_ep_readb(s, ep, addr & 0xf);
-
-    case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
-        ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
-        return musb_read_fifo(s->ep + ep);
-
-    default:
-        TRACE("unknown register 0x%02x", (int) addr);
-        return 0x00;
-    };
-}
-
-static void musb_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
-{
-    MUSBState *s = (MUSBState *) opaque;
-    int ep;
-
-    switch (addr) {
-    case MUSB_HDRC_FADDR:
-        s->faddr = value & 0x7f;
-        break;
-    case MUSB_HDRC_POWER:
-        s->power = (value & 0xef) | (s->power & 0x10);
-        /* MGC_M_POWER_RESET is also read-only in Peripheral Mode */
-        if ((value & MGC_M_POWER_RESET) && s->port.dev) {
-            usb_device_reset(s->port.dev);
-            /* Negotiate high-speed operation if MGC_M_POWER_HSENAB is set.  */
-            if ((value & MGC_M_POWER_HSENAB) &&
-                            s->port.dev->speed == USB_SPEED_HIGH)
-                s->power |= MGC_M_POWER_HSMODE;	/* Success */
-            /* Restart frame counting.  */
-        }
-        if (value & MGC_M_POWER_SUSPENDM) {
-            /* When all transfers finish, suspend and if MGC_M_POWER_ENSUSPEND
-             * is set, also go into low power mode.  Frame counting stops.  */
-            /* XXX: Cleared when the interrupt register is read */
-        }
-        if (value & MGC_M_POWER_RESUME) {
-            /* Wait 20ms and signal resuming on the bus.  Frame counting
-             * restarts.  */
-        }
-        break;
-    case MUSB_HDRC_INTRUSB:
-        break;
-    case MUSB_HDRC_INTRUSBE:
-        s->mask = value & 0xff;
-        break;
-    case MUSB_HDRC_INDEX:
-        s->idx = value & 0xf;
-        break;
-    case MUSB_HDRC_TESTMODE:
-        break;
-
-    case MUSB_HDRC_EP_IDX ... (MUSB_HDRC_EP_IDX + 0xf):
-        musb_ep_writeb(s, s->idx, addr & 0xf, value);
-        break;
-
-    case MUSB_HDRC_DEVCTL:
-        s->session = !!(value & MGC_M_DEVCTL_SESSION);
-        musb_session_update(s,
-                        !!s->port.dev,
-                        !!(s->devctl & MGC_M_DEVCTL_SESSION));
-
-        /* It seems this is the only R/W bit in this register?  */
-        s->devctl &= ~MGC_M_DEVCTL_SESSION;
-        s->devctl |= value & MGC_M_DEVCTL_SESSION;
-        break;
-
-    case MUSB_HDRC_TXFIFOSZ:
-    case MUSB_HDRC_RXFIFOSZ:
-    case MUSB_HDRC_VCTRL:
-        /* TODO */
-        break;
-
-    case (MUSB_HDRC_VCTRL | 1):
-    case (MUSB_HDRC_DEVCTL | 1):
-        break;
-
-    case MUSB_HDRC_BUSCTL ... (MUSB_HDRC_BUSCTL + 0x7f):
-        ep = (addr >> 3) & 0xf;
-        musb_busctl_writeb(s, ep, addr & 0x7, value);
-        break;
-
-    case MUSB_HDRC_EP ... (MUSB_HDRC_EP + 0xff):
-        ep = (addr >> 4) & 0xf;
-        musb_ep_writeb(s, ep, addr & 0xf, value);
-        break;
-
-    case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
-        ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
-        musb_write_fifo(s->ep + ep, value & 0xff);
-        break;
-
-    default:
-        TRACE("unknown register 0x%02x", (int) addr);
-        break;
-    };
-}
-
-static uint32_t musb_readh(void *opaque, target_phys_addr_t addr)
-{
-    MUSBState *s = (MUSBState *) opaque;
-    int ep, i;
-    uint16_t ret;
-
-    switch (addr) {
-    case MUSB_HDRC_INTRTX:
-        ret = s->tx_intr;
-        /* Auto clear */
-        for (i = 0; i < sizeof(ret) * 8; i ++)
-            if (ret & (1 << i))
-                musb_tx_intr_set(s, i, 0);
-        return ret;
-    case MUSB_HDRC_INTRRX:
-        ret = s->rx_intr;
-        /* Auto clear */
-        for (i = 0; i < sizeof(ret) * 8; i ++)
-            if (ret & (1 << i))
-                musb_rx_intr_set(s, i, 0);
-        return ret;
-    case MUSB_HDRC_INTRTXE:
-        return s->tx_mask;
-    case MUSB_HDRC_INTRRXE:
-        return s->rx_mask;
-
-    case MUSB_HDRC_FRAME:
-        /* TODO */
-        return 0x0000;
-    case MUSB_HDRC_TXFIFOADDR:
-        return s->ep[s->idx].fifoaddr[0];
-    case MUSB_HDRC_RXFIFOADDR:
-        return s->ep[s->idx].fifoaddr[1];
-
-    case MUSB_HDRC_EP_IDX ... (MUSB_HDRC_EP_IDX + 0xf):
-        return musb_ep_readh(s, s->idx, addr & 0xf);
-
-    case MUSB_HDRC_BUSCTL ... (MUSB_HDRC_BUSCTL + 0x7f):
-        ep = (addr >> 3) & 0xf;
-        return musb_busctl_readh(s, ep, addr & 0x7);
-
-    case MUSB_HDRC_EP ... (MUSB_HDRC_EP + 0xff):
-        ep = (addr >> 4) & 0xf;
-        return musb_ep_readh(s, ep, addr & 0xf);
-
-    case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
-        ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
-        return (musb_read_fifo(s->ep + ep) | musb_read_fifo(s->ep + ep) << 8);
-
-    default:
-        return musb_readb(s, addr) | (musb_readb(s, addr | 1) << 8);
-    };
-}
-
-static void musb_writeh(void *opaque, target_phys_addr_t addr, uint32_t value)
-{
-    MUSBState *s = (MUSBState *) opaque;
-    int ep;
-
-    switch (addr) {
-    case MUSB_HDRC_INTRTXE:
-        s->tx_mask = value;
-        /* XXX: the masks seem to apply on the raising edge like with
-         * edge-triggered interrupts, thus no need to update.  I may be
-         * wrong though.  */
-        break;
-    case MUSB_HDRC_INTRRXE:
-        s->rx_mask = value;
-        break;
-
-    case MUSB_HDRC_FRAME:
-        /* TODO */
-        break;
-    case MUSB_HDRC_TXFIFOADDR:
-        s->ep[s->idx].fifoaddr[0] = value;
-        s->ep[s->idx].buf[0] =
-                s->buf + ((value << 3) & 0x7ff );
-        break;
-    case MUSB_HDRC_RXFIFOADDR:
-        s->ep[s->idx].fifoaddr[1] = value;
-        s->ep[s->idx].buf[1] =
-                s->buf + ((value << 3) & 0x7ff);
-        break;
-
-    case MUSB_HDRC_EP_IDX ... (MUSB_HDRC_EP_IDX + 0xf):
-        musb_ep_writeh(s, s->idx, addr & 0xf, value);
-        break;
-
-    case MUSB_HDRC_BUSCTL ... (MUSB_HDRC_BUSCTL + 0x7f):
-        ep = (addr >> 3) & 0xf;
-        musb_busctl_writeh(s, ep, addr & 0x7, value);
-        break;
-
-    case MUSB_HDRC_EP ... (MUSB_HDRC_EP + 0xff):
-        ep = (addr >> 4) & 0xf;
-        musb_ep_writeh(s, ep, addr & 0xf, value);
-        break;
-
-    case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
-        ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
-        musb_write_fifo(s->ep + ep, value & 0xff);
-        musb_write_fifo(s->ep + ep, (value >> 8) & 0xff);
-        break;
-
-    default:
-        musb_writeb(s, addr, value & 0xff);
-        musb_writeb(s, addr | 1, value >> 8);
-    };
-}
-
-static uint32_t musb_readw(void *opaque, target_phys_addr_t addr)
-{
-    MUSBState *s = (MUSBState *) opaque;
-    int ep;
-
-    switch (addr) {
-    case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
-        ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
-        return ( musb_read_fifo(s->ep + ep)       |
-                 musb_read_fifo(s->ep + ep) << 8  |
-                 musb_read_fifo(s->ep + ep) << 16 |
-                 musb_read_fifo(s->ep + ep) << 24 );
-    default:
-        TRACE("unknown register 0x%02x", (int) addr);
-        return 0x00000000;
-    };
-}
-
-static void musb_writew(void *opaque, target_phys_addr_t addr, uint32_t value)
-{
-    MUSBState *s = (MUSBState *) opaque;
-    int ep;
-
-    switch (addr) {
-    case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
-        ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
-        musb_write_fifo(s->ep + ep, value & 0xff);
-        musb_write_fifo(s->ep + ep, (value >> 8 ) & 0xff);
-        musb_write_fifo(s->ep + ep, (value >> 16) & 0xff);
-        musb_write_fifo(s->ep + ep, (value >> 24) & 0xff);
-            break;
-    default:
-        TRACE("unknown register 0x%02x", (int) addr);
-        break;
-    };
-}
-
-CPUReadMemoryFunc * const musb_read[] = {
-    musb_readb,
-    musb_readh,
-    musb_readw,
-};
-
-CPUWriteMemoryFunc * const musb_write[] = {
-    musb_writeb,
-    musb_writeh,
-    musb_writew,
-};
diff --git a/hw/usb-net.c b/hw/usb-net.c
deleted file mode 100644
index 22b8201..0000000
--- a/hw/usb-net.c
+++ /dev/null
@@ -1,1423 +0,0 @@
-/*
- * QEMU USB Net devices
- *
- * Copyright (c) 2006 Thomas Sailer
- * Copyright (c) 2008 Andrzej Zaborowski
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "qemu-common.h"
-#include "usb.h"
-#include "usb-desc.h"
-#include "net.h"
-#include "qemu-queue.h"
-#include "sysemu.h"
-#include "iov.h"
-
-/*#define TRAFFIC_DEBUG*/
-/* Thanks to NetChip Technologies for donating this product ID.
- * It's for devices with only CDC Ethernet configurations.
- */
-#define CDC_VENDOR_NUM          0x0525  /* NetChip */
-#define CDC_PRODUCT_NUM         0xa4a1  /* Linux-USB Ethernet Gadget */
-/* For hardware that can talk RNDIS and either of the above protocols,
- * use this ID ... the windows INF files will know it.
- */
-#define RNDIS_VENDOR_NUM        0x0525  /* NetChip */
-#define RNDIS_PRODUCT_NUM       0xa4a2  /* Ethernet/RNDIS Gadget */
-
-enum usbstring_idx {
-    STRING_MANUFACTURER		= 1,
-    STRING_PRODUCT,
-    STRING_ETHADDR,
-    STRING_DATA,
-    STRING_CONTROL,
-    STRING_RNDIS_CONTROL,
-    STRING_CDC,
-    STRING_SUBSET,
-    STRING_RNDIS,
-    STRING_SERIALNUMBER,
-};
-
-#define DEV_CONFIG_VALUE		1	/* CDC or a subset */
-#define DEV_RNDIS_CONFIG_VALUE		2	/* RNDIS; optional */
-
-#define USB_CDC_SUBCLASS_ACM		0x02
-#define USB_CDC_SUBCLASS_ETHERNET	0x06
-
-#define USB_CDC_PROTO_NONE		0
-#define USB_CDC_ACM_PROTO_VENDOR	0xff
-
-#define USB_CDC_HEADER_TYPE		0x00	/* header_desc */
-#define USB_CDC_CALL_MANAGEMENT_TYPE	0x01	/* call_mgmt_descriptor */
-#define USB_CDC_ACM_TYPE		0x02	/* acm_descriptor */
-#define USB_CDC_UNION_TYPE		0x06	/* union_desc */
-#define USB_CDC_ETHERNET_TYPE		0x0f	/* ether_desc */
-
-#define USB_CDC_SEND_ENCAPSULATED_COMMAND	0x00
-#define USB_CDC_GET_ENCAPSULATED_RESPONSE	0x01
-#define USB_CDC_REQ_SET_LINE_CODING		0x20
-#define USB_CDC_REQ_GET_LINE_CODING		0x21
-#define USB_CDC_REQ_SET_CONTROL_LINE_STATE	0x22
-#define USB_CDC_REQ_SEND_BREAK			0x23
-#define USB_CDC_SET_ETHERNET_MULTICAST_FILTERS	0x40
-#define USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER	0x41
-#define USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER	0x42
-#define USB_CDC_SET_ETHERNET_PACKET_FILTER	0x43
-#define USB_CDC_GET_ETHERNET_STATISTIC		0x44
-
-#define LOG2_STATUS_INTERVAL_MSEC	5    /* 1 << 5 == 32 msec */
-#define STATUS_BYTECOUNT		16   /* 8 byte header + data */
-
-#define ETH_FRAME_LEN			1514 /* Max. octets in frame sans FCS */
-
-static const USBDescStrings usb_net_stringtable = {
-    [STRING_MANUFACTURER]       = "QEMU",
-    [STRING_PRODUCT]            = "RNDIS/QEMU USB Network Device",
-    [STRING_ETHADDR]            = "400102030405",
-    [STRING_DATA]               = "QEMU USB Net Data Interface",
-    [STRING_CONTROL]            = "QEMU USB Net Control Interface",
-    [STRING_RNDIS_CONTROL]      = "QEMU USB Net RNDIS Control Interface",
-    [STRING_CDC]                = "QEMU USB Net CDC",
-    [STRING_SUBSET]             = "QEMU USB Net Subset",
-    [STRING_RNDIS]              = "QEMU USB Net RNDIS",
-    [STRING_SERIALNUMBER]       = "1",
-};
-
-static const USBDescIface desc_iface_rndis[] = {
-    {
-        /* RNDIS Control Interface */
-        .bInterfaceNumber              = 0,
-        .bNumEndpoints                 = 1,
-        .bInterfaceClass               = USB_CLASS_COMM,
-        .bInterfaceSubClass            = USB_CDC_SUBCLASS_ACM,
-        .bInterfaceProtocol            = USB_CDC_ACM_PROTO_VENDOR,
-        .iInterface                    = STRING_RNDIS_CONTROL,
-        .ndesc                         = 4,
-        .descs = (USBDescOther[]) {
-            {
-                /* Header Descriptor */
-                .data = (uint8_t[]) {
-                    0x05,                       /*  u8    bLength */
-                    USB_DT_CS_INTERFACE,        /*  u8    bDescriptorType */
-                    USB_CDC_HEADER_TYPE,        /*  u8    bDescriptorSubType */
-                    0x10, 0x01,                 /*  le16  bcdCDC */
-                },
-            },{
-                /* Call Management Descriptor */
-                .data = (uint8_t[]) {
-                    0x05,                       /*  u8    bLength */
-                    USB_DT_CS_INTERFACE,        /*  u8    bDescriptorType */
-                    USB_CDC_CALL_MANAGEMENT_TYPE, /*  u8    bDescriptorSubType */
-                    0x00,                       /*  u8    bmCapabilities */
-                    0x01,                       /*  u8    bDataInterface */
-                },
-            },{
-                /* ACM Descriptor */
-                .data = (uint8_t[]) {
-                    0x04,                       /*  u8    bLength */
-                    USB_DT_CS_INTERFACE,        /*  u8    bDescriptorType */
-                    USB_CDC_ACM_TYPE,           /*  u8    bDescriptorSubType */
-                    0x00,                       /*  u8    bmCapabilities */
-                },
-            },{
-                /* Union Descriptor */
-                .data = (uint8_t[]) {
-                    0x05,                       /*  u8    bLength */
-                    USB_DT_CS_INTERFACE,        /*  u8    bDescriptorType */
-                    USB_CDC_UNION_TYPE,         /*  u8    bDescriptorSubType */
-                    0x00,                       /*  u8    bMasterInterface0 */
-                    0x01,                       /*  u8    bSlaveInterface0 */
-                },
-            },
-        },
-        .eps = (USBDescEndpoint[]) {
-            {
-                .bEndpointAddress      = USB_DIR_IN | 0x01,
-                .bmAttributes          = USB_ENDPOINT_XFER_INT,
-                .wMaxPacketSize        = STATUS_BYTECOUNT,
-                .bInterval             = 1 << LOG2_STATUS_INTERVAL_MSEC,
-            },
-        }
-    },{
-        /* RNDIS Data Interface */
-        .bInterfaceNumber              = 1,
-        .bNumEndpoints                 = 2,
-        .bInterfaceClass               = USB_CLASS_CDC_DATA,
-        .iInterface                    = STRING_DATA,
-        .eps = (USBDescEndpoint[]) {
-            {
-                .bEndpointAddress      = USB_DIR_IN | 0x02,
-                .bmAttributes          = USB_ENDPOINT_XFER_BULK,
-                .wMaxPacketSize        = 0x40,
-            },{
-                .bEndpointAddress      = USB_DIR_OUT | 0x02,
-                .bmAttributes          = USB_ENDPOINT_XFER_BULK,
-                .wMaxPacketSize        = 0x40,
-            }
-        }
-    }
-};
-
-static const USBDescIface desc_iface_cdc[] = {
-    {
-        /* CDC Control Interface */
-        .bInterfaceNumber              = 0,
-        .bNumEndpoints                 = 1,
-        .bInterfaceClass               = USB_CLASS_COMM,
-        .bInterfaceSubClass            = USB_CDC_SUBCLASS_ETHERNET,
-        .bInterfaceProtocol            = USB_CDC_PROTO_NONE,
-        .iInterface                    = STRING_CONTROL,
-        .ndesc                         = 3,
-        .descs = (USBDescOther[]) {
-            {
-                /* Header Descriptor */
-                .data = (uint8_t[]) {
-                    0x05,                       /*  u8    bLength */
-                    USB_DT_CS_INTERFACE,        /*  u8    bDescriptorType */
-                    USB_CDC_HEADER_TYPE,        /*  u8    bDescriptorSubType */
-                    0x10, 0x01,                 /*  le16  bcdCDC */
-                },
-            },{
-                /* Union Descriptor */
-                .data = (uint8_t[]) {
-                    0x05,                       /*  u8    bLength */
-                    USB_DT_CS_INTERFACE,        /*  u8    bDescriptorType */
-                    USB_CDC_UNION_TYPE,         /*  u8    bDescriptorSubType */
-                    0x00,                       /*  u8    bMasterInterface0 */
-                    0x01,                       /*  u8    bSlaveInterface0 */
-                },
-            },{
-                /* Ethernet Descriptor */
-                .data = (uint8_t[]) {
-                    0x0d,                       /*  u8    bLength */
-                    USB_DT_CS_INTERFACE,        /*  u8    bDescriptorType */
-                    USB_CDC_ETHERNET_TYPE,      /*  u8    bDescriptorSubType */
-                    STRING_ETHADDR,             /*  u8    iMACAddress */
-                    0x00, 0x00, 0x00, 0x00,     /*  le32  bmEthernetStatistics */
-                    ETH_FRAME_LEN & 0xff,
-                    ETH_FRAME_LEN >> 8,         /*  le16  wMaxSegmentSize */
-                    0x00, 0x00,                 /*  le16  wNumberMCFilters */
-                    0x00,                       /*  u8    bNumberPowerFilters */
-                },
-            },
-        },
-        .eps = (USBDescEndpoint[]) {
-            {
-                .bEndpointAddress      = USB_DIR_IN | 0x01,
-                .bmAttributes          = USB_ENDPOINT_XFER_INT,
-                .wMaxPacketSize        = STATUS_BYTECOUNT,
-                .bInterval             = 1 << LOG2_STATUS_INTERVAL_MSEC,
-            },
-        }
-    },{
-        /* CDC Data Interface (off) */
-        .bInterfaceNumber              = 1,
-        .bAlternateSetting             = 0,
-        .bNumEndpoints                 = 0,
-        .bInterfaceClass               = USB_CLASS_CDC_DATA,
-    },{
-        /* CDC Data Interface */
-        .bInterfaceNumber              = 1,
-        .bAlternateSetting             = 1,
-        .bNumEndpoints                 = 2,
-        .bInterfaceClass               = USB_CLASS_CDC_DATA,
-        .iInterface                    = STRING_DATA,
-        .eps = (USBDescEndpoint[]) {
-            {
-                .bEndpointAddress      = USB_DIR_IN | 0x02,
-                .bmAttributes          = USB_ENDPOINT_XFER_BULK,
-                .wMaxPacketSize        = 0x40,
-            },{
-                .bEndpointAddress      = USB_DIR_OUT | 0x02,
-                .bmAttributes          = USB_ENDPOINT_XFER_BULK,
-                .wMaxPacketSize        = 0x40,
-            }
-        }
-    }
-};
-
-static const USBDescDevice desc_device_net = {
-    .bcdUSB                        = 0x0200,
-    .bDeviceClass                  = USB_CLASS_COMM,
-    .bMaxPacketSize0               = 0x40,
-    .bNumConfigurations            = 2,
-    .confs = (USBDescConfig[]) {
-        {
-            .bNumInterfaces        = 2,
-            .bConfigurationValue   = DEV_RNDIS_CONFIG_VALUE,
-            .iConfiguration        = STRING_RNDIS,
-            .bmAttributes          = 0xc0,
-            .bMaxPower             = 0x32,
-            .nif = ARRAY_SIZE(desc_iface_rndis),
-            .ifs = desc_iface_rndis,
-        },{
-            .bNumInterfaces        = 2,
-            .bConfigurationValue   = DEV_CONFIG_VALUE,
-            .iConfiguration        = STRING_CDC,
-            .bmAttributes          = 0xc0,
-            .bMaxPower             = 0x32,
-            .nif = ARRAY_SIZE(desc_iface_cdc),
-            .ifs = desc_iface_cdc,
-        }
-    },
-};
-
-static const USBDesc desc_net = {
-    .id = {
-        .idVendor          = RNDIS_VENDOR_NUM,
-        .idProduct         = RNDIS_PRODUCT_NUM,
-        .bcdDevice         = 0,
-        .iManufacturer     = STRING_MANUFACTURER,
-        .iProduct          = STRING_PRODUCT,
-        .iSerialNumber     = STRING_SERIALNUMBER,
-    },
-    .full = &desc_device_net,
-    .str  = usb_net_stringtable,
-};
-
-/*
- * RNDIS Definitions - in theory not specific to USB.
- */
-#define RNDIS_MAXIMUM_FRAME_SIZE	1518
-#define RNDIS_MAX_TOTAL_SIZE		1558
-
-/* Remote NDIS Versions */
-#define RNDIS_MAJOR_VERSION		1
-#define RNDIS_MINOR_VERSION		0
-
-/* Status Values */
-#define RNDIS_STATUS_SUCCESS		0x00000000U /* Success */
-#define RNDIS_STATUS_FAILURE		0xc0000001U /* Unspecified error */
-#define RNDIS_STATUS_INVALID_DATA	0xc0010015U /* Invalid data */
-#define RNDIS_STATUS_NOT_SUPPORTED	0xc00000bbU /* Unsupported request */
-#define RNDIS_STATUS_MEDIA_CONNECT	0x4001000bU /* Device connected */
-#define RNDIS_STATUS_MEDIA_DISCONNECT	0x4001000cU /* Device disconnected */
-
-/* Message Set for Connectionless (802.3) Devices */
-enum {
-    RNDIS_PACKET_MSG		= 1,
-    RNDIS_INITIALIZE_MSG	= 2,	/* Initialize device */
-    RNDIS_HALT_MSG		= 3,
-    RNDIS_QUERY_MSG		= 4,
-    RNDIS_SET_MSG		= 5,
-    RNDIS_RESET_MSG		= 6,
-    RNDIS_INDICATE_STATUS_MSG	= 7,
-    RNDIS_KEEPALIVE_MSG		= 8,
-};
-
-/* Message completion */
-enum {
-    RNDIS_INITIALIZE_CMPLT	= 0x80000002U,
-    RNDIS_QUERY_CMPLT		= 0x80000004U,
-    RNDIS_SET_CMPLT		= 0x80000005U,
-    RNDIS_RESET_CMPLT		= 0x80000006U,
-    RNDIS_KEEPALIVE_CMPLT	= 0x80000008U,
-};
-
-/* Device Flags */
-enum {
-    RNDIS_DF_CONNECTIONLESS	= 1,
-    RNDIS_DF_CONNECTIONORIENTED	= 2,
-};
-
-#define RNDIS_MEDIUM_802_3		0x00000000U
-
-/* from drivers/net/sk98lin/h/skgepnmi.h */
-#define OID_PNP_CAPABILITIES		0xfd010100
-#define OID_PNP_SET_POWER		0xfd010101
-#define OID_PNP_QUERY_POWER		0xfd010102
-#define OID_PNP_ADD_WAKE_UP_PATTERN	0xfd010103
-#define OID_PNP_REMOVE_WAKE_UP_PATTERN	0xfd010104
-#define OID_PNP_ENABLE_WAKE_UP		0xfd010106
-
-typedef uint32_t le32;
-
-typedef struct rndis_init_msg_type {
-    le32 MessageType;
-    le32 MessageLength;
-    le32 RequestID;
-    le32 MajorVersion;
-    le32 MinorVersion;
-    le32 MaxTransferSize;
-} rndis_init_msg_type;
-
-typedef struct rndis_init_cmplt_type {
-    le32 MessageType;
-    le32 MessageLength;
-    le32 RequestID;
-    le32 Status;
-    le32 MajorVersion;
-    le32 MinorVersion;
-    le32 DeviceFlags;
-    le32 Medium;
-    le32 MaxPacketsPerTransfer;
-    le32 MaxTransferSize;
-    le32 PacketAlignmentFactor;
-    le32 AFListOffset;
-    le32 AFListSize;
-} rndis_init_cmplt_type;
-
-typedef struct rndis_halt_msg_type {
-    le32 MessageType;
-    le32 MessageLength;
-    le32 RequestID;
-} rndis_halt_msg_type;
-
-typedef struct rndis_query_msg_type {
-    le32 MessageType;
-    le32 MessageLength;
-    le32 RequestID;
-    le32 OID;
-    le32 InformationBufferLength;
-    le32 InformationBufferOffset;
-    le32 DeviceVcHandle;
-} rndis_query_msg_type;
-
-typedef struct rndis_query_cmplt_type {
-    le32 MessageType;
-    le32 MessageLength;
-    le32 RequestID;
-    le32 Status;
-    le32 InformationBufferLength;
-    le32 InformationBufferOffset;
-} rndis_query_cmplt_type;
-
-typedef struct rndis_set_msg_type {
-    le32 MessageType;
-    le32 MessageLength;
-    le32 RequestID;
-    le32 OID;
-    le32 InformationBufferLength;
-    le32 InformationBufferOffset;
-    le32 DeviceVcHandle;
-} rndis_set_msg_type;
-
-typedef struct rndis_set_cmplt_type {
-    le32 MessageType;
-    le32 MessageLength;
-    le32 RequestID;
-    le32 Status;
-} rndis_set_cmplt_type;
-
-typedef struct rndis_reset_msg_type {
-    le32 MessageType;
-    le32 MessageLength;
-    le32 Reserved;
-} rndis_reset_msg_type;
-
-typedef struct rndis_reset_cmplt_type {
-    le32 MessageType;
-    le32 MessageLength;
-    le32 Status;
-    le32 AddressingReset;
-} rndis_reset_cmplt_type;
-
-typedef struct rndis_indicate_status_msg_type {
-    le32 MessageType;
-    le32 MessageLength;
-    le32 Status;
-    le32 StatusBufferLength;
-    le32 StatusBufferOffset;
-} rndis_indicate_status_msg_type;
-
-typedef struct rndis_keepalive_msg_type {
-    le32 MessageType;
-    le32 MessageLength;
-    le32 RequestID;
-} rndis_keepalive_msg_type;
-
-typedef struct rndis_keepalive_cmplt_type {
-    le32 MessageType;
-    le32 MessageLength;
-    le32 RequestID;
-    le32 Status;
-} rndis_keepalive_cmplt_type;
-
-struct rndis_packet_msg_type {
-    le32 MessageType;
-    le32 MessageLength;
-    le32 DataOffset;
-    le32 DataLength;
-    le32 OOBDataOffset;
-    le32 OOBDataLength;
-    le32 NumOOBDataElements;
-    le32 PerPacketInfoOffset;
-    le32 PerPacketInfoLength;
-    le32 VcHandle;
-    le32 Reserved;
-};
-
-struct rndis_config_parameter {
-    le32 ParameterNameOffset;
-    le32 ParameterNameLength;
-    le32 ParameterType;
-    le32 ParameterValueOffset;
-    le32 ParameterValueLength;
-};
-
-/* implementation specific */
-enum rndis_state
-{
-    RNDIS_UNINITIALIZED,
-    RNDIS_INITIALIZED,
-    RNDIS_DATA_INITIALIZED,
-};
-
-/* from ndis.h */
-enum ndis_oid {
-    /* Required Object IDs (OIDs) */
-    OID_GEN_SUPPORTED_LIST		= 0x00010101,
-    OID_GEN_HARDWARE_STATUS		= 0x00010102,
-    OID_GEN_MEDIA_SUPPORTED		= 0x00010103,
-    OID_GEN_MEDIA_IN_USE		= 0x00010104,
-    OID_GEN_MAXIMUM_LOOKAHEAD		= 0x00010105,
-    OID_GEN_MAXIMUM_FRAME_SIZE		= 0x00010106,
-    OID_GEN_LINK_SPEED			= 0x00010107,
-    OID_GEN_TRANSMIT_BUFFER_SPACE	= 0x00010108,
-    OID_GEN_RECEIVE_BUFFER_SPACE	= 0x00010109,
-    OID_GEN_TRANSMIT_BLOCK_SIZE		= 0x0001010a,
-    OID_GEN_RECEIVE_BLOCK_SIZE		= 0x0001010b,
-    OID_GEN_VENDOR_ID			= 0x0001010c,
-    OID_GEN_VENDOR_DESCRIPTION		= 0x0001010d,
-    OID_GEN_CURRENT_PACKET_FILTER	= 0x0001010e,
-    OID_GEN_CURRENT_LOOKAHEAD		= 0x0001010f,
-    OID_GEN_DRIVER_VERSION		= 0x00010110,
-    OID_GEN_MAXIMUM_TOTAL_SIZE		= 0x00010111,
-    OID_GEN_PROTOCOL_OPTIONS		= 0x00010112,
-    OID_GEN_MAC_OPTIONS			= 0x00010113,
-    OID_GEN_MEDIA_CONNECT_STATUS	= 0x00010114,
-    OID_GEN_MAXIMUM_SEND_PACKETS	= 0x00010115,
-    OID_GEN_VENDOR_DRIVER_VERSION	= 0x00010116,
-    OID_GEN_SUPPORTED_GUIDS		= 0x00010117,
-    OID_GEN_NETWORK_LAYER_ADDRESSES	= 0x00010118,
-    OID_GEN_TRANSPORT_HEADER_OFFSET	= 0x00010119,
-    OID_GEN_MACHINE_NAME		= 0x0001021a,
-    OID_GEN_RNDIS_CONFIG_PARAMETER	= 0x0001021b,
-    OID_GEN_VLAN_ID			= 0x0001021c,
-
-    /* Optional OIDs */
-    OID_GEN_MEDIA_CAPABILITIES		= 0x00010201,
-    OID_GEN_PHYSICAL_MEDIUM		= 0x00010202,
-
-    /* Required statistics OIDs */
-    OID_GEN_XMIT_OK			= 0x00020101,
-    OID_GEN_RCV_OK			= 0x00020102,
-    OID_GEN_XMIT_ERROR			= 0x00020103,
-    OID_GEN_RCV_ERROR			= 0x00020104,
-    OID_GEN_RCV_NO_BUFFER		= 0x00020105,
-
-    /* Optional statistics OIDs */
-    OID_GEN_DIRECTED_BYTES_XMIT		= 0x00020201,
-    OID_GEN_DIRECTED_FRAMES_XMIT	= 0x00020202,
-    OID_GEN_MULTICAST_BYTES_XMIT	= 0x00020203,
-    OID_GEN_MULTICAST_FRAMES_XMIT	= 0x00020204,
-    OID_GEN_BROADCAST_BYTES_XMIT	= 0x00020205,
-    OID_GEN_BROADCAST_FRAMES_XMIT	= 0x00020206,
-    OID_GEN_DIRECTED_BYTES_RCV		= 0x00020207,
-    OID_GEN_DIRECTED_FRAMES_RCV		= 0x00020208,
-    OID_GEN_MULTICAST_BYTES_RCV		= 0x00020209,
-    OID_GEN_MULTICAST_FRAMES_RCV	= 0x0002020a,
-    OID_GEN_BROADCAST_BYTES_RCV		= 0x0002020b,
-    OID_GEN_BROADCAST_FRAMES_RCV	= 0x0002020c,
-    OID_GEN_RCV_CRC_ERROR		= 0x0002020d,
-    OID_GEN_TRANSMIT_QUEUE_LENGTH	= 0x0002020e,
-    OID_GEN_GET_TIME_CAPS		= 0x0002020f,
-    OID_GEN_GET_NETCARD_TIME		= 0x00020210,
-    OID_GEN_NETCARD_LOAD		= 0x00020211,
-    OID_GEN_DEVICE_PROFILE		= 0x00020212,
-    OID_GEN_INIT_TIME_MS		= 0x00020213,
-    OID_GEN_RESET_COUNTS		= 0x00020214,
-    OID_GEN_MEDIA_SENSE_COUNTS		= 0x00020215,
-    OID_GEN_FRIENDLY_NAME		= 0x00020216,
-    OID_GEN_MINIPORT_INFO		= 0x00020217,
-    OID_GEN_RESET_VERIFY_PARAMETERS	= 0x00020218,
-
-    /* IEEE 802.3 (Ethernet) OIDs */
-    OID_802_3_PERMANENT_ADDRESS		= 0x01010101,
-    OID_802_3_CURRENT_ADDRESS		= 0x01010102,
-    OID_802_3_MULTICAST_LIST		= 0x01010103,
-    OID_802_3_MAXIMUM_LIST_SIZE		= 0x01010104,
-    OID_802_3_MAC_OPTIONS		= 0x01010105,
-    OID_802_3_RCV_ERROR_ALIGNMENT	= 0x01020101,
-    OID_802_3_XMIT_ONE_COLLISION	= 0x01020102,
-    OID_802_3_XMIT_MORE_COLLISIONS	= 0x01020103,
-    OID_802_3_XMIT_DEFERRED		= 0x01020201,
-    OID_802_3_XMIT_MAX_COLLISIONS	= 0x01020202,
-    OID_802_3_RCV_OVERRUN		= 0x01020203,
-    OID_802_3_XMIT_UNDERRUN		= 0x01020204,
-    OID_802_3_XMIT_HEARTBEAT_FAILURE	= 0x01020205,
-    OID_802_3_XMIT_TIMES_CRS_LOST	= 0x01020206,
-    OID_802_3_XMIT_LATE_COLLISIONS	= 0x01020207,
-};
-
-static const uint32_t oid_supported_list[] =
-{
-    /* the general stuff */
-    OID_GEN_SUPPORTED_LIST,
-    OID_GEN_HARDWARE_STATUS,
-    OID_GEN_MEDIA_SUPPORTED,
-    OID_GEN_MEDIA_IN_USE,
-    OID_GEN_MAXIMUM_FRAME_SIZE,
-    OID_GEN_LINK_SPEED,
-    OID_GEN_TRANSMIT_BLOCK_SIZE,
-    OID_GEN_RECEIVE_BLOCK_SIZE,
-    OID_GEN_VENDOR_ID,
-    OID_GEN_VENDOR_DESCRIPTION,
-    OID_GEN_VENDOR_DRIVER_VERSION,
-    OID_GEN_CURRENT_PACKET_FILTER,
-    OID_GEN_MAXIMUM_TOTAL_SIZE,
-    OID_GEN_MEDIA_CONNECT_STATUS,
-    OID_GEN_PHYSICAL_MEDIUM,
-
-    /* the statistical stuff */
-    OID_GEN_XMIT_OK,
-    OID_GEN_RCV_OK,
-    OID_GEN_XMIT_ERROR,
-    OID_GEN_RCV_ERROR,
-    OID_GEN_RCV_NO_BUFFER,
-
-    /* IEEE 802.3 */
-    /* the general stuff */
-    OID_802_3_PERMANENT_ADDRESS,
-    OID_802_3_CURRENT_ADDRESS,
-    OID_802_3_MULTICAST_LIST,
-    OID_802_3_MAC_OPTIONS,
-    OID_802_3_MAXIMUM_LIST_SIZE,
-
-    /* the statistical stuff */
-    OID_802_3_RCV_ERROR_ALIGNMENT,
-    OID_802_3_XMIT_ONE_COLLISION,
-    OID_802_3_XMIT_MORE_COLLISIONS,
-};
-
-#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA	(1 << 0)
-#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED	(1 << 1)
-#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND	(1 << 2)
-#define NDIS_MAC_OPTION_NO_LOOPBACK		(1 << 3)
-#define NDIS_MAC_OPTION_FULL_DUPLEX		(1 << 4)
-#define NDIS_MAC_OPTION_EOTX_INDICATION		(1 << 5)
-#define NDIS_MAC_OPTION_8021P_PRIORITY		(1 << 6)
-
-struct rndis_response {
-    QTAILQ_ENTRY(rndis_response) entries;
-    uint32_t length;
-    uint8_t buf[0];
-};
-
-typedef struct USBNetState {
-    USBDevice dev;
-
-    enum rndis_state rndis_state;
-    uint32_t medium;
-    uint32_t speed;
-    uint32_t media_state;
-    uint16_t filter;
-    uint32_t vendorid;
-
-    unsigned int out_ptr;
-    uint8_t out_buf[2048];
-
-    USBPacket *inpkt;
-    unsigned int in_ptr, in_len;
-    uint8_t in_buf[2048];
-
-    char usbstring_mac[13];
-    NICState *nic;
-    NICConf conf;
-    QTAILQ_HEAD(rndis_resp_head, rndis_response) rndis_resp;
-} USBNetState;
-
-static int is_rndis(USBNetState *s)
-{
-    return s->dev.config->bConfigurationValue == DEV_RNDIS_CONFIG_VALUE;
-}
-
-static int ndis_query(USBNetState *s, uint32_t oid,
-                      uint8_t *inbuf, unsigned int inlen, uint8_t *outbuf,
-                      size_t outlen)
-{
-    unsigned int i;
-
-    switch (oid) {
-    /* general oids (table 4-1) */
-    /* mandatory */
-    case OID_GEN_SUPPORTED_LIST:
-        for (i = 0; i < ARRAY_SIZE(oid_supported_list); i++)
-            ((le32 *) outbuf)[i] = cpu_to_le32(oid_supported_list[i]);
-        return sizeof(oid_supported_list);
-
-    /* mandatory */
-    case OID_GEN_HARDWARE_STATUS:
-        *((le32 *) outbuf) = cpu_to_le32(0);
-        return sizeof(le32);
-
-    /* mandatory */
-    case OID_GEN_MEDIA_SUPPORTED:
-        *((le32 *) outbuf) = cpu_to_le32(s->medium);
-        return sizeof(le32);
-
-    /* mandatory */
-    case OID_GEN_MEDIA_IN_USE:
-        *((le32 *) outbuf) = cpu_to_le32(s->medium);
-        return sizeof(le32);
-
-    /* mandatory */
-    case OID_GEN_MAXIMUM_FRAME_SIZE:
-        *((le32 *) outbuf) = cpu_to_le32(ETH_FRAME_LEN);
-        return sizeof(le32);
-
-    /* mandatory */
-    case OID_GEN_LINK_SPEED:
-        *((le32 *) outbuf) = cpu_to_le32(s->speed);
-        return sizeof(le32);
-
-    /* mandatory */
-    case OID_GEN_TRANSMIT_BLOCK_SIZE:
-        *((le32 *) outbuf) = cpu_to_le32(ETH_FRAME_LEN);
-        return sizeof(le32);
-
-    /* mandatory */
-    case OID_GEN_RECEIVE_BLOCK_SIZE:
-        *((le32 *) outbuf) = cpu_to_le32(ETH_FRAME_LEN);
-        return sizeof(le32);
-
-    /* mandatory */
-    case OID_GEN_VENDOR_ID:
-        *((le32 *) outbuf) = cpu_to_le32(s->vendorid);
-        return sizeof(le32);
-
-    /* mandatory */
-    case OID_GEN_VENDOR_DESCRIPTION:
-        pstrcpy((char *)outbuf, outlen, "QEMU USB RNDIS Net");
-        return strlen((char *)outbuf) + 1;
-
-    case OID_GEN_VENDOR_DRIVER_VERSION:
-        *((le32 *) outbuf) = cpu_to_le32(1);
-        return sizeof(le32);
-
-    /* mandatory */
-    case OID_GEN_CURRENT_PACKET_FILTER:
-        *((le32 *) outbuf) = cpu_to_le32(s->filter);
-        return sizeof(le32);
-
-    /* mandatory */
-    case OID_GEN_MAXIMUM_TOTAL_SIZE:
-        *((le32 *) outbuf) = cpu_to_le32(RNDIS_MAX_TOTAL_SIZE);
-        return sizeof(le32);
-
-    /* mandatory */
-    case OID_GEN_MEDIA_CONNECT_STATUS:
-        *((le32 *) outbuf) = cpu_to_le32(s->media_state);
-        return sizeof(le32);
-
-    case OID_GEN_PHYSICAL_MEDIUM:
-        *((le32 *) outbuf) = cpu_to_le32(0);
-        return sizeof(le32);
-
-    case OID_GEN_MAC_OPTIONS:
-        *((le32 *) outbuf) = cpu_to_le32(
-                        NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
-                        NDIS_MAC_OPTION_FULL_DUPLEX);
-        return sizeof(le32);
-
-    /* statistics OIDs (table 4-2) */
-    /* mandatory */
-    case OID_GEN_XMIT_OK:
-        *((le32 *) outbuf) = cpu_to_le32(0);
-        return sizeof(le32);
-
-    /* mandatory */
-    case OID_GEN_RCV_OK:
-        *((le32 *) outbuf) = cpu_to_le32(0);
-        return sizeof(le32);
-
-    /* mandatory */
-    case OID_GEN_XMIT_ERROR:
-        *((le32 *) outbuf) = cpu_to_le32(0);
-        return sizeof(le32);
-
-    /* mandatory */
-    case OID_GEN_RCV_ERROR:
-        *((le32 *) outbuf) = cpu_to_le32(0);
-        return sizeof(le32);
-
-    /* mandatory */
-    case OID_GEN_RCV_NO_BUFFER:
-        *((le32 *) outbuf) = cpu_to_le32(0);
-        return sizeof(le32);
-
-    /* ieee802.3 OIDs (table 4-3) */
-    /* mandatory */
-    case OID_802_3_PERMANENT_ADDRESS:
-        memcpy(outbuf, s->conf.macaddr.a, 6);
-        return 6;
-
-    /* mandatory */
-    case OID_802_3_CURRENT_ADDRESS:
-        memcpy(outbuf, s->conf.macaddr.a, 6);
-        return 6;
-
-    /* mandatory */
-    case OID_802_3_MULTICAST_LIST:
-        *((le32 *) outbuf) = cpu_to_le32(0xe0000000);
-        return sizeof(le32);
-
-    /* mandatory */
-    case OID_802_3_MAXIMUM_LIST_SIZE:
-        *((le32 *) outbuf) = cpu_to_le32(1);
-        return sizeof(le32);
-
-    case OID_802_3_MAC_OPTIONS:
-        return 0;
-
-    /* ieee802.3 statistics OIDs (table 4-4) */
-    /* mandatory */
-    case OID_802_3_RCV_ERROR_ALIGNMENT:
-        *((le32 *) outbuf) = cpu_to_le32(0);
-        return sizeof(le32);
-
-    /* mandatory */
-    case OID_802_3_XMIT_ONE_COLLISION:
-        *((le32 *) outbuf) = cpu_to_le32(0);
-        return sizeof(le32);
-
-    /* mandatory */
-    case OID_802_3_XMIT_MORE_COLLISIONS:
-        *((le32 *) outbuf) = cpu_to_le32(0);
-        return sizeof(le32);
-
-    default:
-        fprintf(stderr, "usbnet: unknown OID 0x%08x\n", oid);
-        return 0;
-    }
-    return -1;
-}
-
-static int ndis_set(USBNetState *s, uint32_t oid,
-                uint8_t *inbuf, unsigned int inlen)
-{
-    switch (oid) {
-    case OID_GEN_CURRENT_PACKET_FILTER:
-        s->filter = le32_to_cpup((le32 *) inbuf);
-        if (s->filter) {
-            s->rndis_state = RNDIS_DATA_INITIALIZED;
-        } else {
-            s->rndis_state = RNDIS_INITIALIZED;
-        }
-        return 0;
-
-    case OID_802_3_MULTICAST_LIST:
-        return 0;
-    }
-    return -1;
-}
-
-static int rndis_get_response(USBNetState *s, uint8_t *buf)
-{
-    int ret = 0;
-    struct rndis_response *r = s->rndis_resp.tqh_first;
-
-    if (!r)
-        return ret;
-
-    QTAILQ_REMOVE(&s->rndis_resp, r, entries);
-    ret = r->length;
-    memcpy(buf, r->buf, r->length);
-    g_free(r);
-
-    return ret;
-}
-
-static void *rndis_queue_response(USBNetState *s, unsigned int length)
-{
-    struct rndis_response *r =
-            g_malloc0(sizeof(struct rndis_response) + length);
-
-    QTAILQ_INSERT_TAIL(&s->rndis_resp, r, entries);
-    r->length = length;
-
-    return &r->buf[0];
-}
-
-static void rndis_clear_responsequeue(USBNetState *s)
-{
-    struct rndis_response *r;
-
-    while ((r = s->rndis_resp.tqh_first)) {
-        QTAILQ_REMOVE(&s->rndis_resp, r, entries);
-        g_free(r);
-    }
-}
-
-static int rndis_init_response(USBNetState *s, rndis_init_msg_type *buf)
-{
-    rndis_init_cmplt_type *resp =
-            rndis_queue_response(s, sizeof(rndis_init_cmplt_type));
-
-    if (!resp)
-        return USB_RET_STALL;
-
-    resp->MessageType = cpu_to_le32(RNDIS_INITIALIZE_CMPLT);
-    resp->MessageLength = cpu_to_le32(sizeof(rndis_init_cmplt_type));
-    resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
-    resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
-    resp->MajorVersion = cpu_to_le32(RNDIS_MAJOR_VERSION);
-    resp->MinorVersion = cpu_to_le32(RNDIS_MINOR_VERSION);
-    resp->DeviceFlags = cpu_to_le32(RNDIS_DF_CONNECTIONLESS);
-    resp->Medium = cpu_to_le32(RNDIS_MEDIUM_802_3);
-    resp->MaxPacketsPerTransfer = cpu_to_le32(1);
-    resp->MaxTransferSize = cpu_to_le32(ETH_FRAME_LEN +
-                    sizeof(struct rndis_packet_msg_type) + 22);
-    resp->PacketAlignmentFactor = cpu_to_le32(0);
-    resp->AFListOffset = cpu_to_le32(0);
-    resp->AFListSize = cpu_to_le32(0);
-    return 0;
-}
-
-static int rndis_query_response(USBNetState *s,
-                rndis_query_msg_type *buf, unsigned int length)
-{
-    rndis_query_cmplt_type *resp;
-    /* oid_supported_list is the largest data reply */
-    uint8_t infobuf[sizeof(oid_supported_list)];
-    uint32_t bufoffs, buflen;
-    int infobuflen;
-    unsigned int resplen;
-
-    bufoffs = le32_to_cpu(buf->InformationBufferOffset) + 8;
-    buflen = le32_to_cpu(buf->InformationBufferLength);
-    if (bufoffs + buflen > length)
-        return USB_RET_STALL;
-
-    infobuflen = ndis_query(s, le32_to_cpu(buf->OID),
-                            bufoffs + (uint8_t *) buf, buflen, infobuf,
-                            sizeof(infobuf));
-    resplen = sizeof(rndis_query_cmplt_type) +
-            ((infobuflen < 0) ? 0 : infobuflen);
-    resp = rndis_queue_response(s, resplen);
-    if (!resp)
-        return USB_RET_STALL;
-
-    resp->MessageType = cpu_to_le32(RNDIS_QUERY_CMPLT);
-    resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
-    resp->MessageLength = cpu_to_le32(resplen);
-
-    if (infobuflen < 0) {
-        /* OID not supported */
-        resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED);
-        resp->InformationBufferLength = cpu_to_le32(0);
-        resp->InformationBufferOffset = cpu_to_le32(0);
-        return 0;
-    }
-
-    resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
-    resp->InformationBufferOffset =
-            cpu_to_le32(infobuflen ? sizeof(rndis_query_cmplt_type) - 8 : 0);
-    resp->InformationBufferLength = cpu_to_le32(infobuflen);
-    memcpy(resp + 1, infobuf, infobuflen);
-
-    return 0;
-}
-
-static int rndis_set_response(USBNetState *s,
-                rndis_set_msg_type *buf, unsigned int length)
-{
-    rndis_set_cmplt_type *resp =
-            rndis_queue_response(s, sizeof(rndis_set_cmplt_type));
-    uint32_t bufoffs, buflen;
-    int ret;
-
-    if (!resp)
-        return USB_RET_STALL;
-
-    bufoffs = le32_to_cpu(buf->InformationBufferOffset) + 8;
-    buflen = le32_to_cpu(buf->InformationBufferLength);
-    if (bufoffs + buflen > length)
-        return USB_RET_STALL;
-
-    ret = ndis_set(s, le32_to_cpu(buf->OID),
-                    bufoffs + (uint8_t *) buf, buflen);
-    resp->MessageType = cpu_to_le32(RNDIS_SET_CMPLT);
-    resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
-    resp->MessageLength = cpu_to_le32(sizeof(rndis_set_cmplt_type));
-    if (ret < 0) {
-        /* OID not supported */
-        resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED);
-        return 0;
-    }
-    resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
-
-    return 0;
-}
-
-static int rndis_reset_response(USBNetState *s, rndis_reset_msg_type *buf)
-{
-    rndis_reset_cmplt_type *resp =
-            rndis_queue_response(s, sizeof(rndis_reset_cmplt_type));
-
-    if (!resp)
-        return USB_RET_STALL;
-
-    resp->MessageType = cpu_to_le32(RNDIS_RESET_CMPLT);
-    resp->MessageLength = cpu_to_le32(sizeof(rndis_reset_cmplt_type));
-    resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
-    resp->AddressingReset = cpu_to_le32(1); /* reset information */
-
-    return 0;
-}
-
-static int rndis_keepalive_response(USBNetState *s,
-                rndis_keepalive_msg_type *buf)
-{
-    rndis_keepalive_cmplt_type *resp =
-            rndis_queue_response(s, sizeof(rndis_keepalive_cmplt_type));
-
-    if (!resp)
-        return USB_RET_STALL;
-
-    resp->MessageType = cpu_to_le32(RNDIS_KEEPALIVE_CMPLT);
-    resp->MessageLength = cpu_to_le32(sizeof(rndis_keepalive_cmplt_type));
-    resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
-    resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
-
-    return 0;
-}
-
-static int rndis_parse(USBNetState *s, uint8_t *data, int length)
-{
-    uint32_t msg_type;
-    le32 *tmp = (le32 *) data;
-
-    msg_type = le32_to_cpup(tmp);
-
-    switch (msg_type) {
-    case RNDIS_INITIALIZE_MSG:
-        s->rndis_state = RNDIS_INITIALIZED;
-        return rndis_init_response(s, (rndis_init_msg_type *) data);
-
-    case RNDIS_HALT_MSG:
-        s->rndis_state = RNDIS_UNINITIALIZED;
-        return 0;
-
-    case RNDIS_QUERY_MSG:
-        return rndis_query_response(s, (rndis_query_msg_type *) data, length);
-
-    case RNDIS_SET_MSG:
-        return rndis_set_response(s, (rndis_set_msg_type *) data, length);
-
-    case RNDIS_RESET_MSG:
-        rndis_clear_responsequeue(s);
-        s->out_ptr = s->in_ptr = s->in_len = 0;
-        return rndis_reset_response(s, (rndis_reset_msg_type *) data);
-
-    case RNDIS_KEEPALIVE_MSG:
-        /* For USB: host does this every 5 seconds */
-        return rndis_keepalive_response(s, (rndis_keepalive_msg_type *) data);
-    }
-
-    return USB_RET_STALL;
-}
-
-static void usb_net_handle_reset(USBDevice *dev)
-{
-}
-
-static int usb_net_handle_control(USBDevice *dev, USBPacket *p,
-               int request, int value, int index, int length, uint8_t *data)
-{
-    USBNetState *s = (USBNetState *) dev;
-    int ret;
-
-    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
-    if (ret >= 0) {
-        return ret;
-    }
-
-    ret = 0;
-    switch(request) {
-    case ClassInterfaceOutRequest | USB_CDC_SEND_ENCAPSULATED_COMMAND:
-        if (!is_rndis(s) || value || index != 0) {
-            goto fail;
-        }
-#ifdef TRAFFIC_DEBUG
-        {
-            unsigned int i;
-            fprintf(stderr, "SEND_ENCAPSULATED_COMMAND:");
-            for (i = 0; i < length; i++) {
-                if (!(i & 15))
-                    fprintf(stderr, "\n%04x:", i);
-                fprintf(stderr, " %02x", data[i]);
-            }
-            fprintf(stderr, "\n\n");
-        }
-#endif
-        ret = rndis_parse(s, data, length);
-        break;
-
-    case ClassInterfaceRequest | USB_CDC_GET_ENCAPSULATED_RESPONSE:
-        if (!is_rndis(s) || value || index != 0) {
-            goto fail;
-        }
-        ret = rndis_get_response(s, data);
-        if (!ret) {
-            data[0] = 0;
-            ret = 1;
-        }
-#ifdef TRAFFIC_DEBUG
-        {
-            unsigned int i;
-            fprintf(stderr, "GET_ENCAPSULATED_RESPONSE:");
-            for (i = 0; i < ret; i++) {
-                if (!(i & 15))
-                    fprintf(stderr, "\n%04x:", i);
-                fprintf(stderr, " %02x", data[i]);
-            }
-            fprintf(stderr, "\n\n");
-        }
-#endif
-        break;
-
-    default:
-    fail:
-        fprintf(stderr, "usbnet: failed control transaction: "
-                        "request 0x%x value 0x%x index 0x%x length 0x%x\n",
-                        request, value, index, length);
-        ret = USB_RET_STALL;
-        break;
-    }
-    return ret;
-}
-
-static int usb_net_handle_statusin(USBNetState *s, USBPacket *p)
-{
-    le32 buf[2];
-    int ret = 8;
-
-    if (p->iov.size < 8) {
-        return USB_RET_STALL;
-    }
-
-    buf[0] = cpu_to_le32(1);
-    buf[1] = cpu_to_le32(0);
-    usb_packet_copy(p, buf, 8);
-    if (!s->rndis_resp.tqh_first)
-        ret = USB_RET_NAK;
-
-#ifdef TRAFFIC_DEBUG
-    fprintf(stderr, "usbnet: interrupt poll len %zu return %d",
-            p->iov.size, ret);
-    iov_hexdump(p->iov.iov, p->iov.niov, stderr, "usbnet", ret);
-#endif
-
-    return ret;
-}
-
-static int usb_net_handle_datain(USBNetState *s, USBPacket *p)
-{
-    int ret = USB_RET_NAK;
-
-    if (s->in_ptr > s->in_len) {
-        s->in_ptr = s->in_len = 0;
-        ret = USB_RET_NAK;
-        return ret;
-    }
-    if (!s->in_len) {
-        ret = USB_RET_NAK;
-        return ret;
-    }
-    ret = s->in_len - s->in_ptr;
-    if (ret > p->iov.size) {
-        ret = p->iov.size;
-    }
-    usb_packet_copy(p, &s->in_buf[s->in_ptr], ret);
-    s->in_ptr += ret;
-    if (s->in_ptr >= s->in_len &&
-                    (is_rndis(s) || (s->in_len & (64 - 1)) || !ret)) {
-        /* no short packet necessary */
-        s->in_ptr = s->in_len = 0;
-    }
-
-#ifdef TRAFFIC_DEBUG
-    fprintf(stderr, "usbnet: data in len %zu return %d", p->iov.size, ret);
-    iov_hexdump(p->iov.iov, p->iov.niov, stderr, "usbnet", ret);
-#endif
-
-    return ret;
-}
-
-static int usb_net_handle_dataout(USBNetState *s, USBPacket *p)
-{
-    int ret = p->iov.size;
-    int sz = sizeof(s->out_buf) - s->out_ptr;
-    struct rndis_packet_msg_type *msg =
-            (struct rndis_packet_msg_type *) s->out_buf;
-    uint32_t len;
-
-#ifdef TRAFFIC_DEBUG
-    fprintf(stderr, "usbnet: data out len %zu\n", p->iov.size);
-    iov_hexdump(p->iov.iov, p->iov.niov, stderr, "usbnet", p->iov.size);
-#endif
-
-    if (sz > ret)
-        sz = ret;
-    usb_packet_copy(p, &s->out_buf[s->out_ptr], sz);
-    s->out_ptr += sz;
-
-    if (!is_rndis(s)) {
-        if (ret < 64) {
-            qemu_send_packet(&s->nic->nc, s->out_buf, s->out_ptr);
-            s->out_ptr = 0;
-        }
-        return ret;
-    }
-    len = le32_to_cpu(msg->MessageLength);
-    if (s->out_ptr < 8 || s->out_ptr < len)
-        return ret;
-    if (le32_to_cpu(msg->MessageType) == RNDIS_PACKET_MSG) {
-        uint32_t offs = 8 + le32_to_cpu(msg->DataOffset);
-        uint32_t size = le32_to_cpu(msg->DataLength);
-        if (offs + size <= len)
-            qemu_send_packet(&s->nic->nc, s->out_buf + offs, size);
-    }
-    s->out_ptr -= len;
-    memmove(s->out_buf, &s->out_buf[len], s->out_ptr);
-
-    return ret;
-}
-
-static int usb_net_handle_data(USBDevice *dev, USBPacket *p)
-{
-    USBNetState *s = (USBNetState *) dev;
-    int ret = 0;
-
-    switch(p->pid) {
-    case USB_TOKEN_IN:
-        switch (p->ep->nr) {
-        case 1:
-            ret = usb_net_handle_statusin(s, p);
-            break;
-
-        case 2:
-            ret = usb_net_handle_datain(s, p);
-            break;
-
-        default:
-            goto fail;
-        }
-        break;
-
-    case USB_TOKEN_OUT:
-        switch (p->ep->nr) {
-        case 2:
-            ret = usb_net_handle_dataout(s, p);
-            break;
-
-        default:
-            goto fail;
-        }
-        break;
-
-    default:
-    fail:
-        ret = USB_RET_STALL;
-        break;
-    }
-    if (ret == USB_RET_STALL)
-        fprintf(stderr, "usbnet: failed data transaction: "
-                        "pid 0x%x ep 0x%x len 0x%zx\n",
-                        p->pid, p->ep->nr, p->iov.size);
-    return ret;
-}
-
-static ssize_t usbnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
-{
-    USBNetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
-    struct rndis_packet_msg_type *msg;
-
-    if (is_rndis(s)) {
-        msg = (struct rndis_packet_msg_type *) s->in_buf;
-        if (s->rndis_state != RNDIS_DATA_INITIALIZED) {
-            return -1;
-        }
-        if (size + sizeof(struct rndis_packet_msg_type) > sizeof(s->in_buf))
-            return -1;
-
-        memset(msg, 0, sizeof(struct rndis_packet_msg_type));
-        msg->MessageType = cpu_to_le32(RNDIS_PACKET_MSG);
-        msg->MessageLength = cpu_to_le32(size + sizeof(struct rndis_packet_msg_type));
-        msg->DataOffset = cpu_to_le32(sizeof(struct rndis_packet_msg_type) - 8);
-        msg->DataLength = cpu_to_le32(size);
-        /* msg->OOBDataOffset;
-         * msg->OOBDataLength;
-         * msg->NumOOBDataElements;
-         * msg->PerPacketInfoOffset;
-         * msg->PerPacketInfoLength;
-         * msg->VcHandle;
-         * msg->Reserved;
-         */
-        memcpy(msg + 1, buf, size);
-        s->in_len = size + sizeof(struct rndis_packet_msg_type);
-    } else {
-        if (size > sizeof(s->in_buf))
-            return -1;
-        memcpy(s->in_buf, buf, size);
-        s->in_len = size;
-    }
-    s->in_ptr = 0;
-    return size;
-}
-
-static int usbnet_can_receive(VLANClientState *nc)
-{
-    USBNetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
-
-    if (is_rndis(s) && s->rndis_state != RNDIS_DATA_INITIALIZED) {
-        return 1;
-    }
-
-    return !s->in_len;
-}
-
-static void usbnet_cleanup(VLANClientState *nc)
-{
-    USBNetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
-
-    s->nic = NULL;
-}
-
-static void usb_net_handle_destroy(USBDevice *dev)
-{
-    USBNetState *s = (USBNetState *) dev;
-
-    /* TODO: remove the nd_table[] entry */
-    rndis_clear_responsequeue(s);
-    qemu_del_vlan_client(&s->nic->nc);
-}
-
-static NetClientInfo net_usbnet_info = {
-    .type = NET_CLIENT_TYPE_NIC,
-    .size = sizeof(NICState),
-    .can_receive = usbnet_can_receive,
-    .receive = usbnet_receive,
-    .cleanup = usbnet_cleanup,
-};
-
-static int usb_net_initfn(USBDevice *dev)
-{
-    USBNetState *s = DO_UPCAST(USBNetState, dev, dev);
-
-    usb_desc_init(dev);
-
-    s->rndis_state = RNDIS_UNINITIALIZED;
-    QTAILQ_INIT(&s->rndis_resp);
-
-    s->medium = 0;	/* NDIS_MEDIUM_802_3 */
-    s->speed = 1000000; /* 100MBps, in 100Bps units */
-    s->media_state = 0;	/* NDIS_MEDIA_STATE_CONNECTED */;
-    s->filter = 0;
-    s->vendorid = 0x1234;
-
-    qemu_macaddr_default_if_unset(&s->conf.macaddr);
-    s->nic = qemu_new_nic(&net_usbnet_info, &s->conf,
-                          object_get_typename(OBJECT(s)), s->dev.qdev.id, s);
-    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
-    snprintf(s->usbstring_mac, sizeof(s->usbstring_mac),
-             "%02x%02x%02x%02x%02x%02x",
-             0x40,
-             s->conf.macaddr.a[1],
-             s->conf.macaddr.a[2],
-             s->conf.macaddr.a[3],
-             s->conf.macaddr.a[4],
-             s->conf.macaddr.a[5]);
-    usb_desc_set_string(dev, STRING_ETHADDR, s->usbstring_mac);
-
-    add_boot_device_path(s->conf.bootindex, &dev->qdev, "/ethernet at 0");
-    return 0;
-}
-
-static USBDevice *usb_net_init(USBBus *bus, const char *cmdline)
-{
-    USBDevice *dev;
-    QemuOpts *opts;
-    int idx;
-
-    opts = qemu_opts_parse(qemu_find_opts("net"), cmdline, 0);
-    if (!opts) {
-        return NULL;
-    }
-    qemu_opt_set(opts, "type", "nic");
-    qemu_opt_set(opts, "model", "usb");
-
-    idx = net_client_init(NULL, opts, 0);
-    if (idx == -1) {
-        return NULL;
-    }
-
-    dev = usb_create(bus, "usb-net");
-    if (!dev) {
-        return NULL;
-    }
-    qdev_set_nic_properties(&dev->qdev, &nd_table[idx]);
-    qdev_init_nofail(&dev->qdev);
-    return dev;
-}
-
-static const VMStateDescription vmstate_usb_net = {
-    .name = "usb-net",
-    .unmigratable = 1,
-};
-
-static Property net_properties[] = {
-    DEFINE_NIC_PROPERTIES(USBNetState, conf),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void usb_net_class_initfn(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
-
-    uc->init           = usb_net_initfn;
-    uc->product_desc   = "QEMU USB Network Interface";
-    uc->usb_desc       = &desc_net;
-    uc->handle_reset   = usb_net_handle_reset;
-    uc->handle_control = usb_net_handle_control;
-    uc->handle_data    = usb_net_handle_data;
-    uc->handle_destroy = usb_net_handle_destroy;
-    dc->fw_name = "network";
-    dc->vmsd = &vmstate_usb_net;
-    dc->props = net_properties;
-}
-
-static TypeInfo net_info = {
-    .name          = "usb-net",
-    .parent        = TYPE_USB_DEVICE,
-    .instance_size = sizeof(USBNetState),
-    .class_init    = usb_net_class_initfn,
-};
-
-static void usb_net_register_types(void)
-{
-    type_register_static(&net_info);
-    usb_legacy_register("usb-net", "net", usb_net_init);
-}
-
-type_init(usb_net_register_types)
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
deleted file mode 100644
index 20aaa74..0000000
--- a/hw/usb-ohci.c
+++ /dev/null
@@ -1,1898 +0,0 @@
-/*
- * QEMU USB OHCI Emulation
- * Copyright (c) 2004 Gianni Tedesco
- * Copyright (c) 2006 CodeSourcery
- * Copyright (c) 2006 Openedhand Ltd.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- *
- * TODO:
- *  o Isochronous transfers
- *  o Allocate bandwidth in frames properly
- *  o Disable timers when nothing needs to be done, or remove timer usage
- *    all together.
- *  o Handle unrecoverable errors properly
- *  o BIOS work to boot from USB storage
-*/
-
-#include "hw.h"
-#include "qemu-timer.h"
-#include "usb.h"
-#include "pci.h"
-#include "usb-ohci.h"
-#include "sysbus.h"
-#include "qdev-addr.h"
-
-//#define DEBUG_OHCI
-/* Dump packet contents.  */
-//#define DEBUG_PACKET
-//#define DEBUG_ISOCH
-/* This causes frames to occur 1000x slower */
-//#define OHCI_TIME_WARP 1
-
-#ifdef DEBUG_OHCI
-#define DPRINTF printf
-#else
-#define DPRINTF(...)
-#endif
-
-/* Number of Downstream Ports on the root hub.  */
-
-#define OHCI_MAX_PORTS 15
-
-static int64_t usb_frame_time;
-static int64_t usb_bit_time;
-
-typedef struct OHCIPort {
-    USBPort port;
-    uint32_t ctrl;
-} OHCIPort;
-
-typedef struct {
-    USBBus bus;
-    qemu_irq irq;
-    MemoryRegion mem;
-    int num_ports;
-    const char *name;
-
-    QEMUTimer *eof_timer;
-    int64_t sof_time;
-
-    /* OHCI state */
-    /* Control partition */
-    uint32_t ctl, status;
-    uint32_t intr_status;
-    uint32_t intr;
-
-    /* memory pointer partition */
-    uint32_t hcca;
-    uint32_t ctrl_head, ctrl_cur;
-    uint32_t bulk_head, bulk_cur;
-    uint32_t per_cur;
-    uint32_t done;
-    int done_count;
-
-    /* Frame counter partition */
-    uint32_t fsmps:15;
-    uint32_t fit:1;
-    uint32_t fi:14;
-    uint32_t frt:1;
-    uint16_t frame_number;
-    uint16_t padding;
-    uint32_t pstart;
-    uint32_t lst;
-
-    /* Root Hub partition */
-    uint32_t rhdesc_a, rhdesc_b;
-    uint32_t rhstatus;
-    OHCIPort rhport[OHCI_MAX_PORTS];
-
-    /* PXA27x Non-OHCI events */
-    uint32_t hstatus;
-    uint32_t hmask;
-    uint32_t hreset;
-    uint32_t htest;
-
-    /* SM501 local memory offset */
-    target_phys_addr_t localmem_base;
-
-    /* Active packets.  */
-    uint32_t old_ctl;
-    USBPacket usb_packet;
-    uint8_t usb_buf[8192];
-    uint32_t async_td;
-    int async_complete;
-
-} OHCIState;
-
-/* Host Controller Communications Area */
-struct ohci_hcca {
-    uint32_t intr[32];
-    uint16_t frame, pad;
-    uint32_t done;
-};
-
-static void ohci_bus_stop(OHCIState *ohci);
-static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev);
-
-/* Bitfields for the first word of an Endpoint Desciptor.  */
-#define OHCI_ED_FA_SHIFT  0
-#define OHCI_ED_FA_MASK   (0x7f<<OHCI_ED_FA_SHIFT)
-#define OHCI_ED_EN_SHIFT  7
-#define OHCI_ED_EN_MASK   (0xf<<OHCI_ED_EN_SHIFT)
-#define OHCI_ED_D_SHIFT   11
-#define OHCI_ED_D_MASK    (3<<OHCI_ED_D_SHIFT)
-#define OHCI_ED_S         (1<<13)
-#define OHCI_ED_K         (1<<14)
-#define OHCI_ED_F         (1<<15)
-#define OHCI_ED_MPS_SHIFT 16
-#define OHCI_ED_MPS_MASK  (0x7ff<<OHCI_ED_MPS_SHIFT)
-
-/* Flags in the head field of an Endpoint Desciptor.  */
-#define OHCI_ED_H         1
-#define OHCI_ED_C         2
-
-/* Bitfields for the first word of a Transfer Desciptor.  */
-#define OHCI_TD_R         (1<<18)
-#define OHCI_TD_DP_SHIFT  19
-#define OHCI_TD_DP_MASK   (3<<OHCI_TD_DP_SHIFT)
-#define OHCI_TD_DI_SHIFT  21
-#define OHCI_TD_DI_MASK   (7<<OHCI_TD_DI_SHIFT)
-#define OHCI_TD_T0        (1<<24)
-#define OHCI_TD_T1        (1<<25)
-#define OHCI_TD_EC_SHIFT  26
-#define OHCI_TD_EC_MASK   (3<<OHCI_TD_EC_SHIFT)
-#define OHCI_TD_CC_SHIFT  28
-#define OHCI_TD_CC_MASK   (0xf<<OHCI_TD_CC_SHIFT)
-
-/* Bitfields for the first word of an Isochronous Transfer Desciptor.  */
-/* CC & DI - same as in the General Transfer Desciptor */
-#define OHCI_TD_SF_SHIFT  0
-#define OHCI_TD_SF_MASK   (0xffff<<OHCI_TD_SF_SHIFT)
-#define OHCI_TD_FC_SHIFT  24
-#define OHCI_TD_FC_MASK   (7<<OHCI_TD_FC_SHIFT)
-
-/* Isochronous Transfer Desciptor - Offset / PacketStatusWord */
-#define OHCI_TD_PSW_CC_SHIFT 12
-#define OHCI_TD_PSW_CC_MASK  (0xf<<OHCI_TD_PSW_CC_SHIFT)
-#define OHCI_TD_PSW_SIZE_SHIFT 0
-#define OHCI_TD_PSW_SIZE_MASK  (0xfff<<OHCI_TD_PSW_SIZE_SHIFT)
-
-#define OHCI_PAGE_MASK    0xfffff000
-#define OHCI_OFFSET_MASK  0xfff
-
-#define OHCI_DPTR_MASK    0xfffffff0
-
-#define OHCI_BM(val, field) \
-  (((val) & OHCI_##field##_MASK) >> OHCI_##field##_SHIFT)
-
-#define OHCI_SET_BM(val, field, newval) do { \
-    val &= ~OHCI_##field##_MASK; \
-    val |= ((newval) << OHCI_##field##_SHIFT) & OHCI_##field##_MASK; \
-    } while(0)
-
-/* endpoint descriptor */
-struct ohci_ed {
-    uint32_t flags;
-    uint32_t tail;
-    uint32_t head;
-    uint32_t next;
-};
-
-/* General transfer descriptor */
-struct ohci_td {
-    uint32_t flags;
-    uint32_t cbp;
-    uint32_t next;
-    uint32_t be;
-};
-
-/* Isochronous transfer descriptor */
-struct ohci_iso_td {
-    uint32_t flags;
-    uint32_t bp;
-    uint32_t next;
-    uint32_t be;
-    uint16_t offset[8];
-};
-
-#define USB_HZ                      12000000
-
-/* OHCI Local stuff */
-#define OHCI_CTL_CBSR         ((1<<0)|(1<<1))
-#define OHCI_CTL_PLE          (1<<2)
-#define OHCI_CTL_IE           (1<<3)
-#define OHCI_CTL_CLE          (1<<4)
-#define OHCI_CTL_BLE          (1<<5)
-#define OHCI_CTL_HCFS         ((1<<6)|(1<<7))
-#define  OHCI_USB_RESET       0x00
-#define  OHCI_USB_RESUME      0x40
-#define  OHCI_USB_OPERATIONAL 0x80
-#define  OHCI_USB_SUSPEND     0xc0
-#define OHCI_CTL_IR           (1<<8)
-#define OHCI_CTL_RWC          (1<<9)
-#define OHCI_CTL_RWE          (1<<10)
-
-#define OHCI_STATUS_HCR       (1<<0)
-#define OHCI_STATUS_CLF       (1<<1)
-#define OHCI_STATUS_BLF       (1<<2)
-#define OHCI_STATUS_OCR       (1<<3)
-#define OHCI_STATUS_SOC       ((1<<6)|(1<<7))
-
-#define OHCI_INTR_SO          (1<<0) /* Scheduling overrun */
-#define OHCI_INTR_WD          (1<<1) /* HcDoneHead writeback */
-#define OHCI_INTR_SF          (1<<2) /* Start of frame */
-#define OHCI_INTR_RD          (1<<3) /* Resume detect */
-#define OHCI_INTR_UE          (1<<4) /* Unrecoverable error */
-#define OHCI_INTR_FNO         (1<<5) /* Frame number overflow */
-#define OHCI_INTR_RHSC        (1<<6) /* Root hub status change */
-#define OHCI_INTR_OC          (1<<30) /* Ownership change */
-#define OHCI_INTR_MIE         (1<<31) /* Master Interrupt Enable */
-
-#define OHCI_HCCA_SIZE        0x100
-#define OHCI_HCCA_MASK        0xffffff00
-
-#define OHCI_EDPTR_MASK       0xfffffff0
-
-#define OHCI_FMI_FI           0x00003fff
-#define OHCI_FMI_FSMPS        0xffff0000
-#define OHCI_FMI_FIT          0x80000000
-
-#define OHCI_FR_RT            (1<<31)
-
-#define OHCI_LS_THRESH        0x628
-
-#define OHCI_RHA_RW_MASK      0x00000000 /* Mask of supported features.  */
-#define OHCI_RHA_PSM          (1<<8)
-#define OHCI_RHA_NPS          (1<<9)
-#define OHCI_RHA_DT           (1<<10)
-#define OHCI_RHA_OCPM         (1<<11)
-#define OHCI_RHA_NOCP         (1<<12)
-#define OHCI_RHA_POTPGT_MASK  0xff000000
-
-#define OHCI_RHS_LPS          (1<<0)
-#define OHCI_RHS_OCI          (1<<1)
-#define OHCI_RHS_DRWE         (1<<15)
-#define OHCI_RHS_LPSC         (1<<16)
-#define OHCI_RHS_OCIC         (1<<17)
-#define OHCI_RHS_CRWE         (1<<31)
-
-#define OHCI_PORT_CCS         (1<<0)
-#define OHCI_PORT_PES         (1<<1)
-#define OHCI_PORT_PSS         (1<<2)
-#define OHCI_PORT_POCI        (1<<3)
-#define OHCI_PORT_PRS         (1<<4)
-#define OHCI_PORT_PPS         (1<<8)
-#define OHCI_PORT_LSDA        (1<<9)
-#define OHCI_PORT_CSC         (1<<16)
-#define OHCI_PORT_PESC        (1<<17)
-#define OHCI_PORT_PSSC        (1<<18)
-#define OHCI_PORT_OCIC        (1<<19)
-#define OHCI_PORT_PRSC        (1<<20)
-#define OHCI_PORT_WTC         (OHCI_PORT_CSC|OHCI_PORT_PESC|OHCI_PORT_PSSC \
-                               |OHCI_PORT_OCIC|OHCI_PORT_PRSC)
-
-#define OHCI_TD_DIR_SETUP     0x0
-#define OHCI_TD_DIR_OUT       0x1
-#define OHCI_TD_DIR_IN        0x2
-#define OHCI_TD_DIR_RESERVED  0x3
-
-#define OHCI_CC_NOERROR             0x0
-#define OHCI_CC_CRC                 0x1
-#define OHCI_CC_BITSTUFFING         0x2
-#define OHCI_CC_DATATOGGLEMISMATCH  0x3
-#define OHCI_CC_STALL               0x4
-#define OHCI_CC_DEVICENOTRESPONDING 0x5
-#define OHCI_CC_PIDCHECKFAILURE     0x6
-#define OHCI_CC_UNDEXPETEDPID       0x7
-#define OHCI_CC_DATAOVERRUN         0x8
-#define OHCI_CC_DATAUNDERRUN        0x9
-#define OHCI_CC_BUFFEROVERRUN       0xc
-#define OHCI_CC_BUFFERUNDERRUN      0xd
-
-#define OHCI_HRESET_FSBIR       (1 << 0)
-
-/* Update IRQ levels */
-static inline void ohci_intr_update(OHCIState *ohci)
-{
-    int level = 0;
-
-    if ((ohci->intr & OHCI_INTR_MIE) &&
-        (ohci->intr_status & ohci->intr))
-        level = 1;
-
-    qemu_set_irq(ohci->irq, level);
-}
-
-/* Set an interrupt */
-static inline void ohci_set_interrupt(OHCIState *ohci, uint32_t intr)
-{
-    ohci->intr_status |= intr;
-    ohci_intr_update(ohci);
-}
-
-/* Attach or detach a device on a root hub port.  */
-static void ohci_attach(USBPort *port1)
-{
-    OHCIState *s = port1->opaque;
-    OHCIPort *port = &s->rhport[port1->index];
-    uint32_t old_state = port->ctrl;
-
-    /* set connect status */
-    port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
-
-    /* update speed */
-    if (port->port.dev->speed == USB_SPEED_LOW) {
-        port->ctrl |= OHCI_PORT_LSDA;
-    } else {
-        port->ctrl &= ~OHCI_PORT_LSDA;
-    }
-
-    /* notify of remote-wakeup */
-    if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
-        ohci_set_interrupt(s, OHCI_INTR_RD);
-    }
-
-    DPRINTF("usb-ohci: Attached port %d\n", port1->index);
-
-    if (old_state != port->ctrl) {
-        ohci_set_interrupt(s, OHCI_INTR_RHSC);
-    }
-}
-
-static void ohci_detach(USBPort *port1)
-{
-    OHCIState *s = port1->opaque;
-    OHCIPort *port = &s->rhport[port1->index];
-    uint32_t old_state = port->ctrl;
-
-    ohci_async_cancel_device(s, port1->dev);
-
-    /* set connect status */
-    if (port->ctrl & OHCI_PORT_CCS) {
-        port->ctrl &= ~OHCI_PORT_CCS;
-        port->ctrl |= OHCI_PORT_CSC;
-    }
-    /* disable port */
-    if (port->ctrl & OHCI_PORT_PES) {
-        port->ctrl &= ~OHCI_PORT_PES;
-        port->ctrl |= OHCI_PORT_PESC;
-    }
-    DPRINTF("usb-ohci: Detached port %d\n", port1->index);
-
-    if (old_state != port->ctrl) {
-        ohci_set_interrupt(s, OHCI_INTR_RHSC);
-    }
-}
-
-static void ohci_wakeup(USBPort *port1)
-{
-    OHCIState *s = port1->opaque;
-    OHCIPort *port = &s->rhport[port1->index];
-    uint32_t intr = 0;
-    if (port->ctrl & OHCI_PORT_PSS) {
-        DPRINTF("usb-ohci: port %d: wakeup\n", port1->index);
-        port->ctrl |= OHCI_PORT_PSSC;
-        port->ctrl &= ~OHCI_PORT_PSS;
-        intr = OHCI_INTR_RHSC;
-    }
-    /* Note that the controller can be suspended even if this port is not */
-    if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
-        DPRINTF("usb-ohci: remote-wakeup: SUSPEND->RESUME\n");
-        /* This is the one state transition the controller can do by itself */
-        s->ctl &= ~OHCI_CTL_HCFS;
-        s->ctl |= OHCI_USB_RESUME;
-        /* In suspend mode only ResumeDetected is possible, not RHSC:
-         * see the OHCI spec 5.1.2.3.
-         */
-        intr = OHCI_INTR_RD;
-    }
-    ohci_set_interrupt(s, intr);
-}
-
-static void ohci_child_detach(USBPort *port1, USBDevice *child)
-{
-    OHCIState *s = port1->opaque;
-
-    ohci_async_cancel_device(s, child);
-}
-
-static USBDevice *ohci_find_device(OHCIState *ohci, uint8_t addr)
-{
-    USBDevice *dev;
-    int i;
-
-    for (i = 0; i < ohci->num_ports; i++) {
-        if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0) {
-            continue;
-        }
-        dev = usb_find_device(&ohci->rhport[i].port, addr);
-        if (dev != NULL) {
-            return dev;
-        }
-    }
-    return NULL;
-}
-
-/* Reset the controller */
-static void ohci_reset(void *opaque)
-{
-    OHCIState *ohci = opaque;
-    OHCIPort *port;
-    int i;
-
-    ohci_bus_stop(ohci);
-    ohci->ctl = 0;
-    ohci->old_ctl = 0;
-    ohci->status = 0;
-    ohci->intr_status = 0;
-    ohci->intr = OHCI_INTR_MIE;
-
-    ohci->hcca = 0;
-    ohci->ctrl_head = ohci->ctrl_cur = 0;
-    ohci->bulk_head = ohci->bulk_cur = 0;
-    ohci->per_cur = 0;
-    ohci->done = 0;
-    ohci->done_count = 7;
-
-    /* FSMPS is marked TBD in OCHI 1.0, what gives ffs?
-     * I took the value linux sets ...
-     */
-    ohci->fsmps = 0x2778;
-    ohci->fi = 0x2edf;
-    ohci->fit = 0;
-    ohci->frt = 0;
-    ohci->frame_number = 0;
-    ohci->pstart = 0;
-    ohci->lst = OHCI_LS_THRESH;
-
-    ohci->rhdesc_a = OHCI_RHA_NPS | ohci->num_ports;
-    ohci->rhdesc_b = 0x0; /* Impl. specific */
-    ohci->rhstatus = 0;
-
-    for (i = 0; i < ohci->num_ports; i++)
-      {
-        port = &ohci->rhport[i];
-        port->ctrl = 0;
-        if (port->port.dev && port->port.dev->attached) {
-            usb_port_reset(&port->port);
-        }
-      }
-    if (ohci->async_td) {
-        usb_cancel_packet(&ohci->usb_packet);
-        ohci->async_td = 0;
-    }
-    DPRINTF("usb-ohci: Reset %s\n", ohci->name);
-}
-
-/* Get an array of dwords from main memory */
-static inline int get_dwords(OHCIState *ohci,
-                             uint32_t addr, uint32_t *buf, int num)
-{
-    int i;
-
-    addr += ohci->localmem_base;
-
-    for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
-        cpu_physical_memory_read(addr, buf, sizeof(*buf));
-        *buf = le32_to_cpu(*buf);
-    }
-
-    return 1;
-}
-
-/* Put an array of dwords in to main memory */
-static inline int put_dwords(OHCIState *ohci,
-                             uint32_t addr, uint32_t *buf, int num)
-{
-    int i;
-
-    addr += ohci->localmem_base;
-
-    for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
-        uint32_t tmp = cpu_to_le32(*buf);
-        cpu_physical_memory_write(addr, &tmp, sizeof(tmp));
-    }
-
-    return 1;
-}
-
-/* Get an array of words from main memory */
-static inline int get_words(OHCIState *ohci,
-                            uint32_t addr, uint16_t *buf, int num)
-{
-    int i;
-
-    addr += ohci->localmem_base;
-
-    for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
-        cpu_physical_memory_read(addr, buf, sizeof(*buf));
-        *buf = le16_to_cpu(*buf);
-    }
-
-    return 1;
-}
-
-/* Put an array of words in to main memory */
-static inline int put_words(OHCIState *ohci,
-                            uint32_t addr, uint16_t *buf, int num)
-{
-    int i;
-
-    addr += ohci->localmem_base;
-
-    for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
-        uint16_t tmp = cpu_to_le16(*buf);
-        cpu_physical_memory_write(addr, &tmp, sizeof(tmp));
-    }
-
-    return 1;
-}
-
-static inline int ohci_read_ed(OHCIState *ohci,
-                               uint32_t addr, struct ohci_ed *ed)
-{
-    return get_dwords(ohci, addr, (uint32_t *)ed, sizeof(*ed) >> 2);
-}
-
-static inline int ohci_read_td(OHCIState *ohci,
-                               uint32_t addr, struct ohci_td *td)
-{
-    return get_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2);
-}
-
-static inline int ohci_read_iso_td(OHCIState *ohci,
-                                   uint32_t addr, struct ohci_iso_td *td)
-{
-    return (get_dwords(ohci, addr, (uint32_t *)td, 4) &&
-            get_words(ohci, addr + 16, td->offset, 8));
-}
-
-static inline int ohci_read_hcca(OHCIState *ohci,
-                                 uint32_t addr, struct ohci_hcca *hcca)
-{
-    cpu_physical_memory_read(addr + ohci->localmem_base, hcca, sizeof(*hcca));
-    return 1;
-}
-
-static inline int ohci_put_ed(OHCIState *ohci,
-                              uint32_t addr, struct ohci_ed *ed)
-{
-    return put_dwords(ohci, addr, (uint32_t *)ed, sizeof(*ed) >> 2);
-}
-
-static inline int ohci_put_td(OHCIState *ohci,
-                              uint32_t addr, struct ohci_td *td)
-{
-    return put_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2);
-}
-
-static inline int ohci_put_iso_td(OHCIState *ohci,
-                                  uint32_t addr, struct ohci_iso_td *td)
-{
-    return (put_dwords(ohci, addr, (uint32_t *)td, 4) &&
-            put_words(ohci, addr + 16, td->offset, 8));
-}
-
-static inline int ohci_put_hcca(OHCIState *ohci,
-                                uint32_t addr, struct ohci_hcca *hcca)
-{
-    cpu_physical_memory_write(addr + ohci->localmem_base, hcca, sizeof(*hcca));
-    return 1;
-}
-
-/* Read/Write the contents of a TD from/to main memory.  */
-static void ohci_copy_td(OHCIState *ohci, struct ohci_td *td,
-                         uint8_t *buf, int len, int write)
-{
-    uint32_t ptr;
-    uint32_t n;
-
-    ptr = td->cbp;
-    n = 0x1000 - (ptr & 0xfff);
-    if (n > len)
-        n = len;
-    cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, n, write);
-    if (n == len)
-        return;
-    ptr = td->be & ~0xfffu;
-    buf += n;
-    cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, len - n, write);
-}
-
-/* Read/Write the contents of an ISO TD from/to main memory.  */
-static void ohci_copy_iso_td(OHCIState *ohci,
-                             uint32_t start_addr, uint32_t end_addr,
-                             uint8_t *buf, int len, int write)
-{
-    uint32_t ptr;
-    uint32_t n;
-
-    ptr = start_addr;
-    n = 0x1000 - (ptr & 0xfff);
-    if (n > len)
-        n = len;
-    cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, n, write);
-    if (n == len)
-        return;
-    ptr = end_addr & ~0xfffu;
-    buf += n;
-    cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, len - n, write);
-}
-
-static void ohci_process_lists(OHCIState *ohci, int completion);
-
-static void ohci_async_complete_packet(USBPort *port, USBPacket *packet)
-{
-    OHCIState *ohci = container_of(packet, OHCIState, usb_packet);
-#ifdef DEBUG_PACKET
-    DPRINTF("Async packet complete\n");
-#endif
-    ohci->async_complete = 1;
-    ohci_process_lists(ohci, 1);
-}
-
-#define USUB(a, b) ((int16_t)((uint16_t)(a) - (uint16_t)(b)))
-
-static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
-                               int completion)
-{
-    int dir;
-    size_t len = 0;
-#ifdef DEBUG_ISOCH
-    const char *str = NULL;
-#endif
-    int pid;
-    int ret;
-    int i;
-    USBDevice *dev;
-    USBEndpoint *ep;
-    struct ohci_iso_td iso_td;
-    uint32_t addr;
-    uint16_t starting_frame;
-    int16_t relative_frame_number;
-    int frame_count;
-    uint32_t start_offset, next_offset, end_offset = 0;
-    uint32_t start_addr, end_addr;
-
-    addr = ed->head & OHCI_DPTR_MASK;
-
-    if (!ohci_read_iso_td(ohci, addr, &iso_td)) {
-        printf("usb-ohci: ISO_TD read error at %x\n", addr);
-        return 0;
-    }
-
-    starting_frame = OHCI_BM(iso_td.flags, TD_SF);
-    frame_count = OHCI_BM(iso_td.flags, TD_FC);
-    relative_frame_number = USUB(ohci->frame_number, starting_frame); 
-
-#ifdef DEBUG_ISOCH
-    printf("--- ISO_TD ED head 0x%.8x tailp 0x%.8x\n"
-           "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n"
-           "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n"
-           "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n"
-           "frame_number 0x%.8x starting_frame 0x%.8x\n"
-           "frame_count  0x%.8x relative %d\n"
-           "di 0x%.8x cc 0x%.8x\n",
-           ed->head & OHCI_DPTR_MASK, ed->tail & OHCI_DPTR_MASK,
-           iso_td.flags, iso_td.bp, iso_td.next, iso_td.be,
-           iso_td.offset[0], iso_td.offset[1], iso_td.offset[2], iso_td.offset[3],
-           iso_td.offset[4], iso_td.offset[5], iso_td.offset[6], iso_td.offset[7],
-           ohci->frame_number, starting_frame, 
-           frame_count, relative_frame_number,         
-           OHCI_BM(iso_td.flags, TD_DI), OHCI_BM(iso_td.flags, TD_CC));
-#endif
-
-    if (relative_frame_number < 0) {
-        DPRINTF("usb-ohci: ISO_TD R=%d < 0\n", relative_frame_number);
-        return 1;
-    } else if (relative_frame_number > frame_count) {
-        /* ISO TD expired - retire the TD to the Done Queue and continue with
-           the next ISO TD of the same ED */
-        DPRINTF("usb-ohci: ISO_TD R=%d > FC=%d\n", relative_frame_number, 
-               frame_count);
-        OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_DATAOVERRUN);
-        ed->head &= ~OHCI_DPTR_MASK;
-        ed->head |= (iso_td.next & OHCI_DPTR_MASK);
-        iso_td.next = ohci->done;
-        ohci->done = addr;
-        i = OHCI_BM(iso_td.flags, TD_DI);
-        if (i < ohci->done_count)
-            ohci->done_count = i;
-        ohci_put_iso_td(ohci, addr, &iso_td);
-        return 0;
-    }
-
-    dir = OHCI_BM(ed->flags, ED_D);
-    switch (dir) {
-    case OHCI_TD_DIR_IN:
-#ifdef DEBUG_ISOCH
-        str = "in";
-#endif
-        pid = USB_TOKEN_IN;
-        break;
-    case OHCI_TD_DIR_OUT:
-#ifdef DEBUG_ISOCH
-        str = "out";
-#endif
-        pid = USB_TOKEN_OUT;
-        break;
-    case OHCI_TD_DIR_SETUP:
-#ifdef DEBUG_ISOCH
-        str = "setup";
-#endif
-        pid = USB_TOKEN_SETUP;
-        break;
-    default:
-        printf("usb-ohci: Bad direction %d\n", dir);
-        return 1;
-    }
-
-    if (!iso_td.bp || !iso_td.be) {
-        printf("usb-ohci: ISO_TD bp 0x%.8x be 0x%.8x\n", iso_td.bp, iso_td.be);
-        return 1;
-    }
-
-    start_offset = iso_td.offset[relative_frame_number];
-    next_offset = iso_td.offset[relative_frame_number + 1];
-
-    if (!(OHCI_BM(start_offset, TD_PSW_CC) & 0xe) || 
-        ((relative_frame_number < frame_count) && 
-         !(OHCI_BM(next_offset, TD_PSW_CC) & 0xe))) {
-        printf("usb-ohci: ISO_TD cc != not accessed 0x%.8x 0x%.8x\n",
-               start_offset, next_offset);
-        return 1;
-    }
-
-    if ((relative_frame_number < frame_count) && (start_offset > next_offset)) {
-        printf("usb-ohci: ISO_TD start_offset=0x%.8x > next_offset=0x%.8x\n",
-                start_offset, next_offset);
-        return 1;
-    }
-
-    if ((start_offset & 0x1000) == 0) {
-        start_addr = (iso_td.bp & OHCI_PAGE_MASK) |
-            (start_offset & OHCI_OFFSET_MASK);
-    } else {
-        start_addr = (iso_td.be & OHCI_PAGE_MASK) |
-            (start_offset & OHCI_OFFSET_MASK);
-    }
-
-    if (relative_frame_number < frame_count) {
-        end_offset = next_offset - 1;
-        if ((end_offset & 0x1000) == 0) {
-            end_addr = (iso_td.bp & OHCI_PAGE_MASK) |
-                (end_offset & OHCI_OFFSET_MASK);
-        } else {
-            end_addr = (iso_td.be & OHCI_PAGE_MASK) |
-                (end_offset & OHCI_OFFSET_MASK);
-        }
-    } else {
-        /* Last packet in the ISO TD */
-        end_addr = iso_td.be;
-    }
-
-    if ((start_addr & OHCI_PAGE_MASK) != (end_addr & OHCI_PAGE_MASK)) {
-        len = (end_addr & OHCI_OFFSET_MASK) + 0x1001
-            - (start_addr & OHCI_OFFSET_MASK);
-    } else {
-        len = end_addr - start_addr + 1;
-    }
-
-    if (len && dir != OHCI_TD_DIR_IN) {
-        ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, len, 0);
-    }
-
-    if (completion) {
-        ret = ohci->usb_packet.result;
-    } else {
-        dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
-        ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
-        usb_packet_setup(&ohci->usb_packet, pid, ep);
-        usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
-        ret = usb_handle_packet(dev, &ohci->usb_packet);
-        if (ret == USB_RET_ASYNC) {
-            return 1;
-        }
-    }
-
-#ifdef DEBUG_ISOCH
-    printf("so 0x%.8x eo 0x%.8x\nsa 0x%.8x ea 0x%.8x\ndir %s len %zu ret %d\n",
-           start_offset, end_offset, start_addr, end_addr, str, len, ret);
-#endif
-
-    /* Writeback */
-    if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) {
-        /* IN transfer succeeded */
-        ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, ret, 1);
-        OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
-                    OHCI_CC_NOERROR);
-        OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ret);
-    } else if (dir == OHCI_TD_DIR_OUT && ret == len) {
-        /* OUT transfer succeeded */
-        OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
-                    OHCI_CC_NOERROR);
-        OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 0);
-    } else {
-        if (ret > (ssize_t) len) {
-            printf("usb-ohci: DataOverrun %d > %zu\n", ret, len);
-            OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
-                        OHCI_CC_DATAOVERRUN);
-            OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
-                        len);
-        } else if (ret >= 0) {
-            printf("usb-ohci: DataUnderrun %d\n", ret);
-            OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
-                        OHCI_CC_DATAUNDERRUN);
-        } else {
-            switch (ret) {
-            case USB_RET_IOERROR:
-            case USB_RET_NODEV:
-                OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
-                            OHCI_CC_DEVICENOTRESPONDING);
-                OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
-                            0);
-                break;
-            case USB_RET_NAK:
-            case USB_RET_STALL:
-                printf("usb-ohci: got NAK/STALL %d\n", ret);
-                OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
-                            OHCI_CC_STALL);
-                OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
-                            0);
-                break;
-            default:
-                printf("usb-ohci: Bad device response %d\n", ret);
-                OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
-                            OHCI_CC_UNDEXPETEDPID);
-                break;
-            }
-        }
-    }
-
-    if (relative_frame_number == frame_count) {
-        /* Last data packet of ISO TD - retire the TD to the Done Queue */
-        OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_NOERROR);
-        ed->head &= ~OHCI_DPTR_MASK;
-        ed->head |= (iso_td.next & OHCI_DPTR_MASK);
-        iso_td.next = ohci->done;
-        ohci->done = addr;
-        i = OHCI_BM(iso_td.flags, TD_DI);
-        if (i < ohci->done_count)
-            ohci->done_count = i;
-    }
-    ohci_put_iso_td(ohci, addr, &iso_td);
-    return 1;
-}
-
-/* Service a transport descriptor.
-   Returns nonzero to terminate processing of this endpoint.  */
-
-static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
-{
-    int dir;
-    size_t len = 0, pktlen = 0;
-#ifdef DEBUG_PACKET
-    const char *str = NULL;
-#endif
-    int pid;
-    int ret;
-    int i;
-    USBDevice *dev;
-    USBEndpoint *ep;
-    struct ohci_td td;
-    uint32_t addr;
-    int flag_r;
-    int completion;
-
-    addr = ed->head & OHCI_DPTR_MASK;
-    /* See if this TD has already been submitted to the device.  */
-    completion = (addr == ohci->async_td);
-    if (completion && !ohci->async_complete) {
-#ifdef DEBUG_PACKET
-        DPRINTF("Skipping async TD\n");
-#endif
-        return 1;
-    }
-    if (!ohci_read_td(ohci, addr, &td)) {
-        fprintf(stderr, "usb-ohci: TD read error at %x\n", addr);
-        return 0;
-    }
-
-    dir = OHCI_BM(ed->flags, ED_D);
-    switch (dir) {
-    case OHCI_TD_DIR_OUT:
-    case OHCI_TD_DIR_IN:
-        /* Same value.  */
-        break;
-    default:
-        dir = OHCI_BM(td.flags, TD_DP);
-        break;
-    }
-
-    switch (dir) {
-    case OHCI_TD_DIR_IN:
-#ifdef DEBUG_PACKET
-        str = "in";
-#endif
-        pid = USB_TOKEN_IN;
-        break;
-    case OHCI_TD_DIR_OUT:
-#ifdef DEBUG_PACKET
-        str = "out";
-#endif
-        pid = USB_TOKEN_OUT;
-        break;
-    case OHCI_TD_DIR_SETUP:
-#ifdef DEBUG_PACKET
-        str = "setup";
-#endif
-        pid = USB_TOKEN_SETUP;
-        break;
-    default:
-        fprintf(stderr, "usb-ohci: Bad direction\n");
-        return 1;
-    }
-    if (td.cbp && td.be) {
-        if ((td.cbp & 0xfffff000) != (td.be & 0xfffff000)) {
-            len = (td.be & 0xfff) + 0x1001 - (td.cbp & 0xfff);
-        } else {
-            len = (td.be - td.cbp) + 1;
-        }
-
-        pktlen = len;
-        if (len && dir != OHCI_TD_DIR_IN) {
-            /* The endpoint may not allow us to transfer it all now */
-            pktlen = (ed->flags & OHCI_ED_MPS_MASK) >> OHCI_ED_MPS_SHIFT;
-            if (pktlen > len) {
-                pktlen = len;
-            }
-            if (!completion) {
-                ohci_copy_td(ohci, &td, ohci->usb_buf, pktlen, 0);
-            }
-        }
-    }
-
-    flag_r = (td.flags & OHCI_TD_R) != 0;
-#ifdef DEBUG_PACKET
-    DPRINTF(" TD @ 0x%.8x %" PRId64 " of %" PRId64
-            " bytes %s r=%d cbp=0x%.8x be=0x%.8x\n",
-            addr, (int64_t)pktlen, (int64_t)len, str, flag_r, td.cbp, td.be);
-
-    if (pktlen > 0 && dir != OHCI_TD_DIR_IN) {
-        DPRINTF("  data:");
-        for (i = 0; i < pktlen; i++) {
-            printf(" %.2x", ohci->usb_buf[i]);
-        }
-        DPRINTF("\n");
-    }
-#endif
-    if (completion) {
-        ret = ohci->usb_packet.result;
-        ohci->async_td = 0;
-        ohci->async_complete = 0;
-    } else {
-        if (ohci->async_td) {
-            /* ??? The hardware should allow one active packet per
-               endpoint.  We only allow one active packet per controller.
-               This should be sufficient as long as devices respond in a
-               timely manner.
-            */
-#ifdef DEBUG_PACKET
-            DPRINTF("Too many pending packets\n");
-#endif
-            return 1;
-        }
-        dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
-        ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
-        usb_packet_setup(&ohci->usb_packet, pid, ep);
-        usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen);
-        ret = usb_handle_packet(dev, &ohci->usb_packet);
-#ifdef DEBUG_PACKET
-        DPRINTF("ret=%d\n", ret);
-#endif
-        if (ret == USB_RET_ASYNC) {
-            ohci->async_td = addr;
-            return 1;
-        }
-    }
-    if (ret >= 0) {
-        if (dir == OHCI_TD_DIR_IN) {
-            ohci_copy_td(ohci, &td, ohci->usb_buf, ret, 1);
-#ifdef DEBUG_PACKET
-            DPRINTF("  data:");
-            for (i = 0; i < ret; i++)
-                printf(" %.2x", ohci->usb_buf[i]);
-            DPRINTF("\n");
-#endif
-        } else {
-            ret = pktlen;
-        }
-    }
-
-    /* Writeback */
-    if (ret == pktlen || (dir == OHCI_TD_DIR_IN && ret >= 0 && flag_r)) {
-        /* Transmission succeeded.  */
-        if (ret == len) {
-            td.cbp = 0;
-        } else {
-            if ((td.cbp & 0xfff) + ret > 0xfff) {
-                td.cbp = (td.be & ~0xfff) + ((td.cbp + ret) & 0xfff);
-            } else {
-                td.cbp += ret;
-            }
-        }
-        td.flags |= OHCI_TD_T1;
-        td.flags ^= OHCI_TD_T0;
-        OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_NOERROR);
-        OHCI_SET_BM(td.flags, TD_EC, 0);
-
-        if ((dir != OHCI_TD_DIR_IN) && (ret != len)) {
-            /* Partial packet transfer: TD not ready to retire yet */
-            goto exit_no_retire;
-        }
-
-        /* Setting ED_C is part of the TD retirement process */
-        ed->head &= ~OHCI_ED_C;
-        if (td.flags & OHCI_TD_T0)
-            ed->head |= OHCI_ED_C;
-    } else {
-        if (ret >= 0) {
-            DPRINTF("usb-ohci: Underrun\n");
-            OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAUNDERRUN);
-        } else {
-            switch (ret) {
-            case USB_RET_IOERROR:
-            case USB_RET_NODEV:
-                OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING);
-            case USB_RET_NAK:
-                DPRINTF("usb-ohci: got NAK\n");
-                return 1;
-            case USB_RET_STALL:
-                DPRINTF("usb-ohci: got STALL\n");
-                OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_STALL);
-                break;
-            case USB_RET_BABBLE:
-                DPRINTF("usb-ohci: got BABBLE\n");
-                OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAOVERRUN);
-                break;
-            default:
-                fprintf(stderr, "usb-ohci: Bad device response %d\n", ret);
-                OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_UNDEXPETEDPID);
-                OHCI_SET_BM(td.flags, TD_EC, 3);
-                break;
-            }
-        }
-        ed->head |= OHCI_ED_H;
-    }
-
-    /* Retire this TD */
-    ed->head &= ~OHCI_DPTR_MASK;
-    ed->head |= td.next & OHCI_DPTR_MASK;
-    td.next = ohci->done;
-    ohci->done = addr;
-    i = OHCI_BM(td.flags, TD_DI);
-    if (i < ohci->done_count)
-        ohci->done_count = i;
-exit_no_retire:
-    ohci_put_td(ohci, addr, &td);
-    return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR;
-}
-
-/* Service an endpoint list.  Returns nonzero if active TD were found.  */
-static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion)
-{
-    struct ohci_ed ed;
-    uint32_t next_ed;
-    uint32_t cur;
-    int active;
-
-    active = 0;
-
-    if (head == 0)
-        return 0;
-
-    for (cur = head; cur; cur = next_ed) {
-        if (!ohci_read_ed(ohci, cur, &ed)) {
-            fprintf(stderr, "usb-ohci: ED read error at %x\n", cur);
-            return 0;
-        }
-
-        next_ed = ed.next & OHCI_DPTR_MASK;
-
-        if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K)) {
-            uint32_t addr;
-            /* Cancel pending packets for ED that have been paused.  */
-            addr = ed.head & OHCI_DPTR_MASK;
-            if (ohci->async_td && addr == ohci->async_td) {
-                usb_cancel_packet(&ohci->usb_packet);
-                ohci->async_td = 0;
-            }
-            continue;
-        }
-
-        while ((ed.head & OHCI_DPTR_MASK) != ed.tail) {
-#ifdef DEBUG_PACKET
-            DPRINTF("ED @ 0x%.8x fa=%u en=%u d=%u s=%u k=%u f=%u mps=%u "
-                    "h=%u c=%u\n  head=0x%.8x tailp=0x%.8x next=0x%.8x\n", cur,
-                    OHCI_BM(ed.flags, ED_FA), OHCI_BM(ed.flags, ED_EN),
-                    OHCI_BM(ed.flags, ED_D), (ed.flags & OHCI_ED_S)!= 0,
-                    (ed.flags & OHCI_ED_K) != 0, (ed.flags & OHCI_ED_F) != 0,
-                    OHCI_BM(ed.flags, ED_MPS), (ed.head & OHCI_ED_H) != 0,
-                    (ed.head & OHCI_ED_C) != 0, ed.head & OHCI_DPTR_MASK,
-                    ed.tail & OHCI_DPTR_MASK, ed.next & OHCI_DPTR_MASK);
-#endif
-            active = 1;
-
-            if ((ed.flags & OHCI_ED_F) == 0) {
-                if (ohci_service_td(ohci, &ed))
-                    break;
-            } else {
-                /* Handle isochronous endpoints */
-                if (ohci_service_iso_td(ohci, &ed, completion))
-                    break;
-            }
-        }
-
-        ohci_put_ed(ohci, cur, &ed);
-    }
-
-    return active;
-}
-
-/* Generate a SOF event, and set a timer for EOF */
-static void ohci_sof(OHCIState *ohci)
-{
-    ohci->sof_time = qemu_get_clock_ns(vm_clock);
-    qemu_mod_timer(ohci->eof_timer, ohci->sof_time + usb_frame_time);
-    ohci_set_interrupt(ohci, OHCI_INTR_SF);
-}
-
-/* Process Control and Bulk lists.  */
-static void ohci_process_lists(OHCIState *ohci, int completion)
-{
-    if ((ohci->ctl & OHCI_CTL_CLE) && (ohci->status & OHCI_STATUS_CLF)) {
-        if (ohci->ctrl_cur && ohci->ctrl_cur != ohci->ctrl_head) {
-            DPRINTF("usb-ohci: head %x, cur %x\n",
-                    ohci->ctrl_head, ohci->ctrl_cur);
-        }
-        if (!ohci_service_ed_list(ohci, ohci->ctrl_head, completion)) {
-            ohci->ctrl_cur = 0;
-            ohci->status &= ~OHCI_STATUS_CLF;
-        }
-    }
-
-    if ((ohci->ctl & OHCI_CTL_BLE) && (ohci->status & OHCI_STATUS_BLF)) {
-        if (!ohci_service_ed_list(ohci, ohci->bulk_head, completion)) {
-            ohci->bulk_cur = 0;
-            ohci->status &= ~OHCI_STATUS_BLF;
-        }
-    }
-}
-
-/* Do frame processing on frame boundary */
-static void ohci_frame_boundary(void *opaque)
-{
-    OHCIState *ohci = opaque;
-    struct ohci_hcca hcca;
-
-    ohci_read_hcca(ohci, ohci->hcca, &hcca);
-
-    /* Process all the lists at the end of the frame */
-    if (ohci->ctl & OHCI_CTL_PLE) {
-        int n;
-
-        n = ohci->frame_number & 0x1f;
-        ohci_service_ed_list(ohci, le32_to_cpu(hcca.intr[n]), 0);
-    }
-
-    /* Cancel all pending packets if either of the lists has been disabled.  */
-    if (ohci->async_td &&
-        ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) {
-        usb_cancel_packet(&ohci->usb_packet);
-        ohci->async_td = 0;
-    }
-    ohci->old_ctl = ohci->ctl;
-    ohci_process_lists(ohci, 0);
-
-    /* Frame boundary, so do EOF stuf here */
-    ohci->frt = ohci->fit;
-
-    /* Increment frame number and take care of endianness. */
-    ohci->frame_number = (ohci->frame_number + 1) & 0xffff;
-    hcca.frame = cpu_to_le16(ohci->frame_number);
-
-    if (ohci->done_count == 0 && !(ohci->intr_status & OHCI_INTR_WD)) {
-        if (!ohci->done)
-            abort();
-        if (ohci->intr & ohci->intr_status)
-            ohci->done |= 1;
-        hcca.done = cpu_to_le32(ohci->done);
-        ohci->done = 0;
-        ohci->done_count = 7;
-        ohci_set_interrupt(ohci, OHCI_INTR_WD);
-    }
-
-    if (ohci->done_count != 7 && ohci->done_count != 0)
-        ohci->done_count--;
-
-    /* Do SOF stuff here */
-    ohci_sof(ohci);
-
-    /* Writeback HCCA */
-    ohci_put_hcca(ohci, ohci->hcca, &hcca);
-}
-
-/* Start sending SOF tokens across the USB bus, lists are processed in
- * next frame
- */
-static int ohci_bus_start(OHCIState *ohci)
-{
-    ohci->eof_timer = qemu_new_timer_ns(vm_clock,
-                    ohci_frame_boundary,
-                    ohci);
-
-    if (ohci->eof_timer == NULL) {
-        fprintf(stderr, "usb-ohci: %s: qemu_new_timer_ns failed\n", ohci->name);
-        /* TODO: Signal unrecoverable error */
-        return 0;
-    }
-
-    DPRINTF("usb-ohci: %s: USB Operational\n", ohci->name);
-
-    ohci_sof(ohci);
-
-    return 1;
-}
-
-/* Stop sending SOF tokens on the bus */
-static void ohci_bus_stop(OHCIState *ohci)
-{
-    if (ohci->eof_timer)
-        qemu_del_timer(ohci->eof_timer);
-    ohci->eof_timer = NULL;
-}
-
-/* Sets a flag in a port status register but only set it if the port is
- * connected, if not set ConnectStatusChange flag. If flag is enabled
- * return 1.
- */
-static int ohci_port_set_if_connected(OHCIState *ohci, int i, uint32_t val)
-{
-    int ret = 1;
-
-    /* writing a 0 has no effect */
-    if (val == 0)
-        return 0;
-
-    /* If CurrentConnectStatus is cleared we set
-     * ConnectStatusChange
-     */
-    if (!(ohci->rhport[i].ctrl & OHCI_PORT_CCS)) {
-        ohci->rhport[i].ctrl |= OHCI_PORT_CSC;
-        if (ohci->rhstatus & OHCI_RHS_DRWE) {
-            /* TODO: CSC is a wakeup event */
-        }
-        return 0;
-    }
-
-    if (ohci->rhport[i].ctrl & val)
-        ret = 0;
-
-    /* set the bit */
-    ohci->rhport[i].ctrl |= val;
-
-    return ret;
-}
-
-/* Set the frame interval - frame interval toggle is manipulated by the hcd only */
-static void ohci_set_frame_interval(OHCIState *ohci, uint16_t val)
-{
-    val &= OHCI_FMI_FI;
-
-    if (val != ohci->fi) {
-        DPRINTF("usb-ohci: %s: FrameInterval = 0x%x (%u)\n",
-            ohci->name, ohci->fi, ohci->fi);
-    }
-
-    ohci->fi = val;
-}
-
-static void ohci_port_power(OHCIState *ohci, int i, int p)
-{
-    if (p) {
-        ohci->rhport[i].ctrl |= OHCI_PORT_PPS;
-    } else {
-        ohci->rhport[i].ctrl &= ~(OHCI_PORT_PPS|
-                    OHCI_PORT_CCS|
-                    OHCI_PORT_PSS|
-                    OHCI_PORT_PRS);
-    }
-}
-
-/* Set HcControlRegister */
-static void ohci_set_ctl(OHCIState *ohci, uint32_t val)
-{
-    uint32_t old_state;
-    uint32_t new_state;
-
-    old_state = ohci->ctl & OHCI_CTL_HCFS;
-    ohci->ctl = val;
-    new_state = ohci->ctl & OHCI_CTL_HCFS;
-
-    /* no state change */
-    if (old_state == new_state)
-        return;
-
-    switch (new_state) {
-    case OHCI_USB_OPERATIONAL:
-        ohci_bus_start(ohci);
-        break;
-    case OHCI_USB_SUSPEND:
-        ohci_bus_stop(ohci);
-        DPRINTF("usb-ohci: %s: USB Suspended\n", ohci->name);
-        break;
-    case OHCI_USB_RESUME:
-        DPRINTF("usb-ohci: %s: USB Resume\n", ohci->name);
-        break;
-    case OHCI_USB_RESET:
-        ohci_reset(ohci);
-        DPRINTF("usb-ohci: %s: USB Reset\n", ohci->name);
-        break;
-    }
-}
-
-static uint32_t ohci_get_frame_remaining(OHCIState *ohci)
-{
-    uint16_t fr;
-    int64_t tks;
-
-    if ((ohci->ctl & OHCI_CTL_HCFS) != OHCI_USB_OPERATIONAL)
-        return (ohci->frt << 31);
-
-    /* Being in USB operational state guarnatees sof_time was
-     * set already.
-     */
-    tks = qemu_get_clock_ns(vm_clock) - ohci->sof_time;
-
-    /* avoid muldiv if possible */
-    if (tks >= usb_frame_time)
-        return (ohci->frt << 31);
-
-    tks = muldiv64(1, tks, usb_bit_time);
-    fr = (uint16_t)(ohci->fi - tks);
-
-    return (ohci->frt << 31) | fr;
-}
-
-
-/* Set root hub status */
-static void ohci_set_hub_status(OHCIState *ohci, uint32_t val)
-{
-    uint32_t old_state;
-
-    old_state = ohci->rhstatus;
-
-    /* write 1 to clear OCIC */
-    if (val & OHCI_RHS_OCIC)
-        ohci->rhstatus &= ~OHCI_RHS_OCIC;
-
-    if (val & OHCI_RHS_LPS) {
-        int i;
-
-        for (i = 0; i < ohci->num_ports; i++)
-            ohci_port_power(ohci, i, 0);
-        DPRINTF("usb-ohci: powered down all ports\n");
-    }
-
-    if (val & OHCI_RHS_LPSC) {
-        int i;
-
-        for (i = 0; i < ohci->num_ports; i++)
-            ohci_port_power(ohci, i, 1);
-        DPRINTF("usb-ohci: powered up all ports\n");
-    }
-
-    if (val & OHCI_RHS_DRWE)
-        ohci->rhstatus |= OHCI_RHS_DRWE;
-
-    if (val & OHCI_RHS_CRWE)
-        ohci->rhstatus &= ~OHCI_RHS_DRWE;
-
-    if (old_state != ohci->rhstatus)
-        ohci_set_interrupt(ohci, OHCI_INTR_RHSC);
-}
-
-/* Set root hub port status */
-static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val)
-{
-    uint32_t old_state;
-    OHCIPort *port;
-
-    port = &ohci->rhport[portnum];
-    old_state = port->ctrl;
-
-    /* Write to clear CSC, PESC, PSSC, OCIC, PRSC */
-    if (val & OHCI_PORT_WTC)
-        port->ctrl &= ~(val & OHCI_PORT_WTC);
-
-    if (val & OHCI_PORT_CCS)
-        port->ctrl &= ~OHCI_PORT_PES;
-
-    ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PES);
-
-    if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PSS)) {
-        DPRINTF("usb-ohci: port %d: SUSPEND\n", portnum);
-    }
-
-    if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PRS)) {
-        DPRINTF("usb-ohci: port %d: RESET\n", portnum);
-        usb_device_reset(port->port.dev);
-        port->ctrl &= ~OHCI_PORT_PRS;
-        /* ??? Should this also set OHCI_PORT_PESC.  */
-        port->ctrl |= OHCI_PORT_PES | OHCI_PORT_PRSC;
-    }
-
-    /* Invert order here to ensure in ambiguous case, device is
-     * powered up...
-     */
-    if (val & OHCI_PORT_LSDA)
-        ohci_port_power(ohci, portnum, 0);
-    if (val & OHCI_PORT_PPS)
-        ohci_port_power(ohci, portnum, 1);
-
-    if (old_state != port->ctrl)
-        ohci_set_interrupt(ohci, OHCI_INTR_RHSC);
-
-    return;
-}
-
-static uint64_t ohci_mem_read(void *opaque,
-                              target_phys_addr_t addr,
-                              unsigned size)
-{
-    OHCIState *ohci = opaque;
-    uint32_t retval;
-
-    /* Only aligned reads are allowed on OHCI */
-    if (addr & 3) {
-        fprintf(stderr, "usb-ohci: Mis-aligned read\n");
-        return 0xffffffff;
-    } else if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) {
-        /* HcRhPortStatus */
-        retval = ohci->rhport[(addr - 0x54) >> 2].ctrl | OHCI_PORT_PPS;
-    } else {
-        switch (addr >> 2) {
-        case 0: /* HcRevision */
-            retval = 0x10;
-            break;
-
-        case 1: /* HcControl */
-            retval = ohci->ctl;
-            break;
-
-        case 2: /* HcCommandStatus */
-            retval = ohci->status;
-            break;
-
-        case 3: /* HcInterruptStatus */
-            retval = ohci->intr_status;
-            break;
-
-        case 4: /* HcInterruptEnable */
-        case 5: /* HcInterruptDisable */
-            retval = ohci->intr;
-            break;
-
-        case 6: /* HcHCCA */
-            retval = ohci->hcca;
-            break;
-
-        case 7: /* HcPeriodCurrentED */
-            retval = ohci->per_cur;
-            break;
-
-        case 8: /* HcControlHeadED */
-            retval = ohci->ctrl_head;
-            break;
-
-        case 9: /* HcControlCurrentED */
-            retval = ohci->ctrl_cur;
-            break;
-
-        case 10: /* HcBulkHeadED */
-            retval = ohci->bulk_head;
-            break;
-
-        case 11: /* HcBulkCurrentED */
-            retval = ohci->bulk_cur;
-            break;
-
-        case 12: /* HcDoneHead */
-            retval = ohci->done;
-            break;
-
-        case 13: /* HcFmInterretval */
-            retval = (ohci->fit << 31) | (ohci->fsmps << 16) | (ohci->fi);
-            break;
-
-        case 14: /* HcFmRemaining */
-            retval = ohci_get_frame_remaining(ohci);
-            break;
-
-        case 15: /* HcFmNumber */
-            retval = ohci->frame_number;
-            break;
-
-        case 16: /* HcPeriodicStart */
-            retval = ohci->pstart;
-            break;
-
-        case 17: /* HcLSThreshold */
-            retval = ohci->lst;
-            break;
-
-        case 18: /* HcRhDescriptorA */
-            retval = ohci->rhdesc_a;
-            break;
-
-        case 19: /* HcRhDescriptorB */
-            retval = ohci->rhdesc_b;
-            break;
-
-        case 20: /* HcRhStatus */
-            retval = ohci->rhstatus;
-            break;
-
-        /* PXA27x specific registers */
-        case 24: /* HcStatus */
-            retval = ohci->hstatus & ohci->hmask;
-            break;
-
-        case 25: /* HcHReset */
-            retval = ohci->hreset;
-            break;
-
-        case 26: /* HcHInterruptEnable */
-            retval = ohci->hmask;
-            break;
-
-        case 27: /* HcHInterruptTest */
-            retval = ohci->htest;
-            break;
-
-        default:
-            fprintf(stderr, "ohci_read: Bad offset %x\n", (int)addr);
-            retval = 0xffffffff;
-        }
-    }
-
-    return retval;
-}
-
-static void ohci_mem_write(void *opaque,
-                           target_phys_addr_t addr,
-                           uint64_t val,
-                           unsigned size)
-{
-    OHCIState *ohci = opaque;
-
-    /* Only aligned reads are allowed on OHCI */
-    if (addr & 3) {
-        fprintf(stderr, "usb-ohci: Mis-aligned write\n");
-        return;
-    }
-
-    if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) {
-        /* HcRhPortStatus */
-        ohci_port_set_status(ohci, (addr - 0x54) >> 2, val);
-        return;
-    }
-
-    switch (addr >> 2) {
-    case 1: /* HcControl */
-        ohci_set_ctl(ohci, val);
-        break;
-
-    case 2: /* HcCommandStatus */
-        /* SOC is read-only */
-        val = (val & ~OHCI_STATUS_SOC);
-
-        /* Bits written as '0' remain unchanged in the register */
-        ohci->status |= val;
-
-        if (ohci->status & OHCI_STATUS_HCR)
-            ohci_reset(ohci);
-        break;
-
-    case 3: /* HcInterruptStatus */
-        ohci->intr_status &= ~val;
-        ohci_intr_update(ohci);
-        break;
-
-    case 4: /* HcInterruptEnable */
-        ohci->intr |= val;
-        ohci_intr_update(ohci);
-        break;
-
-    case 5: /* HcInterruptDisable */
-        ohci->intr &= ~val;
-        ohci_intr_update(ohci);
-        break;
-
-    case 6: /* HcHCCA */
-        ohci->hcca = val & OHCI_HCCA_MASK;
-        break;
-
-    case 7: /* HcPeriodCurrentED */
-        /* Ignore writes to this read-only register, Linux does them */
-        break;
-
-    case 8: /* HcControlHeadED */
-        ohci->ctrl_head = val & OHCI_EDPTR_MASK;
-        break;
-
-    case 9: /* HcControlCurrentED */
-        ohci->ctrl_cur = val & OHCI_EDPTR_MASK;
-        break;
-
-    case 10: /* HcBulkHeadED */
-        ohci->bulk_head = val & OHCI_EDPTR_MASK;
-        break;
-
-    case 11: /* HcBulkCurrentED */
-        ohci->bulk_cur = val & OHCI_EDPTR_MASK;
-        break;
-
-    case 13: /* HcFmInterval */
-        ohci->fsmps = (val & OHCI_FMI_FSMPS) >> 16;
-        ohci->fit = (val & OHCI_FMI_FIT) >> 31;
-        ohci_set_frame_interval(ohci, val);
-        break;
-
-    case 15: /* HcFmNumber */
-        break;
-
-    case 16: /* HcPeriodicStart */
-        ohci->pstart = val & 0xffff;
-        break;
-
-    case 17: /* HcLSThreshold */
-        ohci->lst = val & 0xffff;
-        break;
-
-    case 18: /* HcRhDescriptorA */
-        ohci->rhdesc_a &= ~OHCI_RHA_RW_MASK;
-        ohci->rhdesc_a |= val & OHCI_RHA_RW_MASK;
-        break;
-
-    case 19: /* HcRhDescriptorB */
-        break;
-
-    case 20: /* HcRhStatus */
-        ohci_set_hub_status(ohci, val);
-        break;
-
-    /* PXA27x specific registers */
-    case 24: /* HcStatus */
-        ohci->hstatus &= ~(val & ohci->hmask);
-
-    case 25: /* HcHReset */
-        ohci->hreset = val & ~OHCI_HRESET_FSBIR;
-        if (val & OHCI_HRESET_FSBIR)
-            ohci_reset(ohci);
-        break;
-
-    case 26: /* HcHInterruptEnable */
-        ohci->hmask = val;
-        break;
-
-    case 27: /* HcHInterruptTest */
-        ohci->htest = val;
-        break;
-
-    default:
-        fprintf(stderr, "ohci_write: Bad offset %x\n", (int)addr);
-        break;
-    }
-}
-
-static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev)
-{
-    if (ohci->async_td &&
-        usb_packet_is_inflight(&ohci->usb_packet) &&
-        ohci->usb_packet.ep->dev == dev) {
-        usb_cancel_packet(&ohci->usb_packet);
-        ohci->async_td = 0;
-    }
-}
-
-static const MemoryRegionOps ohci_mem_ops = {
-    .read = ohci_mem_read,
-    .write = ohci_mem_write,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static USBPortOps ohci_port_ops = {
-    .attach = ohci_attach,
-    .detach = ohci_detach,
-    .child_detach = ohci_child_detach,
-    .wakeup = ohci_wakeup,
-    .complete = ohci_async_complete_packet,
-};
-
-static USBBusOps ohci_bus_ops = {
-};
-
-static int usb_ohci_init(OHCIState *ohci, DeviceState *dev,
-                         int num_ports, uint32_t localmem_base,
-                         char *masterbus, uint32_t firstport)
-{
-    int i;
-
-    if (usb_frame_time == 0) {
-#ifdef OHCI_TIME_WARP
-        usb_frame_time = get_ticks_per_sec();
-        usb_bit_time = muldiv64(1, get_ticks_per_sec(), USB_HZ/1000);
-#else
-        usb_frame_time = muldiv64(1, get_ticks_per_sec(), 1000);
-        if (get_ticks_per_sec() >= USB_HZ) {
-            usb_bit_time = muldiv64(1, get_ticks_per_sec(), USB_HZ);
-        } else {
-            usb_bit_time = 1;
-        }
-#endif
-        DPRINTF("usb-ohci: usb_bit_time=%" PRId64 " usb_frame_time=%" PRId64 "\n",
-                usb_frame_time, usb_bit_time);
-    }
-
-    ohci->num_ports = num_ports;
-    if (masterbus) {
-        USBPort *ports[OHCI_MAX_PORTS];
-        for(i = 0; i < num_ports; i++) {
-            ports[i] = &ohci->rhport[i].port;
-        }
-        if (usb_register_companion(masterbus, ports, num_ports,
-                firstport, ohci, &ohci_port_ops,
-                USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL) != 0) {
-            return -1;
-        }
-    } else {
-        usb_bus_new(&ohci->bus, &ohci_bus_ops, dev);
-        for (i = 0; i < num_ports; i++) {
-            usb_register_port(&ohci->bus, &ohci->rhport[i].port,
-                              ohci, i, &ohci_port_ops,
-                              USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
-        }
-    }
-
-    memory_region_init_io(&ohci->mem, &ohci_mem_ops, ohci, "ohci", 256);
-    ohci->localmem_base = localmem_base;
-
-    ohci->name = object_get_typename(OBJECT(dev));
-    usb_packet_init(&ohci->usb_packet);
-
-    ohci->async_td = 0;
-    qemu_register_reset(ohci_reset, ohci);
-
-    return 0;
-}
-
-typedef struct {
-    PCIDevice pci_dev;
-    OHCIState state;
-    char *masterbus;
-    uint32_t num_ports;
-    uint32_t firstport;
-} OHCIPCIState;
-
-static int usb_ohci_initfn_pci(struct PCIDevice *dev)
-{
-    OHCIPCIState *ohci = DO_UPCAST(OHCIPCIState, pci_dev, dev);
-
-    ohci->pci_dev.config[PCI_CLASS_PROG] = 0x10; /* OHCI */
-    ohci->pci_dev.config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */
-
-    if (usb_ohci_init(&ohci->state, &dev->qdev, ohci->num_ports, 0,
-                      ohci->masterbus, ohci->firstport) != 0) {
-        return -1;
-    }
-    ohci->state.irq = ohci->pci_dev.irq[0];
-
-    /* TODO: avoid cast below by using dev */
-    pci_register_bar(&ohci->pci_dev, 0, 0, &ohci->state.mem);
-    return 0;
-}
-
-void usb_ohci_init_pci(struct PCIBus *bus, int devfn)
-{
-    pci_create_simple(bus, devfn, "pci-ohci");
-}
-
-typedef struct {
-    SysBusDevice busdev;
-    OHCIState ohci;
-    uint32_t num_ports;
-    target_phys_addr_t dma_offset;
-} OHCISysBusState;
-
-static int ohci_init_pxa(SysBusDevice *dev)
-{
-    OHCISysBusState *s = FROM_SYSBUS(OHCISysBusState, dev);
-
-    /* Cannot fail as we pass NULL for masterbus */
-    usb_ohci_init(&s->ohci, &dev->qdev, s->num_ports, s->dma_offset, NULL, 0);
-    sysbus_init_irq(dev, &s->ohci.irq);
-    sysbus_init_mmio(dev, &s->ohci.mem);
-
-    return 0;
-}
-
-static Property ohci_pci_properties[] = {
-    DEFINE_PROP_STRING("masterbus", OHCIPCIState, masterbus),
-    DEFINE_PROP_UINT32("num-ports", OHCIPCIState, num_ports, 3),
-    DEFINE_PROP_UINT32("firstport", OHCIPCIState, firstport, 0),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void ohci_pci_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = usb_ohci_initfn_pci;
-    k->vendor_id = PCI_VENDOR_ID_APPLE;
-    k->device_id = PCI_DEVICE_ID_APPLE_IPID_USB;
-    k->class_id = PCI_CLASS_SERIAL_USB;
-    dc->desc = "Apple USB Controller";
-    dc->props = ohci_pci_properties;
-}
-
-static TypeInfo ohci_pci_info = {
-    .name          = "pci-ohci",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(OHCIPCIState),
-    .class_init    = ohci_pci_class_init,
-};
-
-static Property ohci_sysbus_properties[] = {
-    DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3),
-    DEFINE_PROP_TADDR("dma-offset", OHCISysBusState, dma_offset, 3),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void ohci_sysbus_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
-
-    sbc->init = ohci_init_pxa;
-    dc->desc = "OHCI USB Controller";
-    dc->props = ohci_sysbus_properties;
-}
-
-static TypeInfo ohci_sysbus_info = {
-    .name          = "sysbus-ohci",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(OHCISysBusState),
-    .class_init    = ohci_sysbus_class_init,
-};
-
-static void ohci_register_types(void)
-{
-    type_register_static(&ohci_pci_info);
-    type_register_static(&ohci_sysbus_info);
-}
-
-type_init(ohci_register_types)
diff --git a/hw/usb-serial.c b/hw/usb-serial.c
deleted file mode 100644
index 0aae379..0000000
--- a/hw/usb-serial.c
+++ /dev/null
@@ -1,637 +0,0 @@
-/*
- * FTDI FT232BM Device emulation
- *
- * Copyright (c) 2006 CodeSourcery.
- * Copyright (c) 2008 Samuel Thibault <samuel.thibault at ens-lyon.org>
- * Written by Paul Brook, reused for FTDI by Samuel Thibault
- *
- * This code is licensed under the LGPL.
- */
-
-#include "qemu-common.h"
-#include "qemu-error.h"
-#include "usb.h"
-#include "usb-desc.h"
-#include "qemu-char.h"
-
-//#define DEBUG_Serial
-
-#ifdef DEBUG_Serial
-#define DPRINTF(fmt, ...) \
-do { printf("usb-serial: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while(0)
-#endif
-
-#define RECV_BUF 384
-
-/* Commands */
-#define FTDI_RESET		0
-#define FTDI_SET_MDM_CTRL	1
-#define FTDI_SET_FLOW_CTRL	2
-#define FTDI_SET_BAUD		3
-#define FTDI_SET_DATA		4
-#define FTDI_GET_MDM_ST		5
-#define FTDI_SET_EVENT_CHR	6
-#define FTDI_SET_ERROR_CHR	7
-#define FTDI_SET_LATENCY	9
-#define FTDI_GET_LATENCY	10
-
-#define DeviceOutVendor	((USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8)
-#define DeviceInVendor	((USB_DIR_IN |USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8)
-
-/* RESET */
-
-#define FTDI_RESET_SIO	0
-#define FTDI_RESET_RX	1
-#define FTDI_RESET_TX	2
-
-/* SET_MDM_CTRL */
-
-#define FTDI_DTR	1
-#define FTDI_SET_DTR	(FTDI_DTR << 8)
-#define FTDI_RTS	2
-#define FTDI_SET_RTS	(FTDI_RTS << 8)
-
-/* SET_FLOW_CTRL */
-
-#define FTDI_RTS_CTS_HS		1
-#define FTDI_DTR_DSR_HS		2
-#define FTDI_XON_XOFF_HS	4
-
-/* SET_DATA */
-
-#define FTDI_PARITY	(0x7 << 8)
-#define FTDI_ODD	(0x1 << 8)
-#define FTDI_EVEN	(0x2 << 8)
-#define FTDI_MARK	(0x3 << 8)
-#define FTDI_SPACE	(0x4 << 8)
-
-#define FTDI_STOP	(0x3 << 11)
-#define FTDI_STOP1	(0x0 << 11)
-#define FTDI_STOP15	(0x1 << 11)
-#define FTDI_STOP2	(0x2 << 11)
-
-/* GET_MDM_ST */
-/* TODO: should be sent every 40ms */
-#define FTDI_CTS  (1<<4)        // CTS line status
-#define FTDI_DSR  (1<<5)        // DSR line status
-#define FTDI_RI   (1<<6)        // RI line status
-#define FTDI_RLSD (1<<7)        // Receive Line Signal Detect
-
-/* Status */
-
-#define FTDI_DR   (1<<0)        // Data Ready
-#define FTDI_OE   (1<<1)        // Overrun Err
-#define FTDI_PE   (1<<2)        // Parity Err
-#define FTDI_FE   (1<<3)        // Framing Err
-#define FTDI_BI   (1<<4)        // Break Interrupt
-#define FTDI_THRE (1<<5)        // Transmitter Holding Register
-#define FTDI_TEMT (1<<6)        // Transmitter Empty
-#define FTDI_FIFO (1<<7)        // Error in FIFO
-
-typedef struct {
-    USBDevice dev;
-    uint8_t recv_buf[RECV_BUF];
-    uint16_t recv_ptr;
-    uint16_t recv_used;
-    uint8_t event_chr;
-    uint8_t error_chr;
-    uint8_t event_trigger;
-    QEMUSerialSetParams params;
-    int latency;        /* ms */
-    CharDriverState *cs;
-} USBSerialState;
-
-enum {
-    STR_MANUFACTURER = 1,
-    STR_PRODUCT_SERIAL,
-    STR_PRODUCT_BRAILLE,
-    STR_SERIALNUMBER,
-};
-
-static const USBDescStrings desc_strings = {
-    [STR_MANUFACTURER]    = "QEMU " QEMU_VERSION,
-    [STR_PRODUCT_SERIAL]  = "QEMU USB SERIAL",
-    [STR_PRODUCT_BRAILLE] = "QEMU USB BRAILLE",
-    [STR_SERIALNUMBER]    = "1",
-};
-
-static const USBDescIface desc_iface0 = {
-    .bInterfaceNumber              = 0,
-    .bNumEndpoints                 = 2,
-    .bInterfaceClass               = 0xff,
-    .bInterfaceSubClass            = 0xff,
-    .bInterfaceProtocol            = 0xff,
-    .eps = (USBDescEndpoint[]) {
-        {
-            .bEndpointAddress      = USB_DIR_IN | 0x01,
-            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
-            .wMaxPacketSize        = 64,
-        },{
-            .bEndpointAddress      = USB_DIR_OUT | 0x02,
-            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
-            .wMaxPacketSize        = 64,
-        },
-    }
-};
-
-static const USBDescDevice desc_device = {
-    .bcdUSB                        = 0x0200,
-    .bMaxPacketSize0               = 8,
-    .bNumConfigurations            = 1,
-    .confs = (USBDescConfig[]) {
-        {
-            .bNumInterfaces        = 1,
-            .bConfigurationValue   = 1,
-            .bmAttributes          = 0x80,
-            .bMaxPower             = 50,
-            .nif = 1,
-            .ifs = &desc_iface0,
-        },
-    },
-};
-
-static const USBDesc desc_serial = {
-    .id = {
-        .idVendor          = 0x0403,
-        .idProduct         = 0x6001,
-        .bcdDevice         = 0x0400,
-        .iManufacturer     = STR_MANUFACTURER,
-        .iProduct          = STR_PRODUCT_SERIAL,
-        .iSerialNumber     = STR_SERIALNUMBER,
-    },
-    .full = &desc_device,
-    .str  = desc_strings,
-};
-
-static const USBDesc desc_braille = {
-    .id = {
-        .idVendor          = 0x0403,
-        .idProduct         = 0xfe72,
-        .bcdDevice         = 0x0400,
-        .iManufacturer     = STR_MANUFACTURER,
-        .iProduct          = STR_PRODUCT_BRAILLE,
-        .iSerialNumber     = STR_SERIALNUMBER,
-    },
-    .full = &desc_device,
-    .str  = desc_strings,
-};
-
-static void usb_serial_reset(USBSerialState *s)
-{
-    /* TODO: Set flow control to none */
-    s->event_chr = 0x0d;
-    s->event_trigger = 0;
-    s->recv_ptr = 0;
-    s->recv_used = 0;
-    /* TODO: purge in char driver */
-}
-
-static void usb_serial_handle_reset(USBDevice *dev)
-{
-    USBSerialState *s = (USBSerialState *)dev;
-
-    DPRINTF("Reset\n");
-
-    usb_serial_reset(s);
-    /* TODO: Reset char device, send BREAK? */
-}
-
-static uint8_t usb_get_modem_lines(USBSerialState *s)
-{
-    int flags;
-    uint8_t ret;
-
-    if (qemu_chr_fe_ioctl(s->cs, CHR_IOCTL_SERIAL_GET_TIOCM, &flags) == -ENOTSUP)
-        return FTDI_CTS|FTDI_DSR|FTDI_RLSD;
-
-    ret = 0;
-    if (flags & CHR_TIOCM_CTS)
-        ret |= FTDI_CTS;
-    if (flags & CHR_TIOCM_DSR)
-        ret |= FTDI_DSR;
-    if (flags & CHR_TIOCM_RI)
-        ret |= FTDI_RI;
-    if (flags & CHR_TIOCM_CAR)
-        ret |= FTDI_RLSD;
-
-    return ret;
-}
-
-static int usb_serial_handle_control(USBDevice *dev, USBPacket *p,
-               int request, int value, int index, int length, uint8_t *data)
-{
-    USBSerialState *s = (USBSerialState *)dev;
-    int ret;
-
-    DPRINTF("got control %x, value %x\n",request, value);
-    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
-    if (ret >= 0) {
-        return ret;
-    }
-
-    ret = 0;
-    switch (request) {
-    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
-        ret = 0;
-        break;
-
-        /* Class specific requests.  */
-    case DeviceOutVendor | FTDI_RESET:
-        switch (value) {
-        case FTDI_RESET_SIO:
-            usb_serial_reset(s);
-            break;
-        case FTDI_RESET_RX:
-            s->recv_ptr = 0;
-            s->recv_used = 0;
-            /* TODO: purge from char device */
-            break;
-        case FTDI_RESET_TX:
-            /* TODO: purge from char device */
-            break;
-        }
-        break;
-    case DeviceOutVendor | FTDI_SET_MDM_CTRL:
-    {
-        static int flags;
-        qemu_chr_fe_ioctl(s->cs,CHR_IOCTL_SERIAL_GET_TIOCM, &flags);
-        if (value & FTDI_SET_RTS) {
-            if (value & FTDI_RTS)
-                flags |= CHR_TIOCM_RTS;
-            else
-                flags &= ~CHR_TIOCM_RTS;
-        }
-        if (value & FTDI_SET_DTR) {
-            if (value & FTDI_DTR)
-                flags |= CHR_TIOCM_DTR;
-            else
-                flags &= ~CHR_TIOCM_DTR;
-        }
-        qemu_chr_fe_ioctl(s->cs,CHR_IOCTL_SERIAL_SET_TIOCM, &flags);
-        break;
-    }
-    case DeviceOutVendor | FTDI_SET_FLOW_CTRL:
-        /* TODO: ioctl */
-        break;
-    case DeviceOutVendor | FTDI_SET_BAUD: {
-        static const int subdivisors8[8] = { 0, 4, 2, 1, 3, 5, 6, 7 };
-        int subdivisor8 = subdivisors8[((value & 0xc000) >> 14)
-                                     | ((index & 1) << 2)];
-        int divisor = value & 0x3fff;
-
-        /* chip special cases */
-        if (divisor == 1 && subdivisor8 == 0)
-            subdivisor8 = 4;
-        if (divisor == 0 && subdivisor8 == 0)
-            divisor = 1;
-
-        s->params.speed = (48000000 / 2) / (8 * divisor + subdivisor8);
-        qemu_chr_fe_ioctl(s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);
-        break;
-    }
-    case DeviceOutVendor | FTDI_SET_DATA:
-        switch (value & FTDI_PARITY) {
-            case 0:
-                s->params.parity = 'N';
-                break;
-            case FTDI_ODD:
-                s->params.parity = 'O';
-                break;
-            case FTDI_EVEN:
-                s->params.parity = 'E';
-                break;
-            default:
-                DPRINTF("unsupported parity %d\n", value & FTDI_PARITY);
-                goto fail;
-        }
-        switch (value & FTDI_STOP) {
-            case FTDI_STOP1:
-                s->params.stop_bits = 1;
-                break;
-            case FTDI_STOP2:
-                s->params.stop_bits = 2;
-                break;
-            default:
-                DPRINTF("unsupported stop bits %d\n", value & FTDI_STOP);
-                goto fail;
-        }
-        qemu_chr_fe_ioctl(s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);
-        /* TODO: TX ON/OFF */
-        break;
-    case DeviceInVendor | FTDI_GET_MDM_ST:
-        data[0] = usb_get_modem_lines(s) | 1;
-        data[1] = 0;
-        ret = 2;
-        break;
-    case DeviceOutVendor | FTDI_SET_EVENT_CHR:
-        /* TODO: handle it */
-        s->event_chr = value;
-        break;
-    case DeviceOutVendor | FTDI_SET_ERROR_CHR:
-        /* TODO: handle it */
-        s->error_chr = value;
-        break;
-    case DeviceOutVendor | FTDI_SET_LATENCY:
-        s->latency = value;
-        break;
-    case DeviceInVendor | FTDI_GET_LATENCY:
-        data[0] = s->latency;
-        ret = 1;
-        break;
-    default:
-    fail:
-        DPRINTF("got unsupported/bogus control %x, value %x\n", request, value);
-        ret = USB_RET_STALL;
-        break;
-    }
-    return ret;
-}
-
-static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
-{
-    USBSerialState *s = (USBSerialState *)dev;
-    int i, ret = 0;
-    uint8_t devep = p->ep->nr;
-    struct iovec *iov;
-    uint8_t header[2];
-    int first_len, len;
-
-    switch (p->pid) {
-    case USB_TOKEN_OUT:
-        if (devep != 2)
-            goto fail;
-        for (i = 0; i < p->iov.niov; i++) {
-            iov = p->iov.iov + i;
-            qemu_chr_fe_write(s->cs, iov->iov_base, iov->iov_len);
-        }
-        break;
-
-    case USB_TOKEN_IN:
-        if (devep != 1)
-            goto fail;
-        first_len = RECV_BUF - s->recv_ptr;
-        len = p->iov.size;
-        if (len <= 2) {
-            ret = USB_RET_NAK;
-            break;
-        }
-        header[0] = usb_get_modem_lines(s) | 1;
-        /* We do not have the uart details */
-        /* handle serial break */
-        if (s->event_trigger && s->event_trigger & FTDI_BI) {
-            s->event_trigger &= ~FTDI_BI;
-            header[1] = FTDI_BI;
-            usb_packet_copy(p, header, 2);
-            ret = 2;
-            break;
-        } else {
-            header[1] = 0;
-        }
-        len -= 2;
-        if (len > s->recv_used)
-            len = s->recv_used;
-        if (!len) {
-            ret = USB_RET_NAK;
-            break;
-        }
-        if (first_len > len)
-            first_len = len;
-        usb_packet_copy(p, header, 2);
-        usb_packet_copy(p, s->recv_buf + s->recv_ptr, first_len);
-        if (len > first_len)
-            usb_packet_copy(p, s->recv_buf, len - first_len);
-        s->recv_used -= len;
-        s->recv_ptr = (s->recv_ptr + len) % RECV_BUF;
-        ret = len + 2;
-        break;
-
-    default:
-        DPRINTF("Bad token\n");
-    fail:
-        ret = USB_RET_STALL;
-        break;
-    }
-
-    return ret;
-}
-
-static void usb_serial_handle_destroy(USBDevice *dev)
-{
-    USBSerialState *s = (USBSerialState *)dev;
-
-    qemu_chr_delete(s->cs);
-}
-
-static int usb_serial_can_read(void *opaque)
-{
-    USBSerialState *s = opaque;
-    return RECV_BUF - s->recv_used;
-}
-
-static void usb_serial_read(void *opaque, const uint8_t *buf, int size)
-{
-    USBSerialState *s = opaque;
-    int first_size, start;
-
-    /* room in the buffer? */
-    if (size > (RECV_BUF - s->recv_used))
-        size = RECV_BUF - s->recv_used;
-
-    start = s->recv_ptr + s->recv_used;
-    if (start < RECV_BUF) {
-        /* copy data to end of buffer */
-        first_size = RECV_BUF - start;
-        if (first_size > size)
-            first_size = size;
-
-        memcpy(s->recv_buf + start, buf, first_size);
-
-        /* wrap around to front if needed */
-        if (size > first_size)
-            memcpy(s->recv_buf, buf + first_size, size - first_size);
-    } else {
-        start -= RECV_BUF;
-        memcpy(s->recv_buf + start, buf, size);
-    }
-    s->recv_used += size;
-}
-
-static void usb_serial_event(void *opaque, int event)
-{
-    USBSerialState *s = opaque;
-
-    switch (event) {
-        case CHR_EVENT_BREAK:
-            s->event_trigger |= FTDI_BI;
-            break;
-        case CHR_EVENT_FOCUS:
-            break;
-        case CHR_EVENT_OPENED:
-            usb_serial_reset(s);
-            /* TODO: Reset USB port */
-            break;
-    }
-}
-
-static int usb_serial_initfn(USBDevice *dev)
-{
-    USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev);
-
-    usb_desc_init(dev);
-
-    if (!s->cs) {
-        error_report("Property chardev is required");
-        return -1;
-    }
-
-    qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
-                          usb_serial_event, s);
-    usb_serial_handle_reset(dev);
-    return 0;
-}
-
-static USBDevice *usb_serial_init(USBBus *bus, const char *filename)
-{
-    USBDevice *dev;
-    CharDriverState *cdrv;
-    uint32_t vendorid = 0, productid = 0;
-    char label[32];
-    static int index;
-
-    while (*filename && *filename != ':') {
-        const char *p;
-        char *e;
-        if (strstart(filename, "vendorid=", &p)) {
-            vendorid = strtol(p, &e, 16);
-            if (e == p || (*e && *e != ',' && *e != ':')) {
-                error_report("bogus vendor ID %s", p);
-                return NULL;
-            }
-            filename = e;
-        } else if (strstart(filename, "productid=", &p)) {
-            productid = strtol(p, &e, 16);
-            if (e == p || (*e && *e != ',' && *e != ':')) {
-                error_report("bogus product ID %s", p);
-                return NULL;
-            }
-            filename = e;
-        } else {
-            error_report("unrecognized serial USB option %s", filename);
-            return NULL;
-        }
-        while(*filename == ',')
-            filename++;
-    }
-    if (!*filename) {
-        error_report("character device specification needed");
-        return NULL;
-    }
-    filename++;
-
-    snprintf(label, sizeof(label), "usbserial%d", index++);
-    cdrv = qemu_chr_new(label, filename, NULL);
-    if (!cdrv)
-        return NULL;
-
-    dev = usb_create(bus, "usb-serial");
-    if (!dev) {
-        return NULL;
-    }
-    qdev_prop_set_chr(&dev->qdev, "chardev", cdrv);
-    if (vendorid)
-        qdev_prop_set_uint16(&dev->qdev, "vendorid", vendorid);
-    if (productid)
-        qdev_prop_set_uint16(&dev->qdev, "productid", productid);
-    qdev_init_nofail(&dev->qdev);
-
-    return dev;
-}
-
-static USBDevice *usb_braille_init(USBBus *bus, const char *unused)
-{
-    USBDevice *dev;
-    CharDriverState *cdrv;
-
-    cdrv = qemu_chr_new("braille", "braille", NULL);
-    if (!cdrv)
-        return NULL;
-
-    dev = usb_create(bus, "usb-braille");
-    qdev_prop_set_chr(&dev->qdev, "chardev", cdrv);
-    qdev_init_nofail(&dev->qdev);
-
-    return dev;
-}
-
-static const VMStateDescription vmstate_usb_serial = {
-    .name = "usb-serial",
-    .unmigratable = 1,
-};
-
-static Property serial_properties[] = {
-    DEFINE_PROP_CHR("chardev", USBSerialState, cs),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void usb_serial_class_initfn(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
-
-    uc->init = usb_serial_initfn;
-    uc->product_desc   = "QEMU USB Serial";
-    uc->usb_desc       = &desc_serial;
-    uc->handle_reset   = usb_serial_handle_reset;
-    uc->handle_control = usb_serial_handle_control;
-    uc->handle_data    = usb_serial_handle_data;
-    uc->handle_destroy = usb_serial_handle_destroy;
-    dc->vmsd = &vmstate_usb_serial;
-    dc->props = serial_properties;
-}
-
-static TypeInfo serial_info = {
-    .name          = "usb-serial",
-    .parent        = TYPE_USB_DEVICE,
-    .instance_size = sizeof(USBSerialState),
-    .class_init    = usb_serial_class_initfn,
-};
-
-static Property braille_properties[] = {
-    DEFINE_PROP_CHR("chardev", USBSerialState, cs),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void usb_braille_class_initfn(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
-
-    uc->init           = usb_serial_initfn;
-    uc->product_desc   = "QEMU USB Braille";
-    uc->usb_desc       = &desc_braille;
-    uc->handle_reset   = usb_serial_handle_reset;
-    uc->handle_control = usb_serial_handle_control;
-    uc->handle_data    = usb_serial_handle_data;
-    uc->handle_destroy = usb_serial_handle_destroy;
-    dc->vmsd = &vmstate_usb_serial;
-    dc->props = braille_properties;
-}
-
-static TypeInfo braille_info = {
-    .name          = "usb-braille",
-    .parent        = TYPE_USB_DEVICE,
-    .instance_size = sizeof(USBSerialState),
-    .class_init    = usb_braille_class_initfn,
-};
-
-static void usb_serial_register_types(void)
-{
-    type_register_static(&serial_info);
-    usb_legacy_register("usb-serial", "serial", usb_serial_init);
-    type_register_static(&braille_info);
-    usb_legacy_register("usb-braille", "braille", usb_braille_init);
-}
-
-type_init(usb_serial_register_types)
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
deleted file mode 100644
index 304b84b..0000000
--- a/hw/usb-uhci.c
+++ /dev/null
@@ -1,1408 +0,0 @@
-/*
- * USB UHCI controller emulation
- *
- * Copyright (c) 2005 Fabrice Bellard
- *
- * Copyright (c) 2008 Max Krasnyansky
- *     Magor rewrite of the UHCI data structures parser and frame processor
- *     Support for fully async operation and multiple outstanding transactions
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "hw.h"
-#include "usb.h"
-#include "pci.h"
-#include "qemu-timer.h"
-#include "usb-uhci.h"
-#include "iov.h"
-#include "dma.h"
-
-//#define DEBUG
-//#define DEBUG_DUMP_DATA
-
-#define UHCI_CMD_FGR      (1 << 4)
-#define UHCI_CMD_EGSM     (1 << 3)
-#define UHCI_CMD_GRESET   (1 << 2)
-#define UHCI_CMD_HCRESET  (1 << 1)
-#define UHCI_CMD_RS       (1 << 0)
-
-#define UHCI_STS_HCHALTED (1 << 5)
-#define UHCI_STS_HCPERR   (1 << 4)
-#define UHCI_STS_HSERR    (1 << 3)
-#define UHCI_STS_RD       (1 << 2)
-#define UHCI_STS_USBERR   (1 << 1)
-#define UHCI_STS_USBINT   (1 << 0)
-
-#define TD_CTRL_SPD     (1 << 29)
-#define TD_CTRL_ERROR_SHIFT  27
-#define TD_CTRL_IOS     (1 << 25)
-#define TD_CTRL_IOC     (1 << 24)
-#define TD_CTRL_ACTIVE  (1 << 23)
-#define TD_CTRL_STALL   (1 << 22)
-#define TD_CTRL_BABBLE  (1 << 20)
-#define TD_CTRL_NAK     (1 << 19)
-#define TD_CTRL_TIMEOUT (1 << 18)
-
-#define UHCI_PORT_SUSPEND (1 << 12)
-#define UHCI_PORT_RESET (1 << 9)
-#define UHCI_PORT_LSDA  (1 << 8)
-#define UHCI_PORT_RD    (1 << 6)
-#define UHCI_PORT_ENC   (1 << 3)
-#define UHCI_PORT_EN    (1 << 2)
-#define UHCI_PORT_CSC   (1 << 1)
-#define UHCI_PORT_CCS   (1 << 0)
-
-#define UHCI_PORT_READ_ONLY    (0x1bb)
-#define UHCI_PORT_WRITE_CLEAR  (UHCI_PORT_CSC | UHCI_PORT_ENC)
-
-#define FRAME_TIMER_FREQ 1000
-
-#define FRAME_MAX_LOOPS  256
-
-#define NB_PORTS 2
-
-#ifdef DEBUG
-#define DPRINTF printf
-
-static const char *pid2str(int pid)
-{
-    switch (pid) {
-    case USB_TOKEN_SETUP: return "SETUP";
-    case USB_TOKEN_IN:    return "IN";
-    case USB_TOKEN_OUT:   return "OUT";
-    }
-    return "?";
-}
-
-#else
-#define DPRINTF(...)
-#endif
-
-typedef struct UHCIState UHCIState;
-typedef struct UHCIAsync UHCIAsync;
-typedef struct UHCIQueue UHCIQueue;
-
-/* 
- * Pending async transaction.
- * 'packet' must be the first field because completion
- * handler does "(UHCIAsync *) pkt" cast.
- */
-
-struct UHCIAsync {
-    USBPacket packet;
-    QEMUSGList sgl;
-    UHCIQueue *queue;
-    QTAILQ_ENTRY(UHCIAsync) next;
-    uint32_t  td;
-    uint8_t   isoc;
-    uint8_t   done;
-};
-
-struct UHCIQueue {
-    uint32_t  token;
-    UHCIState *uhci;
-    QTAILQ_ENTRY(UHCIQueue) next;
-    QTAILQ_HEAD(, UHCIAsync) asyncs;
-    int8_t    valid;
-};
-
-typedef struct UHCIPort {
-    USBPort port;
-    uint16_t ctrl;
-} UHCIPort;
-
-struct UHCIState {
-    PCIDevice dev;
-    MemoryRegion io_bar;
-    USBBus bus; /* Note unused when we're a companion controller */
-    uint16_t cmd; /* cmd register */
-    uint16_t status;
-    uint16_t intr; /* interrupt enable register */
-    uint16_t frnum; /* frame number */
-    uint32_t fl_base_addr; /* frame list base address */
-    uint8_t sof_timing;
-    uint8_t status2; /* bit 0 and 1 are used to generate UHCI_STS_USBINT */
-    int64_t expire_time;
-    QEMUTimer *frame_timer;
-    UHCIPort ports[NB_PORTS];
-
-    /* Interrupts that should be raised at the end of the current frame.  */
-    uint32_t pending_int_mask;
-
-    /* Active packets */
-    QTAILQ_HEAD(, UHCIQueue) queues;
-    uint8_t num_ports_vmstate;
-
-    /* Properties */
-    char *masterbus;
-    uint32_t firstport;
-};
-
-typedef struct UHCI_TD {
-    uint32_t link;
-    uint32_t ctrl; /* see TD_CTRL_xxx */
-    uint32_t token;
-    uint32_t buffer;
-} UHCI_TD;
-
-typedef struct UHCI_QH {
-    uint32_t link;
-    uint32_t el_link;
-} UHCI_QH;
-
-static inline int32_t uhci_queue_token(UHCI_TD *td)
-{
-    /* covers ep, dev, pid -> identifies the endpoint */
-    return td->token & 0x7ffff;
-}
-
-static UHCIQueue *uhci_queue_get(UHCIState *s, UHCI_TD *td)
-{
-    uint32_t token = uhci_queue_token(td);
-    UHCIQueue *queue;
-
-    QTAILQ_FOREACH(queue, &s->queues, next) {
-        if (queue->token == token) {
-            return queue;
-        }
-    }
-
-    queue = g_new0(UHCIQueue, 1);
-    queue->uhci = s;
-    queue->token = token;
-    QTAILQ_INIT(&queue->asyncs);
-    QTAILQ_INSERT_HEAD(&s->queues, queue, next);
-    return queue;
-}
-
-static void uhci_queue_free(UHCIQueue *queue)
-{
-    UHCIState *s = queue->uhci;
-
-    QTAILQ_REMOVE(&s->queues, queue, next);
-    g_free(queue);
-}
-
-static UHCIAsync *uhci_async_alloc(UHCIQueue *queue)
-{
-    UHCIAsync *async = g_new0(UHCIAsync, 1);
-
-    async->queue = queue;
-    usb_packet_init(&async->packet);
-    pci_dma_sglist_init(&async->sgl, &queue->uhci->dev, 1);
-
-    return async;
-}
-
-static void uhci_async_free(UHCIAsync *async)
-{
-    usb_packet_cleanup(&async->packet);
-    qemu_sglist_destroy(&async->sgl);
-    g_free(async);
-}
-
-static void uhci_async_link(UHCIAsync *async)
-{
-    UHCIQueue *queue = async->queue;
-    QTAILQ_INSERT_TAIL(&queue->asyncs, async, next);
-}
-
-static void uhci_async_unlink(UHCIAsync *async)
-{
-    UHCIQueue *queue = async->queue;
-    QTAILQ_REMOVE(&queue->asyncs, async, next);
-}
-
-static void uhci_async_cancel(UHCIAsync *async)
-{
-    DPRINTF("uhci: cancel td 0x%x token 0x%x done %u\n",
-           async->td, async->token, async->done);
-
-    if (!async->done)
-        usb_cancel_packet(&async->packet);
-    uhci_async_free(async);
-}
-
-/*
- * Mark all outstanding async packets as invalid.
- * This is used for canceling them when TDs are removed by the HCD.
- */
-static void uhci_async_validate_begin(UHCIState *s)
-{
-    UHCIQueue *queue;
-
-    QTAILQ_FOREACH(queue, &s->queues, next) {
-        queue->valid--;
-    }
-}
-
-/*
- * Cancel async packets that are no longer valid
- */
-static void uhci_async_validate_end(UHCIState *s)
-{
-    UHCIQueue *queue, *n;
-    UHCIAsync *async;
-
-    QTAILQ_FOREACH_SAFE(queue, &s->queues, next, n) {
-        if (queue->valid > 0) {
-            continue;
-        }
-        while (!QTAILQ_EMPTY(&queue->asyncs)) {
-            async = QTAILQ_FIRST(&queue->asyncs);
-            uhci_async_unlink(async);
-            uhci_async_cancel(async);
-        }
-        uhci_queue_free(queue);
-    }
-}
-
-static void uhci_async_cancel_device(UHCIState *s, USBDevice *dev)
-{
-    UHCIQueue *queue;
-    UHCIAsync *curr, *n;
-
-    QTAILQ_FOREACH(queue, &s->queues, next) {
-        QTAILQ_FOREACH_SAFE(curr, &queue->asyncs, next, n) {
-            if (!usb_packet_is_inflight(&curr->packet) ||
-                curr->packet.ep->dev != dev) {
-                continue;
-            }
-            uhci_async_unlink(curr);
-            uhci_async_cancel(curr);
-        }
-    }
-}
-
-static void uhci_async_cancel_all(UHCIState *s)
-{
-    UHCIQueue *queue;
-    UHCIAsync *curr, *n;
-
-    QTAILQ_FOREACH(queue, &s->queues, next) {
-        QTAILQ_FOREACH_SAFE(curr, &queue->asyncs, next, n) {
-            uhci_async_unlink(curr);
-            uhci_async_cancel(curr);
-        }
-    }
-}
-
-static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t addr, UHCI_TD *td)
-{
-    uint32_t token = uhci_queue_token(td);
-    UHCIQueue *queue;
-    UHCIAsync *async;
-
-    QTAILQ_FOREACH(queue, &s->queues, next) {
-        if (queue->token == token) {
-            break;
-        }
-    }
-    if (queue == NULL) {
-        return NULL;
-    }
-
-    QTAILQ_FOREACH(async, &queue->asyncs, next) {
-        if (async->td == addr) {
-            return async;
-        }
-    }
-
-    return NULL;
-}
-
-static void uhci_update_irq(UHCIState *s)
-{
-    int level;
-    if (((s->status2 & 1) && (s->intr & (1 << 2))) ||
-        ((s->status2 & 2) && (s->intr & (1 << 3))) ||
-        ((s->status & UHCI_STS_USBERR) && (s->intr & (1 << 0))) ||
-        ((s->status & UHCI_STS_RD) && (s->intr & (1 << 1))) ||
-        (s->status & UHCI_STS_HSERR) ||
-        (s->status & UHCI_STS_HCPERR)) {
-        level = 1;
-    } else {
-        level = 0;
-    }
-    qemu_set_irq(s->dev.irq[3], level);
-}
-
-static void uhci_reset(void *opaque)
-{
-    UHCIState *s = opaque;
-    uint8_t *pci_conf;
-    int i;
-    UHCIPort *port;
-
-    DPRINTF("uhci: full reset\n");
-
-    pci_conf = s->dev.config;
-
-    pci_conf[0x6a] = 0x01; /* usb clock */
-    pci_conf[0x6b] = 0x00;
-    s->cmd = 0;
-    s->status = 0;
-    s->status2 = 0;
-    s->intr = 0;
-    s->fl_base_addr = 0;
-    s->sof_timing = 64;
-
-    for(i = 0; i < NB_PORTS; i++) {
-        port = &s->ports[i];
-        port->ctrl = 0x0080;
-        if (port->port.dev && port->port.dev->attached) {
-            usb_port_reset(&port->port);
-        }
-    }
-
-    uhci_async_cancel_all(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,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField []) {
-        VMSTATE_UINT16(ctrl, UHCIPort),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static const VMStateDescription vmstate_uhci = {
-    .name = "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),
-        VMSTATE_STRUCT_ARRAY(ports, UHCIState, NB_PORTS, 1,
-                             vmstate_uhci_port, UHCIPort),
-        VMSTATE_UINT16(cmd, UHCIState),
-        VMSTATE_UINT16(status, UHCIState),
-        VMSTATE_UINT16(intr, UHCIState),
-        VMSTATE_UINT16(frnum, UHCIState),
-        VMSTATE_UINT32(fl_base_addr, UHCIState),
-        VMSTATE_UINT8(sof_timing, UHCIState),
-        VMSTATE_UINT8(status2, UHCIState),
-        VMSTATE_TIMER(frame_timer, UHCIState),
-        VMSTATE_INT64_V(expire_time, UHCIState, 2),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void uhci_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
-{
-    UHCIState *s = opaque;
-
-    addr &= 0x1f;
-    switch(addr) {
-    case 0x0c:
-        s->sof_timing = val;
-        break;
-    }
-}
-
-static uint32_t uhci_ioport_readb(void *opaque, uint32_t addr)
-{
-    UHCIState *s = opaque;
-    uint32_t val;
-
-    addr &= 0x1f;
-    switch(addr) {
-    case 0x0c:
-        val = s->sof_timing;
-        break;
-    default:
-        val = 0xff;
-        break;
-    }
-    return val;
-}
-
-static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
-{
-    UHCIState *s = opaque;
-
-    addr &= 0x1f;
-    DPRINTF("uhci: writew port=0x%04x val=0x%04x\n", addr, val);
-
-    switch(addr) {
-    case 0x00:
-        if ((val & UHCI_CMD_RS) && !(s->cmd & UHCI_CMD_RS)) {
-            /* start frame processing */
-            s->expire_time = qemu_get_clock_ns(vm_clock) +
-                (get_ticks_per_sec() / FRAME_TIMER_FREQ);
-            qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
-            s->status &= ~UHCI_STS_HCHALTED;
-        } else if (!(val & UHCI_CMD_RS)) {
-            s->status |= UHCI_STS_HCHALTED;
-        }
-        if (val & UHCI_CMD_GRESET) {
-            UHCIPort *port;
-            int i;
-
-            /* send reset on the USB bus */
-            for(i = 0; i < NB_PORTS; i++) {
-                port = &s->ports[i];
-                usb_device_reset(port->port.dev);
-            }
-            uhci_reset(s);
-            return;
-        }
-        if (val & UHCI_CMD_HCRESET) {
-            uhci_reset(s);
-            return;
-        }
-        s->cmd = val;
-        break;
-    case 0x02:
-        s->status &= ~val;
-        /* XXX: the chip spec is not coherent, so we add a hidden
-           register to distinguish between IOC and SPD */
-        if (val & UHCI_STS_USBINT)
-            s->status2 = 0;
-        uhci_update_irq(s);
-        break;
-    case 0x04:
-        s->intr = val;
-        uhci_update_irq(s);
-        break;
-    case 0x06:
-        if (s->status & UHCI_STS_HCHALTED)
-            s->frnum = val & 0x7ff;
-        break;
-    case 0x10 ... 0x1f:
-        {
-            UHCIPort *port;
-            USBDevice *dev;
-            int n;
-
-            n = (addr >> 1) & 7;
-            if (n >= NB_PORTS)
-                return;
-            port = &s->ports[n];
-            dev = port->port.dev;
-            if (dev && dev->attached) {
-                /* port reset */
-                if ( (val & UHCI_PORT_RESET) &&
-                     !(port->ctrl & UHCI_PORT_RESET) ) {
-                    usb_device_reset(dev);
-                }
-            }
-            port->ctrl &= UHCI_PORT_READ_ONLY;
-            port->ctrl |= (val & ~UHCI_PORT_READ_ONLY);
-            /* some bits are reset when a '1' is written to them */
-            port->ctrl &= ~(val & UHCI_PORT_WRITE_CLEAR);
-        }
-        break;
-    }
-}
-
-static uint32_t uhci_ioport_readw(void *opaque, uint32_t addr)
-{
-    UHCIState *s = opaque;
-    uint32_t val;
-
-    addr &= 0x1f;
-    switch(addr) {
-    case 0x00:
-        val = s->cmd;
-        break;
-    case 0x02:
-        val = s->status;
-        break;
-    case 0x04:
-        val = s->intr;
-        break;
-    case 0x06:
-        val = s->frnum;
-        break;
-    case 0x10 ... 0x1f:
-        {
-            UHCIPort *port;
-            int n;
-            n = (addr >> 1) & 7;
-            if (n >= NB_PORTS)
-                goto read_default;
-            port = &s->ports[n];
-            val = port->ctrl;
-        }
-        break;
-    default:
-    read_default:
-        val = 0xff7f; /* disabled port */
-        break;
-    }
-
-    DPRINTF("uhci: readw port=0x%04x val=0x%04x\n", addr, val);
-
-    return val;
-}
-
-static void uhci_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
-{
-    UHCIState *s = opaque;
-
-    addr &= 0x1f;
-    DPRINTF("uhci: writel port=0x%04x val=0x%08x\n", addr, val);
-
-    switch(addr) {
-    case 0x08:
-        s->fl_base_addr = val & ~0xfff;
-        break;
-    }
-}
-
-static uint32_t uhci_ioport_readl(void *opaque, uint32_t addr)
-{
-    UHCIState *s = opaque;
-    uint32_t val;
-
-    addr &= 0x1f;
-    switch(addr) {
-    case 0x08:
-        val = s->fl_base_addr;
-        break;
-    default:
-        val = 0xffffffff;
-        break;
-    }
-    return val;
-}
-
-/* signal resume if controller suspended */
-static void uhci_resume (void *opaque)
-{
-    UHCIState *s = (UHCIState *)opaque;
-
-    if (!s)
-        return;
-
-    if (s->cmd & UHCI_CMD_EGSM) {
-        s->cmd |= UHCI_CMD_FGR;
-        s->status |= UHCI_STS_RD;
-        uhci_update_irq(s);
-    }
-}
-
-static void uhci_attach(USBPort *port1)
-{
-    UHCIState *s = port1->opaque;
-    UHCIPort *port = &s->ports[port1->index];
-
-    /* set connect status */
-    port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
-
-    /* update speed */
-    if (port->port.dev->speed == USB_SPEED_LOW) {
-        port->ctrl |= UHCI_PORT_LSDA;
-    } else {
-        port->ctrl &= ~UHCI_PORT_LSDA;
-    }
-
-    uhci_resume(s);
-}
-
-static void uhci_detach(USBPort *port1)
-{
-    UHCIState *s = port1->opaque;
-    UHCIPort *port = &s->ports[port1->index];
-
-    uhci_async_cancel_device(s, port1->dev);
-
-    /* set connect status */
-    if (port->ctrl & UHCI_PORT_CCS) {
-        port->ctrl &= ~UHCI_PORT_CCS;
-        port->ctrl |= UHCI_PORT_CSC;
-    }
-    /* disable port */
-    if (port->ctrl & UHCI_PORT_EN) {
-        port->ctrl &= ~UHCI_PORT_EN;
-        port->ctrl |= UHCI_PORT_ENC;
-    }
-
-    uhci_resume(s);
-}
-
-static void uhci_child_detach(USBPort *port1, USBDevice *child)
-{
-    UHCIState *s = port1->opaque;
-
-    uhci_async_cancel_device(s, child);
-}
-
-static void uhci_wakeup(USBPort *port1)
-{
-    UHCIState *s = port1->opaque;
-    UHCIPort *port = &s->ports[port1->index];
-
-    if (port->ctrl & UHCI_PORT_SUSPEND && !(port->ctrl & UHCI_PORT_RD)) {
-        port->ctrl |= UHCI_PORT_RD;
-        uhci_resume(s);
-    }
-}
-
-static USBDevice *uhci_find_device(UHCIState *s, uint8_t addr)
-{
-    USBDevice *dev;
-    int i;
-
-    for (i = 0; i < NB_PORTS; i++) {
-        UHCIPort *port = &s->ports[i];
-        if (!(port->ctrl & UHCI_PORT_EN)) {
-            continue;
-        }
-        dev = usb_find_device(&port->port, addr);
-        if (dev != NULL) {
-            return dev;
-        }
-    }
-    return NULL;
-}
-
-static void uhci_async_complete(USBPort *port, USBPacket *packet);
-static void uhci_process_frame(UHCIState *s);
-
-/* return -1 if fatal error (frame must be stopped)
-          0 if TD successful
-          1 if TD unsuccessful or inactive
-*/
-static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_t *int_mask)
-{
-    int len = 0, max_len, err, ret;
-    uint8_t pid;
-
-    max_len = ((td->token >> 21) + 1) & 0x7ff;
-    pid = td->token & 0xff;
-
-    ret = async->packet.result;
-
-    if (td->ctrl & TD_CTRL_IOS)
-        td->ctrl &= ~TD_CTRL_ACTIVE;
-
-    if (ret < 0)
-        goto out;
-
-    len = async->packet.result;
-    td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff);
-
-    /* The NAK bit may have been set by a previous frame, so clear it
-       here.  The docs are somewhat unclear, but win2k relies on this
-       behavior.  */
-    td->ctrl &= ~(TD_CTRL_ACTIVE | TD_CTRL_NAK);
-    if (td->ctrl & TD_CTRL_IOC)
-        *int_mask |= 0x01;
-
-    if (pid == USB_TOKEN_IN) {
-        if (len > max_len) {
-            ret = USB_RET_BABBLE;
-            goto out;
-        }
-
-        if ((td->ctrl & TD_CTRL_SPD) && len < max_len) {
-            *int_mask |= 0x02;
-            /* short packet: do not update QH */
-            DPRINTF("uhci: short packet. td 0x%x token 0x%x\n", async->td, async->token);
-            return 1;
-        }
-    }
-
-    /* success */
-    return 0;
-
-out:
-    switch(ret) {
-    case USB_RET_STALL:
-        td->ctrl |= TD_CTRL_STALL;
-        td->ctrl &= ~TD_CTRL_ACTIVE;
-        s->status |= UHCI_STS_USBERR;
-        if (td->ctrl & TD_CTRL_IOC) {
-            *int_mask |= 0x01;
-        }
-        uhci_update_irq(s);
-        return 1;
-
-    case USB_RET_BABBLE:
-        td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL;
-        td->ctrl &= ~TD_CTRL_ACTIVE;
-        s->status |= UHCI_STS_USBERR;
-        if (td->ctrl & TD_CTRL_IOC) {
-            *int_mask |= 0x01;
-        }
-        uhci_update_irq(s);
-        /* frame interrupted */
-        return -1;
-
-    case USB_RET_NAK:
-        td->ctrl |= TD_CTRL_NAK;
-        if (pid == USB_TOKEN_SETUP)
-            break;
-	return 1;
-
-    case USB_RET_IOERROR:
-    case USB_RET_NODEV:
-    default:
-	break;
-    }
-
-    /* Retry the TD if error count is not zero */
-
-    td->ctrl |= TD_CTRL_TIMEOUT;
-    err = (td->ctrl >> TD_CTRL_ERROR_SHIFT) & 3;
-    if (err != 0) {
-        err--;
-        if (err == 0) {
-            td->ctrl &= ~TD_CTRL_ACTIVE;
-            s->status |= UHCI_STS_USBERR;
-            if (td->ctrl & TD_CTRL_IOC)
-                *int_mask |= 0x01;
-            uhci_update_irq(s);
-        }
-    }
-    td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) |
-        (err << TD_CTRL_ERROR_SHIFT);
-    return 1;
-}
-
-static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *int_mask)
-{
-    UHCIAsync *async;
-    int len = 0, max_len;
-    uint8_t pid;
-    USBDevice *dev;
-    USBEndpoint *ep;
-
-    /* Is active ? */
-    if (!(td->ctrl & TD_CTRL_ACTIVE))
-        return 1;
-
-    async = uhci_async_find_td(s, addr, td);
-    if (async) {
-        /* Already submitted */
-        async->queue->valid = 32;
-
-        if (!async->done)
-            return 1;
-
-        uhci_async_unlink(async);
-        goto done;
-    }
-
-    /* Allocate new packet */
-    async = uhci_async_alloc(uhci_queue_get(s, td));
-    if (!async)
-        return 1;
-
-    /* valid needs to be large enough to handle 10 frame delay
-     * for initial isochronous requests
-     */
-    async->queue->valid = 32;
-    async->td    = addr;
-    async->isoc  = td->ctrl & TD_CTRL_IOS;
-
-    max_len = ((td->token >> 21) + 1) & 0x7ff;
-    pid = td->token & 0xff;
-
-    dev = uhci_find_device(s, (td->token >> 8) & 0x7f);
-    ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf);
-    usb_packet_setup(&async->packet, pid, ep);
-    qemu_sglist_add(&async->sgl, td->buffer, max_len);
-    usb_packet_map(&async->packet, &async->sgl);
-
-    switch(pid) {
-    case USB_TOKEN_OUT:
-    case USB_TOKEN_SETUP:
-        len = usb_handle_packet(dev, &async->packet);
-        if (len >= 0)
-            len = max_len;
-        break;
-
-    case USB_TOKEN_IN:
-        len = usb_handle_packet(dev, &async->packet);
-        break;
-
-    default:
-        /* invalid pid : frame interrupted */
-        uhci_async_free(async);
-        s->status |= UHCI_STS_HCPERR;
-        uhci_update_irq(s);
-        return -1;
-    }
- 
-    if (len == USB_RET_ASYNC) {
-        uhci_async_link(async);
-        return 2;
-    }
-
-    async->packet.result = len;
-
-done:
-    len = uhci_complete_td(s, td, async, int_mask);
-    usb_packet_unmap(&async->packet);
-    uhci_async_free(async);
-    return len;
-}
-
-static void uhci_async_complete(USBPort *port, USBPacket *packet)
-{
-    UHCIAsync *async = container_of(packet, UHCIAsync, packet);
-    UHCIState *s = async->queue->uhci;
-
-    DPRINTF("uhci: async complete. td 0x%x token 0x%x\n", async->td, async->token);
-
-    if (async->isoc) {
-        UHCI_TD td;
-        uint32_t link = async->td;
-        uint32_t int_mask = 0, val;
-
-        pci_dma_read(&s->dev, link & ~0xf, &td, sizeof(td));
-        le32_to_cpus(&td.link);
-        le32_to_cpus(&td.ctrl);
-        le32_to_cpus(&td.token);
-        le32_to_cpus(&td.buffer);
-
-        uhci_async_unlink(async);
-        uhci_complete_td(s, &td, async, &int_mask);
-        s->pending_int_mask |= int_mask;
-
-        /* update the status bits of the TD */
-        val = cpu_to_le32(td.ctrl);
-        pci_dma_write(&s->dev, (link & ~0xf) + 4, &val, sizeof(val));
-        uhci_async_free(async);
-    } else {
-        async->done = 1;
-        uhci_process_frame(s);
-    }
-}
-
-static int is_valid(uint32_t link)
-{
-    return (link & 1) == 0;
-}
-
-static int is_qh(uint32_t link)
-{
-    return (link & 2) != 0;
-}
-
-static int depth_first(uint32_t link)
-{
-    return (link & 4) != 0;
-}
-
-/* QH DB used for detecting QH loops */
-#define UHCI_MAX_QUEUES 128
-typedef struct {
-    uint32_t addr[UHCI_MAX_QUEUES];
-    int      count;
-} QhDb;
-
-static void qhdb_reset(QhDb *db)
-{
-    db->count = 0;
-}
-
-/* Add QH to DB. Returns 1 if already present or DB is full. */
-static int qhdb_insert(QhDb *db, uint32_t addr)
-{
-    int i;
-    for (i = 0; i < db->count; i++)
-        if (db->addr[i] == addr)
-            return 1;
-
-    if (db->count >= UHCI_MAX_QUEUES)
-        return 1;
-
-    db->addr[db->count++] = addr;
-    return 0;
-}
-
-static void uhci_fill_queue(UHCIState *s, UHCI_TD *td)
-{
-    uint32_t int_mask = 0;
-    uint32_t plink = td->link;
-    uint32_t token = uhci_queue_token(td);
-    UHCI_TD ptd;
-    int ret;
-
-    while (is_valid(plink)) {
-        pci_dma_read(&s->dev, plink & ~0xf, &ptd, sizeof(ptd));
-        le32_to_cpus(&ptd.link);
-        le32_to_cpus(&ptd.ctrl);
-        le32_to_cpus(&ptd.token);
-        le32_to_cpus(&ptd.buffer);
-        if (!(ptd.ctrl & TD_CTRL_ACTIVE)) {
-            break;
-        }
-        if (uhci_queue_token(&ptd) != token) {
-            break;
-        }
-        ret = uhci_handle_td(s, plink, &ptd, &int_mask);
-        assert(ret == 2); /* got USB_RET_ASYNC */
-        assert(int_mask == 0);
-        plink = ptd.link;
-    }
-}
-
-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;
-    int cnt, ret;
-    UHCI_TD td;
-    UHCI_QH qh;
-    QhDb qhdb;
-
-    frame_addr = s->fl_base_addr + ((s->frnum & 0x3ff) << 2);
-
-    DPRINTF("uhci: processing frame %d addr 0x%x\n" , s->frnum, frame_addr);
-
-    pci_dma_read(&s->dev, frame_addr, &link, 4);
-    le32_to_cpus(&link);
-
-    int_mask = 0;
-    curr_qh  = 0;
-
-    qhdb_reset(&qhdb);
-
-    for (cnt = FRAME_MAX_LOOPS; is_valid(link) && cnt; cnt--) {
-        if (is_qh(link)) {
-            /* QH */
-
-            if (qhdb_insert(&qhdb, link)) {
-                /*
-                 * 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.
-                 */
-                DPRINTF("uhci: detected loop. qh 0x%x\n", link);
-                if (td_count == 0) {
-                    DPRINTF("uhci: no transaction last round, stop\n");
-                    break;
-                } else if (bytes_count >= 1280) {
-                    DPRINTF("uhci: bandwidth limit reached, stop\n");
-                    break;
-                } else {
-                    td_count = 0;
-                    qhdb_reset(&qhdb);
-                    qhdb_insert(&qhdb, link);
-                }
-            }
-
-            pci_dma_read(&s->dev, link & ~0xf, &qh, sizeof(qh));
-            le32_to_cpus(&qh.link);
-            le32_to_cpus(&qh.el_link);
-
-            DPRINTF("uhci: QH 0x%x load. link 0x%x elink 0x%x\n",
-                    link, qh.link, qh.el_link);
-
-            if (!is_valid(qh.el_link)) {
-                /* QH w/o elements */
-                curr_qh = 0;
-                link = qh.link;
-            } else {
-                /* QH with elements */
-            	curr_qh = link;
-            	link = qh.el_link;
-            }
-            continue;
-        }
-
-        /* TD */
-        pci_dma_read(&s->dev, link & ~0xf, &td, sizeof(td));
-        le32_to_cpus(&td.link);
-        le32_to_cpus(&td.ctrl);
-        le32_to_cpus(&td.token);
-        le32_to_cpus(&td.buffer);
-
-        DPRINTF("uhci: TD 0x%x load. link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n", 
-                link, td.link, td.ctrl, td.token, curr_qh);
-
-        old_td_ctrl = td.ctrl;
-        ret = uhci_handle_td(s, link, &td, &int_mask);
-        if (old_td_ctrl != td.ctrl) {
-            /* update the status bits of the TD */
-            val = cpu_to_le32(td.ctrl);
-            pci_dma_write(&s->dev, (link & ~0xf) + 4, &val, sizeof(val));
-        }
-
-        switch (ret) {
-        case -1: /* interrupted frame */
-            goto out;
-
-        case 1: /* goto next queue */
-            DPRINTF("uhci: TD 0x%x skip. "
-                    "link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n",
-                    link, td.link, td.ctrl, td.token, curr_qh);
-            link = curr_qh ? qh.link : td.link;
-            continue;
-
-        case 2: /* got USB_RET_ASYNC */
-            DPRINTF("uhci: TD 0x%x async. "
-                    "link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n",
-                    link, td.link, td.ctrl, td.token, curr_qh);
-            if (is_valid(td.link)) {
-                uhci_fill_queue(s, &td);
-            }
-            link = curr_qh ? qh.link : td.link;
-            continue;
-
-        case 0: /* completed TD */
-            DPRINTF("uhci: TD 0x%x done. "
-                    "link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n",
-                    link, td.link, td.ctrl, td.token, curr_qh);
-
-            link = td.link;
-            td_count++;
-            bytes_count += (td.ctrl & 0x7ff) + 1;
-
-            if (curr_qh) {
-                /* update QH element link */
-                qh.el_link = link;
-                val = cpu_to_le32(qh.el_link);
-                pci_dma_write(&s->dev, (curr_qh & ~0xf) + 4, &val, sizeof(val));
-
-                if (!depth_first(link)) {
-                    /* done with this QH */
-
-                    DPRINTF("uhci: QH 0x%x done. link 0x%x elink 0x%x\n",
-                            curr_qh, qh.link, qh.el_link);
-
-                    curr_qh = 0;
-                    link    = qh.link;
-                }
-            }
-            break;
-
-        default:
-            assert(!"unknown return code");
-        }
-
-        /* go to the next entry */
-    }
-
-out:
-    s->pending_int_mask |= int_mask;
-}
-
-static void uhci_frame_timer(void *opaque)
-{
-    UHCIState *s = opaque;
-
-    /* prepare the timer for the next frame */
-    s->expire_time += (get_ticks_per_sec() / FRAME_TIMER_FREQ);
-
-    if (!(s->cmd & UHCI_CMD_RS)) {
-        /* Full stop */
-        qemu_del_timer(s->frame_timer);
-        /* set hchalted bit in status - UHCI11D 2.1.2 */
-        s->status |= UHCI_STS_HCHALTED;
-
-        DPRINTF("uhci: halted\n");
-        return;
-    }
-
-    /* Complete the previous frame */
-    if (s->pending_int_mask) {
-        s->status2 |= s->pending_int_mask;
-        s->status  |= UHCI_STS_USBINT;
-        uhci_update_irq(s);
-    }
-    s->pending_int_mask = 0;
-
-    /* Start new frame */
-    s->frnum = (s->frnum + 1) & 0x7ff;
-
-    DPRINTF("uhci: new frame #%u\n" , s->frnum);
-
-    uhci_async_validate_begin(s);
-
-    uhci_process_frame(s);
-
-    uhci_async_validate_end(s);
-
-    qemu_mod_timer(s->frame_timer, s->expire_time);
-}
-
-static const MemoryRegionPortio uhci_portio[] = {
-    { 0, 32, 2, .write = uhci_ioport_writew, },
-    { 0, 32, 2, .read = uhci_ioport_readw, },
-    { 0, 32, 4, .write = uhci_ioport_writel, },
-    { 0, 32, 4, .read = uhci_ioport_readl, },
-    { 0, 32, 1, .write = uhci_ioport_writeb, },
-    { 0, 32, 1, .read = uhci_ioport_readb, },
-    PORTIO_END_OF_LIST()
-};
-
-static const MemoryRegionOps uhci_ioport_ops = {
-    .old_portio = uhci_portio,
-};
-
-static USBPortOps uhci_port_ops = {
-    .attach = uhci_attach,
-    .detach = uhci_detach,
-    .child_detach = uhci_child_detach,
-    .wakeup = uhci_wakeup,
-    .complete = uhci_async_complete,
-};
-
-static USBBusOps uhci_bus_ops = {
-};
-
-static int usb_uhci_common_initfn(PCIDevice *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
-
-    if (s->masterbus) {
-        USBPort *ports[NB_PORTS];
-        for(i = 0; i < NB_PORTS; i++) {
-            ports[i] = &s->ports[i].port;
-        }
-        if (usb_register_companion(s->masterbus, ports, NB_PORTS,
-                s->firstport, s, &uhci_port_ops,
-                USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL) != 0) {
-            return -1;
-        }
-    } else {
-        usb_bus_new(&s->bus, &uhci_bus_ops, &s->dev.qdev);
-        for (i = 0; i < NB_PORTS; i++) {
-            usb_register_port(&s->bus, &s->ports[i].port, s, i, &uhci_port_ops,
-                              USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
-        }
-    }
-    s->frame_timer = qemu_new_timer_ns(vm_clock, uhci_frame_timer, s);
-    s->num_ports_vmstate = NB_PORTS;
-    QTAILQ_INIT(&s->queues);
-
-    qemu_register_reset(uhci_reset, s);
-
-    memory_region_init_io(&s->io_bar, &uhci_ioport_ops, s, "uhci", 0x20);
-    /* Use region 4 for consistency with real hardware.  BSD guests seem
-       to rely on this.  */
-    pci_register_bar(&s->dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar);
-
-    return 0;
-}
-
-static int usb_uhci_vt82c686b_initfn(PCIDevice *dev)
-{
-    UHCIState *s = DO_UPCAST(UHCIState, dev, dev);
-    uint8_t *pci_conf = s->dev.config;
-
-    /* USB misc control 1/2 */
-    pci_set_long(pci_conf + 0x40,0x00001000);
-    /* PM capability */
-    pci_set_long(pci_conf + 0x80,0x00020001);
-    /* USB legacy support  */
-    pci_set_long(pci_conf + 0xc0,0x00002000);
-
-    return usb_uhci_common_initfn(dev);
-}
-
-static int usb_uhci_exit(PCIDevice *dev)
-{
-    UHCIState *s = DO_UPCAST(UHCIState, dev, dev);
-
-    memory_region_destroy(&s->io_bar);
-    return 0;
-}
-
-static Property uhci_properties[] = {
-    DEFINE_PROP_STRING("masterbus", UHCIState, masterbus),
-    DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void piix3_uhci_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = usb_uhci_common_initfn;
-    k->exit = usb_uhci_exit;
-    k->vendor_id = PCI_VENDOR_ID_INTEL;
-    k->device_id = PCI_DEVICE_ID_INTEL_82371SB_2;
-    k->revision = 0x01;
-    k->class_id = PCI_CLASS_SERIAL_USB;
-    dc->vmsd = &vmstate_uhci;
-    dc->props = uhci_properties;
-}
-
-static TypeInfo piix3_uhci_info = {
-    .name          = "piix3-usb-uhci",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(UHCIState),
-    .class_init    = piix3_uhci_class_init,
-};
-
-static void piix4_uhci_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = usb_uhci_common_initfn;
-    k->exit = usb_uhci_exit;
-    k->vendor_id = PCI_VENDOR_ID_INTEL;
-    k->device_id = PCI_DEVICE_ID_INTEL_82371AB_2;
-    k->revision = 0x01;
-    k->class_id = PCI_CLASS_SERIAL_USB;
-    dc->vmsd = &vmstate_uhci;
-    dc->props = uhci_properties;
-}
-
-static TypeInfo piix4_uhci_info = {
-    .name          = "piix4-usb-uhci",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(UHCIState),
-    .class_init    = piix4_uhci_class_init,
-};
-
-static void vt82c686b_uhci_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = usb_uhci_vt82c686b_initfn;
-    k->exit = usb_uhci_exit;
-    k->vendor_id = PCI_VENDOR_ID_VIA;
-    k->device_id = PCI_DEVICE_ID_VIA_UHCI;
-    k->revision = 0x01;
-    k->class_id = PCI_CLASS_SERIAL_USB;
-    dc->vmsd = &vmstate_uhci;
-    dc->props = uhci_properties;
-}
-
-static TypeInfo vt82c686b_uhci_info = {
-    .name          = "vt82c686b-usb-uhci",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(UHCIState),
-    .class_init    = vt82c686b_uhci_class_init,
-};
-
-static void ich9_uhci1_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = usb_uhci_common_initfn;
-    k->vendor_id = PCI_VENDOR_ID_INTEL;
-    k->device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI1;
-    k->revision = 0x03;
-    k->class_id = PCI_CLASS_SERIAL_USB;
-    dc->vmsd = &vmstate_uhci;
-    dc->props = uhci_properties;
-}
-
-static TypeInfo ich9_uhci1_info = {
-    .name          = "ich9-usb-uhci1",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(UHCIState),
-    .class_init    = ich9_uhci1_class_init,
-};
-
-static void ich9_uhci2_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = usb_uhci_common_initfn;
-    k->vendor_id = PCI_VENDOR_ID_INTEL;
-    k->device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI2;
-    k->revision = 0x03;
-    k->class_id = PCI_CLASS_SERIAL_USB;
-    dc->vmsd = &vmstate_uhci;
-    dc->props = uhci_properties;
-}
-
-static TypeInfo ich9_uhci2_info = {
-    .name          = "ich9-usb-uhci2",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(UHCIState),
-    .class_init    = ich9_uhci2_class_init,
-};
-
-static void ich9_uhci3_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = usb_uhci_common_initfn;
-    k->vendor_id = PCI_VENDOR_ID_INTEL;
-    k->device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI3;
-    k->revision = 0x03;
-    k->class_id = PCI_CLASS_SERIAL_USB;
-    dc->vmsd = &vmstate_uhci;
-    dc->props = uhci_properties;
-}
-
-static TypeInfo ich9_uhci3_info = {
-    .name          = "ich9-usb-uhci3",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(UHCIState),
-    .class_init    = ich9_uhci3_class_init,
-};
-
-static void uhci_register_types(void)
-{
-    type_register_static(&piix3_uhci_info);
-    type_register_static(&piix4_uhci_info);
-    type_register_static(&vt82c686b_uhci_info);
-    type_register_static(&ich9_uhci1_info);
-    type_register_static(&ich9_uhci2_info);
-    type_register_static(&ich9_uhci3_info);
-}
-
-type_init(uhci_register_types)
-
-void usb_uhci_piix3_init(PCIBus *bus, int devfn)
-{
-    pci_create_simple(bus, devfn, "piix3-usb-uhci");
-}
-
-void usb_uhci_piix4_init(PCIBus *bus, int devfn)
-{
-    pci_create_simple(bus, devfn, "piix4-usb-uhci");
-}
-
-void usb_uhci_vt82c686b_init(PCIBus *bus, int devfn)
-{
-    pci_create_simple(bus, devfn, "vt82c686b-usb-uhci");
-}
diff --git a/hw/usb-wacom.c b/hw/usb-wacom.c
deleted file mode 100644
index 197e2dc..0000000
--- a/hw/usb-wacom.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * Wacom PenPartner USB tablet emulation.
- *
- * Copyright (c) 2006 Openedhand Ltd.
- * Author: Andrzej Zaborowski <balrog at zabor.org>
- *
- * Based on hw/usb-hid.c:
- * Copyright (c) 2005 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "hw.h"
-#include "console.h"
-#include "usb.h"
-#include "usb-desc.h"
-
-/* Interface requests */
-#define WACOM_GET_REPORT	0x2101
-#define WACOM_SET_REPORT	0x2109
-
-/* HID interface requests */
-#define HID_GET_REPORT		0xa101
-#define HID_GET_IDLE		0xa102
-#define HID_GET_PROTOCOL	0xa103
-#define HID_SET_IDLE		0x210a
-#define HID_SET_PROTOCOL	0x210b
-
-typedef struct USBWacomState {
-    USBDevice dev;
-    QEMUPutMouseEntry *eh_entry;
-    int dx, dy, dz, buttons_state;
-    int x, y;
-    int mouse_grabbed;
-    enum {
-        WACOM_MODE_HID = 1,
-        WACOM_MODE_WACOM = 2,
-    } mode;
-    uint8_t idle;
-    int changed;
-} USBWacomState;
-
-enum {
-    STR_MANUFACTURER = 1,
-    STR_PRODUCT,
-    STR_SERIALNUMBER,
-};
-
-static const USBDescStrings desc_strings = {
-    [STR_MANUFACTURER]     = "QEMU " QEMU_VERSION,
-    [STR_PRODUCT]          = "Wacom PenPartner",
-    [STR_SERIALNUMBER]     = "1",
-};
-
-static const USBDescIface desc_iface_wacom = {
-    .bInterfaceNumber              = 0,
-    .bNumEndpoints                 = 1,
-    .bInterfaceClass               = USB_CLASS_HID,
-    .bInterfaceSubClass            = 0x01, /* boot */
-    .bInterfaceProtocol            = 0x02,
-    .ndesc                         = 1,
-    .descs = (USBDescOther[]) {
-        {
-            /* HID descriptor */
-            .data = (uint8_t[]) {
-                0x09,          /*  u8  bLength */
-                0x21,          /*  u8  bDescriptorType */
-                0x01, 0x10,    /*  u16 HID_class */
-                0x00,          /*  u8  country_code */
-                0x01,          /*  u8  num_descriptors */
-                0x22,          /*  u8  type: Report */
-                0x6e, 0,       /*  u16 len */
-            },
-        },
-    },
-    .eps = (USBDescEndpoint[]) {
-        {
-            .bEndpointAddress      = USB_DIR_IN | 0x01,
-            .bmAttributes          = USB_ENDPOINT_XFER_INT,
-            .wMaxPacketSize        = 8,
-            .bInterval             = 0x0a,
-        },
-    },
-};
-
-static const USBDescDevice desc_device_wacom = {
-    .bcdUSB                        = 0x0110,
-    .bMaxPacketSize0               = 8,
-    .bNumConfigurations            = 1,
-    .confs = (USBDescConfig[]) {
-        {
-            .bNumInterfaces        = 1,
-            .bConfigurationValue   = 1,
-            .bmAttributes          = 0x80,
-            .bMaxPower             = 40,
-            .nif = 1,
-            .ifs = &desc_iface_wacom,
-        },
-    },
-};
-
-static const USBDesc desc_wacom = {
-    .id = {
-        .idVendor          = 0x056a,
-        .idProduct         = 0x0000,
-        .bcdDevice         = 0x4210,
-        .iManufacturer     = STR_MANUFACTURER,
-        .iProduct          = STR_PRODUCT,
-        .iSerialNumber     = STR_SERIALNUMBER,
-    },
-    .full = &desc_device_wacom,
-    .str  = desc_strings,
-};
-
-static void usb_mouse_event(void *opaque,
-                            int dx1, int dy1, int dz1, int buttons_state)
-{
-    USBWacomState *s = opaque;
-
-    s->dx += dx1;
-    s->dy += dy1;
-    s->dz += dz1;
-    s->buttons_state = buttons_state;
-    s->changed = 1;
-}
-
-static void usb_wacom_event(void *opaque,
-                            int x, int y, int dz, int buttons_state)
-{
-    USBWacomState *s = opaque;
-
-    /* scale to Penpartner resolution */
-    s->x = (x * 5040 / 0x7FFF);
-    s->y = (y * 3780 / 0x7FFF);
-    s->dz += dz;
-    s->buttons_state = buttons_state;
-    s->changed = 1;
-}
-
-static inline int int_clamp(int val, int vmin, int vmax)
-{
-    if (val < vmin)
-        return vmin;
-    else if (val > vmax)
-        return vmax;
-    else
-        return val;
-}
-
-static int usb_mouse_poll(USBWacomState *s, uint8_t *buf, int len)
-{
-    int dx, dy, dz, b, l;
-
-    if (!s->mouse_grabbed) {
-        s->eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, s, 0,
-                        "QEMU PenPartner tablet");
-        qemu_activate_mouse_event_handler(s->eh_entry);
-        s->mouse_grabbed = 1;
-    }
-
-    dx = int_clamp(s->dx, -128, 127);
-    dy = int_clamp(s->dy, -128, 127);
-    dz = int_clamp(s->dz, -128, 127);
-
-    s->dx -= dx;
-    s->dy -= dy;
-    s->dz -= dz;
-
-    b = 0;
-    if (s->buttons_state & MOUSE_EVENT_LBUTTON)
-        b |= 0x01;
-    if (s->buttons_state & MOUSE_EVENT_RBUTTON)
-        b |= 0x02;
-    if (s->buttons_state & MOUSE_EVENT_MBUTTON)
-        b |= 0x04;
-
-    buf[0] = b;
-    buf[1] = dx;
-    buf[2] = dy;
-    l = 3;
-    if (len >= 4) {
-        buf[3] = dz;
-        l = 4;
-    }
-    return l;
-}
-
-static int usb_wacom_poll(USBWacomState *s, uint8_t *buf, int len)
-{
-    int b;
-
-    if (!s->mouse_grabbed) {
-        s->eh_entry = qemu_add_mouse_event_handler(usb_wacom_event, s, 1,
-                        "QEMU PenPartner tablet");
-        qemu_activate_mouse_event_handler(s->eh_entry);
-        s->mouse_grabbed = 1;
-    }
-
-    b = 0;
-    if (s->buttons_state & MOUSE_EVENT_LBUTTON)
-        b |= 0x01;
-    if (s->buttons_state & MOUSE_EVENT_RBUTTON)
-        b |= 0x40;
-    if (s->buttons_state & MOUSE_EVENT_MBUTTON)
-        b |= 0x20; /* eraser */
-
-    if (len < 7)
-        return 0;
-
-    buf[0] = s->mode;
-    buf[5] = 0x00 | (b & 0xf0);
-    buf[1] = s->x & 0xff;
-    buf[2] = s->x >> 8;
-    buf[3] = s->y & 0xff;
-    buf[4] = s->y >> 8;
-    if (b & 0x3f) {
-        buf[6] = 0;
-    } else {
-        buf[6] = (unsigned char) -127;
-    }
-
-    return 7;
-}
-
-static void usb_wacom_handle_reset(USBDevice *dev)
-{
-    USBWacomState *s = (USBWacomState *) dev;
-
-    s->dx = 0;
-    s->dy = 0;
-    s->dz = 0;
-    s->x = 0;
-    s->y = 0;
-    s->buttons_state = 0;
-    s->mode = WACOM_MODE_HID;
-}
-
-static int usb_wacom_handle_control(USBDevice *dev, USBPacket *p,
-               int request, int value, int index, int length, uint8_t *data)
-{
-    USBWacomState *s = (USBWacomState *) dev;
-    int ret;
-
-    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
-    if (ret >= 0) {
-        return ret;
-    }
-
-    ret = 0;
-    switch (request) {
-    case WACOM_SET_REPORT:
-        if (s->mouse_grabbed) {
-            qemu_remove_mouse_event_handler(s->eh_entry);
-            s->mouse_grabbed = 0;
-        }
-        s->mode = data[0];
-        ret = 0;
-        break;
-    case WACOM_GET_REPORT:
-        data[0] = 0;
-        data[1] = s->mode;
-        ret = 2;
-        break;
-    /* USB HID requests */
-    case HID_GET_REPORT:
-        if (s->mode == WACOM_MODE_HID)
-            ret = usb_mouse_poll(s, data, length);
-        else if (s->mode == WACOM_MODE_WACOM)
-            ret = usb_wacom_poll(s, data, length);
-        break;
-    case HID_GET_IDLE:
-        ret = 1;
-        data[0] = s->idle;
-        break;
-    case HID_SET_IDLE:
-        s->idle = (uint8_t) (value >> 8);
-        ret = 0;
-        break;
-    default:
-        ret = USB_RET_STALL;
-        break;
-    }
-    return ret;
-}
-
-static int usb_wacom_handle_data(USBDevice *dev, USBPacket *p)
-{
-    USBWacomState *s = (USBWacomState *) dev;
-    uint8_t buf[p->iov.size];
-    int ret = 0;
-
-    switch (p->pid) {
-    case USB_TOKEN_IN:
-        if (p->ep->nr == 1) {
-            if (!(s->changed || s->idle))
-                return USB_RET_NAK;
-            s->changed = 0;
-            if (s->mode == WACOM_MODE_HID)
-                ret = usb_mouse_poll(s, buf, p->iov.size);
-            else if (s->mode == WACOM_MODE_WACOM)
-                ret = usb_wacom_poll(s, buf, p->iov.size);
-            usb_packet_copy(p, buf, ret);
-            break;
-        }
-        /* Fall through.  */
-    case USB_TOKEN_OUT:
-    default:
-        ret = USB_RET_STALL;
-        break;
-    }
-    return ret;
-}
-
-static void usb_wacom_handle_destroy(USBDevice *dev)
-{
-    USBWacomState *s = (USBWacomState *) dev;
-
-    if (s->mouse_grabbed) {
-        qemu_remove_mouse_event_handler(s->eh_entry);
-        s->mouse_grabbed = 0;
-    }
-}
-
-static int usb_wacom_initfn(USBDevice *dev)
-{
-    USBWacomState *s = DO_UPCAST(USBWacomState, dev, dev);
-    usb_desc_init(dev);
-    s->changed = 1;
-    return 0;
-}
-
-static const VMStateDescription vmstate_usb_wacom = {
-    .name = "usb-wacom",
-    .unmigratable = 1,
-};
-
-static void usb_wacom_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
-
-    uc->product_desc   = "QEMU PenPartner Tablet";
-    uc->usb_desc       = &desc_wacom;
-    uc->init           = usb_wacom_initfn;
-    uc->handle_reset   = usb_wacom_handle_reset;
-    uc->handle_control = usb_wacom_handle_control;
-    uc->handle_data    = usb_wacom_handle_data;
-    uc->handle_destroy = usb_wacom_handle_destroy;
-    dc->desc = "QEMU PenPartner Tablet";
-    dc->vmsd = &vmstate_usb_wacom;
-}
-
-static TypeInfo wacom_info = {
-    .name          = "usb-wacom-tablet",
-    .parent        = TYPE_USB_DEVICE,
-    .instance_size = sizeof(USBWacomState),
-    .class_init    = usb_wacom_class_init,
-};
-
-static void usb_wacom_register_types(void)
-{
-    type_register_static(&wacom_info);
-    usb_legacy_register("usb-wacom-tablet", "wacom-tablet", NULL);
-}
-
-type_init(usb_wacom_register_types)
diff --git a/hw/usb-xhci.c b/hw/usb-xhci.c
deleted file mode 100644
index e8f1b6e..0000000
--- a/hw/usb-xhci.c
+++ /dev/null
@@ -1,2925 +0,0 @@
-/*
- * USB xHCI controller emulation
- *
- * Copyright (c) 2011 Securiforest
- * Date: 2011-05-11 ;  Author: Hector Martin <hector at marcansoft.com>
- * Based on usb-ohci.c, emulates Renesas NEC USB 3.0
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#include "hw.h"
-#include "qemu-timer.h"
-#include "usb.h"
-#include "pci.h"
-#include "qdev-addr.h"
-#include "msi.h"
-
-//#define DEBUG_XHCI
-//#define DEBUG_DATA
-
-#ifdef DEBUG_XHCI
-#define DPRINTF(...) fprintf(stderr, __VA_ARGS__)
-#else
-#define DPRINTF(...) do {} while (0)
-#endif
-#define FIXME() do { fprintf(stderr, "FIXME %s:%d\n", \
-                             __func__, __LINE__); abort(); } while (0)
-
-#define MAXSLOTS 8
-#define MAXINTRS 1
-
-#define USB2_PORTS 4
-#define USB3_PORTS 4
-
-#define MAXPORTS (USB2_PORTS+USB3_PORTS)
-
-#define TD_QUEUE 24
-#define BG_XFERS 8
-#define BG_PKTS 8
-
-/* Very pessimistic, let's hope it's enough for all cases */
-#define EV_QUEUE (((3*TD_QUEUE)+16)*MAXSLOTS)
-/* Do not deliver ER Full events. NEC's driver does some things not bound
- * to the specs when it gets them */
-#define ER_FULL_HACK
-
-#define LEN_CAP         0x40
-#define OFF_OPER        LEN_CAP
-#define LEN_OPER        (0x400 + 0x10 * MAXPORTS)
-#define OFF_RUNTIME     ((OFF_OPER + LEN_OPER + 0x20) & ~0x1f)
-#define LEN_RUNTIME     (0x20 + MAXINTRS * 0x20)
-#define OFF_DOORBELL    (OFF_RUNTIME + LEN_RUNTIME)
-#define LEN_DOORBELL    ((MAXSLOTS + 1) * 0x20)
-
-/* must be power of 2 */
-#define LEN_REGS        0x2000
-
-#if (OFF_DOORBELL + LEN_DOORBELL) > LEN_REGS
-# error Increase LEN_REGS
-#endif
-
-#if MAXINTRS > 1
-# error TODO: only one interrupter supported
-#endif
-
-/* bit definitions */
-#define USBCMD_RS       (1<<0)
-#define USBCMD_HCRST    (1<<1)
-#define USBCMD_INTE     (1<<2)
-#define USBCMD_HSEE     (1<<3)
-#define USBCMD_LHCRST   (1<<7)
-#define USBCMD_CSS      (1<<8)
-#define USBCMD_CRS      (1<<9)
-#define USBCMD_EWE      (1<<10)
-#define USBCMD_EU3S     (1<<11)
-
-#define USBSTS_HCH      (1<<0)
-#define USBSTS_HSE      (1<<2)
-#define USBSTS_EINT     (1<<3)
-#define USBSTS_PCD      (1<<4)
-#define USBSTS_SSS      (1<<8)
-#define USBSTS_RSS      (1<<9)
-#define USBSTS_SRE      (1<<10)
-#define USBSTS_CNR      (1<<11)
-#define USBSTS_HCE      (1<<12)
-
-
-#define PORTSC_CCS          (1<<0)
-#define PORTSC_PED          (1<<1)
-#define PORTSC_OCA          (1<<3)
-#define PORTSC_PR           (1<<4)
-#define PORTSC_PLS_SHIFT        5
-#define PORTSC_PLS_MASK     0xf
-#define PORTSC_PP           (1<<9)
-#define PORTSC_SPEED_SHIFT      10
-#define PORTSC_SPEED_MASK   0xf
-#define PORTSC_SPEED_FULL   (1<<10)
-#define PORTSC_SPEED_LOW    (2<<10)
-#define PORTSC_SPEED_HIGH   (3<<10)
-#define PORTSC_SPEED_SUPER  (4<<10)
-#define PORTSC_PIC_SHIFT        14
-#define PORTSC_PIC_MASK     0x3
-#define PORTSC_LWS          (1<<16)
-#define PORTSC_CSC          (1<<17)
-#define PORTSC_PEC          (1<<18)
-#define PORTSC_WRC          (1<<19)
-#define PORTSC_OCC          (1<<20)
-#define PORTSC_PRC          (1<<21)
-#define PORTSC_PLC          (1<<22)
-#define PORTSC_CEC          (1<<23)
-#define PORTSC_CAS          (1<<24)
-#define PORTSC_WCE          (1<<25)
-#define PORTSC_WDE          (1<<26)
-#define PORTSC_WOE          (1<<27)
-#define PORTSC_DR           (1<<30)
-#define PORTSC_WPR          (1<<31)
-
-#define CRCR_RCS        (1<<0)
-#define CRCR_CS         (1<<1)
-#define CRCR_CA         (1<<2)
-#define CRCR_CRR        (1<<3)
-
-#define IMAN_IP         (1<<0)
-#define IMAN_IE         (1<<1)
-
-#define ERDP_EHB        (1<<3)
-
-#define TRB_SIZE 16
-typedef struct XHCITRB {
-    uint64_t parameter;
-    uint32_t status;
-    uint32_t control;
-    target_phys_addr_t addr;
-    bool ccs;
-} XHCITRB;
-
-
-typedef enum TRBType {
-    TRB_RESERVED = 0,
-    TR_NORMAL,
-    TR_SETUP,
-    TR_DATA,
-    TR_STATUS,
-    TR_ISOCH,
-    TR_LINK,
-    TR_EVDATA,
-    TR_NOOP,
-    CR_ENABLE_SLOT,
-    CR_DISABLE_SLOT,
-    CR_ADDRESS_DEVICE,
-    CR_CONFIGURE_ENDPOINT,
-    CR_EVALUATE_CONTEXT,
-    CR_RESET_ENDPOINT,
-    CR_STOP_ENDPOINT,
-    CR_SET_TR_DEQUEUE,
-    CR_RESET_DEVICE,
-    CR_FORCE_EVENT,
-    CR_NEGOTIATE_BW,
-    CR_SET_LATENCY_TOLERANCE,
-    CR_GET_PORT_BANDWIDTH,
-    CR_FORCE_HEADER,
-    CR_NOOP,
-    ER_TRANSFER = 32,
-    ER_COMMAND_COMPLETE,
-    ER_PORT_STATUS_CHANGE,
-    ER_BANDWIDTH_REQUEST,
-    ER_DOORBELL,
-    ER_HOST_CONTROLLER,
-    ER_DEVICE_NOTIFICATION,
-    ER_MFINDEX_WRAP,
-    /* vendor specific bits */
-    CR_VENDOR_VIA_CHALLENGE_RESPONSE = 48,
-    CR_VENDOR_NEC_FIRMWARE_REVISION  = 49,
-    CR_VENDOR_NEC_CHALLENGE_RESPONSE = 50,
-} TRBType;
-
-#define CR_LINK TR_LINK
-
-typedef enum TRBCCode {
-    CC_INVALID = 0,
-    CC_SUCCESS,
-    CC_DATA_BUFFER_ERROR,
-    CC_BABBLE_DETECTED,
-    CC_USB_TRANSACTION_ERROR,
-    CC_TRB_ERROR,
-    CC_STALL_ERROR,
-    CC_RESOURCE_ERROR,
-    CC_BANDWIDTH_ERROR,
-    CC_NO_SLOTS_ERROR,
-    CC_INVALID_STREAM_TYPE_ERROR,
-    CC_SLOT_NOT_ENABLED_ERROR,
-    CC_EP_NOT_ENABLED_ERROR,
-    CC_SHORT_PACKET,
-    CC_RING_UNDERRUN,
-    CC_RING_OVERRUN,
-    CC_VF_ER_FULL,
-    CC_PARAMETER_ERROR,
-    CC_BANDWIDTH_OVERRUN,
-    CC_CONTEXT_STATE_ERROR,
-    CC_NO_PING_RESPONSE_ERROR,
-    CC_EVENT_RING_FULL_ERROR,
-    CC_INCOMPATIBLE_DEVICE_ERROR,
-    CC_MISSED_SERVICE_ERROR,
-    CC_COMMAND_RING_STOPPED,
-    CC_COMMAND_ABORTED,
-    CC_STOPPED,
-    CC_STOPPED_LENGTH_INVALID,
-    CC_MAX_EXIT_LATENCY_TOO_LARGE_ERROR = 29,
-    CC_ISOCH_BUFFER_OVERRUN = 31,
-    CC_EVENT_LOST_ERROR,
-    CC_UNDEFINED_ERROR,
-    CC_INVALID_STREAM_ID_ERROR,
-    CC_SECONDARY_BANDWIDTH_ERROR,
-    CC_SPLIT_TRANSACTION_ERROR
-} TRBCCode;
-
-#define TRB_C               (1<<0)
-#define TRB_TYPE_SHIFT          10
-#define TRB_TYPE_MASK       0x3f
-#define TRB_TYPE(t)         (((t).control >> TRB_TYPE_SHIFT) & TRB_TYPE_MASK)
-
-#define TRB_EV_ED           (1<<2)
-
-#define TRB_TR_ENT          (1<<1)
-#define TRB_TR_ISP          (1<<2)
-#define TRB_TR_NS           (1<<3)
-#define TRB_TR_CH           (1<<4)
-#define TRB_TR_IOC          (1<<5)
-#define TRB_TR_IDT          (1<<6)
-#define TRB_TR_TBC_SHIFT        7
-#define TRB_TR_TBC_MASK     0x3
-#define TRB_TR_BEI          (1<<9)
-#define TRB_TR_TLBPC_SHIFT      16
-#define TRB_TR_TLBPC_MASK   0xf
-#define TRB_TR_FRAMEID_SHIFT    20
-#define TRB_TR_FRAMEID_MASK 0x7ff
-#define TRB_TR_SIA          (1<<31)
-
-#define TRB_TR_DIR          (1<<16)
-
-#define TRB_CR_SLOTID_SHIFT     24
-#define TRB_CR_SLOTID_MASK  0xff
-#define TRB_CR_EPID_SHIFT       16
-#define TRB_CR_EPID_MASK    0x1f
-
-#define TRB_CR_BSR          (1<<9)
-#define TRB_CR_DC           (1<<9)
-
-#define TRB_LK_TC           (1<<1)
-
-#define EP_TYPE_MASK        0x7
-#define EP_TYPE_SHIFT           3
-
-#define EP_STATE_MASK       0x7
-#define EP_DISABLED         (0<<0)
-#define EP_RUNNING          (1<<0)
-#define EP_HALTED           (2<<0)
-#define EP_STOPPED          (3<<0)
-#define EP_ERROR            (4<<0)
-
-#define SLOT_STATE_MASK     0x1f
-#define SLOT_STATE_SHIFT        27
-#define SLOT_STATE(s)       (((s)>>SLOT_STATE_SHIFT)&SLOT_STATE_MASK)
-#define SLOT_ENABLED        0
-#define SLOT_DEFAULT        1
-#define SLOT_ADDRESSED      2
-#define SLOT_CONFIGURED     3
-
-#define SLOT_CONTEXT_ENTRIES_MASK 0x1f
-#define SLOT_CONTEXT_ENTRIES_SHIFT 27
-
-typedef enum EPType {
-    ET_INVALID = 0,
-    ET_ISO_OUT,
-    ET_BULK_OUT,
-    ET_INTR_OUT,
-    ET_CONTROL,
-    ET_ISO_IN,
-    ET_BULK_IN,
-    ET_INTR_IN,
-} EPType;
-
-typedef struct XHCIRing {
-    target_phys_addr_t base;
-    target_phys_addr_t dequeue;
-    bool ccs;
-} XHCIRing;
-
-typedef struct XHCIPort {
-    USBPort port;
-    uint32_t portsc;
-} XHCIPort;
-
-struct XHCIState;
-typedef struct XHCIState XHCIState;
-
-typedef struct XHCITransfer {
-    XHCIState *xhci;
-    USBPacket packet;
-    bool running_async;
-    bool running_retry;
-    bool cancelled;
-    bool complete;
-    bool backgrounded;
-    unsigned int iso_pkts;
-    unsigned int slotid;
-    unsigned int epid;
-    bool in_xfer;
-    bool iso_xfer;
-    bool bg_xfer;
-
-    unsigned int trb_count;
-    unsigned int trb_alloced;
-    XHCITRB *trbs;
-
-    unsigned int data_length;
-    unsigned int data_alloced;
-    uint8_t *data;
-
-    TRBCCode status;
-
-    unsigned int pkts;
-    unsigned int pktsize;
-    unsigned int cur_pkt;
-} XHCITransfer;
-
-typedef struct XHCIEPContext {
-    XHCIRing ring;
-    unsigned int next_xfer;
-    unsigned int comp_xfer;
-    XHCITransfer transfers[TD_QUEUE];
-    XHCITransfer *retry;
-    bool bg_running;
-    bool bg_updating;
-    unsigned int next_bg;
-    XHCITransfer bg_transfers[BG_XFERS];
-    EPType type;
-    target_phys_addr_t pctx;
-    unsigned int max_psize;
-    bool has_bg;
-    uint32_t state;
-} XHCIEPContext;
-
-typedef struct XHCISlot {
-    bool enabled;
-    target_phys_addr_t ctx;
-    unsigned int port;
-    unsigned int devaddr;
-    XHCIEPContext * eps[31];
-} XHCISlot;
-
-typedef struct XHCIEvent {
-    TRBType type;
-    TRBCCode ccode;
-    uint64_t ptr;
-    uint32_t length;
-    uint32_t flags;
-    uint8_t slotid;
-    uint8_t epid;
-} XHCIEvent;
-
-struct XHCIState {
-    PCIDevice pci_dev;
-    USBBus bus;
-    qemu_irq irq;
-    MemoryRegion mem;
-    const char *name;
-    uint32_t msi;
-    unsigned int devaddr;
-
-    /* Operational Registers */
-    uint32_t usbcmd;
-    uint32_t usbsts;
-    uint32_t dnctrl;
-    uint32_t crcr_low;
-    uint32_t crcr_high;
-    uint32_t dcbaap_low;
-    uint32_t dcbaap_high;
-    uint32_t config;
-
-    XHCIPort ports[MAXPORTS];
-    XHCISlot slots[MAXSLOTS];
-
-    /* Runtime Registers */
-    uint32_t mfindex;
-    /* note: we only support one interrupter */
-    uint32_t iman;
-    uint32_t imod;
-    uint32_t erstsz;
-    uint32_t erstba_low;
-    uint32_t erstba_high;
-    uint32_t erdp_low;
-    uint32_t erdp_high;
-
-    target_phys_addr_t er_start;
-    uint32_t er_size;
-    bool er_pcs;
-    unsigned int er_ep_idx;
-    bool er_full;
-
-    XHCIEvent ev_buffer[EV_QUEUE];
-    unsigned int ev_buffer_put;
-    unsigned int ev_buffer_get;
-
-    XHCIRing cmd_ring;
-};
-
-typedef struct XHCIEvRingSeg {
-    uint32_t addr_low;
-    uint32_t addr_high;
-    uint32_t size;
-    uint32_t rsvd;
-} XHCIEvRingSeg;
-
-#ifdef DEBUG_XHCI
-static const char *TRBType_names[] = {
-    [TRB_RESERVED]                     = "TRB_RESERVED",
-    [TR_NORMAL]                        = "TR_NORMAL",
-    [TR_SETUP]                         = "TR_SETUP",
-    [TR_DATA]                          = "TR_DATA",
-    [TR_STATUS]                        = "TR_STATUS",
-    [TR_ISOCH]                         = "TR_ISOCH",
-    [TR_LINK]                          = "TR_LINK",
-    [TR_EVDATA]                        = "TR_EVDATA",
-    [TR_NOOP]                          = "TR_NOOP",
-    [CR_ENABLE_SLOT]                   = "CR_ENABLE_SLOT",
-    [CR_DISABLE_SLOT]                  = "CR_DISABLE_SLOT",
-    [CR_ADDRESS_DEVICE]                = "CR_ADDRESS_DEVICE",
-    [CR_CONFIGURE_ENDPOINT]            = "CR_CONFIGURE_ENDPOINT",
-    [CR_EVALUATE_CONTEXT]              = "CR_EVALUATE_CONTEXT",
-    [CR_RESET_ENDPOINT]                = "CR_RESET_ENDPOINT",
-    [CR_STOP_ENDPOINT]                 = "CR_STOP_ENDPOINT",
-    [CR_SET_TR_DEQUEUE]                = "CR_SET_TR_DEQUEUE",
-    [CR_RESET_DEVICE]                  = "CR_RESET_DEVICE",
-    [CR_FORCE_EVENT]                   = "CR_FORCE_EVENT",
-    [CR_NEGOTIATE_BW]                  = "CR_NEGOTIATE_BW",
-    [CR_SET_LATENCY_TOLERANCE]         = "CR_SET_LATENCY_TOLERANCE",
-    [CR_GET_PORT_BANDWIDTH]            = "CR_GET_PORT_BANDWIDTH",
-    [CR_FORCE_HEADER]                  = "CR_FORCE_HEADER",
-    [CR_NOOP]                          = "CR_NOOP",
-    [ER_TRANSFER]                      = "ER_TRANSFER",
-    [ER_COMMAND_COMPLETE]              = "ER_COMMAND_COMPLETE",
-    [ER_PORT_STATUS_CHANGE]            = "ER_PORT_STATUS_CHANGE",
-    [ER_BANDWIDTH_REQUEST]             = "ER_BANDWIDTH_REQUEST",
-    [ER_DOORBELL]                      = "ER_DOORBELL",
-    [ER_HOST_CONTROLLER]               = "ER_HOST_CONTROLLER",
-    [ER_DEVICE_NOTIFICATION]           = "ER_DEVICE_NOTIFICATION",
-    [ER_MFINDEX_WRAP]                  = "ER_MFINDEX_WRAP",
-    [CR_VENDOR_VIA_CHALLENGE_RESPONSE] = "CR_VENDOR_VIA_CHALLENGE_RESPONSE",
-    [CR_VENDOR_NEC_FIRMWARE_REVISION]  = "CR_VENDOR_NEC_FIRMWARE_REVISION",
-    [CR_VENDOR_NEC_CHALLENGE_RESPONSE] = "CR_VENDOR_NEC_CHALLENGE_RESPONSE",
-};
-
-static const char *lookup_name(uint32_t index, const char **list, uint32_t llen)
-{
-    if (index >= llen || list[index] == NULL) {
-        return "???";
-    }
-    return list[index];
-}
-
-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);
-
-static inline target_phys_addr_t xhci_addr64(uint32_t low, uint32_t high)
-{
-#if TARGET_PHYS_ADDR_BITS > 32
-    return low | ((target_phys_addr_t)high << 32);
-#else
-    return low;
-#endif
-}
-
-static inline target_phys_addr_t xhci_mask64(uint64_t addr)
-{
-#if TARGET_PHYS_ADDR_BITS > 32
-    return addr;
-#else
-    return addr & 0xffffffff;
-#endif
-}
-
-static void xhci_irq_update(XHCIState *xhci)
-{
-    int level = 0;
-
-    if (xhci->iman & IMAN_IP && xhci->iman & IMAN_IE &&
-        xhci->usbcmd && USBCMD_INTE) {
-        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");
-            msi_notify(&xhci->pci_dev, 0);
-        }
-    } else {
-        qemu_set_irq(xhci->irq, level);
-    }
-}
-
-static inline int xhci_running(XHCIState *xhci)
-{
-    return !(xhci->usbsts & USBSTS_HCH) && !xhci->er_full;
-}
-
-static void xhci_die(XHCIState *xhci)
-{
-    xhci->usbsts |= USBSTS_HCE;
-    fprintf(stderr, "xhci: asserted controller error\n");
-}
-
-static void xhci_write_event(XHCIState *xhci, XHCIEvent *event)
-{
-    XHCITRB ev_trb;
-    target_phys_addr_t addr;
-
-    ev_trb.parameter = cpu_to_le64(event->ptr);
-    ev_trb.status = cpu_to_le32(event->length | (event->ccode << 24));
-    ev_trb.control = (event->slotid << 24) | (event->epid << 16) |
-                     event->flags | (event->type << TRB_TYPE_SHIFT);
-    if (xhci->er_pcs) {
-        ev_trb.control |= TRB_C;
-    }
-    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));
-
-    addr = xhci->er_start + TRB_SIZE*xhci->er_ep_idx;
-    cpu_physical_memory_write(addr, (uint8_t *) &ev_trb, TRB_SIZE);
-
-    xhci->er_ep_idx++;
-    if (xhci->er_ep_idx >= xhci->er_size) {
-        xhci->er_ep_idx = 0;
-        xhci->er_pcs = !xhci->er_pcs;
-    }
-}
-
-static void xhci_events_update(XHCIState *xhci)
-{
-    target_phys_addr_t erdp;
-    unsigned int dp_idx;
-    bool do_irq = 0;
-
-    if (xhci->usbsts & USBSTS_HCH) {
-        return;
-    }
-
-    erdp = xhci_addr64(xhci->erdp_low, xhci->erdp_high);
-    if (erdp < xhci->er_start ||
-        erdp >= (xhci->er_start + TRB_SIZE*xhci->er_size)) {
-        fprintf(stderr, "xhci: ERDP out of bounds: "TARGET_FMT_plx"\n", erdp);
-        fprintf(stderr, "xhci: ER at "TARGET_FMT_plx" len %d\n",
-                xhci->er_start, xhci->er_size);
-        xhci_die(xhci);
-        return;
-    }
-    dp_idx = (erdp - xhci->er_start) / TRB_SIZE;
-    assert(dp_idx < xhci->er_size);
-
-    /* NEC didn't read section 4.9.4 of the spec (v1.0 p139 top Note) and thus
-     * deadlocks when the ER is full. Hack it by holding off events until
-     * the driver decides to free at least half of the ring */
-    if (xhci->er_full) {
-        int er_free = dp_idx - xhci->er_ep_idx;
-        if (er_free <= 0) {
-            er_free += xhci->er_size;
-        }
-        if (er_free < (xhci->er_size/2)) {
-            DPRINTF("xhci_events_update(): event ring still "
-                    "more than half full (hack)\n");
-            return;
-        }
-    }
-
-    while (xhci->ev_buffer_put != xhci->ev_buffer_get) {
-        assert(xhci->er_full);
-        if (((xhci->er_ep_idx+1) % xhci->er_size) == dp_idx) {
-            DPRINTF("xhci_events_update(): event ring full again\n");
-#ifndef ER_FULL_HACK
-            XHCIEvent full = {ER_HOST_CONTROLLER, CC_EVENT_RING_FULL_ERROR};
-            xhci_write_event(xhci, &full);
-#endif
-            do_irq = 1;
-            break;
-        }
-        XHCIEvent *event = &xhci->ev_buffer[xhci->ev_buffer_get];
-        xhci_write_event(xhci, event);
-        xhci->ev_buffer_get++;
-        do_irq = 1;
-        if (xhci->ev_buffer_get == EV_QUEUE) {
-            xhci->ev_buffer_get = 0;
-        }
-    }
-
-    if (do_irq) {
-        xhci->erdp_low |= ERDP_EHB;
-        xhci->iman |= IMAN_IP;
-        xhci->usbsts |= USBSTS_EINT;
-        xhci_irq_update(xhci);
-    }
-
-    if (xhci->er_full && xhci->ev_buffer_put == xhci->ev_buffer_get) {
-        DPRINTF("xhci_events_update(): event ring no longer full\n");
-        xhci->er_full = 0;
-    }
-    return;
-}
-
-static void xhci_event(XHCIState *xhci, XHCIEvent *event)
-{
-    target_phys_addr_t erdp;
-    unsigned int dp_idx;
-
-    if (xhci->er_full) {
-        DPRINTF("xhci_event(): ER full, queueing\n");
-        if (((xhci->ev_buffer_put+1) % EV_QUEUE) == xhci->ev_buffer_get) {
-            fprintf(stderr, "xhci: event queue full, dropping event!\n");
-            return;
-        }
-        xhci->ev_buffer[xhci->ev_buffer_put++] = *event;
-        if (xhci->ev_buffer_put == EV_QUEUE) {
-            xhci->ev_buffer_put = 0;
-        }
-        return;
-    }
-
-    erdp = xhci_addr64(xhci->erdp_low, xhci->erdp_high);
-    if (erdp < xhci->er_start ||
-        erdp >= (xhci->er_start + TRB_SIZE*xhci->er_size)) {
-        fprintf(stderr, "xhci: ERDP out of bounds: "TARGET_FMT_plx"\n", erdp);
-        fprintf(stderr, "xhci: ER at "TARGET_FMT_plx" len %d\n",
-                xhci->er_start, xhci->er_size);
-        xhci_die(xhci);
-        return;
-    }
-
-    dp_idx = (erdp - xhci->er_start) / TRB_SIZE;
-    assert(dp_idx < xhci->er_size);
-
-    if ((xhci->er_ep_idx+1) % xhci->er_size == dp_idx) {
-        DPRINTF("xhci_event(): ER full, queueing\n");
-#ifndef ER_FULL_HACK
-        XHCIEvent full = {ER_HOST_CONTROLLER, CC_EVENT_RING_FULL_ERROR};
-        xhci_write_event(xhci, &full);
-#endif
-        xhci->er_full = 1;
-        if (((xhci->ev_buffer_put+1) % EV_QUEUE) == xhci->ev_buffer_get) {
-            fprintf(stderr, "xhci: event queue full, dropping event!\n");
-            return;
-        }
-        xhci->ev_buffer[xhci->ev_buffer_put++] = *event;
-        if (xhci->ev_buffer_put == EV_QUEUE) {
-            xhci->ev_buffer_put = 0;
-        }
-    } else {
-        xhci_write_event(xhci, event);
-    }
-
-    xhci->erdp_low |= ERDP_EHB;
-    xhci->iman |= IMAN_IP;
-    xhci->usbsts |= USBSTS_EINT;
-
-    xhci_irq_update(xhci);
-}
-
-static void xhci_ring_init(XHCIState *xhci, XHCIRing *ring,
-                           target_phys_addr_t base)
-{
-    ring->base = base;
-    ring->dequeue = base;
-    ring->ccs = 1;
-}
-
-static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb,
-                               target_phys_addr_t *addr)
-{
-    while (1) {
-        TRBType type;
-        cpu_physical_memory_read(ring->dequeue, (uint8_t *) trb, TRB_SIZE);
-        trb->addr = ring->dequeue;
-        trb->ccs = ring->ccs;
-        le64_to_cpus(&trb->parameter);
-        le32_to_cpus(&trb->status);
-        le32_to_cpus(&trb->control);
-
-        DPRINTF("xhci: TRB fetched [" TARGET_FMT_plx "]: "
-                "%016" PRIx64 " %08x %08x %s\n",
-                ring->dequeue, trb->parameter, trb->status, trb->control,
-                trb_name(trb));
-
-        if ((trb->control & TRB_C) != ring->ccs) {
-            return 0;
-        }
-
-        type = TRB_TYPE(*trb);
-
-        if (type != TR_LINK) {
-            if (addr) {
-                *addr = ring->dequeue;
-            }
-            ring->dequeue += TRB_SIZE;
-            return type;
-        } else {
-            ring->dequeue = xhci_mask64(trb->parameter);
-            if (trb->control & TRB_LK_TC) {
-                ring->ccs = !ring->ccs;
-            }
-        }
-    }
-}
-
-static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring)
-{
-    XHCITRB trb;
-    int length = 0;
-    target_phys_addr_t dequeue = ring->dequeue;
-    bool ccs = ring->ccs;
-    /* hack to bundle together the two/three TDs that make a setup transfer */
-    bool control_td_set = 0;
-
-    while (1) {
-        TRBType type;
-        cpu_physical_memory_read(dequeue, (uint8_t *) &trb, TRB_SIZE);
-        le64_to_cpus(&trb.parameter);
-        le32_to_cpus(&trb.status);
-        le32_to_cpus(&trb.control);
-
-        DPRINTF("xhci: TRB peeked [" TARGET_FMT_plx "]: "
-                "%016" PRIx64 " %08x %08x\n",
-                dequeue, trb.parameter, trb.status, trb.control);
-
-        if ((trb.control & TRB_C) != ccs) {
-            return -length;
-        }
-
-        type = TRB_TYPE(trb);
-
-        if (type == TR_LINK) {
-            dequeue = xhci_mask64(trb.parameter);
-            if (trb.control & TRB_LK_TC) {
-                ccs = !ccs;
-            }
-            continue;
-        }
-
-        length += 1;
-        dequeue += TRB_SIZE;
-
-        if (type == TR_SETUP) {
-            control_td_set = 1;
-        } else if (type == TR_STATUS) {
-            control_td_set = 0;
-        }
-
-        if (!control_td_set && !(trb.control & TRB_TR_CH)) {
-            return length;
-        }
-    }
-}
-
-static void xhci_er_reset(XHCIState *xhci)
-{
-    XHCIEvRingSeg seg;
-
-    /* cache the (sole) event ring segment location */
-    if (xhci->erstsz != 1) {
-        fprintf(stderr, "xhci: invalid value for ERSTSZ: %d\n", xhci->erstsz);
-        xhci_die(xhci);
-        return;
-    }
-    target_phys_addr_t erstba = xhci_addr64(xhci->erstba_low, xhci->erstba_high);
-    cpu_physical_memory_read(erstba, (uint8_t *) &seg, sizeof(seg));
-    le32_to_cpus(&seg.addr_low);
-    le32_to_cpus(&seg.addr_high);
-    le32_to_cpus(&seg.size);
-    if (seg.size < 16 || seg.size > 4096) {
-        fprintf(stderr, "xhci: invalid value for segment size: %d\n", seg.size);
-        xhci_die(xhci);
-        return;
-    }
-    xhci->er_start = xhci_addr64(seg.addr_low, seg.addr_high);
-    xhci->er_size = seg.size;
-
-    xhci->er_ep_idx = 0;
-    xhci->er_pcs = 1;
-    xhci->er_full = 0;
-
-    DPRINTF("xhci: event ring:" TARGET_FMT_plx " [%d]\n",
-            xhci->er_start, xhci->er_size);
-}
-
-static void xhci_run(XHCIState *xhci)
-{
-    DPRINTF("xhci_run()\n");
-
-    xhci->usbsts &= ~USBSTS_HCH;
-}
-
-static void xhci_stop(XHCIState *xhci)
-{
-    DPRINTF("xhci_stop()\n");
-    xhci->usbsts |= USBSTS_HCH;
-    xhci->crcr_low &= ~CRCR_CRR;
-}
-
-static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx,
-                              uint32_t state)
-{
-    uint32_t ctx[5];
-    if (epctx->state == state) {
-        return;
-    }
-
-    cpu_physical_memory_read(epctx->pctx, (uint8_t *) ctx, sizeof(ctx));
-    ctx[0] &= ~EP_STATE_MASK;
-    ctx[0] |= state;
-    ctx[2] = epctx->ring.dequeue | epctx->ring.ccs;
-    ctx[3] = (epctx->ring.dequeue >> 16) >> 16;
-    DPRINTF("xhci: set epctx: " TARGET_FMT_plx " state=%d dequeue=%08x%08x\n",
-            epctx->pctx, state, ctx[3], ctx[2]);
-    cpu_physical_memory_write(epctx->pctx, (uint8_t *) ctx, sizeof(ctx));
-    epctx->state = state;
-}
-
-static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid,
-                               unsigned int epid, target_phys_addr_t pctx,
-                               uint32_t *ctx)
-{
-    XHCISlot *slot;
-    XHCIEPContext *epctx;
-    target_phys_addr_t dequeue;
-    int i;
-
-    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);
-        return CC_TRB_ERROR;
-    }
-
-    epctx = g_malloc(sizeof(XHCIEPContext));
-    memset(epctx, 0, sizeof(XHCIEPContext));
-
-    slot->eps[epid-1] = epctx;
-
-    dequeue = xhci_addr64(ctx[2] & ~0xf, ctx[3]);
-    xhci_ring_init(xhci, &epctx->ring, dequeue);
-    epctx->ring.ccs = ctx[2] & 1;
-
-    epctx->type = (ctx[1] >> EP_TYPE_SHIFT) & EP_TYPE_MASK;
-    DPRINTF("xhci: endpoint %d.%d type is %d\n", epid/2, epid%2, epctx->type);
-    epctx->pctx = pctx;
-    epctx->max_psize = ctx[1]>>16;
-    epctx->max_psize *= 1+((ctx[1]>>8)&0xff);
-    epctx->has_bg = false;
-    if (epctx->type == ET_ISO_IN) {
-        epctx->has_bg = true;
-    }
-    DPRINTF("xhci: endpoint %d.%d max transaction (burst) size is %d\n",
-            epid/2, epid%2, epctx->max_psize);
-    for (i = 0; i < ARRAY_SIZE(epctx->transfers); i++) {
-        usb_packet_init(&epctx->transfers[i].packet);
-    }
-
-    epctx->state = EP_RUNNING;
-    ctx[0] &= ~EP_STATE_MASK;
-    ctx[0] |= EP_RUNNING;
-
-    return CC_SUCCESS;
-}
-
-static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid,
-                               unsigned int epid)
-{
-    XHCISlot *slot;
-    XHCIEPContext *epctx;
-    int i, xferi, killed = 0;
-    assert(slotid >= 1 && slotid <= MAXSLOTS);
-    assert(epid >= 1 && epid <= 31);
-
-    DPRINTF("xhci_ep_nuke_xfers(%d, %d)\n", slotid, epid);
-
-    slot = &xhci->slots[slotid-1];
-
-    if (!slot->eps[epid-1]) {
-        return 0;
-    }
-
-    epctx = slot->eps[epid-1];
-
-    xferi = epctx->next_xfer;
-    for (i = 0; i < TD_QUEUE; i++) {
-        XHCITransfer *t = &epctx->transfers[xferi];
-        if (t->running_async) {
-            usb_cancel_packet(&t->packet);
-            t->running_async = 0;
-            t->cancelled = 1;
-            DPRINTF("xhci: cancelling transfer %d, waiting for it to complete...\n", i);
-            killed++;
-        }
-        if (t->running_retry) {
-            t->running_retry = 0;
-            epctx->retry = NULL;
-        }
-        if (t->backgrounded) {
-            t->backgrounded = 0;
-        }
-        if (t->trbs) {
-            g_free(t->trbs);
-        }
-        if (t->data) {
-            g_free(t->data);
-        }
-
-        t->trbs = NULL;
-        t->data = NULL;
-        t->trb_count = t->trb_alloced = 0;
-        t->data_length = t->data_alloced = 0;
-        xferi = (xferi + 1) % TD_QUEUE;
-    }
-    if (epctx->has_bg) {
-        xferi = epctx->next_bg;
-        for (i = 0; i < BG_XFERS; i++) {
-            XHCITransfer *t = &epctx->bg_transfers[xferi];
-            if (t->running_async) {
-                usb_cancel_packet(&t->packet);
-                t->running_async = 0;
-                t->cancelled = 1;
-                DPRINTF("xhci: cancelling bg transfer %d, waiting for it to complete...\n", i);
-                killed++;
-            }
-            if (t->data) {
-                g_free(t->data);
-            }
-
-            t->data = NULL;
-            xferi = (xferi + 1) % BG_XFERS;
-        }
-    }
-    return killed;
-}
-
-static TRBCCode xhci_disable_ep(XHCIState *xhci, unsigned int slotid,
-                               unsigned int epid)
-{
-    XHCISlot *slot;
-    XHCIEPContext *epctx;
-
-    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]) {
-        DPRINTF("xhci: slot %d ep %d already disabled\n", slotid, epid);
-        return CC_SUCCESS;
-    }
-
-    xhci_ep_nuke_xfers(xhci, slotid, epid);
-
-    epctx = slot->eps[epid-1];
-
-    xhci_set_ep_state(xhci, epctx, EP_DISABLED);
-
-    g_free(epctx);
-    slot->eps[epid-1] = NULL;
-
-    return CC_SUCCESS;
-}
-
-static TRBCCode xhci_stop_ep(XHCIState *xhci, unsigned int slotid,
-                             unsigned int epid)
-{
-    XHCISlot *slot;
-    XHCIEPContext *epctx;
-
-    DPRINTF("xhci_stop_ep(%d, %d)\n", slotid, epid);
-
-    assert(slotid >= 1 && slotid <= MAXSLOTS);
-
-    if (epid < 1 || epid > 31) {
-        fprintf(stderr, "xhci: bad ep %d\n", epid);
-        return CC_TRB_ERROR;
-    }
-
-    slot = &xhci->slots[slotid-1];
-
-    if (!slot->eps[epid-1]) {
-        DPRINTF("xhci: slot %d ep %d not enabled\n", slotid, epid);
-        return CC_EP_NOT_ENABLED_ERROR;
-    }
-
-    if (xhci_ep_nuke_xfers(xhci, slotid, epid) > 0) {
-        fprintf(stderr, "xhci: FIXME: endpoint stopped w/ xfers running, "
-                "data might be lost\n");
-    }
-
-    epctx = slot->eps[epid-1];
-
-    xhci_set_ep_state(xhci, epctx, EP_STOPPED);
-
-    return CC_SUCCESS;
-}
-
-static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigned int slotid,
-                              unsigned int epid)
-{
-    XHCISlot *slot;
-    XHCIEPContext *epctx;
-    USBDevice *dev;
-
-    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;
-    }
-
-    slot = &xhci->slots[slotid-1];
-
-    if (!slot->eps[epid-1]) {
-        DPRINTF("xhci: slot %d ep %d not enabled\n", slotid, epid);
-        return CC_EP_NOT_ENABLED_ERROR;
-    }
-
-    epctx = slot->eps[epid-1];
-
-    if (epctx->state != EP_HALTED) {
-        fprintf(stderr, "xhci: reset EP while EP %d not halted (%d)\n",
-                epid, epctx->state);
-        return CC_CONTEXT_STATE_ERROR;
-    }
-
-    if (xhci_ep_nuke_xfers(xhci, slotid, epid) > 0) {
-        fprintf(stderr, "xhci: FIXME: endpoint reset w/ xfers running, "
-                "data might be lost\n");
-    }
-
-    uint8_t ep = epid>>1;
-
-    if (epid & 1) {
-        ep |= 0x80;
-    }
-
-    dev = xhci->ports[xhci->slots[slotid-1].port-1].port.dev;
-    if (!dev) {
-        return CC_USB_TRANSACTION_ERROR;
-    }
-
-    xhci_set_ep_state(xhci, epctx, EP_STOPPED);
-
-    return CC_SUCCESS;
-}
-
-static TRBCCode xhci_set_ep_dequeue(XHCIState *xhci, unsigned int slotid,
-                                    unsigned int epid, uint64_t pdequeue)
-{
-    XHCISlot *slot;
-    XHCIEPContext *epctx;
-    target_phys_addr_t dequeue;
-
-    assert(slotid >= 1 && slotid <= MAXSLOTS);
-
-    if (epid < 1 || epid > 31) {
-        fprintf(stderr, "xhci: bad ep %d\n", epid);
-        return CC_TRB_ERROR;
-    }
-
-    DPRINTF("xhci_set_ep_dequeue(%d, %d, %016"PRIx64")\n", slotid, epid, pdequeue);
-    dequeue = xhci_mask64(pdequeue);
-
-    slot = &xhci->slots[slotid-1];
-
-    if (!slot->eps[epid-1]) {
-        DPRINTF("xhci: slot %d ep %d not enabled\n", slotid, epid);
-        return CC_EP_NOT_ENABLED_ERROR;
-    }
-
-    epctx = slot->eps[epid-1];
-
-
-    if (epctx->state != EP_STOPPED) {
-        fprintf(stderr, "xhci: set EP dequeue pointer while EP %d not stopped\n", epid);
-        return CC_CONTEXT_STATE_ERROR;
-    }
-
-    xhci_ring_init(xhci, &epctx->ring, dequeue & ~0xF);
-    epctx->ring.ccs = dequeue & 1;
-
-    xhci_set_ep_state(xhci, epctx, EP_STOPPED);
-
-    return CC_SUCCESS;
-}
-
-static int xhci_xfer_data(XHCITransfer *xfer, uint8_t *data,
-                          unsigned int length, bool in_xfer, bool out_xfer,
-                          bool report)
-{
-    int i;
-    uint32_t edtla = 0;
-    unsigned int transferred = 0;
-    unsigned int left = length;
-    bool reported = 0;
-    bool shortpkt = 0;
-    XHCIEvent event = {ER_TRANSFER, CC_SUCCESS};
-    XHCIState *xhci = xfer->xhci;
-
-    DPRINTF("xhci_xfer_data(len=%d, in_xfer=%d, out_xfer=%d, report=%d)\n",
-            length, in_xfer, out_xfer, report);
-
-    assert(!(in_xfer && out_xfer));
-
-    for (i = 0; i < xfer->trb_count; i++) {
-        XHCITRB *trb = &xfer->trbs[i];
-        target_phys_addr_t addr;
-        unsigned int chunk = 0;
-
-        switch (TRB_TYPE(*trb)) {
-        case TR_DATA:
-            if ((!(trb->control & TRB_TR_DIR)) != (!in_xfer)) {
-                fprintf(stderr, "xhci: data direction mismatch for TR_DATA\n");
-                xhci_die(xhci);
-                return transferred;
-            }
-            /* fallthrough */
-        case TR_NORMAL:
-        case TR_ISOCH:
-            addr = xhci_mask64(trb->parameter);
-            chunk = trb->status & 0x1ffff;
-            if (chunk > left) {
-                chunk = left;
-                shortpkt = 1;
-            }
-            if (in_xfer || out_xfer) {
-                if (trb->control & TRB_TR_IDT) {
-                    uint64_t idata;
-                    if (chunk > 8 || in_xfer) {
-                        fprintf(stderr, "xhci: invalid immediate data TRB\n");
-                        xhci_die(xhci);
-                        return transferred;
-                    }
-                    idata = le64_to_cpu(trb->parameter);
-                    memcpy(data, &idata, chunk);
-                } else {
-                    DPRINTF("xhci_xfer_data: r/w(%d) %d bytes at "
-                            TARGET_FMT_plx "\n", in_xfer, chunk, addr);
-                    if (in_xfer) {
-                        cpu_physical_memory_write(addr, data, chunk);
-                    } else {
-                        cpu_physical_memory_read(addr, data, chunk);
-                    }
-#ifdef DEBUG_DATA
-                    unsigned int count = chunk;
-                    int i;
-                    if (count > 16) {
-                        count = 16;
-                    }
-                    DPRINTF(" ::");
-                    for (i = 0; i < count; i++) {
-                        DPRINTF(" %02x", data[i]);
-                    }
-                    DPRINTF("\n");
-#endif
-                }
-            }
-            left -= chunk;
-            data += chunk;
-            edtla += chunk;
-            transferred += chunk;
-            break;
-        case TR_STATUS:
-            reported = 0;
-            shortpkt = 0;
-            break;
-        }
-
-        if (report && !reported && (trb->control & TRB_TR_IOC ||
-            (shortpkt && (trb->control & TRB_TR_ISP)))) {
-            event.slotid = xfer->slotid;
-            event.epid = xfer->epid;
-            event.length = (trb->status & 0x1ffff) - chunk;
-            event.flags = 0;
-            event.ptr = trb->addr;
-            if (xfer->status == CC_SUCCESS) {
-                event.ccode = shortpkt ? CC_SHORT_PACKET : CC_SUCCESS;
-            } else {
-                event.ccode = xfer->status;
-            }
-            if (TRB_TYPE(*trb) == TR_EVDATA) {
-                event.ptr = trb->parameter;
-                event.flags |= TRB_EV_ED;
-                event.length = edtla & 0xffffff;
-                DPRINTF("xhci_xfer_data: EDTLA=%d\n", event.length);
-                edtla = 0;
-            }
-            xhci_event(xhci, &event);
-            reported = 1;
-        }
-    }
-    return transferred;
-}
-
-static void xhci_stall_ep(XHCITransfer *xfer)
-{
-    XHCIState *xhci = xfer->xhci;
-    XHCISlot *slot = &xhci->slots[xfer->slotid-1];
-    XHCIEPContext *epctx = slot->eps[xfer->epid-1];
-
-    epctx->ring.dequeue = xfer->trbs[0].addr;
-    epctx->ring.ccs = xfer->trbs[0].ccs;
-    xhci_set_ep_state(xhci, epctx, EP_HALTED);
-    DPRINTF("xhci: stalled slot %d ep %d\n", xfer->slotid, xfer->epid);
-    DPRINTF("xhci: will continue at "TARGET_FMT_plx"\n", epctx->ring.dequeue);
-}
-
-static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer,
-                       XHCIEPContext *epctx);
-
-static void xhci_bg_update(XHCIState *xhci, XHCIEPContext *epctx)
-{
-    if (epctx->bg_updating) {
-        return;
-    }
-    DPRINTF("xhci_bg_update(%p, %p)\n", xhci, epctx);
-    assert(epctx->has_bg);
-    DPRINTF("xhci: fg=%d bg=%d\n", epctx->comp_xfer, epctx->next_bg);
-    epctx->bg_updating = 1;
-    while (epctx->transfers[epctx->comp_xfer].backgrounded &&
-           epctx->bg_transfers[epctx->next_bg].complete) {
-        XHCITransfer *fg = &epctx->transfers[epctx->comp_xfer];
-        XHCITransfer *bg = &epctx->bg_transfers[epctx->next_bg];
-#if 0
-        DPRINTF("xhci: completing fg %d from bg %d.%d (stat: %d)\n",
-                epctx->comp_xfer, epctx->next_bg, bg->cur_pkt,
-                bg->usbxfer->iso_packet_desc[bg->cur_pkt].status
-               );
-#endif
-        assert(epctx->type == ET_ISO_IN);
-        assert(bg->iso_xfer);
-        assert(bg->in_xfer);
-        uint8_t *p = bg->data + bg->cur_pkt * bg->pktsize;
-#if 0
-        int len = bg->usbxfer->iso_packet_desc[bg->cur_pkt].actual_length;
-        fg->status = libusb_to_ccode(bg->usbxfer->iso_packet_desc[bg->cur_pkt].status);
-#else
-        int len = 0;
-        FIXME();
-#endif
-        fg->complete = 1;
-        fg->backgrounded = 0;
-
-        if (fg->status == CC_STALL_ERROR) {
-            xhci_stall_ep(fg);
-        }
-
-        xhci_xfer_data(fg, p, len, 1, 0, 1);
-
-        epctx->comp_xfer++;
-        if (epctx->comp_xfer == TD_QUEUE) {
-            epctx->comp_xfer = 0;
-        }
-        DPRINTF("next fg xfer: %d\n", epctx->comp_xfer);
-        bg->cur_pkt++;
-        if (bg->cur_pkt == bg->pkts) {
-            bg->complete = 0;
-            if (xhci_submit(xhci, bg, epctx) < 0) {
-                fprintf(stderr, "xhci: bg resubmit failed\n");
-            }
-            epctx->next_bg++;
-            if (epctx->next_bg == BG_XFERS) {
-                epctx->next_bg = 0;
-            }
-            DPRINTF("next bg xfer: %d\n", epctx->next_bg);
-
-        xhci_kick_ep(xhci, fg->slotid, fg->epid);
-        }
-    }
-    epctx->bg_updating = 0;
-}
-
-#if 0
-static void xhci_xfer_cb(struct libusb_transfer *transfer)
-{
-    XHCIState *xhci;
-    XHCITransfer *xfer;
-
-    xfer = (XHCITransfer *)transfer->user_data;
-    xhci = xfer->xhci;
-
-    DPRINTF("xhci_xfer_cb(slot=%d, ep=%d, status=%d)\n", xfer->slotid,
-            xfer->epid, transfer->status);
-
-    assert(xfer->slotid >= 1 && xfer->slotid <= MAXSLOTS);
-    assert(xfer->epid >= 1 && xfer->epid <= 31);
-
-    if (xfer->cancelled) {
-        DPRINTF("xhci: transfer cancelled, not reporting anything\n");
-        xfer->running = 0;
-        return;
-    }
-
-    XHCIEPContext *epctx;
-    XHCISlot *slot;
-    slot = &xhci->slots[xfer->slotid-1];
-    assert(slot->eps[xfer->epid-1]);
-    epctx = slot->eps[xfer->epid-1];
-
-    if (xfer->bg_xfer) {
-        DPRINTF("xhci: background transfer, updating\n");
-        xfer->complete = 1;
-        xfer->running = 0;
-        xhci_bg_update(xhci, epctx);
-        return;
-    }
-
-    if (xfer->iso_xfer) {
-        transfer->status = transfer->iso_packet_desc[0].status;
-        transfer->actual_length = transfer->iso_packet_desc[0].actual_length;
-    }
-
-    xfer->status = libusb_to_ccode(transfer->status);
-
-    xfer->complete = 1;
-    xfer->running = 0;
-
-    if (transfer->status == LIBUSB_TRANSFER_STALL)
-        xhci_stall_ep(xhci, epctx, xfer);
-
-    DPRINTF("xhci: transfer actual length = %d\n", transfer->actual_length);
-
-    if (xfer->in_xfer) {
-        if (xfer->epid == 1) {
-            xhci_xfer_data(xhci, xfer, xfer->data + 8,
-                           transfer->actual_length, 1, 0, 1);
-        } else {
-            xhci_xfer_data(xhci, xfer, xfer->data,
-                           transfer->actual_length, 1, 0, 1);
-        }
-    } else {
-        xhci_xfer_data(xhci, xfer, NULL, transfer->actual_length, 0, 0, 1);
-    }
-
-    xhci_kick_ep(xhci, xfer->slotid, xfer->epid);
-}
-
-static int xhci_hle_control(XHCIState *xhci, XHCITransfer *xfer,
-                            uint8_t bmRequestType, uint8_t bRequest,
-                            uint16_t wValue, uint16_t wIndex, uint16_t wLength)
-{
-    uint16_t type_req = (bmRequestType << 8) | bRequest;
-
-    switch (type_req) {
-        case 0x0000 | USB_REQ_SET_CONFIGURATION:
-            DPRINTF("xhci: HLE switch configuration\n");
-            return xhci_switch_config(xhci, xfer->slotid, wValue) == 0;
-        case 0x0100 | USB_REQ_SET_INTERFACE:
-            DPRINTF("xhci: HLE set interface altsetting\n");
-            return xhci_set_iface_alt(xhci, xfer->slotid, wIndex, wValue) == 0;
-        case 0x0200 | USB_REQ_CLEAR_FEATURE:
-            if (wValue == 0) { // endpoint halt
-                DPRINTF("xhci: HLE clear halt\n");
-                return xhci_clear_halt(xhci, xfer->slotid, wIndex);
-            }
-        case 0x0000 | USB_REQ_SET_ADDRESS:
-            fprintf(stderr, "xhci: warn: illegal SET_ADDRESS request\n");
-            return 0;
-        default:
-            return 0;
-    }
-}
-#endif
-
-static int xhci_setup_packet(XHCITransfer *xfer, USBDevice *dev)
-{
-    USBEndpoint *ep;
-    int dir;
-
-    dir = xfer->in_xfer ? USB_TOKEN_IN : USB_TOKEN_OUT;
-    ep = usb_ep_get(dev, dir, xfer->epid >> 1);
-    usb_packet_setup(&xfer->packet, dir, ep);
-    usb_packet_addbuf(&xfer->packet, xfer->data, xfer->data_length);
-    DPRINTF("xhci: setup packet pid 0x%x addr %d ep %d\n",
-            xfer->packet.pid, dev->addr, ep->nr);
-    return 0;
-}
-
-static int xhci_complete_packet(XHCITransfer *xfer, int ret)
-{
-    if (ret == USB_RET_ASYNC) {
-        xfer->running_async = 1;
-        xfer->running_retry = 0;
-        xfer->complete = 0;
-        xfer->cancelled = 0;
-        return 0;
-    } else if (ret == USB_RET_NAK) {
-        xfer->running_async = 0;
-        xfer->running_retry = 1;
-        xfer->complete = 0;
-        xfer->cancelled = 0;
-        return 0;
-    } else {
-        xfer->running_async = 0;
-        xfer->running_retry = 0;
-        xfer->complete = 1;
-    }
-
-    if (ret >= 0) {
-        xfer->status = CC_SUCCESS;
-        xhci_xfer_data(xfer, xfer->data, ret, xfer->in_xfer, 0, 1);
-        return 0;
-    }
-
-    /* error */
-    switch (ret) {
-    case USB_RET_NODEV:
-        xfer->status = CC_USB_TRANSACTION_ERROR;
-        xhci_xfer_data(xfer, xfer->data, 0, xfer->in_xfer, 0, 1);
-        xhci_stall_ep(xfer);
-        break;
-    case USB_RET_STALL:
-        xfer->status = CC_STALL_ERROR;
-        xhci_xfer_data(xfer, xfer->data, 0, xfer->in_xfer, 0, 1);
-        xhci_stall_ep(xfer);
-        break;
-    default:
-        fprintf(stderr, "%s: FIXME: ret = %d\n", __FUNCTION__, ret);
-        FIXME();
-    }
-    return 0;
-}
-
-static USBDevice *xhci_find_device(XHCIPort *port, uint8_t addr)
-{
-    if (!(port->portsc & PORTSC_PED)) {
-        return NULL;
-    }
-    return usb_find_device(&port->port, addr);
-}
-
-static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
-{
-    XHCITRB *trb_setup, *trb_status;
-    uint8_t bmRequestType;
-    uint16_t wLength;
-    XHCIPort *port;
-    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];
-
-    /* at most one Event Data TRB allowed after STATUS */
-    if (TRB_TYPE(*trb_status) == TR_EVDATA && xfer->trb_count > 2) {
-        trb_status--;
-    }
-
-    /* do some sanity checks */
-    if (TRB_TYPE(*trb_setup) != TR_SETUP) {
-        fprintf(stderr, "xhci: ep0 first TD not SETUP: %d\n",
-                TRB_TYPE(*trb_setup));
-        return -1;
-    }
-    if (TRB_TYPE(*trb_status) != TR_STATUS) {
-        fprintf(stderr, "xhci: ep0 last TD not STATUS: %d\n",
-                TRB_TYPE(*trb_status));
-        return -1;
-    }
-    if (!(trb_setup->control & TRB_TR_IDT)) {
-        fprintf(stderr, "xhci: Setup TRB doesn't have IDT set\n");
-        return -1;
-    }
-    if ((trb_setup->status & 0x1ffff) != 8) {
-        fprintf(stderr, "xhci: Setup TRB has bad length (%d)\n",
-                (trb_setup->status & 0x1ffff));
-        return -1;
-    }
-
-    bmRequestType = trb_setup->parameter;
-    wLength = trb_setup->parameter >> 48;
-
-    if (xfer->data && xfer->data_alloced < wLength) {
-        xfer->data_alloced = 0;
-        g_free(xfer->data);
-        xfer->data = NULL;
-    }
-    if (!xfer->data) {
-        DPRINTF("xhci: alloc %d bytes data\n", wLength);
-        xfer->data = g_malloc(wLength+1);
-        xfer->data_alloced = wLength;
-    }
-    xfer->data_length = wLength;
-
-    port = &xhci->ports[xhci->slots[xfer->slotid-1].port-1];
-    dev = xhci_find_device(port, xhci->slots[xfer->slotid-1].devaddr);
-    if (!dev) {
-        fprintf(stderr, "xhci: slot %d port %d has no device\n", xfer->slotid,
-                xhci->slots[xfer->slotid-1].port);
-        return -1;
-    }
-
-    xfer->in_xfer = bmRequestType & USB_DIR_IN;
-    xfer->iso_xfer = false;
-
-    xhci_setup_packet(xfer, dev);
-    xfer->packet.parameter = trb_setup->parameter;
-    if (!xfer->in_xfer) {
-        xhci_xfer_data(xfer, xfer->data, wLength, 0, 1, 0);
-    }
-
-    ret = usb_handle_packet(dev, &xfer->packet);
-
-    xhci_complete_packet(xfer, ret);
-    if (!xfer->running_async && !xfer->running_retry) {
-        xhci_kick_ep(xhci, xfer->slotid, xfer->epid);
-    }
-    return 0;
-}
-
-static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx)
-{
-    XHCIPort *port;
-    USBDevice *dev;
-    int ret;
-
-    DPRINTF("xhci_submit(slotid=%d,epid=%d)\n", xfer->slotid, xfer->epid);
-
-    xfer->in_xfer = epctx->type>>2;
-
-    if (xfer->data && xfer->data_alloced < xfer->data_length) {
-        xfer->data_alloced = 0;
-        g_free(xfer->data);
-        xfer->data = NULL;
-    }
-    if (!xfer->data && xfer->data_length) {
-        DPRINTF("xhci: alloc %d bytes data\n", xfer->data_length);
-        xfer->data = g_malloc(xfer->data_length);
-        xfer->data_alloced = xfer->data_length;
-    }
-    if (epctx->type == ET_ISO_IN || epctx->type == ET_ISO_OUT) {
-        if (!xfer->bg_xfer) {
-            xfer->pkts = 1;
-        }
-    } else {
-        xfer->pkts = 0;
-    }
-
-    port = &xhci->ports[xhci->slots[xfer->slotid-1].port-1];
-    dev = xhci_find_device(port, xhci->slots[xfer->slotid-1].devaddr);
-    if (!dev) {
-        fprintf(stderr, "xhci: slot %d port %d has no device\n", xfer->slotid,
-                xhci->slots[xfer->slotid-1].port);
-        return -1;
-    }
-
-    xhci_setup_packet(xfer, dev);
-
-    switch(epctx->type) {
-    case ET_INTR_OUT:
-    case ET_INTR_IN:
-    case ET_BULK_OUT:
-    case ET_BULK_IN:
-        break;
-    case ET_ISO_OUT:
-    case ET_ISO_IN:
-        FIXME();
-        break;
-    default:
-        fprintf(stderr, "xhci: unknown or unhandled EP "
-                "(type %d, in %d, ep %02x)\n",
-                epctx->type, xfer->in_xfer, xfer->epid);
-        return -1;
-    }
-
-    if (!xfer->in_xfer) {
-        xhci_xfer_data(xfer, xfer->data, xfer->data_length, 0, 1, 0);
-    }
-    ret = usb_handle_packet(dev, &xfer->packet);
-
-    xhci_complete_packet(xfer, ret);
-    if (!xfer->running_async && !xfer->running_retry) {
-        xhci_kick_ep(xhci, xfer->slotid, xfer->epid);
-    }
-    return 0;
-}
-
-static int xhci_fire_transfer(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx)
-{
-    int i;
-    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);
-
-    if (!epctx->has_bg) {
-        xfer->data_length = length;
-        xfer->backgrounded = 0;
-        return xhci_submit(xhci, xfer, epctx);
-    } else {
-        if (!epctx->bg_running) {
-            for (i = 0; i < BG_XFERS; i++) {
-                XHCITransfer *t = &epctx->bg_transfers[i];
-                t->xhci = xhci;
-                t->epid = xfer->epid;
-                t->slotid = xfer->slotid;
-                t->pkts = BG_PKTS;
-                t->pktsize = epctx->max_psize;
-                t->data_length = t->pkts * t->pktsize;
-                t->bg_xfer = 1;
-                if (xhci_submit(xhci, t, epctx) < 0) {
-                    fprintf(stderr, "xhci: bg submit failed\n");
-                    return -1;
-                }
-            }
-            epctx->bg_running = 1;
-        }
-        xfer->backgrounded = 1;
-        xhci_bg_update(xhci, epctx);
-        return 0;
-    }
-}
-
-static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid)
-{
-    XHCIEPContext *epctx;
-    int length;
-    int i;
-
-    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);
-        return;
-    }
-    epctx = xhci->slots[slotid-1].eps[epid-1];
-    if (!epctx) {
-        fprintf(stderr, "xhci: xhci_kick_ep for disabled endpoint %d,%d\n",
-                epid, slotid);
-        return;
-    }
-
-    if (epctx->retry) {
-        /* retry nak'ed transfer */
-        XHCITransfer *xfer = epctx->retry;
-        int result;
-
-        DPRINTF("xhci: retry nack'ed transfer ...\n");
-        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;
-    }
-
-    if (epctx->state == EP_HALTED) {
-        DPRINTF("xhci: ep halted, not running schedule\n");
-        return;
-    }
-
-    xhci_set_ep_state(xhci, epctx, EP_RUNNING);
-
-    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;
-            g_free(xfer->trbs);
-            xfer->trbs = NULL;
-        }
-        if (!xfer->trbs) {
-            xfer->trbs = g_malloc(sizeof(XHCITRB) * length);
-            xfer->trb_alloced = length;
-        }
-        xfer->trb_count = length;
-
-        for (i = 0; i < length; i++) {
-            assert(xhci_ring_fetch(xhci, &epctx->ring, &xfer->trbs[i], NULL));
-        }
-        xfer->xhci = xhci;
-        xfer->epid = epid;
-        xfer->slotid = slotid;
-
-        if (epid == 1) {
-            if (xhci_fire_ctl_transfer(xhci, xfer) >= 0) {
-                epctx->next_xfer = (epctx->next_xfer + 1) % TD_QUEUE;
-            } else {
-                fprintf(stderr, "xhci: error firing CTL transfer\n");
-            }
-        } else {
-            if (xhci_fire_transfer(xhci, xfer, epctx) >= 0) {
-                epctx->next_xfer = (epctx->next_xfer + 1) % TD_QUEUE;
-            } else {
-                fprintf(stderr, "xhci: error firing data transfer\n");
-            }
-        }
-
-        if (epctx->state == EP_HALTED) {
-            DPRINTF("xhci: ep halted, stopping schedule\n");
-            break;
-        }
-        if (xfer->running_retry) {
-            DPRINTF("xhci: xfer nacked, stopping schedule\n");
-            epctx->retry = xfer;
-            break;
-        }
-    }
-}
-
-static TRBCCode xhci_enable_slot(XHCIState *xhci, unsigned int 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);
-
-    return CC_SUCCESS;
-}
-
-static TRBCCode xhci_disable_slot(XHCIState *xhci, unsigned int slotid)
-{
-    int i;
-
-    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]) {
-            xhci_disable_ep(xhci, slotid, i);
-        }
-    }
-
-    xhci->slots[slotid-1].enabled = 0;
-    return CC_SUCCESS;
-}
-
-static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
-                                  uint64_t pictx, bool bsr)
-{
-    XHCISlot *slot;
-    USBDevice *dev;
-    target_phys_addr_t ictx, octx, dcbaap;
-    uint64_t poctx;
-    uint32_t ictl_ctx[2];
-    uint32_t slot_ctx[4];
-    uint32_t ep0_ctx[5];
-    unsigned int port;
-    int i;
-    TRBCCode res;
-
-    assert(slotid >= 1 && slotid <= MAXSLOTS);
-    DPRINTF("xhci_address_slot(%d)\n", slotid);
-
-    dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high);
-    cpu_physical_memory_read(dcbaap + 8*slotid,
-                             (uint8_t *) &poctx, sizeof(poctx));
-    ictx = xhci_mask64(pictx);
-    octx = xhci_mask64(le64_to_cpu(poctx));
-
-    DPRINTF("xhci: input context at "TARGET_FMT_plx"\n", ictx);
-    DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx);
-
-    cpu_physical_memory_read(ictx, (uint8_t *) ictl_ctx, sizeof(ictl_ctx));
-
-    if (ictl_ctx[0] != 0x0 || ictl_ctx[1] != 0x3) {
-        fprintf(stderr, "xhci: invalid input context control %08x %08x\n",
-                ictl_ctx[0], ictl_ctx[1]);
-        return CC_TRB_ERROR;
-    }
-
-    cpu_physical_memory_read(ictx+32, (uint8_t *) slot_ctx, sizeof(slot_ctx));
-    cpu_physical_memory_read(ictx+64, (uint8_t *) ep0_ctx, sizeof(ep0_ctx));
-
-    DPRINTF("xhci: input slot context: %08x %08x %08x %08x\n",
-            slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
-
-    DPRINTF("xhci: input ep0 context: %08x %08x %08x %08x %08x\n",
-            ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]);
-
-    port = (slot_ctx[1]>>16) & 0xFF;
-    dev = xhci->ports[port-1].port.dev;
-
-    if (port < 1 || port > MAXPORTS) {
-        fprintf(stderr, "xhci: bad port %d\n", port);
-        return CC_TRB_ERROR;
-    } else if (!dev) {
-        fprintf(stderr, "xhci: port %d not connected\n", port);
-        return CC_USB_TRANSACTION_ERROR;
-    }
-
-    for (i = 0; i < MAXSLOTS; i++) {
-        if (xhci->slots[i].port == port) {
-            fprintf(stderr, "xhci: port %d already assigned to slot %d\n",
-                    port, i+1);
-            return CC_TRB_ERROR;
-        }
-    }
-
-    slot = &xhci->slots[slotid-1];
-    slot->port = port;
-    slot->ctx = octx;
-
-    if (bsr) {
-        slot_ctx[3] = SLOT_DEFAULT << SLOT_STATE_SHIFT;
-    } else {
-        slot->devaddr = xhci->devaddr++;
-        slot_ctx[3] = (SLOT_ADDRESSED << SLOT_STATE_SHIFT) | slot->devaddr;
-        DPRINTF("xhci: device address is %d\n", slot->devaddr);
-        usb_device_handle_control(dev, NULL,
-                                  DeviceOutRequest | USB_REQ_SET_ADDRESS,
-                                  slot->devaddr, 0, 0, NULL);
-    }
-
-    res = xhci_enable_ep(xhci, slotid, 1, octx+32, ep0_ctx);
-
-    DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
-            slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
-    DPRINTF("xhci: output ep0 context: %08x %08x %08x %08x %08x\n",
-            ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]);
-
-    cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
-    cpu_physical_memory_write(octx+32, (uint8_t *) ep0_ctx, sizeof(ep0_ctx));
-
-    return res;
-}
-
-
-static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid,
-                                  uint64_t pictx, bool dc)
-{
-    target_phys_addr_t ictx, octx;
-    uint32_t ictl_ctx[2];
-    uint32_t slot_ctx[4];
-    uint32_t islot_ctx[4];
-    uint32_t ep_ctx[5];
-    int i;
-    TRBCCode res;
-
-    assert(slotid >= 1 && slotid <= MAXSLOTS);
-    DPRINTF("xhci_configure_slot(%d)\n", slotid);
-
-    ictx = xhci_mask64(pictx);
-    octx = xhci->slots[slotid-1].ctx;
-
-    DPRINTF("xhci: input context at "TARGET_FMT_plx"\n", ictx);
-    DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx);
-
-    if (dc) {
-        for (i = 2; i <= 31; i++) {
-            if (xhci->slots[slotid-1].eps[i-1]) {
-                xhci_disable_ep(xhci, slotid, i);
-            }
-        }
-
-        cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
-        slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT);
-        slot_ctx[3] |= SLOT_ADDRESSED << SLOT_STATE_SHIFT;
-        DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
-                slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
-        cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
-
-        return CC_SUCCESS;
-    }
-
-    cpu_physical_memory_read(ictx, (uint8_t *) ictl_ctx, sizeof(ictl_ctx));
-
-    if ((ictl_ctx[0] & 0x3) != 0x0 || (ictl_ctx[1] & 0x3) != 0x1) {
-        fprintf(stderr, "xhci: invalid input context control %08x %08x\n",
-                ictl_ctx[0], ictl_ctx[1]);
-        return CC_TRB_ERROR;
-    }
-
-    cpu_physical_memory_read(ictx+32, (uint8_t *) islot_ctx, sizeof(islot_ctx));
-    cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
-
-    if (SLOT_STATE(slot_ctx[3]) < SLOT_ADDRESSED) {
-        fprintf(stderr, "xhci: invalid slot state %08x\n", slot_ctx[3]);
-        return CC_CONTEXT_STATE_ERROR;
-    }
-
-    for (i = 2; i <= 31; i++) {
-        if (ictl_ctx[0] & (1<<i)) {
-            xhci_disable_ep(xhci, slotid, i);
-        }
-        if (ictl_ctx[1] & (1<<i)) {
-            cpu_physical_memory_read(ictx+32+(32*i),
-                                     (uint8_t *) ep_ctx, sizeof(ep_ctx));
-            DPRINTF("xhci: input ep%d.%d context: %08x %08x %08x %08x %08x\n",
-                    i/2, i%2, ep_ctx[0], ep_ctx[1], ep_ctx[2],
-                    ep_ctx[3], ep_ctx[4]);
-            xhci_disable_ep(xhci, slotid, i);
-            res = xhci_enable_ep(xhci, slotid, i, octx+(32*i), ep_ctx);
-            if (res != CC_SUCCESS) {
-                return res;
-            }
-            DPRINTF("xhci: output ep%d.%d context: %08x %08x %08x %08x %08x\n",
-                    i/2, i%2, ep_ctx[0], ep_ctx[1], ep_ctx[2],
-                    ep_ctx[3], ep_ctx[4]);
-            cpu_physical_memory_write(octx+(32*i),
-                                      (uint8_t *) ep_ctx, sizeof(ep_ctx));
-        }
-    }
-
-    slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT);
-    slot_ctx[3] |= SLOT_CONFIGURED << SLOT_STATE_SHIFT;
-    slot_ctx[0] &= ~(SLOT_CONTEXT_ENTRIES_MASK << SLOT_CONTEXT_ENTRIES_SHIFT);
-    slot_ctx[0] |= islot_ctx[0] & (SLOT_CONTEXT_ENTRIES_MASK <<
-                                   SLOT_CONTEXT_ENTRIES_SHIFT);
-    DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
-            slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
-
-    cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
-
-    return CC_SUCCESS;
-}
-
-
-static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid,
-                                   uint64_t pictx)
-{
-    target_phys_addr_t ictx, octx;
-    uint32_t ictl_ctx[2];
-    uint32_t iep0_ctx[5];
-    uint32_t ep0_ctx[5];
-    uint32_t islot_ctx[4];
-    uint32_t slot_ctx[4];
-
-    assert(slotid >= 1 && slotid <= MAXSLOTS);
-    DPRINTF("xhci_evaluate_slot(%d)\n", slotid);
-
-    ictx = xhci_mask64(pictx);
-    octx = xhci->slots[slotid-1].ctx;
-
-    DPRINTF("xhci: input context at "TARGET_FMT_plx"\n", ictx);
-    DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx);
-
-    cpu_physical_memory_read(ictx, (uint8_t *) ictl_ctx, sizeof(ictl_ctx));
-
-    if (ictl_ctx[0] != 0x0 || ictl_ctx[1] & ~0x3) {
-        fprintf(stderr, "xhci: invalid input context control %08x %08x\n",
-                ictl_ctx[0], ictl_ctx[1]);
-        return CC_TRB_ERROR;
-    }
-
-    if (ictl_ctx[1] & 0x1) {
-        cpu_physical_memory_read(ictx+32,
-                                 (uint8_t *) islot_ctx, sizeof(islot_ctx));
-
-        DPRINTF("xhci: input slot context: %08x %08x %08x %08x\n",
-                islot_ctx[0], islot_ctx[1], islot_ctx[2], islot_ctx[3]);
-
-        cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
-
-        slot_ctx[1] &= ~0xFFFF; /* max exit latency */
-        slot_ctx[1] |= islot_ctx[1] & 0xFFFF;
-        slot_ctx[2] &= ~0xFF00000; /* interrupter target */
-        slot_ctx[2] |= islot_ctx[2] & 0xFF000000;
-
-        DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
-                slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
-
-        cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
-    }
-
-    if (ictl_ctx[1] & 0x2) {
-        cpu_physical_memory_read(ictx+64,
-                                 (uint8_t *) iep0_ctx, sizeof(iep0_ctx));
-
-        DPRINTF("xhci: input ep0 context: %08x %08x %08x %08x %08x\n",
-                iep0_ctx[0], iep0_ctx[1], iep0_ctx[2],
-                iep0_ctx[3], iep0_ctx[4]);
-
-        cpu_physical_memory_read(octx+32, (uint8_t *) ep0_ctx, sizeof(ep0_ctx));
-
-        ep0_ctx[1] &= ~0xFFFF0000; /* max packet size*/
-        ep0_ctx[1] |= iep0_ctx[1] & 0xFFFF0000;
-
-        DPRINTF("xhci: output ep0 context: %08x %08x %08x %08x %08x\n",
-                ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]);
-
-        cpu_physical_memory_write(octx+32,
-                                  (uint8_t *) ep0_ctx, sizeof(ep0_ctx));
-    }
-
-    return CC_SUCCESS;
-}
-
-static TRBCCode xhci_reset_slot(XHCIState *xhci, unsigned int slotid)
-{
-    uint32_t slot_ctx[4];
-    target_phys_addr_t octx;
-    int i;
-
-    assert(slotid >= 1 && slotid <= MAXSLOTS);
-    DPRINTF("xhci_reset_slot(%d)\n", slotid);
-
-    octx = xhci->slots[slotid-1].ctx;
-
-    DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx);
-
-    for (i = 2; i <= 31; i++) {
-        if (xhci->slots[slotid-1].eps[i-1]) {
-            xhci_disable_ep(xhci, slotid, i);
-        }
-    }
-
-    cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
-    slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT);
-    slot_ctx[3] |= SLOT_DEFAULT << SLOT_STATE_SHIFT;
-    DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
-            slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
-    cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
-
-    return CC_SUCCESS;
-}
-
-static unsigned int xhci_get_slot(XHCIState *xhci, XHCIEvent *event, XHCITRB *trb)
-{
-    unsigned int slotid;
-    slotid = (trb->control >> TRB_CR_SLOTID_SHIFT) & TRB_CR_SLOTID_MASK;
-    if (slotid < 1 || slotid > MAXSLOTS) {
-        fprintf(stderr, "xhci: bad slot id %d\n", slotid);
-        event->ccode = CC_TRB_ERROR;
-        return 0;
-    } else if (!xhci->slots[slotid-1].enabled) {
-        fprintf(stderr, "xhci: slot id %d not enabled\n", slotid);
-        event->ccode = CC_SLOT_NOT_ENABLED_ERROR;
-        return 0;
-    }
-    return slotid;
-}
-
-static TRBCCode xhci_get_port_bandwidth(XHCIState *xhci, uint64_t pctx)
-{
-    target_phys_addr_t ctx;
-    uint8_t bw_ctx[MAXPORTS+1];
-
-    DPRINTF("xhci_get_port_bandwidth()\n");
-
-    ctx = xhci_mask64(pctx);
-
-    DPRINTF("xhci: bandwidth context at "TARGET_FMT_plx"\n", ctx);
-
-    /* TODO: actually implement real values here */
-    bw_ctx[0] = 0;
-    memset(&bw_ctx[1], 80, MAXPORTS); /* 80% */
-    cpu_physical_memory_write(ctx, bw_ctx, sizeof(bw_ctx));
-
-    return CC_SUCCESS;
-}
-
-static uint32_t rotl(uint32_t v, unsigned count)
-{
-    count &= 31;
-    return (v << count) | (v >> (32 - count));
-}
-
-
-static uint32_t xhci_nec_challenge(uint32_t hi, uint32_t lo)
-{
-    uint32_t val;
-    val = rotl(lo - 0x49434878, 32 - ((hi>>8) & 0x1F));
-    val += rotl(lo + 0x49434878, hi & 0x1F);
-    val -= rotl(hi ^ 0x49434878, (lo >> 16) & 0x1F);
-    return ~val;
-}
-
-static void xhci_via_challenge(uint64_t addr)
-{
-    uint32_t buf[8];
-    uint32_t obuf[8];
-    target_phys_addr_t paddr = xhci_mask64(addr);
-
-    cpu_physical_memory_read(paddr, (uint8_t *) &buf, 32);
-
-    memcpy(obuf, buf, sizeof(obuf));
-
-    if ((buf[0] & 0xff) == 2) {
-        obuf[0] = 0x49932000 + 0x54dc200 * buf[2] + 0x7429b578 * buf[3];
-        obuf[0] |=  (buf[2] * buf[3]) & 0xff;
-        obuf[1] = 0x0132bb37 + 0xe89 * buf[2] + 0xf09 * buf[3];
-        obuf[2] = 0x0066c2e9 + 0x2091 * buf[2] + 0x19bd * buf[3];
-        obuf[3] = 0xd5281342 + 0x2cc9691 * buf[2] + 0x2367662 * buf[3];
-        obuf[4] = 0x0123c75c + 0x1595 * buf[2] + 0x19ec * buf[3];
-        obuf[5] = 0x00f695de + 0x26fd * buf[2] + 0x3e9 * buf[3];
-        obuf[6] = obuf[2] ^ obuf[3] ^ 0x29472956;
-        obuf[7] = obuf[2] ^ obuf[3] ^ 0x65866593;
-    }
-
-    cpu_physical_memory_write(paddr, (uint8_t *) &obuf, 32);
-}
-
-static void xhci_process_commands(XHCIState *xhci)
-{
-    XHCITRB trb;
-    TRBType type;
-    XHCIEvent event = {ER_COMMAND_COMPLETE, CC_SUCCESS};
-    target_phys_addr_t addr;
-    unsigned int i, slotid = 0;
-
-    DPRINTF("xhci_process_commands()\n");
-    if (!xhci_running(xhci)) {
-        DPRINTF("xhci_process_commands() called while xHC stopped or paused\n");
-        return;
-    }
-
-    xhci->crcr_low |= CRCR_CRR;
-
-    while ((type = xhci_ring_fetch(xhci, &xhci->cmd_ring, &trb, &addr))) {
-        event.ptr = addr;
-        switch (type) {
-        case CR_ENABLE_SLOT:
-            for (i = 0; i < MAXSLOTS; i++) {
-                if (!xhci->slots[i].enabled) {
-                    break;
-                }
-            }
-            if (i >= MAXSLOTS) {
-                fprintf(stderr, "xhci: no device slots available\n");
-                event.ccode = CC_NO_SLOTS_ERROR;
-            } else {
-                slotid = i+1;
-                event.ccode = xhci_enable_slot(xhci, slotid);
-            }
-            break;
-        case CR_DISABLE_SLOT:
-            slotid = xhci_get_slot(xhci, &event, &trb);
-            if (slotid) {
-                event.ccode = xhci_disable_slot(xhci, slotid);
-            }
-            break;
-        case CR_ADDRESS_DEVICE:
-            slotid = xhci_get_slot(xhci, &event, &trb);
-            if (slotid) {
-                event.ccode = xhci_address_slot(xhci, slotid, trb.parameter,
-                                                trb.control & TRB_CR_BSR);
-            }
-            break;
-        case CR_CONFIGURE_ENDPOINT:
-            slotid = xhci_get_slot(xhci, &event, &trb);
-            if (slotid) {
-                event.ccode = xhci_configure_slot(xhci, slotid, trb.parameter,
-                                                  trb.control & TRB_CR_DC);
-            }
-            break;
-        case CR_EVALUATE_CONTEXT:
-            slotid = xhci_get_slot(xhci, &event, &trb);
-            if (slotid) {
-                event.ccode = xhci_evaluate_slot(xhci, slotid, trb.parameter);
-            }
-            break;
-        case CR_STOP_ENDPOINT:
-            slotid = xhci_get_slot(xhci, &event, &trb);
-            if (slotid) {
-                unsigned int epid = (trb.control >> TRB_CR_EPID_SHIFT)
-                    & TRB_CR_EPID_MASK;
-                event.ccode = xhci_stop_ep(xhci, slotid, epid);
-            }
-            break;
-        case CR_RESET_ENDPOINT:
-            slotid = xhci_get_slot(xhci, &event, &trb);
-            if (slotid) {
-                unsigned int epid = (trb.control >> TRB_CR_EPID_SHIFT)
-                    & TRB_CR_EPID_MASK;
-                event.ccode = xhci_reset_ep(xhci, slotid, epid);
-            }
-            break;
-        case CR_SET_TR_DEQUEUE:
-            slotid = xhci_get_slot(xhci, &event, &trb);
-            if (slotid) {
-                unsigned int epid = (trb.control >> TRB_CR_EPID_SHIFT)
-                    & TRB_CR_EPID_MASK;
-                event.ccode = xhci_set_ep_dequeue(xhci, slotid, epid,
-                                                  trb.parameter);
-            }
-            break;
-        case CR_RESET_DEVICE:
-            slotid = xhci_get_slot(xhci, &event, &trb);
-            if (slotid) {
-                event.ccode = xhci_reset_slot(xhci, slotid);
-            }
-            break;
-        case CR_GET_PORT_BANDWIDTH:
-            event.ccode = xhci_get_port_bandwidth(xhci, trb.parameter);
-            break;
-        case CR_VENDOR_VIA_CHALLENGE_RESPONSE:
-            xhci_via_challenge(trb.parameter);
-            break;
-        case CR_VENDOR_NEC_FIRMWARE_REVISION:
-            event.type = 48; /* NEC reply */
-            event.length = 0x3025;
-            break;
-        case CR_VENDOR_NEC_CHALLENGE_RESPONSE:
-        {
-            uint32_t chi = trb.parameter >> 32;
-            uint32_t clo = trb.parameter;
-            uint32_t val = xhci_nec_challenge(chi, clo);
-            event.length = val & 0xFFFF;
-            event.epid = val >> 16;
-            slotid = val >> 24;
-            event.type = 48; /* NEC reply */
-        }
-        break;
-        default:
-            fprintf(stderr, "xhci: unimplemented command %d\n", type);
-            event.ccode = CC_TRB_ERROR;
-            break;
-        }
-        event.slotid = slotid;
-        xhci_event(xhci, &event);
-    }
-}
-
-static void xhci_update_port(XHCIState *xhci, XHCIPort *port, int is_detach)
-{
-    int nr = port->port.index + 1;
-
-    port->portsc = PORTSC_PP;
-    if (port->port.dev && port->port.dev->attached && !is_detach) {
-        port->portsc |= PORTSC_CCS;
-        switch (port->port.dev->speed) {
-        case USB_SPEED_LOW:
-            port->portsc |= PORTSC_SPEED_LOW;
-            break;
-        case USB_SPEED_FULL:
-            port->portsc |= PORTSC_SPEED_FULL;
-            break;
-        case USB_SPEED_HIGH:
-            port->portsc |= PORTSC_SPEED_HIGH;
-            break;
-        }
-    }
-
-    if (xhci_running(xhci)) {
-        port->portsc |= PORTSC_CSC;
-        XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, nr << 24};
-        xhci_event(xhci, &ev);
-        DPRINTF("xhci: port change event for port %d\n", nr);
-    }
-}
-
-static void xhci_reset(void *opaque)
-{
-    XHCIState *xhci = opaque;
-    int i;
-
-    DPRINTF("xhci: full reset\n");
-    if (!(xhci->usbsts & USBSTS_HCH)) {
-        fprintf(stderr, "xhci: reset while running!\n");
-    }
-
-    xhci->usbcmd = 0;
-    xhci->usbsts = USBSTS_HCH;
-    xhci->dnctrl = 0;
-    xhci->crcr_low = 0;
-    xhci->crcr_high = 0;
-    xhci->dcbaap_low = 0;
-    xhci->dcbaap_high = 0;
-    xhci->config = 0;
-    xhci->devaddr = 2;
-
-    for (i = 0; i < MAXSLOTS; i++) {
-        xhci_disable_slot(xhci, i+1);
-    }
-
-    for (i = 0; i < MAXPORTS; i++) {
-        xhci_update_port(xhci, xhci->ports + i, 0);
-    }
-
-    xhci->mfindex = 0;
-    xhci->iman = 0;
-    xhci->imod = 0;
-    xhci->erstsz = 0;
-    xhci->erstba_low = 0;
-    xhci->erstba_high = 0;
-    xhci->erdp_low = 0;
-    xhci->erdp_high = 0;
-
-    xhci->er_ep_idx = 0;
-    xhci->er_pcs = 1;
-    xhci->er_full = 0;
-    xhci->ev_buffer_put = 0;
-    xhci->ev_buffer_get = 0;
-}
-
-static uint32_t xhci_cap_read(XHCIState *xhci, uint32_t reg)
-{
-    DPRINTF("xhci_cap_read(0x%x)\n", reg);
-
-    switch (reg) {
-    case 0x00: /* HCIVERSION, CAPLENGTH */
-        return 0x01000000 | LEN_CAP;
-    case 0x04: /* HCSPARAMS 1 */
-        return (MAXPORTS<<24) | (MAXINTRS<<8) | MAXSLOTS;
-    case 0x08: /* HCSPARAMS 2 */
-        return 0x0000000f;
-    case 0x0c: /* HCSPARAMS 3 */
-        return 0x00000000;
-    case 0x10: /* HCCPARAMS */
-#if TARGET_PHYS_ADDR_BITS > 32
-        return 0x00081001;
-#else
-        return 0x00081000;
-#endif
-    case 0x14: /* DBOFF */
-        return OFF_DOORBELL;
-    case 0x18: /* RTSOFF */
-        return OFF_RUNTIME;
-
-    /* extended capabilities */
-    case 0x20: /* Supported Protocol:00 */
-#if USB3_PORTS > 0
-        return 0x02000402; /* USB 2.0 */
-#else
-        return 0x02000002; /* USB 2.0 */
-#endif
-    case 0x24: /* Supported Protocol:04 */
-        return 0x20425455; /* "USB " */
-    case 0x28: /* Supported Protocol:08 */
-        return 0x00000001 | (USB2_PORTS<<8);
-    case 0x2c: /* Supported Protocol:0c */
-        return 0x00000000; /* reserved */
-#if USB3_PORTS > 0
-    case 0x30: /* Supported Protocol:00 */
-        return 0x03000002; /* USB 3.0 */
-    case 0x34: /* Supported Protocol:04 */
-        return 0x20425455; /* "USB " */
-    case 0x38: /* Supported Protocol:08 */
-        return 0x00000000 | (USB2_PORTS+1) | (USB3_PORTS<<8);
-    case 0x3c: /* Supported Protocol:0c */
-        return 0x00000000; /* reserved */
-#endif
-    default:
-        fprintf(stderr, "xhci_cap_read: reg %d unimplemented\n", reg);
-    }
-    return 0;
-}
-
-static uint32_t xhci_port_read(XHCIState *xhci, uint32_t reg)
-{
-    uint32_t port = reg >> 4;
-    if (port >= MAXPORTS) {
-        fprintf(stderr, "xhci_port_read: port %d out of bounds\n", port);
-        return 0;
-    }
-
-    switch (reg & 0xf) {
-    case 0x00: /* PORTSC */
-        return xhci->ports[port].portsc;
-    case 0x04: /* PORTPMSC */
-    case 0x08: /* PORTLI */
-        return 0;
-    case 0x0c: /* reserved */
-    default:
-        fprintf(stderr, "xhci_port_read (port %d): reg 0x%x unimplemented\n",
-                port, reg);
-        return 0;
-    }
-}
-
-static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val)
-{
-    uint32_t port = reg >> 4;
-    uint32_t portsc;
-
-    if (port >= MAXPORTS) {
-        fprintf(stderr, "xhci_port_read: port %d out of bounds\n", port);
-        return;
-    }
-
-    switch (reg & 0xf) {
-    case 0x00: /* PORTSC */
-        portsc = xhci->ports[port].portsc;
-        /* write-1-to-clear bits*/
-        portsc &= ~(val & (PORTSC_CSC|PORTSC_PEC|PORTSC_WRC|PORTSC_OCC|
-                           PORTSC_PRC|PORTSC_PLC|PORTSC_CEC));
-        if (val & PORTSC_LWS) {
-            /* overwrite PLS only when LWS=1 */
-            portsc &= ~(PORTSC_PLS_MASK << PORTSC_PLS_SHIFT);
-            portsc |= val & (PORTSC_PLS_MASK << PORTSC_PLS_SHIFT);
-        }
-        /* read/write bits */
-        portsc &= ~(PORTSC_PP|PORTSC_WCE|PORTSC_WDE|PORTSC_WOE);
-        portsc |= (val & (PORTSC_PP|PORTSC_WCE|PORTSC_WDE|PORTSC_WOE));
-        /* write-1-to-start bits */
-        if (val & PORTSC_PR) {
-            DPRINTF("xhci: port %d reset\n", port);
-            usb_device_reset(xhci->ports[port].port.dev);
-            portsc |= PORTSC_PRC | PORTSC_PED;
-        }
-        xhci->ports[port].portsc = portsc;
-        break;
-    case 0x04: /* PORTPMSC */
-    case 0x08: /* PORTLI */
-    default:
-        fprintf(stderr, "xhci_port_write (port %d): reg 0x%x unimplemented\n",
-                port, reg);
-    }
-}
-
-static uint32_t xhci_oper_read(XHCIState *xhci, uint32_t reg)
-{
-    DPRINTF("xhci_oper_read(0x%x)\n", reg);
-
-    if (reg >= 0x400) {
-        return xhci_port_read(xhci, reg - 0x400);
-    }
-
-    switch (reg) {
-    case 0x00: /* USBCMD */
-        return xhci->usbcmd;
-    case 0x04: /* USBSTS */
-        return xhci->usbsts;
-    case 0x08: /* PAGESIZE */
-        return 1; /* 4KiB */
-    case 0x14: /* DNCTRL */
-        return xhci->dnctrl;
-    case 0x18: /* CRCR low */
-        return xhci->crcr_low & ~0xe;
-    case 0x1c: /* CRCR high */
-        return xhci->crcr_high;
-    case 0x30: /* DCBAAP low */
-        return xhci->dcbaap_low;
-    case 0x34: /* DCBAAP high */
-        return xhci->dcbaap_high;
-    case 0x38: /* CONFIG */
-        return xhci->config;
-    default:
-        fprintf(stderr, "xhci_oper_read: reg 0x%x unimplemented\n", reg);
-    }
-    return 0;
-}
-
-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;
-    }
-
-    switch (reg) {
-    case 0x00: /* USBCMD */
-        if ((val & USBCMD_RS) && !(xhci->usbcmd & USBCMD_RS)) {
-            xhci_run(xhci);
-        } else if (!(val & USBCMD_RS) && (xhci->usbcmd & USBCMD_RS)) {
-            xhci_stop(xhci);
-        }
-        xhci->usbcmd = val & 0xc0f;
-        if (val & USBCMD_HCRST) {
-            xhci_reset(xhci);
-        }
-        xhci_irq_update(xhci);
-        break;
-
-    case 0x04: /* USBSTS */
-        /* these bits are write-1-to-clear */
-        xhci->usbsts &= ~(val & (USBSTS_HSE|USBSTS_EINT|USBSTS_PCD|USBSTS_SRE));
-        xhci_irq_update(xhci);
-        break;
-
-    case 0x14: /* DNCTRL */
-        xhci->dnctrl = val & 0xffff;
-        break;
-    case 0x18: /* CRCR low */
-        xhci->crcr_low = (val & 0xffffffcf) | (xhci->crcr_low & CRCR_CRR);
-        break;
-    case 0x1c: /* CRCR high */
-        xhci->crcr_high = val;
-        if (xhci->crcr_low & (CRCR_CA|CRCR_CS) && (xhci->crcr_low & CRCR_CRR)) {
-            XHCIEvent event = {ER_COMMAND_COMPLETE, CC_COMMAND_RING_STOPPED};
-            xhci->crcr_low &= ~CRCR_CRR;
-            xhci_event(xhci, &event);
-            DPRINTF("xhci: command ring stopped (CRCR=%08x)\n", xhci->crcr_low);
-        } else {
-            target_phys_addr_t base = xhci_addr64(xhci->crcr_low & ~0x3f, val);
-            xhci_ring_init(xhci, &xhci->cmd_ring, base);
-        }
-        xhci->crcr_low &= ~(CRCR_CA | CRCR_CS);
-        break;
-    case 0x30: /* DCBAAP low */
-        xhci->dcbaap_low = val & 0xffffffc0;
-        break;
-    case 0x34: /* DCBAAP high */
-        xhci->dcbaap_high = val;
-        break;
-    case 0x38: /* CONFIG */
-        xhci->config = val & 0xff;
-        break;
-    default:
-        fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", reg);
-    }
-}
-
-static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg)
-{
-    DPRINTF("xhci_runtime_read(0x%x)\n", reg);
-
-    switch (reg) {
-    case 0x00: /* MFINDEX */
-        fprintf(stderr, "xhci_runtime_read: MFINDEX not yet implemented\n");
-        return xhci->mfindex;
-    case 0x20: /* IMAN */
-        return xhci->iman;
-    case 0x24: /* IMOD */
-        return xhci->imod;
-    case 0x28: /* ERSTSZ */
-        return xhci->erstsz;
-    case 0x30: /* ERSTBA low */
-        return xhci->erstba_low;
-    case 0x34: /* ERSTBA high */
-        return xhci->erstba_high;
-    case 0x38: /* ERDP low */
-        return xhci->erdp_low;
-    case 0x3c: /* ERDP high */
-        return xhci->erdp_high;
-    default:
-        fprintf(stderr, "xhci_runtime_read: reg 0x%x unimplemented\n", reg);
-    }
-    return 0;
-}
-
-static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val)
-{
-    DPRINTF("xhci_runtime_write(0x%x, 0x%08x)\n", reg, val);
-
-    switch (reg) {
-    case 0x20: /* IMAN */
-        if (val & IMAN_IP) {
-            xhci->iman &= ~IMAN_IP;
-        }
-        xhci->iman &= ~IMAN_IE;
-        xhci->iman |= val & IMAN_IE;
-        xhci_irq_update(xhci);
-        break;
-    case 0x24: /* IMOD */
-        xhci->imod = val;
-        break;
-    case 0x28: /* ERSTSZ */
-        xhci->erstsz = val & 0xffff;
-        break;
-    case 0x30: /* ERSTBA low */
-        /* XXX NEC driver bug: it doesn't align this to 64 bytes
-        xhci->erstba_low = val & 0xffffffc0; */
-        xhci->erstba_low = val & 0xfffffff0;
-        break;
-    case 0x34: /* ERSTBA high */
-        xhci->erstba_high = val;
-        xhci_er_reset(xhci);
-        break;
-    case 0x38: /* ERDP low */
-        if (val & ERDP_EHB) {
-            xhci->erdp_low &= ~ERDP_EHB;
-        }
-        xhci->erdp_low = (val & ~ERDP_EHB) | (xhci->erdp_low & ERDP_EHB);
-        break;
-    case 0x3c: /* ERDP high */
-        xhci->erdp_high = val;
-        xhci_events_update(xhci);
-        break;
-    default:
-        fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", reg);
-    }
-}
-
-static uint32_t xhci_doorbell_read(XHCIState *xhci, uint32_t reg)
-{
-    DPRINTF("xhci_doorbell_read(0x%x)\n", reg);
-    /* doorbells always read as 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);
-
-    if (!xhci_running(xhci)) {
-        fprintf(stderr, "xhci: wrote doorbell while xHC stopped or paused\n");
-        return;
-    }
-
-    reg >>= 2;
-
-    if (reg == 0) {
-        if (val == 0) {
-            xhci_process_commands(xhci);
-        } else {
-            fprintf(stderr, "xhci: bad doorbell 0 write: 0x%x\n", val);
-        }
-    } else {
-        if (reg > MAXSLOTS) {
-            fprintf(stderr, "xhci: bad doorbell %d\n", reg);
-        } else if (val > 31) {
-            fprintf(stderr, "xhci: bad doorbell %d write: 0x%x\n", reg, val);
-        } else {
-            xhci_kick_ep(xhci, reg, val);
-        }
-    }
-}
-
-static uint64_t xhci_mem_read(void *ptr, target_phys_addr_t addr,
-                              unsigned size)
-{
-    XHCIState *xhci = ptr;
-
-    /* Only aligned reads are allowed on xHCI */
-    if (addr & 3) {
-        fprintf(stderr, "xhci_mem_read: Mis-aligned read\n");
-        return 0;
-    }
-
-    if (addr < LEN_CAP) {
-        return xhci_cap_read(xhci, addr);
-    } else if (addr >= OFF_OPER && addr < (OFF_OPER + LEN_OPER)) {
-        return xhci_oper_read(xhci, addr - OFF_OPER);
-    } else if (addr >= OFF_RUNTIME && addr < (OFF_RUNTIME + LEN_RUNTIME)) {
-        return xhci_runtime_read(xhci, addr - OFF_RUNTIME);
-    } else if (addr >= OFF_DOORBELL && addr < (OFF_DOORBELL + LEN_DOORBELL)) {
-        return xhci_doorbell_read(xhci, addr - OFF_DOORBELL);
-    } else {
-        fprintf(stderr, "xhci_mem_read: Bad offset %x\n", (int)addr);
-        return 0;
-    }
-}
-
-static void xhci_mem_write(void *ptr, target_phys_addr_t addr,
-                           uint64_t val, unsigned size)
-{
-    XHCIState *xhci = ptr;
-
-    /* Only aligned writes are allowed on xHCI */
-    if (addr & 3) {
-        fprintf(stderr, "xhci_mem_write: Mis-aligned write\n");
-        return;
-    }
-
-    if (addr >= OFF_OPER && addr < (OFF_OPER + LEN_OPER)) {
-        xhci_oper_write(xhci, addr - OFF_OPER, val);
-    } else if (addr >= OFF_RUNTIME && addr < (OFF_RUNTIME + LEN_RUNTIME)) {
-        xhci_runtime_write(xhci, addr - OFF_RUNTIME, val);
-    } else if (addr >= OFF_DOORBELL && addr < (OFF_DOORBELL + LEN_DOORBELL)) {
-        xhci_doorbell_write(xhci, addr - OFF_DOORBELL, val);
-    } else {
-        fprintf(stderr, "xhci_mem_write: Bad offset %x\n", (int)addr);
-    }
-}
-
-static const MemoryRegionOps xhci_mem_ops = {
-    .read = xhci_mem_read,
-    .write = xhci_mem_write,
-    .valid.min_access_size = 4,
-    .valid.max_access_size = 4,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static void xhci_attach(USBPort *usbport)
-{
-    XHCIState *xhci = usbport->opaque;
-    XHCIPort *port = &xhci->ports[usbport->index];
-
-    xhci_update_port(xhci, port, 0);
-}
-
-static void xhci_detach(USBPort *usbport)
-{
-    XHCIState *xhci = usbport->opaque;
-    XHCIPort *port = &xhci->ports[usbport->index];
-
-    xhci_update_port(xhci, port, 1);
-}
-
-static void xhci_wakeup(USBPort *usbport)
-{
-    XHCIState *xhci = usbport->opaque;
-    XHCIPort *port = &xhci->ports[usbport->index];
-    int nr = port->port.index + 1;
-    XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, nr << 24};
-    uint32_t pls;
-
-    pls = (port->portsc >> PORTSC_PLS_SHIFT) & PORTSC_PLS_MASK;
-    if (pls != 3) {
-        return;
-    }
-    port->portsc |= 0xf << PORTSC_PLS_SHIFT;
-    if (port->portsc & PORTSC_PLC) {
-        return;
-    }
-    port->portsc |= PORTSC_PLC;
-    xhci_event(xhci, &ev);
-}
-
-static void xhci_complete(USBPort *port, USBPacket *packet)
-{
-    XHCITransfer *xfer = container_of(packet, XHCITransfer, packet);
-
-    xhci_complete_packet(xfer, packet->result);
-    xhci_kick_ep(xfer->xhci, xfer->slotid, xfer->epid);
-}
-
-static void xhci_child_detach(USBPort *port, USBDevice *child)
-{
-    FIXME();
-}
-
-static USBPortOps xhci_port_ops = {
-    .attach   = xhci_attach,
-    .detach   = xhci_detach,
-    .wakeup   = xhci_wakeup,
-    .complete = xhci_complete,
-    .child_detach = xhci_child_detach,
-};
-
-static int xhci_find_slotid(XHCIState *xhci, USBDevice *dev)
-{
-    XHCISlot *slot;
-    int slotid;
-
-    for (slotid = 1; slotid <= MAXSLOTS; slotid++) {
-        slot = &xhci->slots[slotid-1];
-        if (slot->devaddr == dev->addr) {
-            return slotid;
-        }
-    }
-    return 0;
-}
-
-static int xhci_find_epid(USBEndpoint *ep)
-{
-    if (ep->nr == 0) {
-        return 1;
-    }
-    if (ep->pid == USB_TOKEN_IN) {
-        return ep->nr * 2 + 1;
-    } else {
-        return ep->nr * 2;
-    }
-}
-
-static void xhci_wakeup_endpoint(USBBus *bus, USBEndpoint *ep)
-{
-    XHCIState *xhci = container_of(bus, XHCIState, bus);
-    int slotid;
-
-    DPRINTF("%s\n", __func__);
-    slotid = xhci_find_slotid(xhci, ep->dev);
-    if (slotid == 0 || !xhci->slots[slotid-1].enabled) {
-        DPRINTF("%s: oops, no slot for dev %d\n", __func__, ep->dev->addr);
-        return;
-    }
-    xhci_kick_ep(xhci, slotid, xhci_find_epid(ep));
-}
-
-static USBBusOps xhci_bus_ops = {
-    .wakeup_endpoint = xhci_wakeup_endpoint,
-};
-
-static void usb_xhci_init(XHCIState *xhci, DeviceState *dev)
-{
-    int i;
-
-    xhci->usbsts = USBSTS_HCH;
-
-    usb_bus_new(&xhci->bus, &xhci_bus_ops, &xhci->pci_dev.qdev);
-
-    for (i = 0; i < MAXPORTS; i++) {
-        memset(&xhci->ports[i], 0, sizeof(xhci->ports[i]));
-        usb_register_port(&xhci->bus, &xhci->ports[i].port, xhci, i,
-                          &xhci_port_ops,
-                          USB_SPEED_MASK_LOW  |
-                          USB_SPEED_MASK_FULL |
-                          USB_SPEED_MASK_HIGH);
-    }
-    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)
-{
-    int ret;
-
-    XHCIState *xhci = DO_UPCAST(XHCIState, pci_dev, dev);
-
-    xhci->pci_dev.config[PCI_CLASS_PROG] = 0x30;    /* xHCI */
-    xhci->pci_dev.config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin 1 */
-    xhci->pci_dev.config[PCI_CACHE_LINE_SIZE] = 0x10;
-    xhci->pci_dev.config[0x60] = 0x30; /* release number */
-
-    usb_xhci_init(xhci, &dev->qdev);
-
-    xhci->irq = xhci->pci_dev.irq[0];
-
-    memory_region_init_io(&xhci->mem, &xhci_mem_ops, xhci,
-                          "xhci", LEN_REGS);
-    pci_register_bar(&xhci->pci_dev, 0,
-                     PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64,
-                     &xhci->mem);
-
-    ret = pcie_cap_init(&xhci->pci_dev, 0xa0, PCI_EXP_TYPE_ENDPOINT, 0);
-    assert(ret >= 0);
-
-    if (xhci->msi) {
-        ret = msi_init(&xhci->pci_dev, 0x70, 1, true, false);
-        assert(ret >= 0);
-    }
-
-    return 0;
-}
-
-static void xhci_write_config(PCIDevice *dev, uint32_t addr, uint32_t val,
-                              int len)
-{
-    XHCIState *xhci = DO_UPCAST(XHCIState, pci_dev, dev);
-
-    pci_default_write_config(dev, addr, val, len);
-    if (xhci->msi) {
-        msi_write_config(dev, addr, val, len);
-    }
-}
-
-static const VMStateDescription vmstate_xhci = {
-    .name = "xhci",
-    .unmigratable = 1,
-};
-
-static Property xhci_properties[] = {
-    DEFINE_PROP_UINT32("msi", XHCIState, msi, 0),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void xhci_class_init(ObjectClass *klass, void *data)
-{
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    dc->vmsd    = &vmstate_xhci;
-    dc->props   = xhci_properties;
-    k->init         = usb_xhci_initfn;
-    k->vendor_id    = PCI_VENDOR_ID_NEC;
-    k->device_id    = PCI_DEVICE_ID_NEC_UPD720200;
-    k->class_id     = PCI_CLASS_SERIAL_USB;
-    k->revision     = 0x03;
-    k->is_express   = 1;
-    k->config_write = xhci_write_config;
-}
-
-static TypeInfo xhci_info = {
-    .name          = "nec-usb-xhci",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(XHCIState),
-    .class_init    = xhci_class_init,
-};
-
-static void xhci_register_types(void)
-{
-    type_register_static(&xhci_info);
-}
-
-type_init(xhci_register_types)
diff --git a/hw/usb.c b/hw/usb.c
deleted file mode 100644
index 1ec2e90..0000000
--- a/hw/usb.c
+++ /dev/null
@@ -1,663 +0,0 @@
-/*
- * QEMU USB emulation
- *
- * Copyright (c) 2005 Fabrice Bellard
- *
- * 2008 Generic packet handler rewrite by Max Krasnyansky
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "qemu-common.h"
-#include "usb.h"
-#include "iov.h"
-#include "trace.h"
-
-void usb_attach(USBPort *port)
-{
-    USBDevice *dev = port->dev;
-
-    assert(dev != NULL);
-    assert(dev->attached);
-    assert(dev->state == USB_STATE_NOTATTACHED);
-    port->ops->attach(port);
-    dev->state = USB_STATE_ATTACHED;
-    usb_device_handle_attach(dev);
-}
-
-void usb_detach(USBPort *port)
-{
-    USBDevice *dev = port->dev;
-
-    assert(dev != NULL);
-    assert(dev->state != USB_STATE_NOTATTACHED);
-    port->ops->detach(port);
-    dev->state = USB_STATE_NOTATTACHED;
-}
-
-void usb_port_reset(USBPort *port)
-{
-    USBDevice *dev = port->dev;
-
-    assert(dev != NULL);
-    usb_detach(port);
-    usb_attach(port);
-    usb_device_reset(dev);
-}
-
-void usb_device_reset(USBDevice *dev)
-{
-    if (dev == NULL || !dev->attached) {
-        return;
-    }
-    dev->remote_wakeup = 0;
-    dev->addr = 0;
-    dev->state = USB_STATE_DEFAULT;
-    usb_device_handle_reset(dev);
-}
-
-void usb_wakeup(USBEndpoint *ep)
-{
-    USBDevice *dev = ep->dev;
-    USBBus *bus = usb_bus_from_device(dev);
-
-    if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) {
-        dev->port->ops->wakeup(dev->port);
-    }
-    if (bus->ops->wakeup_endpoint) {
-        bus->ops->wakeup_endpoint(bus, ep);
-    }
-}
-
-/**********************/
-
-/* generic USB device helpers (you are not forced to use them when
-   writing your USB device driver, but they help handling the
-   protocol)
-*/
-
-#define SETUP_STATE_IDLE  0
-#define SETUP_STATE_SETUP 1
-#define SETUP_STATE_DATA  2
-#define SETUP_STATE_ACK   3
-#define SETUP_STATE_PARAM 4
-
-static int do_token_setup(USBDevice *s, USBPacket *p)
-{
-    int request, value, index;
-    int ret = 0;
-
-    if (p->iov.size != 8) {
-        return USB_RET_STALL;
-    }
-
-    usb_packet_copy(p, s->setup_buf, p->iov.size);
-    s->setup_len   = (s->setup_buf[7] << 8) | s->setup_buf[6];
-    s->setup_index = 0;
-
-    request = (s->setup_buf[0] << 8) | s->setup_buf[1];
-    value   = (s->setup_buf[3] << 8) | s->setup_buf[2];
-    index   = (s->setup_buf[5] << 8) | s->setup_buf[4];
-
-    if (s->setup_buf[0] & USB_DIR_IN) {
-        ret = usb_device_handle_control(s, p, request, value, index,
-                                        s->setup_len, s->data_buf);
-        if (ret == USB_RET_ASYNC) {
-             s->setup_state = SETUP_STATE_SETUP;
-             return USB_RET_ASYNC;
-        }
-        if (ret < 0)
-            return ret;
-
-        if (ret < s->setup_len)
-            s->setup_len = ret;
-        s->setup_state = SETUP_STATE_DATA;
-    } else {
-        if (s->setup_len > sizeof(s->data_buf)) {
-            fprintf(stderr,
-                "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
-                s->setup_len, sizeof(s->data_buf));
-            return USB_RET_STALL;
-        }
-        if (s->setup_len == 0)
-            s->setup_state = SETUP_STATE_ACK;
-        else
-            s->setup_state = SETUP_STATE_DATA;
-    }
-
-    return ret;
-}
-
-static int do_token_in(USBDevice *s, USBPacket *p)
-{
-    int request, value, index;
-    int ret = 0;
-
-    assert(p->ep->nr == 0);
-
-    request = (s->setup_buf[0] << 8) | s->setup_buf[1];
-    value   = (s->setup_buf[3] << 8) | s->setup_buf[2];
-    index   = (s->setup_buf[5] << 8) | s->setup_buf[4];
- 
-    switch(s->setup_state) {
-    case SETUP_STATE_ACK:
-        if (!(s->setup_buf[0] & USB_DIR_IN)) {
-            ret = usb_device_handle_control(s, p, request, value, index,
-                                            s->setup_len, s->data_buf);
-            if (ret == USB_RET_ASYNC) {
-                return USB_RET_ASYNC;
-            }
-            s->setup_state = SETUP_STATE_IDLE;
-            if (ret > 0)
-                return 0;
-            return ret;
-        }
-
-        /* return 0 byte */
-        return 0;
-
-    case SETUP_STATE_DATA:
-        if (s->setup_buf[0] & USB_DIR_IN) {
-            int len = s->setup_len - s->setup_index;
-            if (len > p->iov.size) {
-                len = p->iov.size;
-            }
-            usb_packet_copy(p, s->data_buf + s->setup_index, len);
-            s->setup_index += len;
-            if (s->setup_index >= s->setup_len)
-                s->setup_state = SETUP_STATE_ACK;
-            return len;
-        }
-
-        s->setup_state = SETUP_STATE_IDLE;
-        return USB_RET_STALL;
-
-    default:
-        return USB_RET_STALL;
-    }
-}
-
-static int do_token_out(USBDevice *s, USBPacket *p)
-{
-    assert(p->ep->nr == 0);
-
-    switch(s->setup_state) {
-    case SETUP_STATE_ACK:
-        if (s->setup_buf[0] & USB_DIR_IN) {
-            s->setup_state = SETUP_STATE_IDLE;
-            /* transfer OK */
-        } else {
-            /* ignore additional output */
-        }
-        return 0;
-
-    case SETUP_STATE_DATA:
-        if (!(s->setup_buf[0] & USB_DIR_IN)) {
-            int len = s->setup_len - s->setup_index;
-            if (len > p->iov.size) {
-                len = p->iov.size;
-            }
-            usb_packet_copy(p, s->data_buf + s->setup_index, len);
-            s->setup_index += len;
-            if (s->setup_index >= s->setup_len)
-                s->setup_state = SETUP_STATE_ACK;
-            return len;
-        }
-
-        s->setup_state = SETUP_STATE_IDLE;
-        return USB_RET_STALL;
-
-    default:
-        return USB_RET_STALL;
-    }
-}
-
-static int do_parameter(USBDevice *s, USBPacket *p)
-{
-    int request, value, index;
-    int i, ret = 0;
-
-    for (i = 0; i < 8; i++) {
-        s->setup_buf[i] = p->parameter >> (i*8);
-    }
-
-    s->setup_state = SETUP_STATE_PARAM;
-    s->setup_len   = (s->setup_buf[7] << 8) | s->setup_buf[6];
-    s->setup_index = 0;
-
-    request = (s->setup_buf[0] << 8) | s->setup_buf[1];
-    value   = (s->setup_buf[3] << 8) | s->setup_buf[2];
-    index   = (s->setup_buf[5] << 8) | s->setup_buf[4];
-
-    if (s->setup_len > sizeof(s->data_buf)) {
-        fprintf(stderr,
-                "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
-                s->setup_len, sizeof(s->data_buf));
-        return USB_RET_STALL;
-    }
-
-    if (p->pid == USB_TOKEN_OUT) {
-        usb_packet_copy(p, s->data_buf, s->setup_len);
-    }
-
-    ret = usb_device_handle_control(s, p, request, value, index,
-                                    s->setup_len, s->data_buf);
-    if (ret < 0) {
-        return ret;
-    }
-
-    if (ret < s->setup_len) {
-        s->setup_len = ret;
-    }
-    if (p->pid == USB_TOKEN_IN) {
-        usb_packet_copy(p, s->data_buf, s->setup_len);
-    }
-
-    return ret;
-}
-
-/* ctrl complete function for devices which use usb_generic_handle_packet and
-   may return USB_RET_ASYNC from their handle_control callback. Device code
-   which does this *must* call this function instead of the normal
-   usb_packet_complete to complete their async control packets. */
-void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p)
-{
-    if (p->result < 0) {
-        s->setup_state = SETUP_STATE_IDLE;
-    }
-
-    switch (s->setup_state) {
-    case SETUP_STATE_SETUP:
-        if (p->result < s->setup_len) {
-            s->setup_len = p->result;
-        }
-        s->setup_state = SETUP_STATE_DATA;
-        p->result = 8;
-        break;
-
-    case SETUP_STATE_ACK:
-        s->setup_state = SETUP_STATE_IDLE;
-        p->result = 0;
-        break;
-
-    case SETUP_STATE_PARAM:
-        if (p->result < s->setup_len) {
-            s->setup_len = p->result;
-        }
-        if (p->pid == USB_TOKEN_IN) {
-            p->result = 0;
-            usb_packet_copy(p, s->data_buf, s->setup_len);
-        }
-        break;
-
-    default:
-        break;
-    }
-    usb_packet_complete(s, p);
-}
-
-/* XXX: fix overflow */
-int set_usb_string(uint8_t *buf, const char *str)
-{
-    int len, i;
-    uint8_t *q;
-
-    q = buf;
-    len = strlen(str);
-    *q++ = 2 * len + 2;
-    *q++ = 3;
-    for(i = 0; i < len; i++) {
-        *q++ = str[i];
-        *q++ = 0;
-    }
-    return q - buf;
-}
-
-USBDevice *usb_find_device(USBPort *port, uint8_t addr)
-{
-    USBDevice *dev = port->dev;
-
-    if (dev == NULL || !dev->attached || dev->state != USB_STATE_DEFAULT) {
-        return NULL;
-    }
-    if (dev->addr == addr) {
-        return dev;
-    }
-    return usb_device_find_device(dev, addr);
-}
-
-static int usb_process_one(USBPacket *p)
-{
-    USBDevice *dev = p->ep->dev;
-
-    if (p->ep->nr == 0) {
-        /* control pipe */
-        if (p->parameter) {
-            return do_parameter(dev, p);
-        }
-        switch (p->pid) {
-        case USB_TOKEN_SETUP:
-            return do_token_setup(dev, p);
-        case USB_TOKEN_IN:
-            return do_token_in(dev, p);
-        case USB_TOKEN_OUT:
-            return do_token_out(dev, p);
-        default:
-            return USB_RET_STALL;
-        }
-    } else {
-        /* data pipe */
-        return usb_device_handle_data(dev, p);
-    }
-}
-
-/* Hand over a packet to a device for processing.  Return value
-   USB_RET_ASYNC indicates the processing isn't finished yet, the
-   driver will call usb_packet_complete() when done processing it. */
-int usb_handle_packet(USBDevice *dev, USBPacket *p)
-{
-    int ret;
-
-    if (dev == NULL) {
-        return USB_RET_NODEV;
-    }
-    assert(dev == p->ep->dev);
-    assert(dev->state == USB_STATE_DEFAULT);
-    assert(p->state == USB_PACKET_SETUP);
-    assert(p->ep != NULL);
-
-    if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline) {
-        ret = usb_process_one(p);
-        if (ret == USB_RET_ASYNC) {
-            usb_packet_set_state(p, USB_PACKET_ASYNC);
-            QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
-        } else {
-            p->result = ret;
-            usb_packet_set_state(p, USB_PACKET_COMPLETE);
-        }
-    } else {
-        ret = USB_RET_ASYNC;
-        usb_packet_set_state(p, USB_PACKET_QUEUED);
-        QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
-    }
-    return ret;
-}
-
-/* Notify the controller that an async packet is complete.  This should only
-   be called for packets previously deferred by returning USB_RET_ASYNC from
-   handle_packet. */
-void usb_packet_complete(USBDevice *dev, USBPacket *p)
-{
-    USBEndpoint *ep = p->ep;
-    int ret;
-
-    assert(p->state == USB_PACKET_ASYNC);
-    assert(QTAILQ_FIRST(&ep->queue) == p);
-    usb_packet_set_state(p, USB_PACKET_COMPLETE);
-    QTAILQ_REMOVE(&ep->queue, p, queue);
-    dev->port->ops->complete(dev->port, p);
-
-    while (!QTAILQ_EMPTY(&ep->queue)) {
-        p = QTAILQ_FIRST(&ep->queue);
-        if (p->state == USB_PACKET_ASYNC) {
-            break;
-        }
-        assert(p->state == USB_PACKET_QUEUED);
-        ret = usb_process_one(p);
-        if (ret == USB_RET_ASYNC) {
-            usb_packet_set_state(p, USB_PACKET_ASYNC);
-            break;
-        }
-        p->result = ret;
-        usb_packet_set_state(p, USB_PACKET_COMPLETE);
-        QTAILQ_REMOVE(&ep->queue, p, queue);
-        dev->port->ops->complete(dev->port, p);
-    }
-}
-
-/* Cancel an active packet.  The packed must have been deferred by
-   returning USB_RET_ASYNC from handle_packet, and not yet
-   completed.  */
-void usb_cancel_packet(USBPacket * p)
-{
-    bool callback = (p->state == USB_PACKET_ASYNC);
-    assert(usb_packet_is_inflight(p));
-    usb_packet_set_state(p, USB_PACKET_CANCELED);
-    QTAILQ_REMOVE(&p->ep->queue, p, queue);
-    if (callback) {
-        usb_device_cancel_packet(p->ep->dev, p);
-    }
-}
-
-
-void usb_packet_init(USBPacket *p)
-{
-    qemu_iovec_init(&p->iov, 1);
-}
-
-void usb_packet_set_state(USBPacket *p, USBPacketState state)
-{
-    static const char *name[] = {
-        [USB_PACKET_UNDEFINED] = "undef",
-        [USB_PACKET_SETUP]     = "setup",
-        [USB_PACKET_QUEUED]    = "queued",
-        [USB_PACKET_ASYNC]     = "async",
-        [USB_PACKET_COMPLETE]  = "complete",
-        [USB_PACKET_CANCELED]  = "canceled",
-    };
-    USBDevice *dev = p->ep->dev;
-    USBBus *bus = usb_bus_from_device(dev);
-
-    trace_usb_packet_state_change(bus->busnr, dev->port->path, p->ep->nr,
-                                  p, name[p->state], name[state]);
-    p->state = state;
-}
-
-void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep)
-{
-    assert(!usb_packet_is_inflight(p));
-    p->pid = pid;
-    p->ep = ep;
-    p->result = 0;
-    p->parameter = 0;
-    qemu_iovec_reset(&p->iov);
-    usb_packet_set_state(p, USB_PACKET_SETUP);
-}
-
-void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len)
-{
-    qemu_iovec_add(&p->iov, ptr, len);
-}
-
-void usb_packet_copy(USBPacket *p, void *ptr, size_t bytes)
-{
-    assert(p->result >= 0);
-    assert(p->result + bytes <= p->iov.size);
-    switch (p->pid) {
-    case USB_TOKEN_SETUP:
-    case USB_TOKEN_OUT:
-        iov_to_buf(p->iov.iov, p->iov.niov, ptr, p->result, bytes);
-        break;
-    case USB_TOKEN_IN:
-        iov_from_buf(p->iov.iov, p->iov.niov, ptr, p->result, bytes);
-        break;
-    default:
-        fprintf(stderr, "%s: invalid pid: %x\n", __func__, p->pid);
-        abort();
-    }
-    p->result += bytes;
-}
-
-void usb_packet_skip(USBPacket *p, size_t bytes)
-{
-    assert(p->result >= 0);
-    assert(p->result + bytes <= p->iov.size);
-    if (p->pid == USB_TOKEN_IN) {
-        iov_clear(p->iov.iov, p->iov.niov, p->result, bytes);
-    }
-    p->result += bytes;
-}
-
-void usb_packet_cleanup(USBPacket *p)
-{
-    assert(!usb_packet_is_inflight(p));
-    qemu_iovec_destroy(&p->iov);
-}
-
-void usb_ep_init(USBDevice *dev)
-{
-    int ep;
-
-    dev->ep_ctl.nr = 0;
-    dev->ep_ctl.type = USB_ENDPOINT_XFER_CONTROL;
-    dev->ep_ctl.ifnum = 0;
-    dev->ep_ctl.dev = dev;
-    dev->ep_ctl.pipeline = false;
-    QTAILQ_INIT(&dev->ep_ctl.queue);
-    for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
-        dev->ep_in[ep].nr = ep + 1;
-        dev->ep_out[ep].nr = ep + 1;
-        dev->ep_in[ep].pid = USB_TOKEN_IN;
-        dev->ep_out[ep].pid = USB_TOKEN_OUT;
-        dev->ep_in[ep].type = USB_ENDPOINT_XFER_INVALID;
-        dev->ep_out[ep].type = USB_ENDPOINT_XFER_INVALID;
-        dev->ep_in[ep].ifnum = 0;
-        dev->ep_out[ep].ifnum = 0;
-        dev->ep_in[ep].dev = dev;
-        dev->ep_out[ep].dev = dev;
-        dev->ep_in[ep].pipeline = false;
-        dev->ep_out[ep].pipeline = false;
-        QTAILQ_INIT(&dev->ep_in[ep].queue);
-        QTAILQ_INIT(&dev->ep_out[ep].queue);
-    }
-}
-
-void usb_ep_dump(USBDevice *dev)
-{
-    static const char *tname[] = {
-        [USB_ENDPOINT_XFER_CONTROL] = "control",
-        [USB_ENDPOINT_XFER_ISOC]    = "isoc",
-        [USB_ENDPOINT_XFER_BULK]    = "bulk",
-        [USB_ENDPOINT_XFER_INT]     = "int",
-    };
-    int ifnum, ep, first;
-
-    fprintf(stderr, "Device \"%s\", config %d\n",
-            dev->product_desc, dev->configuration);
-    for (ifnum = 0; ifnum < 16; ifnum++) {
-        first = 1;
-        for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
-            if (dev->ep_in[ep].type != USB_ENDPOINT_XFER_INVALID &&
-                dev->ep_in[ep].ifnum == ifnum) {
-                if (first) {
-                    first = 0;
-                    fprintf(stderr, "  Interface %d, alternative %d\n",
-                            ifnum, dev->altsetting[ifnum]);
-                }
-                fprintf(stderr, "    Endpoint %d, IN, %s, %d max\n", ep,
-                        tname[dev->ep_in[ep].type],
-                        dev->ep_in[ep].max_packet_size);
-            }
-            if (dev->ep_out[ep].type != USB_ENDPOINT_XFER_INVALID &&
-                dev->ep_out[ep].ifnum == ifnum) {
-                if (first) {
-                    first = 0;
-                    fprintf(stderr, "  Interface %d, alternative %d\n",
-                            ifnum, dev->altsetting[ifnum]);
-                }
-                fprintf(stderr, "    Endpoint %d, OUT, %s, %d max\n", ep,
-                        tname[dev->ep_out[ep].type],
-                        dev->ep_out[ep].max_packet_size);
-            }
-        }
-    }
-    fprintf(stderr, "--\n");
-}
-
-struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep)
-{
-    struct USBEndpoint *eps;
-
-    if (dev == NULL) {
-        return NULL;
-    }
-    eps = (pid == USB_TOKEN_IN) ? dev->ep_in : dev->ep_out;
-    if (ep == 0) {
-        return &dev->ep_ctl;
-    }
-    assert(pid == USB_TOKEN_IN || pid == USB_TOKEN_OUT);
-    assert(ep > 0 && ep <= USB_MAX_ENDPOINTS);
-    return eps + ep - 1;
-}
-
-uint8_t usb_ep_get_type(USBDevice *dev, int pid, int ep)
-{
-    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
-    return uep->type;
-}
-
-void usb_ep_set_type(USBDevice *dev, int pid, int ep, uint8_t type)
-{
-    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
-    uep->type = type;
-}
-
-uint8_t usb_ep_get_ifnum(USBDevice *dev, int pid, int ep)
-{
-    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
-    return uep->ifnum;
-}
-
-void usb_ep_set_ifnum(USBDevice *dev, int pid, int ep, uint8_t ifnum)
-{
-    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
-    uep->ifnum = ifnum;
-}
-
-void usb_ep_set_max_packet_size(USBDevice *dev, int pid, int ep,
-                                uint16_t raw)
-{
-    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
-    int size, microframes;
-
-    size = raw & 0x7ff;
-    switch ((raw >> 11) & 3) {
-    case 1:
-        microframes = 2;
-        break;
-    case 2:
-        microframes = 3;
-        break;
-    default:
-        microframes = 1;
-        break;
-    }
-    uep->max_packet_size = size * microframes;
-}
-
-int usb_ep_get_max_packet_size(USBDevice *dev, int pid, int ep)
-{
-    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
-    return uep->max_packet_size;
-}
-
-void usb_ep_set_pipeline(USBDevice *dev, int pid, int ep, bool enabled)
-{
-    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
-    uep->pipeline = enabled;
-}
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
new file mode 100644
index 0000000..d3f8358
--- /dev/null
+++ b/hw/usb/bus.c
@@ -0,0 +1,584 @@
+#include "hw/hw.h"
+#include "hw/usb.h"
+#include "hw/qdev.h"
+#include "sysemu.h"
+#include "monitor.h"
+#include "trace.h"
+
+static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
+
+static char *usb_get_dev_path(DeviceState *dev);
+static char *usb_get_fw_dev_path(DeviceState *qdev);
+static int usb_qdev_exit(DeviceState *qdev);
+
+static struct BusInfo usb_bus_info = {
+    .name      = "USB",
+    .size      = sizeof(USBBus),
+    .print_dev = usb_bus_dev_print,
+    .get_dev_path = usb_get_dev_path,
+    .get_fw_dev_path = usb_get_fw_dev_path,
+    .props      = (Property[]) {
+        DEFINE_PROP_STRING("port", USBDevice, port_path),
+        DEFINE_PROP_END_OF_LIST()
+    },
+};
+static int next_usb_bus = 0;
+static QTAILQ_HEAD(, USBBus) busses = QTAILQ_HEAD_INITIALIZER(busses);
+
+const VMStateDescription vmstate_usb_device = {
+    .name = "USBDevice",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_UINT8(addr, USBDevice),
+        VMSTATE_INT32(state, USBDevice),
+        VMSTATE_INT32(remote_wakeup, USBDevice),
+        VMSTATE_INT32(setup_state, USBDevice),
+        VMSTATE_INT32(setup_len, USBDevice),
+        VMSTATE_INT32(setup_index, USBDevice),
+        VMSTATE_UINT8_ARRAY(setup_buf, USBDevice, 8),
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
+void usb_bus_new(USBBus *bus, USBBusOps *ops, DeviceState *host)
+{
+    qbus_create_inplace(&bus->qbus, &usb_bus_info, host, NULL);
+    bus->ops = ops;
+    bus->busnr = next_usb_bus++;
+    bus->qbus.allow_hotplug = 1; /* Yes, we can */
+    QTAILQ_INIT(&bus->free);
+    QTAILQ_INIT(&bus->used);
+    QTAILQ_INSERT_TAIL(&busses, bus, next);
+}
+
+USBBus *usb_bus_find(int busnr)
+{
+    USBBus *bus;
+
+    if (-1 == busnr)
+        return QTAILQ_FIRST(&busses);
+    QTAILQ_FOREACH(bus, &busses, next) {
+        if (bus->busnr == busnr)
+            return bus;
+    }
+    return NULL;
+}
+
+static int usb_device_init(USBDevice *dev)
+{
+    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+    if (klass->init) {
+        return klass->init(dev);
+    }
+    return 0;
+}
+
+USBDevice *usb_device_find_device(USBDevice *dev, uint8_t addr)
+{
+    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+    if (klass->find_device) {
+        return klass->find_device(dev, addr);
+    }
+    return NULL;
+}
+
+static void usb_device_handle_destroy(USBDevice *dev)
+{
+    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+    if (klass->handle_destroy) {
+        klass->handle_destroy(dev);
+    }
+}
+
+void usb_device_cancel_packet(USBDevice *dev, USBPacket *p)
+{
+    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+    if (klass->cancel_packet) {
+        klass->cancel_packet(dev, p);
+    }
+}
+
+void usb_device_handle_attach(USBDevice *dev)
+{
+    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+    if (klass->handle_attach) {
+        klass->handle_attach(dev);
+    }
+}
+
+void usb_device_handle_reset(USBDevice *dev)
+{
+    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+    if (klass->handle_reset) {
+        klass->handle_reset(dev);
+    }
+}
+
+int usb_device_handle_control(USBDevice *dev, USBPacket *p, int request,
+                              int value, int index, int length, uint8_t *data)
+{
+    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+    if (klass->handle_control) {
+        return klass->handle_control(dev, p, request, value, index, length,
+                                         data);
+    }
+    return -ENOSYS;
+}
+
+int usb_device_handle_data(USBDevice *dev, USBPacket *p)
+{
+    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+    if (klass->handle_data) {
+        return klass->handle_data(dev, p);
+    }
+    return -ENOSYS;
+}
+
+const char *usb_device_get_product_desc(USBDevice *dev)
+{
+    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+    return klass->product_desc;
+}
+
+const USBDesc *usb_device_get_usb_desc(USBDevice *dev)
+{
+    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+    return klass->usb_desc;
+}
+
+void usb_device_set_interface(USBDevice *dev, int interface,
+                              int alt_old, int alt_new)
+{
+    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+    if (klass->set_interface) {
+        klass->set_interface(dev, interface, alt_old, alt_new);
+    }
+}
+
+static int usb_qdev_init(DeviceState *qdev)
+{
+    USBDevice *dev = USB_DEVICE(qdev);
+    int rc;
+
+    pstrcpy(dev->product_desc, sizeof(dev->product_desc),
+            usb_device_get_product_desc(dev));
+    dev->auto_attach = 1;
+    QLIST_INIT(&dev->strings);
+    usb_ep_init(dev);
+    rc = usb_claim_port(dev);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = usb_device_init(dev);
+    if (rc != 0) {
+        usb_release_port(dev);
+        return rc;
+    }
+    if (dev->auto_attach) {
+        rc = usb_device_attach(dev);
+        if (rc != 0) {
+            usb_qdev_exit(qdev);
+            return rc;
+        }
+    }
+    return 0;
+}
+
+static int usb_qdev_exit(DeviceState *qdev)
+{
+    USBDevice *dev = USB_DEVICE(qdev);
+
+    if (dev->attached) {
+        usb_device_detach(dev);
+    }
+    usb_device_handle_destroy(dev);
+    if (dev->port) {
+        usb_release_port(dev);
+    }
+    return 0;
+}
+
+typedef struct LegacyUSBFactory
+{
+    const char *name;
+    const char *usbdevice_name;
+    USBDevice *(*usbdevice_init)(USBBus *bus, const char *params);
+} LegacyUSBFactory;
+
+static GSList *legacy_usb_factory;
+
+void usb_legacy_register(const char *typename, const char *usbdevice_name,
+                         USBDevice *(*usbdevice_init)(USBBus *bus,
+                                                      const char *params))
+{
+    if (usbdevice_name) {
+        LegacyUSBFactory *f = g_malloc0(sizeof(*f));
+        f->name = typename;
+        f->usbdevice_name = usbdevice_name;
+        f->usbdevice_init = usbdevice_init;
+        legacy_usb_factory = g_slist_append(legacy_usb_factory, f);
+    }
+}
+
+USBDevice *usb_create(USBBus *bus, const char *name)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(&bus->qbus, name);
+    return USB_DEVICE(dev);
+}
+
+USBDevice *usb_create_simple(USBBus *bus, const char *name)
+{
+    USBDevice *dev = usb_create(bus, name);
+    int rc;
+
+    if (!dev) {
+        error_report("Failed to create USB device '%s'", name);
+        return NULL;
+    }
+    rc = qdev_init(&dev->qdev);
+    if (rc < 0) {
+        error_report("Failed to initialize USB device '%s'", name);
+        return NULL;
+    }
+    return dev;
+}
+
+static void usb_fill_port(USBPort *port, void *opaque, int index,
+                          USBPortOps *ops, int speedmask)
+{
+    port->opaque = opaque;
+    port->index = index;
+    port->ops = ops;
+    port->speedmask = speedmask;
+    usb_port_location(port, NULL, index + 1);
+}
+
+void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
+                       USBPortOps *ops, int speedmask)
+{
+    usb_fill_port(port, opaque, index, ops, speedmask);
+    QTAILQ_INSERT_TAIL(&bus->free, port, next);
+    bus->nfree++;
+}
+
+int usb_register_companion(const char *masterbus, USBPort *ports[],
+                           uint32_t portcount, uint32_t firstport,
+                           void *opaque, USBPortOps *ops, int speedmask)
+{
+    USBBus *bus;
+    int i;
+
+    QTAILQ_FOREACH(bus, &busses, next) {
+        if (strcmp(bus->qbus.name, masterbus) == 0) {
+            break;
+        }
+    }
+
+    if (!bus || !bus->ops->register_companion) {
+        qerror_report(QERR_INVALID_PARAMETER_VALUE, "masterbus",
+                      "an USB masterbus");
+        if (bus) {
+            error_printf_unless_qmp(
+                "USB bus '%s' does not allow companion controllers\n",
+                masterbus);
+        }
+        return -1;
+    }
+
+    for (i = 0; i < portcount; i++) {
+        usb_fill_port(ports[i], opaque, i, ops, speedmask);
+    }
+
+    return bus->ops->register_companion(bus, ports, portcount, firstport);
+}
+
+void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr)
+{
+    if (upstream) {
+        snprintf(downstream->path, sizeof(downstream->path), "%s.%d",
+                 upstream->path, portnr);
+    } else {
+        snprintf(downstream->path, sizeof(downstream->path), "%d", portnr);
+    }
+}
+
+void usb_unregister_port(USBBus *bus, USBPort *port)
+{
+    if (port->dev)
+        qdev_free(&port->dev->qdev);
+    QTAILQ_REMOVE(&bus->free, port, next);
+    bus->nfree--;
+}
+
+int usb_claim_port(USBDevice *dev)
+{
+    USBBus *bus = usb_bus_from_device(dev);
+    USBPort *port;
+
+    assert(dev->port == NULL);
+
+    if (dev->port_path) {
+        QTAILQ_FOREACH(port, &bus->free, next) {
+            if (strcmp(port->path, dev->port_path) == 0) {
+                break;
+            }
+        }
+        if (port == NULL) {
+            error_report("Error: usb port %s (bus %s) not found (in use?)",
+                         dev->port_path, bus->qbus.name);
+            return -1;
+        }
+    } else {
+        if (bus->nfree == 1 && strcmp(object_get_typename(OBJECT(dev)), "usb-hub") != 0) {
+            /* Create a new hub and chain it on */
+            usb_create_simple(bus, "usb-hub");
+        }
+        if (bus->nfree == 0) {
+            error_report("Error: tried to attach usb device %s to a bus "
+                         "with no free ports", dev->product_desc);
+            return -1;
+        }
+        port = QTAILQ_FIRST(&bus->free);
+    }
+    trace_usb_port_claim(bus->busnr, port->path);
+
+    QTAILQ_REMOVE(&bus->free, port, next);
+    bus->nfree--;
+
+    dev->port = port;
+    port->dev = dev;
+
+    QTAILQ_INSERT_TAIL(&bus->used, port, next);
+    bus->nused++;
+    return 0;
+}
+
+void usb_release_port(USBDevice *dev)
+{
+    USBBus *bus = usb_bus_from_device(dev);
+    USBPort *port = dev->port;
+
+    assert(port != NULL);
+    trace_usb_port_release(bus->busnr, port->path);
+
+    QTAILQ_REMOVE(&bus->used, port, next);
+    bus->nused--;
+
+    dev->port = NULL;
+    port->dev = NULL;
+
+    QTAILQ_INSERT_TAIL(&bus->free, port, next);
+    bus->nfree++;
+}
+
+int usb_device_attach(USBDevice *dev)
+{
+    USBBus *bus = usb_bus_from_device(dev);
+    USBPort *port = dev->port;
+
+    assert(port != NULL);
+    assert(!dev->attached);
+    trace_usb_port_attach(bus->busnr, port->path);
+
+    if (!(port->speedmask & dev->speedmask)) {
+        error_report("Warning: speed mismatch trying to attach "
+                     "usb device %s to bus %s",
+                     dev->product_desc, bus->qbus.name);
+        return -1;
+    }
+
+    dev->attached++;
+    usb_attach(port);
+
+    return 0;
+}
+
+int usb_device_detach(USBDevice *dev)
+{
+    USBBus *bus = usb_bus_from_device(dev);
+    USBPort *port = dev->port;
+
+    assert(port != NULL);
+    assert(dev->attached);
+    trace_usb_port_detach(bus->busnr, port->path);
+
+    usb_detach(port);
+    dev->attached--;
+    return 0;
+}
+
+int usb_device_delete_addr(int busnr, int addr)
+{
+    USBBus *bus;
+    USBPort *port;
+    USBDevice *dev;
+
+    bus = usb_bus_find(busnr);
+    if (!bus)
+        return -1;
+
+    QTAILQ_FOREACH(port, &bus->used, next) {
+        if (port->dev->addr == addr)
+            break;
+    }
+    if (!port)
+        return -1;
+    dev = port->dev;
+
+    qdev_free(&dev->qdev);
+    return 0;
+}
+
+static const char *usb_speed(unsigned int speed)
+{
+    static const char *txt[] = {
+        [ USB_SPEED_LOW  ] = "1.5",
+        [ USB_SPEED_FULL ] = "12",
+        [ USB_SPEED_HIGH ] = "480",
+        [ USB_SPEED_SUPER ] = "5000",
+    };
+    if (speed >= ARRAY_SIZE(txt))
+        return "?";
+    return txt[speed];
+}
+
+static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
+{
+    USBDevice *dev = USB_DEVICE(qdev);
+    USBBus *bus = usb_bus_from_device(dev);
+
+    monitor_printf(mon, "%*saddr %d.%d, port %s, speed %s, name %s%s\n",
+                   indent, "", bus->busnr, dev->addr,
+                   dev->port ? dev->port->path : "-",
+                   usb_speed(dev->speed), dev->product_desc,
+                   dev->attached ? ", attached" : "");
+}
+
+static char *usb_get_dev_path(DeviceState *qdev)
+{
+    USBDevice *dev = USB_DEVICE(qdev);
+    return g_strdup(dev->port->path);
+}
+
+static char *usb_get_fw_dev_path(DeviceState *qdev)
+{
+    USBDevice *dev = USB_DEVICE(qdev);
+    char *fw_path, *in;
+    ssize_t pos = 0, fw_len;
+    long nr;
+
+    fw_len = 32 + strlen(dev->port->path) * 6;
+    fw_path = g_malloc(fw_len);
+    in = dev->port->path;
+    while (fw_len - pos > 0) {
+        nr = strtol(in, &in, 10);
+        if (in[0] == '.') {
+            /* some hub between root port and device */
+            pos += snprintf(fw_path + pos, fw_len - pos, "hub@%ld/", nr);
+            in++;
+        } else {
+            /* the device itself */
+            pos += snprintf(fw_path + pos, fw_len - pos, "%s@%ld",
+                            qdev_fw_name(qdev), nr);
+            break;
+        }
+    }
+    return fw_path;
+}
+
+void usb_info(Monitor *mon)
+{
+    USBBus *bus;
+    USBDevice *dev;
+    USBPort *port;
+
+    if (QTAILQ_EMPTY(&busses)) {
+        monitor_printf(mon, "USB support not enabled\n");
+        return;
+    }
+
+    QTAILQ_FOREACH(bus, &busses, next) {
+        QTAILQ_FOREACH(port, &bus->used, next) {
+            dev = port->dev;
+            if (!dev)
+                continue;
+            monitor_printf(mon, "  Device %d.%d, Port %s, Speed %s Mb/s, Product %s\n",
+                           bus->busnr, dev->addr, port->path, usb_speed(dev->speed),
+                           dev->product_desc);
+        }
+    }
+}
+
+/* handle legacy -usbdevice cmd line option */
+USBDevice *usbdevice_create(const char *cmdline)
+{
+    USBBus *bus = usb_bus_find(-1 /* any */);
+    LegacyUSBFactory *f = NULL;
+    GSList *i;
+    char driver[32];
+    const char *params;
+    int len;
+
+    params = strchr(cmdline,':');
+    if (params) {
+        params++;
+        len = params - cmdline;
+        if (len > sizeof(driver))
+            len = sizeof(driver);
+        pstrcpy(driver, len, cmdline);
+    } else {
+        params = "";
+        pstrcpy(driver, sizeof(driver), cmdline);
+    }
+
+    for (i = legacy_usb_factory; i; i = i->next) {
+        f = i->data;
+        if (strcmp(f->usbdevice_name, driver) == 0) {
+            break;
+        }
+    }
+    if (i == NULL) {
+#if 0
+        /* no error because some drivers are not converted (yet) */
+        error_report("usbdevice %s not found", driver);
+#endif
+        return NULL;
+    }
+
+    if (!f->usbdevice_init) {
+        if (*params) {
+            error_report("usbdevice %s accepts no params", driver);
+            return NULL;
+        }
+        return usb_create_simple(bus, f->name);
+    }
+    return f->usbdevice_init(bus, params);
+}
+
+static void usb_device_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *k = DEVICE_CLASS(klass);
+    k->bus_info = &usb_bus_info;
+    k->init     = usb_qdev_init;
+    k->unplug   = qdev_simple_unplug_cb;
+    k->exit     = usb_qdev_exit;
+}
+
+static TypeInfo usb_device_type_info = {
+    .name = TYPE_USB_DEVICE,
+    .parent = TYPE_DEVICE,
+    .instance_size = sizeof(USBDevice),
+    .abstract = true,
+    .class_size = sizeof(USBDeviceClass),
+    .class_init = usb_device_class_init,
+};
+
+static void usb_register_types(void)
+{
+    type_register_static(&usb_device_type_info);
+}
+
+type_init(usb_register_types)
diff --git a/hw/usb/core.c b/hw/usb/core.c
new file mode 100644
index 0000000..494989a
--- /dev/null
+++ b/hw/usb/core.c
@@ -0,0 +1,663 @@
+/*
+ * QEMU USB emulation
+ *
+ * Copyright (c) 2005 Fabrice Bellard
+ *
+ * 2008 Generic packet handler rewrite by Max Krasnyansky
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu-common.h"
+#include "hw/usb.h"
+#include "iov.h"
+#include "trace.h"
+
+void usb_attach(USBPort *port)
+{
+    USBDevice *dev = port->dev;
+
+    assert(dev != NULL);
+    assert(dev->attached);
+    assert(dev->state == USB_STATE_NOTATTACHED);
+    port->ops->attach(port);
+    dev->state = USB_STATE_ATTACHED;
+    usb_device_handle_attach(dev);
+}
+
+void usb_detach(USBPort *port)
+{
+    USBDevice *dev = port->dev;
+
+    assert(dev != NULL);
+    assert(dev->state != USB_STATE_NOTATTACHED);
+    port->ops->detach(port);
+    dev->state = USB_STATE_NOTATTACHED;
+}
+
+void usb_port_reset(USBPort *port)
+{
+    USBDevice *dev = port->dev;
+
+    assert(dev != NULL);
+    usb_detach(port);
+    usb_attach(port);
+    usb_device_reset(dev);
+}
+
+void usb_device_reset(USBDevice *dev)
+{
+    if (dev == NULL || !dev->attached) {
+        return;
+    }
+    dev->remote_wakeup = 0;
+    dev->addr = 0;
+    dev->state = USB_STATE_DEFAULT;
+    usb_device_handle_reset(dev);
+}
+
+void usb_wakeup(USBEndpoint *ep)
+{
+    USBDevice *dev = ep->dev;
+    USBBus *bus = usb_bus_from_device(dev);
+
+    if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) {
+        dev->port->ops->wakeup(dev->port);
+    }
+    if (bus->ops->wakeup_endpoint) {
+        bus->ops->wakeup_endpoint(bus, ep);
+    }
+}
+
+/**********************/
+
+/* generic USB device helpers (you are not forced to use them when
+   writing your USB device driver, but they help handling the
+   protocol)
+*/
+
+#define SETUP_STATE_IDLE  0
+#define SETUP_STATE_SETUP 1
+#define SETUP_STATE_DATA  2
+#define SETUP_STATE_ACK   3
+#define SETUP_STATE_PARAM 4
+
+static int do_token_setup(USBDevice *s, USBPacket *p)
+{
+    int request, value, index;
+    int ret = 0;
+
+    if (p->iov.size != 8) {
+        return USB_RET_STALL;
+    }
+
+    usb_packet_copy(p, s->setup_buf, p->iov.size);
+    s->setup_len   = (s->setup_buf[7] << 8) | s->setup_buf[6];
+    s->setup_index = 0;
+
+    request = (s->setup_buf[0] << 8) | s->setup_buf[1];
+    value   = (s->setup_buf[3] << 8) | s->setup_buf[2];
+    index   = (s->setup_buf[5] << 8) | s->setup_buf[4];
+
+    if (s->setup_buf[0] & USB_DIR_IN) {
+        ret = usb_device_handle_control(s, p, request, value, index,
+                                        s->setup_len, s->data_buf);
+        if (ret == USB_RET_ASYNC) {
+             s->setup_state = SETUP_STATE_SETUP;
+             return USB_RET_ASYNC;
+        }
+        if (ret < 0)
+            return ret;
+
+        if (ret < s->setup_len)
+            s->setup_len = ret;
+        s->setup_state = SETUP_STATE_DATA;
+    } else {
+        if (s->setup_len > sizeof(s->data_buf)) {
+            fprintf(stderr,
+                "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
+                s->setup_len, sizeof(s->data_buf));
+            return USB_RET_STALL;
+        }
+        if (s->setup_len == 0)
+            s->setup_state = SETUP_STATE_ACK;
+        else
+            s->setup_state = SETUP_STATE_DATA;
+    }
+
+    return ret;
+}
+
+static int do_token_in(USBDevice *s, USBPacket *p)
+{
+    int request, value, index;
+    int ret = 0;
+
+    assert(p->ep->nr == 0);
+
+    request = (s->setup_buf[0] << 8) | s->setup_buf[1];
+    value   = (s->setup_buf[3] << 8) | s->setup_buf[2];
+    index   = (s->setup_buf[5] << 8) | s->setup_buf[4];
+ 
+    switch(s->setup_state) {
+    case SETUP_STATE_ACK:
+        if (!(s->setup_buf[0] & USB_DIR_IN)) {
+            ret = usb_device_handle_control(s, p, request, value, index,
+                                            s->setup_len, s->data_buf);
+            if (ret == USB_RET_ASYNC) {
+                return USB_RET_ASYNC;
+            }
+            s->setup_state = SETUP_STATE_IDLE;
+            if (ret > 0)
+                return 0;
+            return ret;
+        }
+
+        /* return 0 byte */
+        return 0;
+
+    case SETUP_STATE_DATA:
+        if (s->setup_buf[0] & USB_DIR_IN) {
+            int len = s->setup_len - s->setup_index;
+            if (len > p->iov.size) {
+                len = p->iov.size;
+            }
+            usb_packet_copy(p, s->data_buf + s->setup_index, len);
+            s->setup_index += len;
+            if (s->setup_index >= s->setup_len)
+                s->setup_state = SETUP_STATE_ACK;
+            return len;
+        }
+
+        s->setup_state = SETUP_STATE_IDLE;
+        return USB_RET_STALL;
+
+    default:
+        return USB_RET_STALL;
+    }
+}
+
+static int do_token_out(USBDevice *s, USBPacket *p)
+{
+    assert(p->ep->nr == 0);
+
+    switch(s->setup_state) {
+    case SETUP_STATE_ACK:
+        if (s->setup_buf[0] & USB_DIR_IN) {
+            s->setup_state = SETUP_STATE_IDLE;
+            /* transfer OK */
+        } else {
+            /* ignore additional output */
+        }
+        return 0;
+
+    case SETUP_STATE_DATA:
+        if (!(s->setup_buf[0] & USB_DIR_IN)) {
+            int len = s->setup_len - s->setup_index;
+            if (len > p->iov.size) {
+                len = p->iov.size;
+            }
+            usb_packet_copy(p, s->data_buf + s->setup_index, len);
+            s->setup_index += len;
+            if (s->setup_index >= s->setup_len)
+                s->setup_state = SETUP_STATE_ACK;
+            return len;
+        }
+
+        s->setup_state = SETUP_STATE_IDLE;
+        return USB_RET_STALL;
+
+    default:
+        return USB_RET_STALL;
+    }
+}
+
+static int do_parameter(USBDevice *s, USBPacket *p)
+{
+    int request, value, index;
+    int i, ret = 0;
+
+    for (i = 0; i < 8; i++) {
+        s->setup_buf[i] = p->parameter >> (i*8);
+    }
+
+    s->setup_state = SETUP_STATE_PARAM;
+    s->setup_len   = (s->setup_buf[7] << 8) | s->setup_buf[6];
+    s->setup_index = 0;
+
+    request = (s->setup_buf[0] << 8) | s->setup_buf[1];
+    value   = (s->setup_buf[3] << 8) | s->setup_buf[2];
+    index   = (s->setup_buf[5] << 8) | s->setup_buf[4];
+
+    if (s->setup_len > sizeof(s->data_buf)) {
+        fprintf(stderr,
+                "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
+                s->setup_len, sizeof(s->data_buf));
+        return USB_RET_STALL;
+    }
+
+    if (p->pid == USB_TOKEN_OUT) {
+        usb_packet_copy(p, s->data_buf, s->setup_len);
+    }
+
+    ret = usb_device_handle_control(s, p, request, value, index,
+                                    s->setup_len, s->data_buf);
+    if (ret < 0) {
+        return ret;
+    }
+
+    if (ret < s->setup_len) {
+        s->setup_len = ret;
+    }
+    if (p->pid == USB_TOKEN_IN) {
+        usb_packet_copy(p, s->data_buf, s->setup_len);
+    }
+
+    return ret;
+}
+
+/* ctrl complete function for devices which use usb_generic_handle_packet and
+   may return USB_RET_ASYNC from their handle_control callback. Device code
+   which does this *must* call this function instead of the normal
+   usb_packet_complete to complete their async control packets. */
+void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p)
+{
+    if (p->result < 0) {
+        s->setup_state = SETUP_STATE_IDLE;
+    }
+
+    switch (s->setup_state) {
+    case SETUP_STATE_SETUP:
+        if (p->result < s->setup_len) {
+            s->setup_len = p->result;
+        }
+        s->setup_state = SETUP_STATE_DATA;
+        p->result = 8;
+        break;
+
+    case SETUP_STATE_ACK:
+        s->setup_state = SETUP_STATE_IDLE;
+        p->result = 0;
+        break;
+
+    case SETUP_STATE_PARAM:
+        if (p->result < s->setup_len) {
+            s->setup_len = p->result;
+        }
+        if (p->pid == USB_TOKEN_IN) {
+            p->result = 0;
+            usb_packet_copy(p, s->data_buf, s->setup_len);
+        }
+        break;
+
+    default:
+        break;
+    }
+    usb_packet_complete(s, p);
+}
+
+/* XXX: fix overflow */
+int set_usb_string(uint8_t *buf, const char *str)
+{
+    int len, i;
+    uint8_t *q;
+
+    q = buf;
+    len = strlen(str);
+    *q++ = 2 * len + 2;
+    *q++ = 3;
+    for(i = 0; i < len; i++) {
+        *q++ = str[i];
+        *q++ = 0;
+    }
+    return q - buf;
+}
+
+USBDevice *usb_find_device(USBPort *port, uint8_t addr)
+{
+    USBDevice *dev = port->dev;
+
+    if (dev == NULL || !dev->attached || dev->state != USB_STATE_DEFAULT) {
+        return NULL;
+    }
+    if (dev->addr == addr) {
+        return dev;
+    }
+    return usb_device_find_device(dev, addr);
+}
+
+static int usb_process_one(USBPacket *p)
+{
+    USBDevice *dev = p->ep->dev;
+
+    if (p->ep->nr == 0) {
+        /* control pipe */
+        if (p->parameter) {
+            return do_parameter(dev, p);
+        }
+        switch (p->pid) {
+        case USB_TOKEN_SETUP:
+            return do_token_setup(dev, p);
+        case USB_TOKEN_IN:
+            return do_token_in(dev, p);
+        case USB_TOKEN_OUT:
+            return do_token_out(dev, p);
+        default:
+            return USB_RET_STALL;
+        }
+    } else {
+        /* data pipe */
+        return usb_device_handle_data(dev, p);
+    }
+}
+
+/* Hand over a packet to a device for processing.  Return value
+   USB_RET_ASYNC indicates the processing isn't finished yet, the
+   driver will call usb_packet_complete() when done processing it. */
+int usb_handle_packet(USBDevice *dev, USBPacket *p)
+{
+    int ret;
+
+    if (dev == NULL) {
+        return USB_RET_NODEV;
+    }
+    assert(dev == p->ep->dev);
+    assert(dev->state == USB_STATE_DEFAULT);
+    assert(p->state == USB_PACKET_SETUP);
+    assert(p->ep != NULL);
+
+    if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline) {
+        ret = usb_process_one(p);
+        if (ret == USB_RET_ASYNC) {
+            usb_packet_set_state(p, USB_PACKET_ASYNC);
+            QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
+        } else {
+            p->result = ret;
+            usb_packet_set_state(p, USB_PACKET_COMPLETE);
+        }
+    } else {
+        ret = USB_RET_ASYNC;
+        usb_packet_set_state(p, USB_PACKET_QUEUED);
+        QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
+    }
+    return ret;
+}
+
+/* Notify the controller that an async packet is complete.  This should only
+   be called for packets previously deferred by returning USB_RET_ASYNC from
+   handle_packet. */
+void usb_packet_complete(USBDevice *dev, USBPacket *p)
+{
+    USBEndpoint *ep = p->ep;
+    int ret;
+
+    assert(p->state == USB_PACKET_ASYNC);
+    assert(QTAILQ_FIRST(&ep->queue) == p);
+    usb_packet_set_state(p, USB_PACKET_COMPLETE);
+    QTAILQ_REMOVE(&ep->queue, p, queue);
+    dev->port->ops->complete(dev->port, p);
+
+    while (!QTAILQ_EMPTY(&ep->queue)) {
+        p = QTAILQ_FIRST(&ep->queue);
+        if (p->state == USB_PACKET_ASYNC) {
+            break;
+        }
+        assert(p->state == USB_PACKET_QUEUED);
+        ret = usb_process_one(p);
+        if (ret == USB_RET_ASYNC) {
+            usb_packet_set_state(p, USB_PACKET_ASYNC);
+            break;
+        }
+        p->result = ret;
+        usb_packet_set_state(p, USB_PACKET_COMPLETE);
+        QTAILQ_REMOVE(&ep->queue, p, queue);
+        dev->port->ops->complete(dev->port, p);
+    }
+}
+
+/* Cancel an active packet.  The packed must have been deferred by
+   returning USB_RET_ASYNC from handle_packet, and not yet
+   completed.  */
+void usb_cancel_packet(USBPacket * p)
+{
+    bool callback = (p->state == USB_PACKET_ASYNC);
+    assert(usb_packet_is_inflight(p));
+    usb_packet_set_state(p, USB_PACKET_CANCELED);
+    QTAILQ_REMOVE(&p->ep->queue, p, queue);
+    if (callback) {
+        usb_device_cancel_packet(p->ep->dev, p);
+    }
+}
+
+
+void usb_packet_init(USBPacket *p)
+{
+    qemu_iovec_init(&p->iov, 1);
+}
+
+void usb_packet_set_state(USBPacket *p, USBPacketState state)
+{
+    static const char *name[] = {
+        [USB_PACKET_UNDEFINED] = "undef",
+        [USB_PACKET_SETUP]     = "setup",
+        [USB_PACKET_QUEUED]    = "queued",
+        [USB_PACKET_ASYNC]     = "async",
+        [USB_PACKET_COMPLETE]  = "complete",
+        [USB_PACKET_CANCELED]  = "canceled",
+    };
+    USBDevice *dev = p->ep->dev;
+    USBBus *bus = usb_bus_from_device(dev);
+
+    trace_usb_packet_state_change(bus->busnr, dev->port->path, p->ep->nr,
+                                  p, name[p->state], name[state]);
+    p->state = state;
+}
+
+void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep)
+{
+    assert(!usb_packet_is_inflight(p));
+    p->pid = pid;
+    p->ep = ep;
+    p->result = 0;
+    p->parameter = 0;
+    qemu_iovec_reset(&p->iov);
+    usb_packet_set_state(p, USB_PACKET_SETUP);
+}
+
+void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len)
+{
+    qemu_iovec_add(&p->iov, ptr, len);
+}
+
+void usb_packet_copy(USBPacket *p, void *ptr, size_t bytes)
+{
+    assert(p->result >= 0);
+    assert(p->result + bytes <= p->iov.size);
+    switch (p->pid) {
+    case USB_TOKEN_SETUP:
+    case USB_TOKEN_OUT:
+        iov_to_buf(p->iov.iov, p->iov.niov, ptr, p->result, bytes);
+        break;
+    case USB_TOKEN_IN:
+        iov_from_buf(p->iov.iov, p->iov.niov, ptr, p->result, bytes);
+        break;
+    default:
+        fprintf(stderr, "%s: invalid pid: %x\n", __func__, p->pid);
+        abort();
+    }
+    p->result += bytes;
+}
+
+void usb_packet_skip(USBPacket *p, size_t bytes)
+{
+    assert(p->result >= 0);
+    assert(p->result + bytes <= p->iov.size);
+    if (p->pid == USB_TOKEN_IN) {
+        iov_clear(p->iov.iov, p->iov.niov, p->result, bytes);
+    }
+    p->result += bytes;
+}
+
+void usb_packet_cleanup(USBPacket *p)
+{
+    assert(!usb_packet_is_inflight(p));
+    qemu_iovec_destroy(&p->iov);
+}
+
+void usb_ep_init(USBDevice *dev)
+{
+    int ep;
+
+    dev->ep_ctl.nr = 0;
+    dev->ep_ctl.type = USB_ENDPOINT_XFER_CONTROL;
+    dev->ep_ctl.ifnum = 0;
+    dev->ep_ctl.dev = dev;
+    dev->ep_ctl.pipeline = false;
+    QTAILQ_INIT(&dev->ep_ctl.queue);
+    for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
+        dev->ep_in[ep].nr = ep + 1;
+        dev->ep_out[ep].nr = ep + 1;
+        dev->ep_in[ep].pid = USB_TOKEN_IN;
+        dev->ep_out[ep].pid = USB_TOKEN_OUT;
+        dev->ep_in[ep].type = USB_ENDPOINT_XFER_INVALID;
+        dev->ep_out[ep].type = USB_ENDPOINT_XFER_INVALID;
+        dev->ep_in[ep].ifnum = 0;
+        dev->ep_out[ep].ifnum = 0;
+        dev->ep_in[ep].dev = dev;
+        dev->ep_out[ep].dev = dev;
+        dev->ep_in[ep].pipeline = false;
+        dev->ep_out[ep].pipeline = false;
+        QTAILQ_INIT(&dev->ep_in[ep].queue);
+        QTAILQ_INIT(&dev->ep_out[ep].queue);
+    }
+}
+
+void usb_ep_dump(USBDevice *dev)
+{
+    static const char *tname[] = {
+        [USB_ENDPOINT_XFER_CONTROL] = "control",
+        [USB_ENDPOINT_XFER_ISOC]    = "isoc",
+        [USB_ENDPOINT_XFER_BULK]    = "bulk",
+        [USB_ENDPOINT_XFER_INT]     = "int",
+    };
+    int ifnum, ep, first;
+
+    fprintf(stderr, "Device \"%s\", config %d\n",
+            dev->product_desc, dev->configuration);
+    for (ifnum = 0; ifnum < 16; ifnum++) {
+        first = 1;
+        for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
+            if (dev->ep_in[ep].type != USB_ENDPOINT_XFER_INVALID &&
+                dev->ep_in[ep].ifnum == ifnum) {
+                if (first) {
+                    first = 0;
+                    fprintf(stderr, "  Interface %d, alternative %d\n",
+                            ifnum, dev->altsetting[ifnum]);
+                }
+                fprintf(stderr, "    Endpoint %d, IN, %s, %d max\n", ep,
+                        tname[dev->ep_in[ep].type],
+                        dev->ep_in[ep].max_packet_size);
+            }
+            if (dev->ep_out[ep].type != USB_ENDPOINT_XFER_INVALID &&
+                dev->ep_out[ep].ifnum == ifnum) {
+                if (first) {
+                    first = 0;
+                    fprintf(stderr, "  Interface %d, alternative %d\n",
+                            ifnum, dev->altsetting[ifnum]);
+                }
+                fprintf(stderr, "    Endpoint %d, OUT, %s, %d max\n", ep,
+                        tname[dev->ep_out[ep].type],
+                        dev->ep_out[ep].max_packet_size);
+            }
+        }
+    }
+    fprintf(stderr, "--\n");
+}
+
+struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep)
+{
+    struct USBEndpoint *eps;
+
+    if (dev == NULL) {
+        return NULL;
+    }
+    eps = (pid == USB_TOKEN_IN) ? dev->ep_in : dev->ep_out;
+    if (ep == 0) {
+        return &dev->ep_ctl;
+    }
+    assert(pid == USB_TOKEN_IN || pid == USB_TOKEN_OUT);
+    assert(ep > 0 && ep <= USB_MAX_ENDPOINTS);
+    return eps + ep - 1;
+}
+
+uint8_t usb_ep_get_type(USBDevice *dev, int pid, int ep)
+{
+    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+    return uep->type;
+}
+
+void usb_ep_set_type(USBDevice *dev, int pid, int ep, uint8_t type)
+{
+    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+    uep->type = type;
+}
+
+uint8_t usb_ep_get_ifnum(USBDevice *dev, int pid, int ep)
+{
+    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+    return uep->ifnum;
+}
+
+void usb_ep_set_ifnum(USBDevice *dev, int pid, int ep, uint8_t ifnum)
+{
+    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+    uep->ifnum = ifnum;
+}
+
+void usb_ep_set_max_packet_size(USBDevice *dev, int pid, int ep,
+                                uint16_t raw)
+{
+    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+    int size, microframes;
+
+    size = raw & 0x7ff;
+    switch ((raw >> 11) & 3) {
+    case 1:
+        microframes = 2;
+        break;
+    case 2:
+        microframes = 3;
+        break;
+    default:
+        microframes = 1;
+        break;
+    }
+    uep->max_packet_size = size * microframes;
+}
+
+int usb_ep_get_max_packet_size(USBDevice *dev, int pid, int ep)
+{
+    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+    return uep->max_packet_size;
+}
+
+void usb_ep_set_pipeline(USBDevice *dev, int pid, int ep, bool enabled)
+{
+    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+    uep->pipeline = enabled;
+}
diff --git a/hw/usb/desc.c b/hw/usb/desc.c
new file mode 100644
index 0000000..9847a75
--- /dev/null
+++ b/hw/usb/desc.c
@@ -0,0 +1,601 @@
+#include "hw/usb.h"
+#include "hw/usb/desc.h"
+#include "trace.h"
+
+/* ------------------------------------------------------------------ */
+
+static uint8_t usb_lo(uint16_t val)
+{
+    return val & 0xff;
+}
+
+static uint8_t usb_hi(uint16_t val)
+{
+    return (val >> 8) & 0xff;
+}
+
+int usb_desc_device(const USBDescID *id, const USBDescDevice *dev,
+                    uint8_t *dest, size_t len)
+{
+    uint8_t bLength = 0x12;
+
+    if (len < bLength) {
+        return -1;
+    }
+
+    dest[0x00] = bLength;
+    dest[0x01] = USB_DT_DEVICE;
+
+    dest[0x02] = usb_lo(dev->bcdUSB);
+    dest[0x03] = usb_hi(dev->bcdUSB);
+    dest[0x04] = dev->bDeviceClass;
+    dest[0x05] = dev->bDeviceSubClass;
+    dest[0x06] = dev->bDeviceProtocol;
+    dest[0x07] = dev->bMaxPacketSize0;
+
+    dest[0x08] = usb_lo(id->idVendor);
+    dest[0x09] = usb_hi(id->idVendor);
+    dest[0x0a] = usb_lo(id->idProduct);
+    dest[0x0b] = usb_hi(id->idProduct);
+    dest[0x0c] = usb_lo(id->bcdDevice);
+    dest[0x0d] = usb_hi(id->bcdDevice);
+    dest[0x0e] = id->iManufacturer;
+    dest[0x0f] = id->iProduct;
+    dest[0x10] = id->iSerialNumber;
+
+    dest[0x11] = dev->bNumConfigurations;
+
+    return bLength;
+}
+
+int usb_desc_device_qualifier(const USBDescDevice *dev,
+                              uint8_t *dest, size_t len)
+{
+    uint8_t bLength = 0x0a;
+
+    if (len < bLength) {
+        return -1;
+    }
+
+    dest[0x00] = bLength;
+    dest[0x01] = USB_DT_DEVICE_QUALIFIER;
+
+    dest[0x02] = usb_lo(dev->bcdUSB);
+    dest[0x03] = usb_hi(dev->bcdUSB);
+    dest[0x04] = dev->bDeviceClass;
+    dest[0x05] = dev->bDeviceSubClass;
+    dest[0x06] = dev->bDeviceProtocol;
+    dest[0x07] = dev->bMaxPacketSize0;
+    dest[0x08] = dev->bNumConfigurations;
+    dest[0x09] = 0; /* reserved */
+
+    return bLength;
+}
+
+int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len)
+{
+    uint8_t  bLength = 0x09;
+    uint16_t wTotalLength = 0;
+    int i, rc;
+
+    if (len < bLength) {
+        return -1;
+    }
+
+    dest[0x00] = bLength;
+    dest[0x01] = USB_DT_CONFIG;
+    dest[0x04] = conf->bNumInterfaces;
+    dest[0x05] = conf->bConfigurationValue;
+    dest[0x06] = conf->iConfiguration;
+    dest[0x07] = conf->bmAttributes;
+    dest[0x08] = conf->bMaxPower;
+    wTotalLength += bLength;
+
+    /* handle grouped interfaces if any*/
+    for (i = 0; i < conf->nif_groups; i++) {
+        rc = usb_desc_iface_group(&(conf->if_groups[i]),
+                                  dest + wTotalLength,
+                                  len - wTotalLength);
+        if (rc < 0) {
+            return rc;
+        }
+        wTotalLength += rc;
+    }
+
+    /* handle normal (ungrouped / no IAD) interfaces if any */
+    for (i = 0; i < conf->nif; i++) {
+        rc = usb_desc_iface(conf->ifs + i, dest + wTotalLength, len - wTotalLength);
+        if (rc < 0) {
+            return rc;
+        }
+        wTotalLength += rc;
+    }
+
+    dest[0x02] = usb_lo(wTotalLength);
+    dest[0x03] = usb_hi(wTotalLength);
+    return wTotalLength;
+}
+
+int usb_desc_iface_group(const USBDescIfaceAssoc *iad, uint8_t *dest,
+                         size_t len)
+{
+    int pos = 0;
+    int i = 0;
+
+    /* handle interface association descriptor */
+    uint8_t bLength = 0x08;
+
+    if (len < bLength) {
+        return -1;
+    }
+
+    dest[0x00] = bLength;
+    dest[0x01] = USB_DT_INTERFACE_ASSOC;
+    dest[0x02] = iad->bFirstInterface;
+    dest[0x03] = iad->bInterfaceCount;
+    dest[0x04] = iad->bFunctionClass;
+    dest[0x05] = iad->bFunctionSubClass;
+    dest[0x06] = iad->bFunctionProtocol;
+    dest[0x07] = iad->iFunction;
+    pos += bLength;
+
+    /* handle associated interfaces in this group */
+    for (i = 0; i < iad->nif; i++) {
+        int rc = usb_desc_iface(&(iad->ifs[i]), dest + pos, len - pos);
+        if (rc < 0) {
+            return rc;
+        }
+        pos += rc;
+    }
+
+    return pos;
+}
+
+int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len)
+{
+    uint8_t bLength = 0x09;
+    int i, rc, pos = 0;
+
+    if (len < bLength) {
+        return -1;
+    }
+
+    dest[0x00] = bLength;
+    dest[0x01] = USB_DT_INTERFACE;
+    dest[0x02] = iface->bInterfaceNumber;
+    dest[0x03] = iface->bAlternateSetting;
+    dest[0x04] = iface->bNumEndpoints;
+    dest[0x05] = iface->bInterfaceClass;
+    dest[0x06] = iface->bInterfaceSubClass;
+    dest[0x07] = iface->bInterfaceProtocol;
+    dest[0x08] = iface->iInterface;
+    pos += bLength;
+
+    for (i = 0; i < iface->ndesc; i++) {
+        rc = usb_desc_other(iface->descs + i, dest + pos, len - pos);
+        if (rc < 0) {
+            return rc;
+        }
+        pos += rc;
+    }
+
+    for (i = 0; i < iface->bNumEndpoints; i++) {
+        rc = usb_desc_endpoint(iface->eps + i, dest + pos, len - pos);
+        if (rc < 0) {
+            return rc;
+        }
+        pos += rc;
+    }
+
+    return pos;
+}
+
+int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len)
+{
+    uint8_t bLength = ep->is_audio ? 0x09 : 0x07;
+    uint8_t extralen = ep->extra ? ep->extra[0] : 0;
+
+    if (len < bLength + extralen) {
+        return -1;
+    }
+
+    dest[0x00] = bLength;
+    dest[0x01] = USB_DT_ENDPOINT;
+    dest[0x02] = ep->bEndpointAddress;
+    dest[0x03] = ep->bmAttributes;
+    dest[0x04] = usb_lo(ep->wMaxPacketSize);
+    dest[0x05] = usb_hi(ep->wMaxPacketSize);
+    dest[0x06] = ep->bInterval;
+    if (ep->is_audio) {
+        dest[0x07] = ep->bRefresh;
+        dest[0x08] = ep->bSynchAddress;
+    }
+    if (ep->extra) {
+        memcpy(dest + bLength, ep->extra, extralen);
+    }
+
+    return bLength + extralen;
+}
+
+int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
+{
+    int bLength = desc->length ? desc->length : desc->data[0];
+
+    if (len < bLength) {
+        return -1;
+    }
+
+    memcpy(dest, desc->data, bLength);
+    return bLength;
+}
+
+/* ------------------------------------------------------------------ */
+
+static void usb_desc_ep_init(USBDevice *dev)
+{
+    const USBDescIface *iface;
+    int i, e, pid, ep;
+
+    usb_ep_init(dev);
+    for (i = 0; i < dev->ninterfaces; i++) {
+        iface = dev->ifaces[i];
+        if (iface == NULL) {
+            continue;
+        }
+        for (e = 0; e < iface->bNumEndpoints; e++) {
+            pid = (iface->eps[e].bEndpointAddress & USB_DIR_IN) ?
+                USB_TOKEN_IN : USB_TOKEN_OUT;
+            ep = iface->eps[e].bEndpointAddress & 0x0f;
+            usb_ep_set_type(dev, pid, ep, iface->eps[e].bmAttributes & 0x03);
+            usb_ep_set_ifnum(dev, pid, ep, iface->bInterfaceNumber);
+            usb_ep_set_max_packet_size(dev, pid, ep,
+                                       iface->eps[e].wMaxPacketSize);
+        }
+    }
+}
+
+static const USBDescIface *usb_desc_find_interface(USBDevice *dev,
+                                                   int nif, int alt)
+{
+    const USBDescIface *iface;
+    int g, i;
+
+    if (!dev->config) {
+        return NULL;
+    }
+    for (g = 0; g < dev->config->nif_groups; g++) {
+        for (i = 0; i < dev->config->if_groups[g].nif; i++) {
+            iface = &dev->config->if_groups[g].ifs[i];
+            if (iface->bInterfaceNumber == nif &&
+                iface->bAlternateSetting == alt) {
+                return iface;
+            }
+        }
+    }
+    for (i = 0; i < dev->config->nif; i++) {
+        iface = &dev->config->ifs[i];
+        if (iface->bInterfaceNumber == nif &&
+            iface->bAlternateSetting == alt) {
+            return iface;
+        }
+    }
+    return NULL;
+}
+
+static int usb_desc_set_interface(USBDevice *dev, int index, int value)
+{
+    const USBDescIface *iface;
+    int old;
+
+    iface = usb_desc_find_interface(dev, index, value);
+    if (iface == NULL) {
+        return -1;
+    }
+
+    old = dev->altsetting[index];
+    dev->altsetting[index] = value;
+    dev->ifaces[index] = iface;
+    usb_desc_ep_init(dev);
+
+    if (old != value) {
+        usb_device_set_interface(dev, index, old, value);
+    }
+    return 0;
+}
+
+static int usb_desc_set_config(USBDevice *dev, int value)
+{
+    int i;
+
+    if (value == 0) {
+        dev->configuration = 0;
+        dev->ninterfaces   = 0;
+        dev->config = NULL;
+    } else {
+        for (i = 0; i < dev->device->bNumConfigurations; i++) {
+            if (dev->device->confs[i].bConfigurationValue == value) {
+                dev->configuration = value;
+                dev->ninterfaces   = dev->device->confs[i].bNumInterfaces;
+                dev->config = dev->device->confs + i;
+                assert(dev->ninterfaces <= USB_MAX_INTERFACES);
+            }
+        }
+        if (i < dev->device->bNumConfigurations) {
+            return -1;
+        }
+    }
+
+    for (i = 0; i < dev->ninterfaces; i++) {
+        usb_desc_set_interface(dev, i, 0);
+    }
+    for (; i < USB_MAX_INTERFACES; i++) {
+        dev->altsetting[i] = 0;
+        dev->ifaces[i] = NULL;
+    }
+
+    return 0;
+}
+
+static void usb_desc_setdefaults(USBDevice *dev)
+{
+    const USBDesc *desc = usb_device_get_usb_desc(dev);
+
+    assert(desc != NULL);
+    switch (dev->speed) {
+    case USB_SPEED_LOW:
+    case USB_SPEED_FULL:
+        dev->device = desc->full;
+        break;
+    case USB_SPEED_HIGH:
+        dev->device = desc->high;
+        break;
+    }
+    usb_desc_set_config(dev, 0);
+}
+
+void usb_desc_init(USBDevice *dev)
+{
+    const USBDesc *desc = usb_device_get_usb_desc(dev);
+
+    assert(desc != NULL);
+    dev->speed = USB_SPEED_FULL;
+    dev->speedmask = 0;
+    if (desc->full) {
+        dev->speedmask |= USB_SPEED_MASK_FULL;
+    }
+    if (desc->high) {
+        dev->speedmask |= USB_SPEED_MASK_HIGH;
+    }
+    usb_desc_setdefaults(dev);
+}
+
+void usb_desc_attach(USBDevice *dev)
+{
+    const USBDesc *desc = usb_device_get_usb_desc(dev);
+
+    assert(desc != NULL);
+    if (desc->high && (dev->port->speedmask & USB_SPEED_MASK_HIGH)) {
+        dev->speed = USB_SPEED_HIGH;
+    } else if (desc->full && (dev->port->speedmask & USB_SPEED_MASK_FULL)) {
+        dev->speed = USB_SPEED_FULL;
+    } else {
+        fprintf(stderr, "usb: port/device speed mismatch for \"%s\"\n",
+                usb_device_get_product_desc(dev));
+        return;
+    }
+    usb_desc_setdefaults(dev);
+}
+
+void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str)
+{
+    USBDescString *s;
+
+    QLIST_FOREACH(s, &dev->strings, next) {
+        if (s->index == index) {
+            break;
+        }
+    }
+    if (s == NULL) {
+        s = g_malloc0(sizeof(*s));
+        s->index = index;
+        QLIST_INSERT_HEAD(&dev->strings, s, next);
+    }
+    g_free(s->str);
+    s->str = g_strdup(str);
+}
+
+const char *usb_desc_get_string(USBDevice *dev, uint8_t index)
+{
+    USBDescString *s;
+
+    QLIST_FOREACH(s, &dev->strings, next) {
+        if (s->index == index) {
+            return s->str;
+        }
+    }
+    return NULL;
+}
+
+int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len)
+{
+    uint8_t bLength, pos, i;
+    const char *str;
+
+    if (len < 4) {
+        return -1;
+    }
+
+    if (index == 0) {
+        /* language ids */
+        dest[0] = 4;
+        dest[1] = USB_DT_STRING;
+        dest[2] = 0x09;
+        dest[3] = 0x04;
+        return 4;
+    }
+
+    str = usb_desc_get_string(dev, index);
+    if (str == NULL) {
+        str = usb_device_get_usb_desc(dev)->str[index];
+        if (str == NULL) {
+            return 0;
+        }
+    }
+
+    bLength = strlen(str) * 2 + 2;
+    dest[0] = bLength;
+    dest[1] = USB_DT_STRING;
+    i = 0; pos = 2;
+    while (pos+1 < bLength && pos+1 < len) {
+        dest[pos++] = str[i++];
+        dest[pos++] = 0;
+    }
+    return pos;
+}
+
+int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len)
+{
+    const USBDesc *desc = usb_device_get_usb_desc(dev);
+    const USBDescDevice *other_dev;
+    uint8_t buf[256];
+    uint8_t type = value >> 8;
+    uint8_t index = value & 0xff;
+    int ret = -1;
+
+    if (dev->speed == USB_SPEED_HIGH) {
+        other_dev = usb_device_get_usb_desc(dev)->full;
+    } else {
+        other_dev = usb_device_get_usb_desc(dev)->high;
+    }
+
+    switch(type) {
+    case USB_DT_DEVICE:
+        ret = usb_desc_device(&desc->id, dev->device, buf, sizeof(buf));
+        trace_usb_desc_device(dev->addr, len, ret);
+        break;
+    case USB_DT_CONFIG:
+        if (index < dev->device->bNumConfigurations) {
+            ret = usb_desc_config(dev->device->confs + index, buf, sizeof(buf));
+        }
+        trace_usb_desc_config(dev->addr, index, len, ret);
+        break;
+    case USB_DT_STRING:
+        ret = usb_desc_string(dev, index, buf, sizeof(buf));
+        trace_usb_desc_string(dev->addr, index, len, ret);
+        break;
+
+    case USB_DT_DEVICE_QUALIFIER:
+        if (other_dev != NULL) {
+            ret = usb_desc_device_qualifier(other_dev, buf, sizeof(buf));
+        }
+        trace_usb_desc_device_qualifier(dev->addr, len, ret);
+        break;
+    case USB_DT_OTHER_SPEED_CONFIG:
+        if (other_dev != NULL && index < other_dev->bNumConfigurations) {
+            ret = usb_desc_config(other_dev->confs + index, buf, sizeof(buf));
+            buf[0x01] = USB_DT_OTHER_SPEED_CONFIG;
+        }
+        trace_usb_desc_other_speed_config(dev->addr, index, len, ret);
+        break;
+
+    case USB_DT_DEBUG:
+        /* ignore silently */
+        break;
+
+    default:
+        fprintf(stderr, "%s: %d unknown type %d (len %zd)\n", __FUNCTION__,
+                dev->addr, type, len);
+        break;
+    }
+
+    if (ret > 0) {
+        if (ret > len) {
+            ret = len;
+        }
+        memcpy(dest, buf, ret);
+    }
+    return ret;
+}
+
+int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
+        int request, int value, int index, int length, uint8_t *data)
+{
+    const USBDesc *desc = usb_device_get_usb_desc(dev);
+    int ret = -1;
+
+    assert(desc != NULL);
+    switch(request) {
+    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
+        dev->addr = value;
+        trace_usb_set_addr(dev->addr);
+        ret = 0;
+        break;
+
+    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
+        ret = usb_desc_get_descriptor(dev, value, data, length);
+        break;
+
+    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
+        /*
+         * 9.4.2: 0 should be returned if the device is unconfigured, otherwise
+         * the non zero value of bConfigurationValue.
+         */
+        data[0] = dev->config ? dev->config->bConfigurationValue : 0;
+        ret = 1;
+        break;
+    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
+        ret = usb_desc_set_config(dev, value);
+        trace_usb_set_config(dev->addr, value, ret);
+        break;
+
+    case DeviceRequest | USB_REQ_GET_STATUS: {
+        const USBDescConfig *config = dev->config ?
+            dev->config : &dev->device->confs[0];
+
+        data[0] = 0;
+        /*
+         * Default state: Device behavior when this request is received while
+         *                the device is in the Default state is not specified.
+         * We return the same value that a configured device would return if
+         * it used the first configuration.
+         */
+        if (config->bmAttributes & 0x40) {
+            data[0] |= 1 << USB_DEVICE_SELF_POWERED;
+        }
+        if (dev->remote_wakeup) {
+            data[0] |= 1 << USB_DEVICE_REMOTE_WAKEUP;
+        }
+        data[1] = 0x00;
+        ret = 2;
+        break;
+    }
+    case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
+        if (value == USB_DEVICE_REMOTE_WAKEUP) {
+            dev->remote_wakeup = 0;
+            ret = 0;
+        }
+        trace_usb_clear_device_feature(dev->addr, value, ret);
+        break;
+    case DeviceOutRequest | USB_REQ_SET_FEATURE:
+        if (value == USB_DEVICE_REMOTE_WAKEUP) {
+            dev->remote_wakeup = 1;
+            ret = 0;
+        }
+        trace_usb_set_device_feature(dev->addr, value, ret);
+        break;
+
+    case InterfaceRequest | USB_REQ_GET_INTERFACE:
+        if (index < 0 || index >= dev->ninterfaces) {
+            break;
+        }
+        data[0] = dev->altsetting[index];
+        ret = 1;
+        break;
+    case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
+        ret = usb_desc_set_interface(dev, index, value);
+        trace_usb_set_interface(dev->addr, index, value, ret);
+        break;
+
+    }
+    return ret;
+}
diff --git a/hw/usb/desc.h b/hw/usb/desc.h
new file mode 100644
index 0000000..d6e07ea
--- /dev/null
+++ b/hw/usb/desc.h
@@ -0,0 +1,117 @@
+#ifndef QEMU_HW_USB_DESC_H
+#define QEMU_HW_USB_DESC_H
+
+#include <inttypes.h>
+
+struct USBDescID {
+    uint16_t                  idVendor;
+    uint16_t                  idProduct;
+    uint16_t                  bcdDevice;
+    uint8_t                   iManufacturer;
+    uint8_t                   iProduct;
+    uint8_t                   iSerialNumber;
+};
+
+struct USBDescDevice {
+    uint16_t                  bcdUSB;
+    uint8_t                   bDeviceClass;
+    uint8_t                   bDeviceSubClass;
+    uint8_t                   bDeviceProtocol;
+    uint8_t                   bMaxPacketSize0;
+    uint8_t                   bNumConfigurations;
+
+    const USBDescConfig       *confs;
+};
+
+struct USBDescConfig {
+    uint8_t                   bNumInterfaces;
+    uint8_t                   bConfigurationValue;
+    uint8_t                   iConfiguration;
+    uint8_t                   bmAttributes;
+    uint8_t                   bMaxPower;
+
+    /* grouped interfaces */
+    uint8_t                   nif_groups;
+    const USBDescIfaceAssoc   *if_groups;
+
+    /* "normal" interfaces */
+    uint8_t                   nif;
+    const USBDescIface        *ifs;
+};
+
+/* conceptually an Interface Association Descriptor, and releated interfaces */
+struct USBDescIfaceAssoc {
+    uint8_t                   bFirstInterface;
+    uint8_t                   bInterfaceCount;
+    uint8_t                   bFunctionClass;
+    uint8_t                   bFunctionSubClass;
+    uint8_t                   bFunctionProtocol;
+    uint8_t                   iFunction;
+
+    uint8_t                   nif;
+    const USBDescIface        *ifs;
+};
+
+struct USBDescIface {
+    uint8_t                   bInterfaceNumber;
+    uint8_t                   bAlternateSetting;
+    uint8_t                   bNumEndpoints;
+    uint8_t                   bInterfaceClass;
+    uint8_t                   bInterfaceSubClass;
+    uint8_t                   bInterfaceProtocol;
+    uint8_t                   iInterface;
+
+    uint8_t                   ndesc;
+    USBDescOther              *descs;
+    USBDescEndpoint           *eps;
+};
+
+struct USBDescEndpoint {
+    uint8_t                   bEndpointAddress;
+    uint8_t                   bmAttributes;
+    uint16_t                  wMaxPacketSize;
+    uint8_t                   bInterval;
+    uint8_t                   bRefresh;
+    uint8_t                   bSynchAddress;
+
+    uint8_t                   is_audio; /* has bRefresh + bSynchAddress */
+    uint8_t                   *extra;
+};
+
+struct USBDescOther {
+    uint8_t                   length;
+    const uint8_t             *data;
+};
+
+typedef const char *USBDescStrings[256];
+
+struct USBDesc {
+    USBDescID                 id;
+    const USBDescDevice       *full;
+    const USBDescDevice       *high;
+    const char* const         *str;
+};
+
+/* generate usb packages from structs */
+int usb_desc_device(const USBDescID *id, const USBDescDevice *dev,
+                    uint8_t *dest, size_t len);
+int usb_desc_device_qualifier(const USBDescDevice *dev,
+                              uint8_t *dest, size_t len);
+int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len);
+int usb_desc_iface_group(const USBDescIfaceAssoc *iad, uint8_t *dest,
+                         size_t len);
+int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len);
+int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len);
+int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len);
+
+/* control message emulation helpers */
+void usb_desc_init(USBDevice *dev);
+void usb_desc_attach(USBDevice *dev);
+void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str);
+const char *usb_desc_get_string(USBDevice *dev, uint8_t index);
+int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len);
+int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len);
+int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
+        int request, int value, int index, int length, uint8_t *data);
+
+#endif /* QEMU_HW_USB_DESC_H */
diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c
new file mode 100644
index 0000000..426b95c
--- /dev/null
+++ b/hw/usb/dev-audio.c
@@ -0,0 +1,714 @@
+/*
+ * QEMU USB audio device
+ *
+ * written by:
+ *  H. Peter Anvin <hpa at linux.intel.com>
+ *  Gerd Hoffmann <kraxel at redhat.com>
+ *
+ * lousely based on usb net device code which is:
+ *
+ * Copyright (c) 2006 Thomas Sailer
+ * Copyright (c) 2008 Andrzej Zaborowski
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu-common.h"
+#include "hw/usb.h"
+#include "hw/usb/desc.h"
+#include "hw/hw.h"
+#include "hw/audiodev.h"
+#include "audio/audio.h"
+
+#define USBAUDIO_VENDOR_NUM     0x46f4 /* CRC16() of "QEMU" */
+#define USBAUDIO_PRODUCT_NUM    0x0002
+
+#define DEV_CONFIG_VALUE        1 /* The one and only */
+
+/* Descriptor subtypes for AC interfaces */
+#define DST_AC_HEADER           1
+#define DST_AC_INPUT_TERMINAL   2
+#define DST_AC_OUTPUT_TERMINAL  3
+#define DST_AC_FEATURE_UNIT     6
+/* Descriptor subtypes for AS interfaces */
+#define DST_AS_GENERAL          1
+#define DST_AS_FORMAT_TYPE      2
+/* Descriptor subtypes for endpoints */
+#define DST_EP_GENERAL          1
+
+enum usb_audio_strings {
+    STRING_NULL,
+    STRING_MANUFACTURER,
+    STRING_PRODUCT,
+    STRING_SERIALNUMBER,
+    STRING_CONFIG,
+    STRING_USBAUDIO_CONTROL,
+    STRING_INPUT_TERMINAL,
+    STRING_FEATURE_UNIT,
+    STRING_OUTPUT_TERMINAL,
+    STRING_NULL_STREAM,
+    STRING_REAL_STREAM,
+};
+
+static const USBDescStrings usb_audio_stringtable = {
+    [STRING_MANUFACTURER]       = "QEMU",
+    [STRING_PRODUCT]            = "QEMU USB Audio",
+    [STRING_SERIALNUMBER]       = "1",
+    [STRING_CONFIG]             = "Audio Configuration",
+    [STRING_USBAUDIO_CONTROL]   = "Audio Device",
+    [STRING_INPUT_TERMINAL]     = "Audio Output Pipe",
+    [STRING_FEATURE_UNIT]       = "Audio Output Volume Control",
+    [STRING_OUTPUT_TERMINAL]    = "Audio Output Terminal",
+    [STRING_NULL_STREAM]        = "Audio Output - Disabled",
+    [STRING_REAL_STREAM]        = "Audio Output - 48 kHz Stereo",
+};
+
+#define U16(x) ((x) & 0xff), (((x) >> 8) & 0xff)
+#define U24(x) U16(x), (((x) >> 16) & 0xff)
+#define U32(x) U24(x), (((x) >> 24) & 0xff)
+
+/*
+ * A Basic Audio Device uses these specific values
+ */
+#define USBAUDIO_PACKET_SIZE     192
+#define USBAUDIO_SAMPLE_RATE     48000
+#define USBAUDIO_PACKET_INTERVAL 1
+
+static const USBDescIface desc_iface[] = {
+    {
+        .bInterfaceNumber              = 0,
+        .bNumEndpoints                 = 0,
+        .bInterfaceClass               = USB_CLASS_AUDIO,
+        .bInterfaceSubClass            = USB_SUBCLASS_AUDIO_CONTROL,
+        .bInterfaceProtocol            = 0x04,
+        .iInterface                    = STRING_USBAUDIO_CONTROL,
+        .ndesc                         = 4,
+        .descs = (USBDescOther[]) {
+            {
+                /* Headphone Class-Specific AC Interface Header Descriptor */
+                .data = (uint8_t[]) {
+                    0x09,                       /*  u8  bLength */
+                    USB_DT_CS_INTERFACE,        /*  u8  bDescriptorType */
+                    DST_AC_HEADER,              /*  u8  bDescriptorSubtype */
+                    U16(0x0100),                /* u16  bcdADC */
+                    U16(0x2b),                  /* u16  wTotalLength */
+                    0x01,                       /*  u8  bInCollection */
+                    0x01,                       /*  u8  baInterfaceNr */
+                }
+            },{
+                /* Generic Stereo Input Terminal ID1 Descriptor */
+                .data = (uint8_t[]) {
+                    0x0c,                       /*  u8  bLength */
+                    USB_DT_CS_INTERFACE,        /*  u8  bDescriptorType */
+                    DST_AC_INPUT_TERMINAL,      /*  u8  bDescriptorSubtype */
+                    0x01,                       /*  u8  bTerminalID */
+                    U16(0x0101),                /* u16  wTerminalType */
+                    0x00,                       /*  u8  bAssocTerminal */
+                    0x02,                       /* u16  bNrChannels */
+                    U16(0x0003),                /* u16  wChannelConfig */
+                    0x00,                       /*  u8  iChannelNames */
+                    STRING_INPUT_TERMINAL,      /*  u8  iTerminal */
+                }
+            },{
+                /* Generic Stereo Feature Unit ID2 Descriptor */
+                .data = (uint8_t[]) {
+                    0x0d,                       /*  u8  bLength */
+                    USB_DT_CS_INTERFACE,        /*  u8  bDescriptorType */
+                    DST_AC_FEATURE_UNIT,        /*  u8  bDescriptorSubtype */
+                    0x02,                       /*  u8  bUnitID */
+                    0x01,                       /*  u8  bSourceID */
+                    0x02,                       /*  u8  bControlSize */
+                    U16(0x0001),                /* u16  bmaControls(0) */
+                    U16(0x0002),                /* u16  bmaControls(1) */
+                    U16(0x0002),                /* u16  bmaControls(2) */
+                    STRING_FEATURE_UNIT,        /*  u8  iFeature */
+                }
+            },{
+                /* Headphone Ouptut Terminal ID3 Descriptor */
+                .data = (uint8_t[]) {
+                    0x09,                       /*  u8  bLength */
+                    USB_DT_CS_INTERFACE,        /*  u8  bDescriptorType */
+                    DST_AC_OUTPUT_TERMINAL,     /*  u8  bDescriptorSubtype */
+                    0x03,                       /*  u8  bUnitID */
+                    U16(0x0301),                /* u16  wTerminalType (SPK) */
+                    0x00,                       /*  u8  bAssocTerminal */
+                    0x02,                       /*  u8  bSourceID */
+                    STRING_OUTPUT_TERMINAL,     /*  u8  iTerminal */
+                }
+            }
+        },
+    },{
+        .bInterfaceNumber              = 1,
+        .bAlternateSetting             = 0,
+        .bNumEndpoints                 = 0,
+        .bInterfaceClass               = USB_CLASS_AUDIO,
+        .bInterfaceSubClass            = USB_SUBCLASS_AUDIO_STREAMING,
+        .iInterface                    = STRING_NULL_STREAM,
+    },{
+        .bInterfaceNumber              = 1,
+        .bAlternateSetting             = 1,
+        .bNumEndpoints                 = 1,
+        .bInterfaceClass               = USB_CLASS_AUDIO,
+        .bInterfaceSubClass            = USB_SUBCLASS_AUDIO_STREAMING,
+        .iInterface                    = STRING_REAL_STREAM,
+        .ndesc                         = 2,
+        .descs = (USBDescOther[]) {
+            {
+                /* Headphone Class-specific AS General Interface Descriptor */
+                .data = (uint8_t[]) {
+                    0x07,                       /*  u8  bLength */
+                    USB_DT_CS_INTERFACE,        /*  u8  bDescriptorType */
+                    DST_AS_GENERAL,             /*  u8  bDescriptorSubtype */
+                    0x01,                       /*  u8  bTerminalLink */
+                    0x00,                       /*  u8  bDelay */
+                    0x01, 0x00,                 /* u16  wFormatTag */
+                }
+            },{
+                /* Headphone Type I Format Type Descriptor */
+                .data = (uint8_t[]) {
+                    0x0b,                       /*  u8  bLength */
+                    USB_DT_CS_INTERFACE,        /*  u8  bDescriptorType */
+                    DST_AS_FORMAT_TYPE,         /*  u8  bDescriptorSubtype */
+                    0x01,                       /*  u8  bFormatType */
+                    0x02,                       /*  u8  bNrChannels */
+                    0x02,                       /*  u8  bSubFrameSize */
+                    0x10,                       /*  u8  bBitResolution */
+                    0x01,                       /*  u8  bSamFreqType */
+                    U24(USBAUDIO_SAMPLE_RATE),  /* u24  tSamFreq */
+                }
+            }
+        },
+        .eps = (USBDescEndpoint[]) {
+            {
+                .bEndpointAddress      = USB_DIR_OUT | 0x01,
+                .bmAttributes          = 0x0d,
+                .wMaxPacketSize        = USBAUDIO_PACKET_SIZE,
+                .bInterval             = 1,
+                .is_audio              = 1,
+                /* Stereo Headphone Class-specific
+                   AS Audio Data Endpoint Descriptor */
+                .extra = (uint8_t[]) {
+                    0x07,                       /*  u8  bLength */
+                    USB_DT_CS_ENDPOINT,         /*  u8  bDescriptorType */
+                    DST_EP_GENERAL,             /*  u8  bDescriptorSubtype */
+                    0x00,                       /*  u8  bmAttributes */
+                    0x00,                       /*  u8  bLockDelayUnits */
+                    U16(0x0000),                /* u16  wLockDelay */
+                },
+            },
+        }
+    }
+};
+
+static const USBDescDevice desc_device = {
+    .bcdUSB                        = 0x0200,
+    .bMaxPacketSize0               = 64,
+    .bNumConfigurations            = 1,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 2,
+            .bConfigurationValue   = DEV_CONFIG_VALUE,
+            .iConfiguration        = STRING_CONFIG,
+            .bmAttributes          = 0xc0,
+            .bMaxPower             = 0x32,
+            .nif = ARRAY_SIZE(desc_iface),
+            .ifs = desc_iface,
+        },
+    },
+};
+
+static const USBDesc desc_audio = {
+    .id = {
+        .idVendor          = USBAUDIO_VENDOR_NUM,
+        .idProduct         = USBAUDIO_PRODUCT_NUM,
+        .bcdDevice         = 0,
+        .iManufacturer     = STRING_MANUFACTURER,
+        .iProduct          = STRING_PRODUCT,
+        .iSerialNumber     = STRING_SERIALNUMBER,
+    },
+    .full = &desc_device,
+    .str  = usb_audio_stringtable,
+};
+
+/*
+ * A USB audio device supports an arbitrary number of alternate
+ * interface settings for each interface.  Each corresponds to a block
+ * diagram of parameterized blocks.  This can thus refer to things like
+ * number of channels, data rates, or in fact completely different
+ * block diagrams.  Alternative setting 0 is always the null block diagram,
+ * which is used by a disabled device.
+ */
+enum usb_audio_altset {
+    ALTSET_OFF  = 0x00,         /* No endpoint */
+    ALTSET_ON   = 0x01,         /* Single endpoint */
+};
+
+/*
+ * Class-specific control requests
+ */
+#define CR_SET_CUR      0x01
+#define CR_GET_CUR      0x81
+#define CR_SET_MIN      0x02
+#define CR_GET_MIN      0x82
+#define CR_SET_MAX      0x03
+#define CR_GET_MAX      0x83
+#define CR_SET_RES      0x04
+#define CR_GET_RES      0x84
+#define CR_SET_MEM      0x05
+#define CR_GET_MEM      0x85
+#define CR_GET_STAT     0xff
+
+/*
+ * Feature Unit Control Selectors
+ */
+#define MUTE_CONTROL                    0x01
+#define VOLUME_CONTROL                  0x02
+#define BASS_CONTROL                    0x03
+#define MID_CONTROL                     0x04
+#define TREBLE_CONTROL                  0x05
+#define GRAPHIC_EQUALIZER_CONTROL       0x06
+#define AUTOMATIC_GAIN_CONTROL          0x07
+#define DELAY_CONTROL                   0x08
+#define BASS_BOOST_CONTROL              0x09
+#define LOUDNESS_CONTROL                0x0a
+
+/*
+ * buffering
+ */
+
+struct streambuf {
+    uint8_t *data;
+    uint32_t size;
+    uint32_t prod;
+    uint32_t cons;
+};
+
+static void streambuf_init(struct streambuf *buf, uint32_t size)
+{
+    g_free(buf->data);
+    buf->size = size - (size % USBAUDIO_PACKET_SIZE);
+    buf->data = g_malloc(buf->size);
+    buf->prod = 0;
+    buf->cons = 0;
+}
+
+static void streambuf_fini(struct streambuf *buf)
+{
+    g_free(buf->data);
+    buf->data = NULL;
+}
+
+static int streambuf_put(struct streambuf *buf, USBPacket *p)
+{
+    uint32_t free = buf->size - (buf->prod - buf->cons);
+
+    if (!free) {
+        return 0;
+    }
+    assert(free >= USBAUDIO_PACKET_SIZE);
+    usb_packet_copy(p, buf->data + (buf->prod % buf->size),
+                    USBAUDIO_PACKET_SIZE);
+    buf->prod += USBAUDIO_PACKET_SIZE;
+    return USBAUDIO_PACKET_SIZE;
+}
+
+static uint8_t *streambuf_get(struct streambuf *buf)
+{
+    uint32_t used = buf->prod - buf->cons;
+    uint8_t *data;
+
+    if (!used) {
+        return NULL;
+    }
+    assert(used >= USBAUDIO_PACKET_SIZE);
+    data = buf->data + (buf->cons % buf->size);
+    buf->cons += USBAUDIO_PACKET_SIZE;
+    return data;
+}
+
+typedef struct USBAudioState {
+    /* qemu interfaces */
+    USBDevice dev;
+    QEMUSoundCard card;
+
+    /* state */
+    struct {
+        enum usb_audio_altset altset;
+        struct audsettings as;
+        SWVoiceOut *voice;
+        bool mute;
+        uint8_t vol[2];
+        struct streambuf buf;
+    } out;
+
+    /* properties */
+    uint32_t debug;
+    uint32_t buffer;
+} USBAudioState;
+
+static void output_callback(void *opaque, int avail)
+{
+    USBAudioState *s = opaque;
+    uint8_t *data;
+
+    for (;;) {
+        if (avail < USBAUDIO_PACKET_SIZE) {
+            return;
+        }
+        data = streambuf_get(&s->out.buf);
+        if (NULL == data) {
+            return;
+        }
+        AUD_write(s->out.voice, data, USBAUDIO_PACKET_SIZE);
+        avail -= USBAUDIO_PACKET_SIZE;
+    }
+}
+
+static int usb_audio_set_output_altset(USBAudioState *s, int altset)
+{
+    switch (altset) {
+    case ALTSET_OFF:
+        streambuf_init(&s->out.buf, s->buffer);
+        AUD_set_active_out(s->out.voice, false);
+        break;
+    case ALTSET_ON:
+        AUD_set_active_out(s->out.voice, true);
+        break;
+    default:
+        return -1;
+    }
+
+    if (s->debug) {
+        fprintf(stderr, "usb-audio: set interface %d\n", altset);
+    }
+    s->out.altset = altset;
+    return 0;
+}
+
+/*
+ * Note: we arbitrarily map the volume control range onto -inf..+8 dB
+ */
+#define ATTRIB_ID(cs, attrib, idif)     \
+    (((cs) << 24) | ((attrib) << 16) | (idif))
+
+static int usb_audio_get_control(USBAudioState *s, uint8_t attrib,
+                                 uint16_t cscn, uint16_t idif,
+                                 int length, uint8_t *data)
+{
+    uint8_t cs = cscn >> 8;
+    uint8_t cn = cscn - 1;      /* -1 for the non-present master control */
+    uint32_t aid = ATTRIB_ID(cs, attrib, idif);
+    int ret = USB_RET_STALL;
+
+    switch (aid) {
+    case ATTRIB_ID(MUTE_CONTROL, CR_GET_CUR, 0x0200):
+        data[0] = s->out.mute;
+        ret = 1;
+        break;
+    case ATTRIB_ID(VOLUME_CONTROL, CR_GET_CUR, 0x0200):
+        if (cn < 2) {
+            uint16_t vol = (s->out.vol[cn] * 0x8800 + 127) / 255 + 0x8000;
+            data[0] = vol;
+            data[1] = vol >> 8;
+            ret = 2;
+        }
+        break;
+    case ATTRIB_ID(VOLUME_CONTROL, CR_GET_MIN, 0x0200):
+        if (cn < 2) {
+            data[0] = 0x01;
+            data[1] = 0x80;
+            ret = 2;
+        }
+        break;
+    case ATTRIB_ID(VOLUME_CONTROL, CR_GET_MAX, 0x0200):
+        if (cn < 2) {
+            data[0] = 0x00;
+            data[1] = 0x08;
+            ret = 2;
+        }
+        break;
+    case ATTRIB_ID(VOLUME_CONTROL, CR_GET_RES, 0x0200):
+        if (cn < 2) {
+            data[0] = 0x88;
+            data[1] = 0x00;
+            ret = 2;
+        }
+        break;
+    }
+
+    return ret;
+}
+static int usb_audio_set_control(USBAudioState *s, uint8_t attrib,
+                                 uint16_t cscn, uint16_t idif,
+                                 int length, uint8_t *data)
+{
+    uint8_t cs = cscn >> 8;
+    uint8_t cn = cscn - 1;      /* -1 for the non-present master control */
+    uint32_t aid = ATTRIB_ID(cs, attrib, idif);
+    int ret = USB_RET_STALL;
+    bool set_vol = false;
+
+    switch (aid) {
+    case ATTRIB_ID(MUTE_CONTROL, CR_SET_CUR, 0x0200):
+        s->out.mute = data[0] & 1;
+        set_vol = true;
+        ret = 0;
+        break;
+    case ATTRIB_ID(VOLUME_CONTROL, CR_SET_CUR, 0x0200):
+        if (cn < 2) {
+            uint16_t vol = data[0] + (data[1] << 8);
+
+            if (s->debug) {
+                fprintf(stderr, "usb-audio: vol %04x\n", (uint16_t)vol);
+            }
+
+            vol -= 0x8000;
+            vol = (vol * 255 + 0x4400) / 0x8800;
+            if (vol > 255) {
+                vol = 255;
+            }
+
+            s->out.vol[cn] = vol;
+            set_vol = true;
+            ret = 0;
+        }
+        break;
+    }
+
+    if (set_vol) {
+        if (s->debug) {
+            fprintf(stderr, "usb-audio: mute %d, lvol %3d, rvol %3d\n",
+                    s->out.mute, s->out.vol[0], s->out.vol[1]);
+        }
+        AUD_set_volume_out(s->out.voice, s->out.mute,
+                           s->out.vol[0], s->out.vol[1]);
+    }
+
+    return ret;
+}
+
+static int usb_audio_handle_control(USBDevice *dev, USBPacket *p,
+                                    int request, int value, int index,
+                                    int length, uint8_t *data)
+{
+    USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
+    int ret = 0;
+
+    if (s->debug) {
+        fprintf(stderr, "usb-audio: control transaction: "
+                "request 0x%04x value 0x%04x index 0x%04x length 0x%04x\n",
+                request, value, index, length);
+    }
+
+    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
+    if (ret >= 0) {
+        return ret;
+    }
+
+    switch (request) {
+    case ClassInterfaceRequest | CR_GET_CUR:
+    case ClassInterfaceRequest | CR_GET_MIN:
+    case ClassInterfaceRequest | CR_GET_MAX:
+    case ClassInterfaceRequest | CR_GET_RES:
+        ret = usb_audio_get_control(s, request & 0xff, value, index,
+                                    length, data);
+        if (ret < 0) {
+            if (s->debug) {
+                fprintf(stderr, "usb-audio: fail: get control\n");
+            }
+            goto fail;
+        }
+        break;
+
+    case ClassInterfaceOutRequest | CR_SET_CUR:
+    case ClassInterfaceOutRequest | CR_SET_MIN:
+    case ClassInterfaceOutRequest | CR_SET_MAX:
+    case ClassInterfaceOutRequest | CR_SET_RES:
+        ret = usb_audio_set_control(s, request & 0xff, value, index,
+                                    length, data);
+        if (ret < 0) {
+            if (s->debug) {
+                fprintf(stderr, "usb-audio: fail: set control\n");
+            }
+            goto fail;
+        }
+        break;
+
+    default:
+fail:
+        if (s->debug) {
+            fprintf(stderr, "usb-audio: failed control transaction: "
+                    "request 0x%04x value 0x%04x index 0x%04x length 0x%04x\n",
+                    request, value, index, length);
+        }
+        ret = USB_RET_STALL;
+        break;
+    }
+    return ret;
+}
+
+static void usb_audio_set_interface(USBDevice *dev, int iface,
+                                    int old, int value)
+{
+    USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
+
+    if (iface == 1) {
+        usb_audio_set_output_altset(s, value);
+    }
+}
+
+static void usb_audio_handle_reset(USBDevice *dev)
+{
+    USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
+
+    if (s->debug) {
+        fprintf(stderr, "usb-audio: reset\n");
+    }
+    usb_audio_set_output_altset(s, ALTSET_OFF);
+}
+
+static int usb_audio_handle_dataout(USBAudioState *s, USBPacket *p)
+{
+    int rc;
+
+    if (s->out.altset == ALTSET_OFF) {
+        return USB_RET_STALL;
+    }
+
+    rc = streambuf_put(&s->out.buf, p);
+    if (rc < p->iov.size && s->debug > 1) {
+        fprintf(stderr, "usb-audio: output overrun (%zd bytes)\n",
+                p->iov.size - rc);
+    }
+
+    return 0;
+}
+
+static int usb_audio_handle_data(USBDevice *dev, USBPacket *p)
+{
+    USBAudioState *s = (USBAudioState *) dev;
+    int ret = 0;
+
+    switch (p->pid) {
+    case USB_TOKEN_OUT:
+        switch (p->ep->nr) {
+        case 1:
+            ret = usb_audio_handle_dataout(s, p);
+            break;
+        default:
+            goto fail;
+        }
+        break;
+
+    default:
+fail:
+        ret = USB_RET_STALL;
+        break;
+    }
+    if (ret == USB_RET_STALL && s->debug) {
+        fprintf(stderr, "usb-audio: failed data transaction: "
+                        "pid 0x%x ep 0x%x len 0x%zx\n",
+                        p->pid, p->ep->nr, p->iov.size);
+    }
+    return ret;
+}
+
+static void usb_audio_handle_destroy(USBDevice *dev)
+{
+    USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
+
+    if (s->debug) {
+        fprintf(stderr, "usb-audio: destroy\n");
+    }
+
+    usb_audio_set_output_altset(s, ALTSET_OFF);
+    AUD_close_out(&s->card, s->out.voice);
+    AUD_remove_card(&s->card);
+
+    streambuf_fini(&s->out.buf);
+}
+
+static int usb_audio_initfn(USBDevice *dev)
+{
+    USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
+
+    usb_desc_init(dev);
+    s->dev.opaque = s;
+    AUD_register_card("usb-audio", &s->card);
+
+    s->out.altset        = ALTSET_OFF;
+    s->out.mute          = false;
+    s->out.vol[0]        = 240; /* 0 dB */
+    s->out.vol[1]        = 240; /* 0 dB */
+    s->out.as.freq       = USBAUDIO_SAMPLE_RATE;
+    s->out.as.nchannels  = 2;
+    s->out.as.fmt        = AUD_FMT_S16;
+    s->out.as.endianness = 0;
+    streambuf_init(&s->out.buf, s->buffer);
+
+    s->out.voice = AUD_open_out(&s->card, s->out.voice, "usb-audio",
+                                s, output_callback, &s->out.as);
+    AUD_set_volume_out(s->out.voice, s->out.mute, s->out.vol[0], s->out.vol[1]);
+    AUD_set_active_out(s->out.voice, 0);
+    return 0;
+}
+
+static const VMStateDescription vmstate_usb_audio = {
+    .name = "usb-audio",
+    .unmigratable = 1,
+};
+
+static Property usb_audio_properties[] = {
+    DEFINE_PROP_UINT32("debug", USBAudioState, debug, 0),
+    DEFINE_PROP_UINT32("buffer", USBAudioState, buffer,
+                       8 * USBAUDIO_PACKET_SIZE),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void usb_audio_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    USBDeviceClass *k = USB_DEVICE_CLASS(klass);
+
+    dc->vmsd          = &vmstate_usb_audio;
+    dc->props         = usb_audio_properties;
+    k->product_desc   = "QEMU USB Audio Interface";
+    k->usb_desc       = &desc_audio;
+    k->init           = usb_audio_initfn;
+    k->handle_reset   = usb_audio_handle_reset;
+    k->handle_control = usb_audio_handle_control;
+    k->handle_data    = usb_audio_handle_data;
+    k->handle_destroy = usb_audio_handle_destroy;
+    k->set_interface  = usb_audio_set_interface;
+}
+
+static TypeInfo usb_audio_info = {
+    .name          = "usb-audio",
+    .parent        = TYPE_USB_DEVICE,
+    .instance_size = sizeof(USBAudioState),
+    .class_init    = usb_audio_class_init,
+};
+
+static void usb_audio_register_types(void)
+{
+    type_register_static(&usb_audio_info);
+    usb_legacy_register("usb-audio", "audio", NULL);
+}
+
+type_init(usb_audio_register_types)
diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c
new file mode 100644
index 0000000..195370c
--- /dev/null
+++ b/hw/usb/dev-bluetooth.c
@@ -0,0 +1,557 @@
+/*
+ * QEMU Bluetooth HCI USB Transport Layer v1.0
+ *
+ * Copyright (C) 2007 OpenMoko, Inc.
+ * Copyright (C) 2008 Andrzej Zaborowski  <balrog at zabor.org>
+ *
+ * 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 or
+ * (at your option) version 3 of the License.
+ *
+ * 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 "qemu-common.h"
+#include "hw/usb.h"
+#include "hw/usb/desc.h"
+#include "net.h"
+#include "hw/bt.h"
+
+struct USBBtState {
+    USBDevice dev;
+    struct HCIInfo *hci;
+
+    int config;
+
+#define CFIFO_LEN_MASK	255
+#define DFIFO_LEN_MASK	4095
+    struct usb_hci_in_fifo_s {
+        uint8_t data[(DFIFO_LEN_MASK + 1) * 2];
+        struct {
+            uint8_t *data;
+            int len;
+        } fifo[CFIFO_LEN_MASK + 1];
+        int dstart, dlen, dsize, start, len;
+    } evt, acl, sco;
+
+    struct usb_hci_out_fifo_s {
+        uint8_t data[4096];
+	int len;
+    } outcmd, outacl, outsco;
+};
+
+#define USB_EVT_EP	1
+#define USB_ACL_EP	2
+#define USB_SCO_EP	3
+
+enum {
+    STR_MANUFACTURER = 1,
+    STR_SERIALNUMBER,
+};
+
+static const USBDescStrings desc_strings = {
+    [STR_MANUFACTURER]     = "QEMU " QEMU_VERSION,
+    [STR_SERIALNUMBER]     = "1",
+};
+
+static const USBDescIface desc_iface_bluetooth[] = {
+    {
+        .bInterfaceNumber              = 0,
+        .bNumEndpoints                 = 3,
+        .bInterfaceClass               = 0xe0, /* Wireless */
+        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
+        .bInterfaceProtocol            = 0x01, /* Bluetooth */
+        .eps = (USBDescEndpoint[]) {
+            {
+                .bEndpointAddress      = USB_DIR_IN | USB_EVT_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .wMaxPacketSize        = 0x10,
+                .bInterval             = 0x02,
+            },
+            {
+                .bEndpointAddress      = USB_DIR_OUT | USB_ACL_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+                .wMaxPacketSize        = 0x40,
+                .bInterval             = 0x0a,
+            },
+            {
+                .bEndpointAddress      = USB_DIR_IN | USB_ACL_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+                .wMaxPacketSize        = 0x40,
+                .bInterval             = 0x0a,
+            },
+        },
+    },{
+        .bInterfaceNumber              = 1,
+        .bAlternateSetting             = 0,
+        .bNumEndpoints                 = 2,
+        .bInterfaceClass               = 0xe0, /* Wireless */
+        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
+        .bInterfaceProtocol            = 0x01, /* Bluetooth */
+        .eps = (USBDescEndpoint[]) {
+            {
+                .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
+                .wMaxPacketSize        = 0,
+                .bInterval             = 0x01,
+            },
+            {
+                .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
+                .wMaxPacketSize        = 0,
+                .bInterval             = 0x01,
+            },
+        },
+    },{
+        .bInterfaceNumber              = 1,
+        .bAlternateSetting             = 1,
+        .bNumEndpoints                 = 2,
+        .bInterfaceClass               = 0xe0, /* Wireless */
+        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
+        .bInterfaceProtocol            = 0x01, /* Bluetooth */
+        .eps = (USBDescEndpoint[]) {
+            {
+                .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
+                .wMaxPacketSize        = 0x09,
+                .bInterval             = 0x01,
+            },
+            {
+                .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
+                .wMaxPacketSize        = 0x09,
+                .bInterval             = 0x01,
+            },
+        },
+    },{
+        .bInterfaceNumber              = 1,
+        .bAlternateSetting             = 2,
+        .bNumEndpoints                 = 2,
+        .bInterfaceClass               = 0xe0, /* Wireless */
+        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
+        .bInterfaceProtocol            = 0x01, /* Bluetooth */
+        .eps = (USBDescEndpoint[]) {
+            {
+                .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
+                .wMaxPacketSize        = 0x11,
+                .bInterval             = 0x01,
+            },
+            {
+                .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
+                .wMaxPacketSize        = 0x11,
+                .bInterval             = 0x01,
+            },
+        },
+    },{
+        .bInterfaceNumber              = 1,
+        .bAlternateSetting             = 3,
+        .bNumEndpoints                 = 2,
+        .bInterfaceClass               = 0xe0, /* Wireless */
+        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
+        .bInterfaceProtocol            = 0x01, /* Bluetooth */
+        .eps = (USBDescEndpoint[]) {
+            {
+                .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
+                .wMaxPacketSize        = 0x19,
+                .bInterval             = 0x01,
+            },
+            {
+                .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
+                .wMaxPacketSize        = 0x19,
+                .bInterval             = 0x01,
+            },
+        },
+    },{
+        .bInterfaceNumber              = 1,
+        .bAlternateSetting             = 4,
+        .bNumEndpoints                 = 2,
+        .bInterfaceClass               = 0xe0, /* Wireless */
+        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
+        .bInterfaceProtocol            = 0x01, /* Bluetooth */
+        .eps = (USBDescEndpoint[]) {
+            {
+                .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
+                .wMaxPacketSize        = 0x21,
+                .bInterval             = 0x01,
+            },
+            {
+                .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
+                .wMaxPacketSize        = 0x21,
+                .bInterval             = 0x01,
+            },
+        },
+    },{
+        .bInterfaceNumber              = 1,
+        .bAlternateSetting             = 5,
+        .bNumEndpoints                 = 2,
+        .bInterfaceClass               = 0xe0, /* Wireless */
+        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
+        .bInterfaceProtocol            = 0x01, /* Bluetooth */
+        .eps = (USBDescEndpoint[]) {
+            {
+                .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
+                .wMaxPacketSize        = 0x31,
+                .bInterval             = 0x01,
+            },
+            {
+                .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
+                .wMaxPacketSize        = 0x31,
+                .bInterval             = 0x01,
+            },
+        },
+    }
+};
+
+static const USBDescDevice desc_device_bluetooth = {
+    .bcdUSB                        = 0x0110,
+    .bDeviceClass                  = 0xe0, /* Wireless */
+    .bDeviceSubClass               = 0x01, /* Radio Frequency */
+    .bDeviceProtocol               = 0x01, /* Bluetooth */
+    .bMaxPacketSize0               = 64,
+    .bNumConfigurations            = 1,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 2,
+            .bConfigurationValue   = 1,
+            .bmAttributes          = 0xc0,
+            .bMaxPower             = 0,
+            .nif = ARRAY_SIZE(desc_iface_bluetooth),
+            .ifs = desc_iface_bluetooth,
+        },
+    },
+};
+
+static const USBDesc desc_bluetooth = {
+    .id = {
+        .idVendor          = 0x0a12,
+        .idProduct         = 0x0001,
+        .bcdDevice         = 0x1958,
+        .iManufacturer     = STR_MANUFACTURER,
+        .iProduct          = 0,
+        .iSerialNumber     = STR_SERIALNUMBER,
+    },
+    .full = &desc_device_bluetooth,
+    .str  = desc_strings,
+};
+
+static void usb_bt_fifo_reset(struct usb_hci_in_fifo_s *fifo)
+{
+    fifo->dstart = 0;
+    fifo->dlen = 0;
+    fifo->dsize = DFIFO_LEN_MASK + 1;
+    fifo->start = 0;
+    fifo->len = 0;
+}
+
+static void usb_bt_fifo_enqueue(struct usb_hci_in_fifo_s *fifo,
+                const uint8_t *data, int len)
+{
+    int off = fifo->dstart + fifo->dlen;
+    uint8_t *buf;
+
+    fifo->dlen += len;
+    if (off <= DFIFO_LEN_MASK) {
+        if (off + len > DFIFO_LEN_MASK + 1 &&
+                        (fifo->dsize = off + len) > (DFIFO_LEN_MASK + 1) * 2) {
+            fprintf(stderr, "%s: can't alloc %i bytes\n", __FUNCTION__, len);
+            exit(-1);
+        }
+        buf = fifo->data + off;
+    } else {
+        if (fifo->dlen > fifo->dsize) {
+            fprintf(stderr, "%s: can't alloc %i bytes\n", __FUNCTION__, len);
+            exit(-1);
+        }
+        buf = fifo->data + off - fifo->dsize;
+    }
+
+    off = (fifo->start + fifo->len ++) & CFIFO_LEN_MASK;
+    fifo->fifo[off].data = memcpy(buf, data, len);
+    fifo->fifo[off].len = len;
+}
+
+static inline int usb_bt_fifo_dequeue(struct usb_hci_in_fifo_s *fifo,
+                USBPacket *p)
+{
+    int len;
+
+    if (likely(!fifo->len))
+        return USB_RET_STALL;
+
+    len = MIN(p->iov.size, fifo->fifo[fifo->start].len);
+    usb_packet_copy(p, fifo->fifo[fifo->start].data, len);
+    if (len == p->iov.size) {
+        fifo->fifo[fifo->start].len -= len;
+        fifo->fifo[fifo->start].data += len;
+    } else {
+        fifo->start ++;
+        fifo->start &= CFIFO_LEN_MASK;
+        fifo->len --;
+    }
+
+    fifo->dstart += len;
+    fifo->dlen -= len;
+    if (fifo->dstart >= fifo->dsize) {
+        fifo->dstart = 0;
+        fifo->dsize = DFIFO_LEN_MASK + 1;
+    }
+
+    return len;
+}
+
+static inline void usb_bt_fifo_out_enqueue(struct USBBtState *s,
+                struct usb_hci_out_fifo_s *fifo,
+                void (*send)(struct HCIInfo *, const uint8_t *, int),
+                int (*complete)(const uint8_t *, int),
+                USBPacket *p)
+{
+    usb_packet_copy(p, fifo->data + fifo->len, p->iov.size);
+    fifo->len += p->iov.size;
+    if (complete(fifo->data, fifo->len)) {
+        send(s->hci, fifo->data, fifo->len);
+        fifo->len = 0;
+    }
+
+    /* TODO: do we need to loop? */
+}
+
+static int usb_bt_hci_cmd_complete(const uint8_t *data, int len)
+{
+    len -= HCI_COMMAND_HDR_SIZE;
+    return len >= 0 &&
+            len >= ((struct hci_command_hdr *) data)->plen;
+}
+
+static int usb_bt_hci_acl_complete(const uint8_t *data, int len)
+{
+    len -= HCI_ACL_HDR_SIZE;
+    return len >= 0 &&
+            len >= le16_to_cpu(((struct hci_acl_hdr *) data)->dlen);
+}
+
+static int usb_bt_hci_sco_complete(const uint8_t *data, int len)
+{
+    len -= HCI_SCO_HDR_SIZE;
+    return len >= 0 &&
+            len >= ((struct hci_sco_hdr *) data)->dlen;
+}
+
+static void usb_bt_handle_reset(USBDevice *dev)
+{
+    struct USBBtState *s = (struct USBBtState *) dev->opaque;
+
+    usb_bt_fifo_reset(&s->evt);
+    usb_bt_fifo_reset(&s->acl);
+    usb_bt_fifo_reset(&s->sco);
+    s->outcmd.len = 0;
+    s->outacl.len = 0;
+    s->outsco.len = 0;
+}
+
+static int usb_bt_handle_control(USBDevice *dev, USBPacket *p,
+               int request, int value, int index, int length, uint8_t *data)
+{
+    struct USBBtState *s = (struct USBBtState *) dev->opaque;
+    int ret;
+
+    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
+    if (ret >= 0) {
+        switch (request) {
+        case DeviceRequest | USB_REQ_GET_CONFIGURATION:
+            s->config = 0;
+            break;
+        case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
+            s->config = 1;
+            usb_bt_fifo_reset(&s->evt);
+            usb_bt_fifo_reset(&s->acl);
+            usb_bt_fifo_reset(&s->sco);
+            break;
+        }
+        return ret;
+    }
+
+    ret = 0;
+    switch (request) {
+    case InterfaceRequest | USB_REQ_GET_STATUS:
+    case EndpointRequest | USB_REQ_GET_STATUS:
+        data[0] = 0x00;
+        data[1] = 0x00;
+        ret = 2;
+        break;
+    case InterfaceOutRequest | USB_REQ_CLEAR_FEATURE:
+    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
+        goto fail;
+    case InterfaceOutRequest | USB_REQ_SET_FEATURE:
+    case EndpointOutRequest | USB_REQ_SET_FEATURE:
+        goto fail;
+        break;
+    case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_DEVICE) << 8):
+        if (s->config)
+            usb_bt_fifo_out_enqueue(s, &s->outcmd, s->hci->cmd_send,
+                            usb_bt_hci_cmd_complete, p);
+        break;
+    default:
+    fail:
+        ret = USB_RET_STALL;
+        break;
+    }
+    return ret;
+}
+
+static int usb_bt_handle_data(USBDevice *dev, USBPacket *p)
+{
+    struct USBBtState *s = (struct USBBtState *) dev->opaque;
+    int ret = 0;
+
+    if (!s->config)
+        goto fail;
+
+    switch (p->pid) {
+    case USB_TOKEN_IN:
+        switch (p->ep->nr) {
+        case USB_EVT_EP:
+            ret = usb_bt_fifo_dequeue(&s->evt, p);
+            break;
+
+        case USB_ACL_EP:
+            ret = usb_bt_fifo_dequeue(&s->acl, p);
+            break;
+
+        case USB_SCO_EP:
+            ret = usb_bt_fifo_dequeue(&s->sco, p);
+            break;
+
+        default:
+            goto fail;
+        }
+        break;
+
+    case USB_TOKEN_OUT:
+        switch (p->ep->nr) {
+        case USB_ACL_EP:
+            usb_bt_fifo_out_enqueue(s, &s->outacl, s->hci->acl_send,
+                            usb_bt_hci_acl_complete, p);
+            break;
+
+        case USB_SCO_EP:
+            usb_bt_fifo_out_enqueue(s, &s->outsco, s->hci->sco_send,
+                            usb_bt_hci_sco_complete, p);
+            break;
+
+        default:
+            goto fail;
+        }
+        break;
+
+    default:
+    fail:
+        ret = USB_RET_STALL;
+        break;
+    }
+
+    return ret;
+}
+
+static void usb_bt_out_hci_packet_event(void *opaque,
+                const uint8_t *data, int len)
+{
+    struct USBBtState *s = (struct USBBtState *) opaque;
+
+    usb_bt_fifo_enqueue(&s->evt, data, len);
+}
+
+static void usb_bt_out_hci_packet_acl(void *opaque,
+                const uint8_t *data, int len)
+{
+    struct USBBtState *s = (struct USBBtState *) opaque;
+
+    usb_bt_fifo_enqueue(&s->acl, data, len);
+}
+
+static void usb_bt_handle_destroy(USBDevice *dev)
+{
+    struct USBBtState *s = (struct USBBtState *) dev->opaque;
+
+    s->hci->opaque = NULL;
+    s->hci->evt_recv = NULL;
+    s->hci->acl_recv = NULL;
+}
+
+static int usb_bt_initfn(USBDevice *dev)
+{
+    usb_desc_init(dev);
+    return 0;
+}
+
+USBDevice *usb_bt_init(USBBus *bus, HCIInfo *hci)
+{
+    USBDevice *dev;
+    struct USBBtState *s;
+
+    if (!hci)
+        return NULL;
+    dev = usb_create_simple(bus, "usb-bt-dongle");
+    if (!dev) {
+        return NULL;
+    }
+    s = DO_UPCAST(struct USBBtState, dev, dev);
+    s->dev.opaque = s;
+
+    s->hci = hci;
+    s->hci->opaque = s;
+    s->hci->evt_recv = usb_bt_out_hci_packet_event;
+    s->hci->acl_recv = usb_bt_out_hci_packet_acl;
+
+    usb_bt_handle_reset(&s->dev);
+
+    return dev;
+}
+
+static const VMStateDescription vmstate_usb_bt = {
+    .name = "usb-bt",
+    .unmigratable = 1,
+};
+
+static void usb_bt_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+    uc->init           = usb_bt_initfn;
+    uc->product_desc   = "QEMU BT dongle";
+    uc->usb_desc       = &desc_bluetooth;
+    uc->handle_reset   = usb_bt_handle_reset;
+    uc->handle_control = usb_bt_handle_control;
+    uc->handle_data    = usb_bt_handle_data;
+    uc->handle_destroy = usb_bt_handle_destroy;
+    dc->vmsd = &vmstate_usb_bt;
+}
+
+static TypeInfo bt_info = {
+    .name          = "usb-bt-dongle",
+    .parent        = TYPE_USB_DEVICE,
+    .instance_size = sizeof(struct USBBtState),
+    .class_init    = usb_bt_class_initfn,
+};
+
+static void usb_bt_register_types(void)
+{
+    type_register_static(&bt_info);
+}
+
+type_init(usb_bt_register_types)
diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c
new file mode 100644
index 0000000..f29544d
--- /dev/null
+++ b/hw/usb/dev-hid.c
@@ -0,0 +1,638 @@
+/*
+ * QEMU USB HID devices
+ *
+ * Copyright (c) 2005 Fabrice Bellard
+ * Copyright (c) 2007 OpenMoko, Inc.  (andrew at openedhand.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw/hw.h"
+#include "console.h"
+#include "hw/usb.h"
+#include "hw/usb/desc.h"
+#include "qemu-timer.h"
+#include "hw/hid.h"
+
+/* HID interface requests */
+#define GET_REPORT   0xa101
+#define GET_IDLE     0xa102
+#define GET_PROTOCOL 0xa103
+#define SET_REPORT   0x2109
+#define SET_IDLE     0x210a
+#define SET_PROTOCOL 0x210b
+
+/* HID descriptor types */
+#define USB_DT_HID    0x21
+#define USB_DT_REPORT 0x22
+#define USB_DT_PHY    0x23
+
+typedef struct USBHIDState {
+    USBDevice dev;
+    USBEndpoint *intr;
+    HIDState hid;
+} USBHIDState;
+
+enum {
+    STR_MANUFACTURER = 1,
+    STR_PRODUCT_MOUSE,
+    STR_PRODUCT_TABLET,
+    STR_PRODUCT_KEYBOARD,
+    STR_SERIALNUMBER,
+    STR_CONFIG_MOUSE,
+    STR_CONFIG_TABLET,
+    STR_CONFIG_KEYBOARD,
+};
+
+static const USBDescStrings desc_strings = {
+    [STR_MANUFACTURER]     = "QEMU " QEMU_VERSION,
+    [STR_PRODUCT_MOUSE]    = "QEMU USB Mouse",
+    [STR_PRODUCT_TABLET]   = "QEMU USB Tablet",
+    [STR_PRODUCT_KEYBOARD] = "QEMU USB Keyboard",
+    [STR_SERIALNUMBER]     = "42", /* == remote wakeup works */
+    [STR_CONFIG_MOUSE]     = "HID Mouse",
+    [STR_CONFIG_TABLET]    = "HID Tablet",
+    [STR_CONFIG_KEYBOARD]  = "HID Keyboard",
+};
+
+static const USBDescIface desc_iface_mouse = {
+    .bInterfaceNumber              = 0,
+    .bNumEndpoints                 = 1,
+    .bInterfaceClass               = USB_CLASS_HID,
+    .bInterfaceSubClass            = 0x01, /* boot */
+    .bInterfaceProtocol            = 0x02,
+    .ndesc                         = 1,
+    .descs = (USBDescOther[]) {
+        {
+            /* HID descriptor */
+            .data = (uint8_t[]) {
+                0x09,          /*  u8  bLength */
+                USB_DT_HID,    /*  u8  bDescriptorType */
+                0x01, 0x00,    /*  u16 HID_class */
+                0x00,          /*  u8  country_code */
+                0x01,          /*  u8  num_descriptors */
+                USB_DT_REPORT, /*  u8  type: Report */
+                52, 0,         /*  u16 len */
+            },
+        },
+    },
+    .eps = (USBDescEndpoint[]) {
+        {
+            .bEndpointAddress      = USB_DIR_IN | 0x01,
+            .bmAttributes          = USB_ENDPOINT_XFER_INT,
+            .wMaxPacketSize        = 4,
+            .bInterval             = 0x0a,
+        },
+    },
+};
+
+static const USBDescIface desc_iface_tablet = {
+    .bInterfaceNumber              = 0,
+    .bNumEndpoints                 = 1,
+    .bInterfaceClass               = USB_CLASS_HID,
+    .bInterfaceProtocol            = 0x02,
+    .ndesc                         = 1,
+    .descs = (USBDescOther[]) {
+        {
+            /* HID descriptor */
+            .data = (uint8_t[]) {
+                0x09,          /*  u8  bLength */
+                USB_DT_HID,    /*  u8  bDescriptorType */
+                0x01, 0x00,    /*  u16 HID_class */
+                0x00,          /*  u8  country_code */
+                0x01,          /*  u8  num_descriptors */
+                USB_DT_REPORT, /*  u8  type: Report */
+                74, 0,         /*  u16 len */
+            },
+        },
+    },
+    .eps = (USBDescEndpoint[]) {
+        {
+            .bEndpointAddress      = USB_DIR_IN | 0x01,
+            .bmAttributes          = USB_ENDPOINT_XFER_INT,
+            .wMaxPacketSize        = 8,
+            .bInterval             = 0x0a,
+        },
+    },
+};
+
+static const USBDescIface desc_iface_keyboard = {
+    .bInterfaceNumber              = 0,
+    .bNumEndpoints                 = 1,
+    .bInterfaceClass               = USB_CLASS_HID,
+    .bInterfaceSubClass            = 0x01, /* boot */
+    .bInterfaceProtocol            = 0x01, /* keyboard */
+    .ndesc                         = 1,
+    .descs = (USBDescOther[]) {
+        {
+            /* HID descriptor */
+            .data = (uint8_t[]) {
+                0x09,          /*  u8  bLength */
+                USB_DT_HID,    /*  u8  bDescriptorType */
+                0x11, 0x01,    /*  u16 HID_class */
+                0x00,          /*  u8  country_code */
+                0x01,          /*  u8  num_descriptors */
+                USB_DT_REPORT, /*  u8  type: Report */
+                0x3f, 0,       /*  u16 len */
+            },
+        },
+    },
+    .eps = (USBDescEndpoint[]) {
+        {
+            .bEndpointAddress      = USB_DIR_IN | 0x01,
+            .bmAttributes          = USB_ENDPOINT_XFER_INT,
+            .wMaxPacketSize        = 8,
+            .bInterval             = 0x0a,
+        },
+    },
+};
+
+static const USBDescDevice desc_device_mouse = {
+    .bcdUSB                        = 0x0100,
+    .bMaxPacketSize0               = 8,
+    .bNumConfigurations            = 1,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 1,
+            .bConfigurationValue   = 1,
+            .iConfiguration        = STR_CONFIG_MOUSE,
+            .bmAttributes          = 0xa0,
+            .bMaxPower             = 50,
+            .nif = 1,
+            .ifs = &desc_iface_mouse,
+        },
+    },
+};
+
+static const USBDescDevice desc_device_tablet = {
+    .bcdUSB                        = 0x0100,
+    .bMaxPacketSize0               = 8,
+    .bNumConfigurations            = 1,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 1,
+            .bConfigurationValue   = 1,
+            .iConfiguration        = STR_CONFIG_TABLET,
+            .bmAttributes          = 0xa0,
+            .bMaxPower             = 50,
+            .nif = 1,
+            .ifs = &desc_iface_tablet,
+        },
+    },
+};
+
+static const USBDescDevice desc_device_keyboard = {
+    .bcdUSB                        = 0x0100,
+    .bMaxPacketSize0               = 8,
+    .bNumConfigurations            = 1,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 1,
+            .bConfigurationValue   = 1,
+            .iConfiguration        = STR_CONFIG_KEYBOARD,
+            .bmAttributes          = 0xa0,
+            .bMaxPower             = 50,
+            .nif = 1,
+            .ifs = &desc_iface_keyboard,
+        },
+    },
+};
+
+static const USBDesc desc_mouse = {
+    .id = {
+        .idVendor          = 0x0627,
+        .idProduct         = 0x0001,
+        .bcdDevice         = 0,
+        .iManufacturer     = STR_MANUFACTURER,
+        .iProduct          = STR_PRODUCT_MOUSE,
+        .iSerialNumber     = STR_SERIALNUMBER,
+    },
+    .full = &desc_device_mouse,
+    .str  = desc_strings,
+};
+
+static const USBDesc desc_tablet = {
+    .id = {
+        .idVendor          = 0x0627,
+        .idProduct         = 0x0001,
+        .bcdDevice         = 0,
+        .iManufacturer     = STR_MANUFACTURER,
+        .iProduct          = STR_PRODUCT_TABLET,
+        .iSerialNumber     = STR_SERIALNUMBER,
+    },
+    .full = &desc_device_tablet,
+    .str  = desc_strings,
+};
+
+static const USBDesc desc_keyboard = {
+    .id = {
+        .idVendor          = 0x0627,
+        .idProduct         = 0x0001,
+        .bcdDevice         = 0,
+        .iManufacturer     = STR_MANUFACTURER,
+        .iProduct          = STR_PRODUCT_KEYBOARD,
+        .iSerialNumber     = STR_SERIALNUMBER,
+    },
+    .full = &desc_device_keyboard,
+    .str  = desc_strings,
+};
+
+static const uint8_t qemu_mouse_hid_report_descriptor[] = {
+    0x05, 0x01,		/* Usage Page (Generic Desktop) */
+    0x09, 0x02,		/* Usage (Mouse) */
+    0xa1, 0x01,		/* Collection (Application) */
+    0x09, 0x01,		/*   Usage (Pointer) */
+    0xa1, 0x00,		/*   Collection (Physical) */
+    0x05, 0x09,		/*     Usage Page (Button) */
+    0x19, 0x01,		/*     Usage Minimum (1) */
+    0x29, 0x03,		/*     Usage Maximum (3) */
+    0x15, 0x00,		/*     Logical Minimum (0) */
+    0x25, 0x01,		/*     Logical Maximum (1) */
+    0x95, 0x03,		/*     Report Count (3) */
+    0x75, 0x01,		/*     Report Size (1) */
+    0x81, 0x02,		/*     Input (Data, Variable, Absolute) */
+    0x95, 0x01,		/*     Report Count (1) */
+    0x75, 0x05,		/*     Report Size (5) */
+    0x81, 0x01,		/*     Input (Constant) */
+    0x05, 0x01,		/*     Usage Page (Generic Desktop) */
+    0x09, 0x30,		/*     Usage (X) */
+    0x09, 0x31,		/*     Usage (Y) */
+    0x09, 0x38,		/*     Usage (Wheel) */
+    0x15, 0x81,		/*     Logical Minimum (-0x7f) */
+    0x25, 0x7f,		/*     Logical Maximum (0x7f) */
+    0x75, 0x08,		/*     Report Size (8) */
+    0x95, 0x03,		/*     Report Count (3) */
+    0x81, 0x06,		/*     Input (Data, Variable, Relative) */
+    0xc0,		/*   End Collection */
+    0xc0,		/* End Collection */
+};
+
+static const uint8_t qemu_tablet_hid_report_descriptor[] = {
+    0x05, 0x01,		/* Usage Page (Generic Desktop) */
+    0x09, 0x01,		/* Usage (Pointer) */
+    0xa1, 0x01,		/* Collection (Application) */
+    0x09, 0x01,		/*   Usage (Pointer) */
+    0xa1, 0x00,		/*   Collection (Physical) */
+    0x05, 0x09,		/*     Usage Page (Button) */
+    0x19, 0x01,		/*     Usage Minimum (1) */
+    0x29, 0x03,		/*     Usage Maximum (3) */
+    0x15, 0x00,		/*     Logical Minimum (0) */
+    0x25, 0x01,		/*     Logical Maximum (1) */
+    0x95, 0x03,		/*     Report Count (3) */
+    0x75, 0x01,		/*     Report Size (1) */
+    0x81, 0x02,		/*     Input (Data, Variable, Absolute) */
+    0x95, 0x01,		/*     Report Count (1) */
+    0x75, 0x05,		/*     Report Size (5) */
+    0x81, 0x01,		/*     Input (Constant) */
+    0x05, 0x01,		/*     Usage Page (Generic Desktop) */
+    0x09, 0x30,		/*     Usage (X) */
+    0x09, 0x31,		/*     Usage (Y) */
+    0x15, 0x00,		/*     Logical Minimum (0) */
+    0x26, 0xff, 0x7f,	/*     Logical Maximum (0x7fff) */
+    0x35, 0x00,		/*     Physical Minimum (0) */
+    0x46, 0xff, 0x7f,	/*     Physical Maximum (0x7fff) */
+    0x75, 0x10,		/*     Report Size (16) */
+    0x95, 0x02,		/*     Report Count (2) */
+    0x81, 0x02,		/*     Input (Data, Variable, Absolute) */
+    0x05, 0x01,		/*     Usage Page (Generic Desktop) */
+    0x09, 0x38,		/*     Usage (Wheel) */
+    0x15, 0x81,		/*     Logical Minimum (-0x7f) */
+    0x25, 0x7f,		/*     Logical Maximum (0x7f) */
+    0x35, 0x00,		/*     Physical Minimum (same as logical) */
+    0x45, 0x00,		/*     Physical Maximum (same as logical) */
+    0x75, 0x08,		/*     Report Size (8) */
+    0x95, 0x01,		/*     Report Count (1) */
+    0x81, 0x06,		/*     Input (Data, Variable, Relative) */
+    0xc0,		/*   End Collection */
+    0xc0,		/* End Collection */
+};
+
+static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
+    0x05, 0x01,		/* Usage Page (Generic Desktop) */
+    0x09, 0x06,		/* Usage (Keyboard) */
+    0xa1, 0x01,		/* Collection (Application) */
+    0x75, 0x01,		/*   Report Size (1) */
+    0x95, 0x08,		/*   Report Count (8) */
+    0x05, 0x07,		/*   Usage Page (Key Codes) */
+    0x19, 0xe0,		/*   Usage Minimum (224) */
+    0x29, 0xe7,		/*   Usage Maximum (231) */
+    0x15, 0x00,		/*   Logical Minimum (0) */
+    0x25, 0x01,		/*   Logical Maximum (1) */
+    0x81, 0x02,		/*   Input (Data, Variable, Absolute) */
+    0x95, 0x01,		/*   Report Count (1) */
+    0x75, 0x08,		/*   Report Size (8) */
+    0x81, 0x01,		/*   Input (Constant) */
+    0x95, 0x05,		/*   Report Count (5) */
+    0x75, 0x01,		/*   Report Size (1) */
+    0x05, 0x08,		/*   Usage Page (LEDs) */
+    0x19, 0x01,		/*   Usage Minimum (1) */
+    0x29, 0x05,		/*   Usage Maximum (5) */
+    0x91, 0x02,		/*   Output (Data, Variable, Absolute) */
+    0x95, 0x01,		/*   Report Count (1) */
+    0x75, 0x03,		/*   Report Size (3) */
+    0x91, 0x01,		/*   Output (Constant) */
+    0x95, 0x06,		/*   Report Count (6) */
+    0x75, 0x08,		/*   Report Size (8) */
+    0x15, 0x00,		/*   Logical Minimum (0) */
+    0x25, 0xff,		/*   Logical Maximum (255) */
+    0x05, 0x07,		/*   Usage Page (Key Codes) */
+    0x19, 0x00,		/*   Usage Minimum (0) */
+    0x29, 0xff,		/*   Usage Maximum (255) */
+    0x81, 0x00,		/*   Input (Data, Array) */
+    0xc0,		/* End Collection */
+};
+
+static void usb_hid_changed(HIDState *hs)
+{
+    USBHIDState *us = container_of(hs, USBHIDState, hid);
+
+    usb_wakeup(us->intr);
+}
+
+static void usb_hid_handle_reset(USBDevice *dev)
+{
+    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
+
+    hid_reset(&us->hid);
+}
+
+static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
+               int request, int value, int index, int length, uint8_t *data)
+{
+    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
+    HIDState *hs = &us->hid;
+    int ret;
+
+    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
+    if (ret >= 0) {
+        return ret;
+    }
+
+    ret = 0;
+    switch (request) {
+        /* hid specific requests */
+    case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
+        switch (value >> 8) {
+        case 0x22:
+            if (hs->kind == HID_MOUSE) {
+		memcpy(data, qemu_mouse_hid_report_descriptor,
+		       sizeof(qemu_mouse_hid_report_descriptor));
+		ret = sizeof(qemu_mouse_hid_report_descriptor);
+            } else if (hs->kind == HID_TABLET) {
+                memcpy(data, qemu_tablet_hid_report_descriptor,
+		       sizeof(qemu_tablet_hid_report_descriptor));
+		ret = sizeof(qemu_tablet_hid_report_descriptor);
+            } else if (hs->kind == HID_KEYBOARD) {
+                memcpy(data, qemu_keyboard_hid_report_descriptor,
+                       sizeof(qemu_keyboard_hid_report_descriptor));
+                ret = sizeof(qemu_keyboard_hid_report_descriptor);
+            }
+            break;
+        default:
+            goto fail;
+        }
+        break;
+    case GET_REPORT:
+        if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
+            ret = hid_pointer_poll(hs, data, length);
+        } else if (hs->kind == HID_KEYBOARD) {
+            ret = hid_keyboard_poll(hs, data, length);
+        }
+        break;
+    case SET_REPORT:
+        if (hs->kind == HID_KEYBOARD) {
+            ret = hid_keyboard_write(hs, data, length);
+        } else {
+            goto fail;
+        }
+        break;
+    case GET_PROTOCOL:
+        if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
+            goto fail;
+        }
+        ret = 1;
+        data[0] = hs->protocol;
+        break;
+    case SET_PROTOCOL:
+        if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
+            goto fail;
+        }
+        ret = 0;
+        hs->protocol = value;
+        break;
+    case GET_IDLE:
+        ret = 1;
+        data[0] = hs->idle;
+        break;
+    case SET_IDLE:
+        hs->idle = (uint8_t) (value >> 8);
+        hid_set_next_idle(hs, qemu_get_clock_ns(vm_clock));
+        if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
+            hid_pointer_activate(hs);
+        }
+        ret = 0;
+        break;
+    default:
+    fail:
+        ret = USB_RET_STALL;
+        break;
+    }
+    return ret;
+}
+
+static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
+{
+    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
+    HIDState *hs = &us->hid;
+    uint8_t buf[p->iov.size];
+    int ret = 0;
+
+    switch (p->pid) {
+    case USB_TOKEN_IN:
+        if (p->ep->nr == 1) {
+            int64_t curtime = qemu_get_clock_ns(vm_clock);
+            if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
+                hid_pointer_activate(hs);
+            }
+            if (!hid_has_events(hs) &&
+                (!hs->idle || hs->next_idle_clock - curtime > 0)) {
+                return USB_RET_NAK;
+            }
+            hid_set_next_idle(hs, curtime);
+            if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
+                ret = hid_pointer_poll(hs, buf, p->iov.size);
+            } else if (hs->kind == HID_KEYBOARD) {
+                ret = hid_keyboard_poll(hs, buf, p->iov.size);
+            }
+            usb_packet_copy(p, buf, ret);
+        } else {
+            goto fail;
+        }
+        break;
+    case USB_TOKEN_OUT:
+    default:
+    fail:
+        ret = USB_RET_STALL;
+        break;
+    }
+    return ret;
+}
+
+static void usb_hid_handle_destroy(USBDevice *dev)
+{
+    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
+
+    hid_free(&us->hid);
+}
+
+static int usb_hid_initfn(USBDevice *dev, int kind)
+{
+    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
+
+    usb_desc_init(dev);
+    us->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
+    hid_init(&us->hid, kind, usb_hid_changed);
+    return 0;
+}
+
+static int usb_tablet_initfn(USBDevice *dev)
+{
+    return usb_hid_initfn(dev, HID_TABLET);
+}
+
+static int usb_mouse_initfn(USBDevice *dev)
+{
+    return usb_hid_initfn(dev, HID_MOUSE);
+}
+
+static int usb_keyboard_initfn(USBDevice *dev)
+{
+    return usb_hid_initfn(dev, HID_KEYBOARD);
+}
+
+static int usb_ptr_post_load(void *opaque, int version_id)
+{
+    USBHIDState *s = opaque;
+
+    if (s->dev.remote_wakeup) {
+        hid_pointer_activate(&s->hid);
+    }
+    return 0;
+}
+
+static const VMStateDescription vmstate_usb_ptr = {
+    .name = "usb-ptr",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .post_load = usb_ptr_post_load,
+    .fields = (VMStateField []) {
+        VMSTATE_USB_DEVICE(dev, USBHIDState),
+        VMSTATE_HID_POINTER_DEVICE(hid, USBHIDState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_usb_kbd = {
+    .name = "usb-kbd",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_USB_DEVICE(dev, USBHIDState),
+        VMSTATE_HID_KEYBOARD_DEVICE(hid, USBHIDState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void usb_hid_class_initfn(ObjectClass *klass, void *data)
+{
+    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+    uc->handle_reset   = usb_hid_handle_reset;
+    uc->handle_control = usb_hid_handle_control;
+    uc->handle_data    = usb_hid_handle_data;
+    uc->handle_destroy = usb_hid_handle_destroy;
+}
+
+static void usb_tablet_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+    usb_hid_class_initfn(klass, data);
+    uc->init           = usb_tablet_initfn;
+    uc->product_desc   = "QEMU USB Tablet";
+    uc->usb_desc       = &desc_tablet;
+    dc->vmsd = &vmstate_usb_ptr;
+}
+
+static TypeInfo usb_tablet_info = {
+    .name          = "usb-tablet",
+    .parent        = TYPE_USB_DEVICE,
+    .instance_size = sizeof(USBHIDState),
+    .class_init    = usb_tablet_class_initfn,
+};
+
+static void usb_mouse_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+    usb_hid_class_initfn(klass, data);
+    uc->init           = usb_mouse_initfn;
+    uc->product_desc   = "QEMU USB Mouse";
+    uc->usb_desc       = &desc_mouse;
+    dc->vmsd = &vmstate_usb_ptr;
+}
+
+static TypeInfo usb_mouse_info = {
+    .name          = "usb-mouse",
+    .parent        = TYPE_USB_DEVICE,
+    .instance_size = sizeof(USBHIDState),
+    .class_init    = usb_mouse_class_initfn,
+};
+
+static void usb_keyboard_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+    usb_hid_class_initfn(klass, data);
+    uc->init           = usb_keyboard_initfn;
+    uc->product_desc   = "QEMU USB Keyboard";
+    uc->usb_desc       = &desc_keyboard;
+    dc->vmsd = &vmstate_usb_kbd;
+}
+
+static TypeInfo usb_keyboard_info = {
+    .name          = "usb-kbd",
+    .parent        = TYPE_USB_DEVICE,
+    .instance_size = sizeof(USBHIDState),
+    .class_init    = usb_keyboard_class_initfn,
+};
+
+static void usb_hid_register_types(void)
+{
+    type_register_static(&usb_tablet_info);
+    usb_legacy_register("usb-tablet", "tablet", NULL);
+    type_register_static(&usb_mouse_info);
+    usb_legacy_register("usb-mouse", "mouse", NULL);
+    type_register_static(&usb_keyboard_info);
+    usb_legacy_register("usb-kbd", "keyboard", NULL);
+}
+
+type_init(usb_hid_register_types)
diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c
new file mode 100644
index 0000000..eb4e711
--- /dev/null
+++ b/hw/usb/dev-hub.c
@@ -0,0 +1,549 @@
+/*
+ * QEMU USB HUB emulation
+ *
+ * Copyright (c) 2005 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu-common.h"
+#include "hw/usb.h"
+#include "hw/usb/desc.h"
+
+//#define DEBUG
+
+#define NUM_PORTS 8
+
+typedef struct USBHubPort {
+    USBPort port;
+    uint16_t wPortStatus;
+    uint16_t wPortChange;
+} USBHubPort;
+
+typedef struct USBHubState {
+    USBDevice dev;
+    USBEndpoint *intr;
+    USBHubPort ports[NUM_PORTS];
+} USBHubState;
+
+#define ClearHubFeature		(0x2000 | USB_REQ_CLEAR_FEATURE)
+#define ClearPortFeature	(0x2300 | USB_REQ_CLEAR_FEATURE)
+#define GetHubDescriptor	(0xa000 | USB_REQ_GET_DESCRIPTOR)
+#define GetHubStatus		(0xa000 | USB_REQ_GET_STATUS)
+#define GetPortStatus		(0xa300 | USB_REQ_GET_STATUS)
+#define SetHubFeature		(0x2000 | USB_REQ_SET_FEATURE)
+#define SetPortFeature		(0x2300 | USB_REQ_SET_FEATURE)
+
+#define PORT_STAT_CONNECTION	0x0001
+#define PORT_STAT_ENABLE	0x0002
+#define PORT_STAT_SUSPEND	0x0004
+#define PORT_STAT_OVERCURRENT	0x0008
+#define PORT_STAT_RESET		0x0010
+#define PORT_STAT_POWER		0x0100
+#define PORT_STAT_LOW_SPEED	0x0200
+#define PORT_STAT_HIGH_SPEED    0x0400
+#define PORT_STAT_TEST          0x0800
+#define PORT_STAT_INDICATOR     0x1000
+
+#define PORT_STAT_C_CONNECTION	0x0001
+#define PORT_STAT_C_ENABLE	0x0002
+#define PORT_STAT_C_SUSPEND	0x0004
+#define PORT_STAT_C_OVERCURRENT	0x0008
+#define PORT_STAT_C_RESET	0x0010
+
+#define PORT_CONNECTION	        0
+#define PORT_ENABLE		1
+#define PORT_SUSPEND		2
+#define PORT_OVERCURRENT	3
+#define PORT_RESET		4
+#define PORT_POWER		8
+#define PORT_LOWSPEED		9
+#define PORT_HIGHSPEED		10
+#define PORT_C_CONNECTION	16
+#define PORT_C_ENABLE		17
+#define PORT_C_SUSPEND		18
+#define PORT_C_OVERCURRENT	19
+#define PORT_C_RESET		20
+#define PORT_TEST               21
+#define PORT_INDICATOR          22
+
+/* same as Linux kernel root hubs */
+
+enum {
+    STR_MANUFACTURER = 1,
+    STR_PRODUCT,
+    STR_SERIALNUMBER,
+};
+
+static const USBDescStrings desc_strings = {
+    [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
+    [STR_PRODUCT]      = "QEMU USB Hub",
+    [STR_SERIALNUMBER] = "314159",
+};
+
+static const USBDescIface desc_iface_hub = {
+    .bInterfaceNumber              = 0,
+    .bNumEndpoints                 = 1,
+    .bInterfaceClass               = USB_CLASS_HUB,
+    .eps = (USBDescEndpoint[]) {
+        {
+            .bEndpointAddress      = USB_DIR_IN | 0x01,
+            .bmAttributes          = USB_ENDPOINT_XFER_INT,
+            .wMaxPacketSize        = 1 + (NUM_PORTS + 7) / 8,
+            .bInterval             = 0xff,
+        },
+    }
+};
+
+static const USBDescDevice desc_device_hub = {
+    .bcdUSB                        = 0x0110,
+    .bDeviceClass                  = USB_CLASS_HUB,
+    .bMaxPacketSize0               = 8,
+    .bNumConfigurations            = 1,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 1,
+            .bConfigurationValue   = 1,
+            .bmAttributes          = 0xe0,
+            .nif = 1,
+            .ifs = &desc_iface_hub,
+        },
+    },
+};
+
+static const USBDesc desc_hub = {
+    .id = {
+        .idVendor          = 0x0409,
+        .idProduct         = 0x55aa,
+        .bcdDevice         = 0x0101,
+        .iManufacturer     = STR_MANUFACTURER,
+        .iProduct          = STR_PRODUCT,
+        .iSerialNumber     = STR_SERIALNUMBER,
+    },
+    .full = &desc_device_hub,
+    .str  = desc_strings,
+};
+
+static const uint8_t qemu_hub_hub_descriptor[] =
+{
+	0x00,			/*  u8  bLength; patched in later */
+	0x29,			/*  u8  bDescriptorType; Hub-descriptor */
+	0x00,			/*  u8  bNbrPorts; (patched later) */
+	0x0a,			/* u16  wHubCharacteristics; */
+	0x00,			/*   (per-port OC, no power switching) */
+	0x01,			/*  u8  bPwrOn2pwrGood; 2ms */
+	0x00			/*  u8  bHubContrCurrent; 0 mA */
+
+        /* DeviceRemovable and PortPwrCtrlMask patched in later */
+};
+
+static void usb_hub_attach(USBPort *port1)
+{
+    USBHubState *s = port1->opaque;
+    USBHubPort *port = &s->ports[port1->index];
+
+    port->wPortStatus |= PORT_STAT_CONNECTION;
+    port->wPortChange |= PORT_STAT_C_CONNECTION;
+    if (port->port.dev->speed == USB_SPEED_LOW) {
+        port->wPortStatus |= PORT_STAT_LOW_SPEED;
+    } else {
+        port->wPortStatus &= ~PORT_STAT_LOW_SPEED;
+    }
+    usb_wakeup(s->intr);
+}
+
+static void usb_hub_detach(USBPort *port1)
+{
+    USBHubState *s = port1->opaque;
+    USBHubPort *port = &s->ports[port1->index];
+
+    usb_wakeup(s->intr);
+
+    /* Let upstream know the device on this port is gone */
+    s->dev.port->ops->child_detach(s->dev.port, port1->dev);
+
+    port->wPortStatus &= ~PORT_STAT_CONNECTION;
+    port->wPortChange |= PORT_STAT_C_CONNECTION;
+    if (port->wPortStatus & PORT_STAT_ENABLE) {
+        port->wPortStatus &= ~PORT_STAT_ENABLE;
+        port->wPortChange |= PORT_STAT_C_ENABLE;
+    }
+}
+
+static void usb_hub_child_detach(USBPort *port1, USBDevice *child)
+{
+    USBHubState *s = port1->opaque;
+
+    /* Pass along upstream */
+    s->dev.port->ops->child_detach(s->dev.port, child);
+}
+
+static void usb_hub_wakeup(USBPort *port1)
+{
+    USBHubState *s = port1->opaque;
+    USBHubPort *port = &s->ports[port1->index];
+
+    if (port->wPortStatus & PORT_STAT_SUSPEND) {
+        port->wPortChange |= PORT_STAT_C_SUSPEND;
+        usb_wakeup(s->intr);
+    }
+}
+
+static void usb_hub_complete(USBPort *port, USBPacket *packet)
+{
+    USBHubState *s = port->opaque;
+
+    /*
+     * Just pass it along upstream for now.
+     *
+     * If we ever implement usb 2.0 split transactions this will
+     * become a little more complicated ...
+     *
+     * Can't use usb_packet_complete() here because packet->owner is
+     * cleared already, go call the ->complete() callback directly
+     * instead.
+     */
+    s->dev.port->ops->complete(s->dev.port, packet);
+}
+
+static USBDevice *usb_hub_find_device(USBDevice *dev, uint8_t addr)
+{
+    USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
+    USBHubPort *port;
+    USBDevice *downstream;
+    int i;
+
+    for (i = 0; i < NUM_PORTS; i++) {
+        port = &s->ports[i];
+        if (!(port->wPortStatus & PORT_STAT_ENABLE)) {
+            continue;
+        }
+        downstream = usb_find_device(&port->port, addr);
+        if (downstream != NULL) {
+            return downstream;
+        }
+    }
+    return NULL;
+}
+
+static void usb_hub_handle_reset(USBDevice *dev)
+{
+    USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
+    USBHubPort *port;
+    int i;
+
+    for (i = 0; i < NUM_PORTS; i++) {
+        port = s->ports + i;
+        port->wPortStatus = PORT_STAT_POWER;
+        port->wPortChange = 0;
+        if (port->port.dev && port->port.dev->attached) {
+            port->wPortStatus |= PORT_STAT_CONNECTION;
+            port->wPortChange |= PORT_STAT_C_CONNECTION;
+            if (port->port.dev->speed == USB_SPEED_LOW) {
+                port->wPortStatus |= PORT_STAT_LOW_SPEED;
+            }
+        }
+    }
+}
+
+static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
+               int request, int value, int index, int length, uint8_t *data)
+{
+    USBHubState *s = (USBHubState *)dev;
+    int ret;
+
+    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
+    if (ret >= 0) {
+        return ret;
+    }
+
+    switch(request) {
+    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
+        if (value == 0 && index != 0x81) { /* clear ep halt */
+            goto fail;
+        }
+        ret = 0;
+        break;
+        /* usb specific requests */
+    case GetHubStatus:
+        data[0] = 0;
+        data[1] = 0;
+        data[2] = 0;
+        data[3] = 0;
+        ret = 4;
+        break;
+    case GetPortStatus:
+        {
+            unsigned int n = index - 1;
+            USBHubPort *port;
+            if (n >= NUM_PORTS) {
+                goto fail;
+            }
+            port = &s->ports[n];
+            data[0] = port->wPortStatus;
+            data[1] = port->wPortStatus >> 8;
+            data[2] = port->wPortChange;
+            data[3] = port->wPortChange >> 8;
+            ret = 4;
+        }
+        break;
+    case SetHubFeature:
+    case ClearHubFeature:
+        if (value == 0 || value == 1) {
+        } else {
+            goto fail;
+        }
+        ret = 0;
+        break;
+    case SetPortFeature:
+        {
+            unsigned int n = index - 1;
+            USBHubPort *port;
+            USBDevice *dev;
+            if (n >= NUM_PORTS) {
+                goto fail;
+            }
+            port = &s->ports[n];
+            dev = port->port.dev;
+            switch(value) {
+            case PORT_SUSPEND:
+                port->wPortStatus |= PORT_STAT_SUSPEND;
+                break;
+            case PORT_RESET:
+                if (dev && dev->attached) {
+                    usb_device_reset(dev);
+                    port->wPortChange |= PORT_STAT_C_RESET;
+                    /* set enable bit */
+                    port->wPortStatus |= PORT_STAT_ENABLE;
+                }
+                break;
+            case PORT_POWER:
+                break;
+            default:
+                goto fail;
+            }
+            ret = 0;
+        }
+        break;
+    case ClearPortFeature:
+        {
+            unsigned int n = index - 1;
+            USBHubPort *port;
+
+            if (n >= NUM_PORTS) {
+                goto fail;
+            }
+            port = &s->ports[n];
+            switch(value) {
+            case PORT_ENABLE:
+                port->wPortStatus &= ~PORT_STAT_ENABLE;
+                break;
+            case PORT_C_ENABLE:
+                port->wPortChange &= ~PORT_STAT_C_ENABLE;
+                break;
+            case PORT_SUSPEND:
+                port->wPortStatus &= ~PORT_STAT_SUSPEND;
+                break;
+            case PORT_C_SUSPEND:
+                port->wPortChange &= ~PORT_STAT_C_SUSPEND;
+                break;
+            case PORT_C_CONNECTION:
+                port->wPortChange &= ~PORT_STAT_C_CONNECTION;
+                break;
+            case PORT_C_OVERCURRENT:
+                port->wPortChange &= ~PORT_STAT_C_OVERCURRENT;
+                break;
+            case PORT_C_RESET:
+                port->wPortChange &= ~PORT_STAT_C_RESET;
+                break;
+            default:
+                goto fail;
+            }
+            ret = 0;
+        }
+        break;
+    case GetHubDescriptor:
+        {
+            unsigned int n, limit, var_hub_size = 0;
+            memcpy(data, qemu_hub_hub_descriptor,
+                   sizeof(qemu_hub_hub_descriptor));
+            data[2] = NUM_PORTS;
+
+            /* fill DeviceRemovable bits */
+            limit = ((NUM_PORTS + 1 + 7) / 8) + 7;
+            for (n = 7; n < limit; n++) {
+                data[n] = 0x00;
+                var_hub_size++;
+            }
+
+            /* fill PortPwrCtrlMask bits */
+            limit = limit + ((NUM_PORTS + 7) / 8);
+            for (;n < limit; n++) {
+                data[n] = 0xff;
+                var_hub_size++;
+            }
+
+            ret = sizeof(qemu_hub_hub_descriptor) + var_hub_size;
+            data[0] = ret;
+            break;
+        }
+    default:
+    fail:
+        ret = USB_RET_STALL;
+        break;
+    }
+    return ret;
+}
+
+static int usb_hub_handle_data(USBDevice *dev, USBPacket *p)
+{
+    USBHubState *s = (USBHubState *)dev;
+    int ret;
+
+    switch(p->pid) {
+    case USB_TOKEN_IN:
+        if (p->ep->nr == 1) {
+            USBHubPort *port;
+            unsigned int status;
+            uint8_t buf[4];
+            int i, n;
+            n = (NUM_PORTS + 1 + 7) / 8;
+            if (p->iov.size == 1) { /* FreeBSD workaround */
+                n = 1;
+            } else if (n > p->iov.size) {
+                return USB_RET_BABBLE;
+            }
+            status = 0;
+            for(i = 0; i < NUM_PORTS; i++) {
+                port = &s->ports[i];
+                if (port->wPortChange)
+                    status |= (1 << (i + 1));
+            }
+            if (status != 0) {
+                for(i = 0; i < n; i++) {
+                    buf[i] = status >> (8 * i);
+                }
+                usb_packet_copy(p, buf, n);
+                ret = n;
+            } else {
+                ret = USB_RET_NAK; /* usb11 11.13.1 */
+            }
+        } else {
+            goto fail;
+        }
+        break;
+    case USB_TOKEN_OUT:
+    default:
+    fail:
+        ret = USB_RET_STALL;
+        break;
+    }
+    return ret;
+}
+
+static void usb_hub_handle_destroy(USBDevice *dev)
+{
+    USBHubState *s = (USBHubState *)dev;
+    int i;
+
+    for (i = 0; i < NUM_PORTS; i++) {
+        usb_unregister_port(usb_bus_from_device(dev),
+                            &s->ports[i].port);
+    }
+}
+
+static USBPortOps usb_hub_port_ops = {
+    .attach = usb_hub_attach,
+    .detach = usb_hub_detach,
+    .child_detach = usb_hub_child_detach,
+    .wakeup = usb_hub_wakeup,
+    .complete = usb_hub_complete,
+};
+
+static int usb_hub_initfn(USBDevice *dev)
+{
+    USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
+    USBHubPort *port;
+    int i;
+
+    usb_desc_init(dev);
+    s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
+    for (i = 0; i < NUM_PORTS; i++) {
+        port = &s->ports[i];
+        usb_register_port(usb_bus_from_device(dev),
+                          &port->port, s, i, &usb_hub_port_ops,
+                          USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
+        usb_port_location(&port->port, dev->port, i+1);
+    }
+    usb_hub_handle_reset(dev);
+    return 0;
+}
+
+static const VMStateDescription vmstate_usb_hub_port = {
+    .name = "usb-hub-port",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_UINT16(wPortStatus, USBHubPort),
+        VMSTATE_UINT16(wPortChange, USBHubPort),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_usb_hub = {
+    .name = "usb-hub",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_USB_DEVICE(dev, USBHubState),
+        VMSTATE_STRUCT_ARRAY(ports, USBHubState, NUM_PORTS, 0,
+                             vmstate_usb_hub_port, USBHubPort),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void usb_hub_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+    uc->init           = usb_hub_initfn;
+    uc->product_desc   = "QEMU USB Hub";
+    uc->usb_desc       = &desc_hub;
+    uc->find_device    = usb_hub_find_device;
+    uc->handle_reset   = usb_hub_handle_reset;
+    uc->handle_control = usb_hub_handle_control;
+    uc->handle_data    = usb_hub_handle_data;
+    uc->handle_destroy = usb_hub_handle_destroy;
+    dc->fw_name = "hub";
+    dc->vmsd = &vmstate_usb_hub;
+}
+
+static TypeInfo hub_info = {
+    .name          = "usb-hub",
+    .parent        = TYPE_USB_DEVICE,
+    .instance_size = sizeof(USBHubState),
+    .class_init    = usb_hub_class_initfn,
+};
+
+static void usb_hub_register_types(void)
+{
+    type_register_static(&hub_info);
+}
+
+type_init(usb_hub_register_types)
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
new file mode 100644
index 0000000..cff55f2
--- /dev/null
+++ b/hw/usb/dev-network.c
@@ -0,0 +1,1423 @@
+/*
+ * QEMU USB Net devices
+ *
+ * Copyright (c) 2006 Thomas Sailer
+ * Copyright (c) 2008 Andrzej Zaborowski
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu-common.h"
+#include "hw/usb.h"
+#include "hw/usb/desc.h"
+#include "net.h"
+#include "qemu-queue.h"
+#include "sysemu.h"
+#include "iov.h"
+
+/*#define TRAFFIC_DEBUG*/
+/* Thanks to NetChip Technologies for donating this product ID.
+ * It's for devices with only CDC Ethernet configurations.
+ */
+#define CDC_VENDOR_NUM          0x0525  /* NetChip */
+#define CDC_PRODUCT_NUM         0xa4a1  /* Linux-USB Ethernet Gadget */
+/* For hardware that can talk RNDIS and either of the above protocols,
+ * use this ID ... the windows INF files will know it.
+ */
+#define RNDIS_VENDOR_NUM        0x0525  /* NetChip */
+#define RNDIS_PRODUCT_NUM       0xa4a2  /* Ethernet/RNDIS Gadget */
+
+enum usbstring_idx {
+    STRING_MANUFACTURER		= 1,
+    STRING_PRODUCT,
+    STRING_ETHADDR,
+    STRING_DATA,
+    STRING_CONTROL,
+    STRING_RNDIS_CONTROL,
+    STRING_CDC,
+    STRING_SUBSET,
+    STRING_RNDIS,
+    STRING_SERIALNUMBER,
+};
+
+#define DEV_CONFIG_VALUE		1	/* CDC or a subset */
+#define DEV_RNDIS_CONFIG_VALUE		2	/* RNDIS; optional */
+
+#define USB_CDC_SUBCLASS_ACM		0x02
+#define USB_CDC_SUBCLASS_ETHERNET	0x06
+
+#define USB_CDC_PROTO_NONE		0
+#define USB_CDC_ACM_PROTO_VENDOR	0xff
+
+#define USB_CDC_HEADER_TYPE		0x00	/* header_desc */
+#define USB_CDC_CALL_MANAGEMENT_TYPE	0x01	/* call_mgmt_descriptor */
+#define USB_CDC_ACM_TYPE		0x02	/* acm_descriptor */
+#define USB_CDC_UNION_TYPE		0x06	/* union_desc */
+#define USB_CDC_ETHERNET_TYPE		0x0f	/* ether_desc */
+
+#define USB_CDC_SEND_ENCAPSULATED_COMMAND	0x00
+#define USB_CDC_GET_ENCAPSULATED_RESPONSE	0x01
+#define USB_CDC_REQ_SET_LINE_CODING		0x20
+#define USB_CDC_REQ_GET_LINE_CODING		0x21
+#define USB_CDC_REQ_SET_CONTROL_LINE_STATE	0x22
+#define USB_CDC_REQ_SEND_BREAK			0x23
+#define USB_CDC_SET_ETHERNET_MULTICAST_FILTERS	0x40
+#define USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER	0x41
+#define USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER	0x42
+#define USB_CDC_SET_ETHERNET_PACKET_FILTER	0x43
+#define USB_CDC_GET_ETHERNET_STATISTIC		0x44
+
+#define LOG2_STATUS_INTERVAL_MSEC	5    /* 1 << 5 == 32 msec */
+#define STATUS_BYTECOUNT		16   /* 8 byte header + data */
+
+#define ETH_FRAME_LEN			1514 /* Max. octets in frame sans FCS */
+
+static const USBDescStrings usb_net_stringtable = {
+    [STRING_MANUFACTURER]       = "QEMU",
+    [STRING_PRODUCT]            = "RNDIS/QEMU USB Network Device",
+    [STRING_ETHADDR]            = "400102030405",
+    [STRING_DATA]               = "QEMU USB Net Data Interface",
+    [STRING_CONTROL]            = "QEMU USB Net Control Interface",
+    [STRING_RNDIS_CONTROL]      = "QEMU USB Net RNDIS Control Interface",
+    [STRING_CDC]                = "QEMU USB Net CDC",
+    [STRING_SUBSET]             = "QEMU USB Net Subset",
+    [STRING_RNDIS]              = "QEMU USB Net RNDIS",
+    [STRING_SERIALNUMBER]       = "1",
+};
+
+static const USBDescIface desc_iface_rndis[] = {
+    {
+        /* RNDIS Control Interface */
+        .bInterfaceNumber              = 0,
+        .bNumEndpoints                 = 1,
+        .bInterfaceClass               = USB_CLASS_COMM,
+        .bInterfaceSubClass            = USB_CDC_SUBCLASS_ACM,
+        .bInterfaceProtocol            = USB_CDC_ACM_PROTO_VENDOR,
+        .iInterface                    = STRING_RNDIS_CONTROL,
+        .ndesc                         = 4,
+        .descs = (USBDescOther[]) {
+            {
+                /* Header Descriptor */
+                .data = (uint8_t[]) {
+                    0x05,                       /*  u8    bLength */
+                    USB_DT_CS_INTERFACE,        /*  u8    bDescriptorType */
+                    USB_CDC_HEADER_TYPE,        /*  u8    bDescriptorSubType */
+                    0x10, 0x01,                 /*  le16  bcdCDC */
+                },
+            },{
+                /* Call Management Descriptor */
+                .data = (uint8_t[]) {
+                    0x05,                       /*  u8    bLength */
+                    USB_DT_CS_INTERFACE,        /*  u8    bDescriptorType */
+                    USB_CDC_CALL_MANAGEMENT_TYPE, /*  u8    bDescriptorSubType */
+                    0x00,                       /*  u8    bmCapabilities */
+                    0x01,                       /*  u8    bDataInterface */
+                },
+            },{
+                /* ACM Descriptor */
+                .data = (uint8_t[]) {
+                    0x04,                       /*  u8    bLength */
+                    USB_DT_CS_INTERFACE,        /*  u8    bDescriptorType */
+                    USB_CDC_ACM_TYPE,           /*  u8    bDescriptorSubType */
+                    0x00,                       /*  u8    bmCapabilities */
+                },
+            },{
+                /* Union Descriptor */
+                .data = (uint8_t[]) {
+                    0x05,                       /*  u8    bLength */
+                    USB_DT_CS_INTERFACE,        /*  u8    bDescriptorType */
+                    USB_CDC_UNION_TYPE,         /*  u8    bDescriptorSubType */
+                    0x00,                       /*  u8    bMasterInterface0 */
+                    0x01,                       /*  u8    bSlaveInterface0 */
+                },
+            },
+        },
+        .eps = (USBDescEndpoint[]) {
+            {
+                .bEndpointAddress      = USB_DIR_IN | 0x01,
+                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .wMaxPacketSize        = STATUS_BYTECOUNT,
+                .bInterval             = 1 << LOG2_STATUS_INTERVAL_MSEC,
+            },
+        }
+    },{
+        /* RNDIS Data Interface */
+        .bInterfaceNumber              = 1,
+        .bNumEndpoints                 = 2,
+        .bInterfaceClass               = USB_CLASS_CDC_DATA,
+        .iInterface                    = STRING_DATA,
+        .eps = (USBDescEndpoint[]) {
+            {
+                .bEndpointAddress      = USB_DIR_IN | 0x02,
+                .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+                .wMaxPacketSize        = 0x40,
+            },{
+                .bEndpointAddress      = USB_DIR_OUT | 0x02,
+                .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+                .wMaxPacketSize        = 0x40,
+            }
+        }
+    }
+};
+
+static const USBDescIface desc_iface_cdc[] = {
+    {
+        /* CDC Control Interface */
+        .bInterfaceNumber              = 0,
+        .bNumEndpoints                 = 1,
+        .bInterfaceClass               = USB_CLASS_COMM,
+        .bInterfaceSubClass            = USB_CDC_SUBCLASS_ETHERNET,
+        .bInterfaceProtocol            = USB_CDC_PROTO_NONE,
+        .iInterface                    = STRING_CONTROL,
+        .ndesc                         = 3,
+        .descs = (USBDescOther[]) {
+            {
+                /* Header Descriptor */
+                .data = (uint8_t[]) {
+                    0x05,                       /*  u8    bLength */
+                    USB_DT_CS_INTERFACE,        /*  u8    bDescriptorType */
+                    USB_CDC_HEADER_TYPE,        /*  u8    bDescriptorSubType */
+                    0x10, 0x01,                 /*  le16  bcdCDC */
+                },
+            },{
+                /* Union Descriptor */
+                .data = (uint8_t[]) {
+                    0x05,                       /*  u8    bLength */
+                    USB_DT_CS_INTERFACE,        /*  u8    bDescriptorType */
+                    USB_CDC_UNION_TYPE,         /*  u8    bDescriptorSubType */
+                    0x00,                       /*  u8    bMasterInterface0 */
+                    0x01,                       /*  u8    bSlaveInterface0 */
+                },
+            },{
+                /* Ethernet Descriptor */
+                .data = (uint8_t[]) {
+                    0x0d,                       /*  u8    bLength */
+                    USB_DT_CS_INTERFACE,        /*  u8    bDescriptorType */
+                    USB_CDC_ETHERNET_TYPE,      /*  u8    bDescriptorSubType */
+                    STRING_ETHADDR,             /*  u8    iMACAddress */
+                    0x00, 0x00, 0x00, 0x00,     /*  le32  bmEthernetStatistics */
+                    ETH_FRAME_LEN & 0xff,
+                    ETH_FRAME_LEN >> 8,         /*  le16  wMaxSegmentSize */
+                    0x00, 0x00,                 /*  le16  wNumberMCFilters */
+                    0x00,                       /*  u8    bNumberPowerFilters */
+                },
+            },
+        },
+        .eps = (USBDescEndpoint[]) {
+            {
+                .bEndpointAddress      = USB_DIR_IN | 0x01,
+                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .wMaxPacketSize        = STATUS_BYTECOUNT,
+                .bInterval             = 1 << LOG2_STATUS_INTERVAL_MSEC,
+            },
+        }
+    },{
+        /* CDC Data Interface (off) */
+        .bInterfaceNumber              = 1,
+        .bAlternateSetting             = 0,
+        .bNumEndpoints                 = 0,
+        .bInterfaceClass               = USB_CLASS_CDC_DATA,
+    },{
+        /* CDC Data Interface */
+        .bInterfaceNumber              = 1,
+        .bAlternateSetting             = 1,
+        .bNumEndpoints                 = 2,
+        .bInterfaceClass               = USB_CLASS_CDC_DATA,
+        .iInterface                    = STRING_DATA,
+        .eps = (USBDescEndpoint[]) {
+            {
+                .bEndpointAddress      = USB_DIR_IN | 0x02,
+                .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+                .wMaxPacketSize        = 0x40,
+            },{
+                .bEndpointAddress      = USB_DIR_OUT | 0x02,
+                .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+                .wMaxPacketSize        = 0x40,
+            }
+        }
+    }
+};
+
+static const USBDescDevice desc_device_net = {
+    .bcdUSB                        = 0x0200,
+    .bDeviceClass                  = USB_CLASS_COMM,
+    .bMaxPacketSize0               = 0x40,
+    .bNumConfigurations            = 2,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 2,
+            .bConfigurationValue   = DEV_RNDIS_CONFIG_VALUE,
+            .iConfiguration        = STRING_RNDIS,
+            .bmAttributes          = 0xc0,
+            .bMaxPower             = 0x32,
+            .nif = ARRAY_SIZE(desc_iface_rndis),
+            .ifs = desc_iface_rndis,
+        },{
+            .bNumInterfaces        = 2,
+            .bConfigurationValue   = DEV_CONFIG_VALUE,
+            .iConfiguration        = STRING_CDC,
+            .bmAttributes          = 0xc0,
+            .bMaxPower             = 0x32,
+            .nif = ARRAY_SIZE(desc_iface_cdc),
+            .ifs = desc_iface_cdc,
+        }
+    },
+};
+
+static const USBDesc desc_net = {
+    .id = {
+        .idVendor          = RNDIS_VENDOR_NUM,
+        .idProduct         = RNDIS_PRODUCT_NUM,
+        .bcdDevice         = 0,
+        .iManufacturer     = STRING_MANUFACTURER,
+        .iProduct          = STRING_PRODUCT,
+        .iSerialNumber     = STRING_SERIALNUMBER,
+    },
+    .full = &desc_device_net,
+    .str  = usb_net_stringtable,
+};
+
+/*
+ * RNDIS Definitions - in theory not specific to USB.
+ */
+#define RNDIS_MAXIMUM_FRAME_SIZE	1518
+#define RNDIS_MAX_TOTAL_SIZE		1558
+
+/* Remote NDIS Versions */
+#define RNDIS_MAJOR_VERSION		1
+#define RNDIS_MINOR_VERSION		0
+
+/* Status Values */
+#define RNDIS_STATUS_SUCCESS		0x00000000U /* Success */
+#define RNDIS_STATUS_FAILURE		0xc0000001U /* Unspecified error */
+#define RNDIS_STATUS_INVALID_DATA	0xc0010015U /* Invalid data */
+#define RNDIS_STATUS_NOT_SUPPORTED	0xc00000bbU /* Unsupported request */
+#define RNDIS_STATUS_MEDIA_CONNECT	0x4001000bU /* Device connected */
+#define RNDIS_STATUS_MEDIA_DISCONNECT	0x4001000cU /* Device disconnected */
+
+/* Message Set for Connectionless (802.3) Devices */
+enum {
+    RNDIS_PACKET_MSG		= 1,
+    RNDIS_INITIALIZE_MSG	= 2,	/* Initialize device */
+    RNDIS_HALT_MSG		= 3,
+    RNDIS_QUERY_MSG		= 4,
+    RNDIS_SET_MSG		= 5,
+    RNDIS_RESET_MSG		= 6,
+    RNDIS_INDICATE_STATUS_MSG	= 7,
+    RNDIS_KEEPALIVE_MSG		= 8,
+};
+
+/* Message completion */
+enum {
+    RNDIS_INITIALIZE_CMPLT	= 0x80000002U,
+    RNDIS_QUERY_CMPLT		= 0x80000004U,
+    RNDIS_SET_CMPLT		= 0x80000005U,
+    RNDIS_RESET_CMPLT		= 0x80000006U,
+    RNDIS_KEEPALIVE_CMPLT	= 0x80000008U,
+};
+
+/* Device Flags */
+enum {
+    RNDIS_DF_CONNECTIONLESS	= 1,
+    RNDIS_DF_CONNECTIONORIENTED	= 2,
+};
+
+#define RNDIS_MEDIUM_802_3		0x00000000U
+
+/* from drivers/net/sk98lin/h/skgepnmi.h */
+#define OID_PNP_CAPABILITIES		0xfd010100
+#define OID_PNP_SET_POWER		0xfd010101
+#define OID_PNP_QUERY_POWER		0xfd010102
+#define OID_PNP_ADD_WAKE_UP_PATTERN	0xfd010103
+#define OID_PNP_REMOVE_WAKE_UP_PATTERN	0xfd010104
+#define OID_PNP_ENABLE_WAKE_UP		0xfd010106
+
+typedef uint32_t le32;
+
+typedef struct rndis_init_msg_type {
+    le32 MessageType;
+    le32 MessageLength;
+    le32 RequestID;
+    le32 MajorVersion;
+    le32 MinorVersion;
+    le32 MaxTransferSize;
+} rndis_init_msg_type;
+
+typedef struct rndis_init_cmplt_type {
+    le32 MessageType;
+    le32 MessageLength;
+    le32 RequestID;
+    le32 Status;
+    le32 MajorVersion;
+    le32 MinorVersion;
+    le32 DeviceFlags;
+    le32 Medium;
+    le32 MaxPacketsPerTransfer;
+    le32 MaxTransferSize;
+    le32 PacketAlignmentFactor;
+    le32 AFListOffset;
+    le32 AFListSize;
+} rndis_init_cmplt_type;
+
+typedef struct rndis_halt_msg_type {
+    le32 MessageType;
+    le32 MessageLength;
+    le32 RequestID;
+} rndis_halt_msg_type;
+
+typedef struct rndis_query_msg_type {
+    le32 MessageType;
+    le32 MessageLength;
+    le32 RequestID;
+    le32 OID;
+    le32 InformationBufferLength;
+    le32 InformationBufferOffset;
+    le32 DeviceVcHandle;
+} rndis_query_msg_type;
+
+typedef struct rndis_query_cmplt_type {
+    le32 MessageType;
+    le32 MessageLength;
+    le32 RequestID;
+    le32 Status;
+    le32 InformationBufferLength;
+    le32 InformationBufferOffset;
+} rndis_query_cmplt_type;
+
+typedef struct rndis_set_msg_type {
+    le32 MessageType;
+    le32 MessageLength;
+    le32 RequestID;
+    le32 OID;
+    le32 InformationBufferLength;
+    le32 InformationBufferOffset;
+    le32 DeviceVcHandle;
+} rndis_set_msg_type;
+
+typedef struct rndis_set_cmplt_type {
+    le32 MessageType;
+    le32 MessageLength;
+    le32 RequestID;
+    le32 Status;
+} rndis_set_cmplt_type;
+
+typedef struct rndis_reset_msg_type {
+    le32 MessageType;
+    le32 MessageLength;
+    le32 Reserved;
+} rndis_reset_msg_type;
+
+typedef struct rndis_reset_cmplt_type {
+    le32 MessageType;
+    le32 MessageLength;
+    le32 Status;
+    le32 AddressingReset;
+} rndis_reset_cmplt_type;
+
+typedef struct rndis_indicate_status_msg_type {
+    le32 MessageType;
+    le32 MessageLength;
+    le32 Status;
+    le32 StatusBufferLength;
+    le32 StatusBufferOffset;
+} rndis_indicate_status_msg_type;
+
+typedef struct rndis_keepalive_msg_type {
+    le32 MessageType;
+    le32 MessageLength;
+    le32 RequestID;
+} rndis_keepalive_msg_type;
+
+typedef struct rndis_keepalive_cmplt_type {
+    le32 MessageType;
+    le32 MessageLength;
+    le32 RequestID;
+    le32 Status;
+} rndis_keepalive_cmplt_type;
+
+struct rndis_packet_msg_type {
+    le32 MessageType;
+    le32 MessageLength;
+    le32 DataOffset;
+    le32 DataLength;
+    le32 OOBDataOffset;
+    le32 OOBDataLength;
+    le32 NumOOBDataElements;
+    le32 PerPacketInfoOffset;
+    le32 PerPacketInfoLength;
+    le32 VcHandle;
+    le32 Reserved;
+};
+
+struct rndis_config_parameter {
+    le32 ParameterNameOffset;
+    le32 ParameterNameLength;
+    le32 ParameterType;
+    le32 ParameterValueOffset;
+    le32 ParameterValueLength;
+};
+
+/* implementation specific */
+enum rndis_state
+{
+    RNDIS_UNINITIALIZED,
+    RNDIS_INITIALIZED,
+    RNDIS_DATA_INITIALIZED,
+};
+
+/* from ndis.h */
+enum ndis_oid {
+    /* Required Object IDs (OIDs) */
+    OID_GEN_SUPPORTED_LIST		= 0x00010101,
+    OID_GEN_HARDWARE_STATUS		= 0x00010102,
+    OID_GEN_MEDIA_SUPPORTED		= 0x00010103,
+    OID_GEN_MEDIA_IN_USE		= 0x00010104,
+    OID_GEN_MAXIMUM_LOOKAHEAD		= 0x00010105,
+    OID_GEN_MAXIMUM_FRAME_SIZE		= 0x00010106,
+    OID_GEN_LINK_SPEED			= 0x00010107,
+    OID_GEN_TRANSMIT_BUFFER_SPACE	= 0x00010108,
+    OID_GEN_RECEIVE_BUFFER_SPACE	= 0x00010109,
+    OID_GEN_TRANSMIT_BLOCK_SIZE		= 0x0001010a,
+    OID_GEN_RECEIVE_BLOCK_SIZE		= 0x0001010b,
+    OID_GEN_VENDOR_ID			= 0x0001010c,
+    OID_GEN_VENDOR_DESCRIPTION		= 0x0001010d,
+    OID_GEN_CURRENT_PACKET_FILTER	= 0x0001010e,
+    OID_GEN_CURRENT_LOOKAHEAD		= 0x0001010f,
+    OID_GEN_DRIVER_VERSION		= 0x00010110,
+    OID_GEN_MAXIMUM_TOTAL_SIZE		= 0x00010111,
+    OID_GEN_PROTOCOL_OPTIONS		= 0x00010112,
+    OID_GEN_MAC_OPTIONS			= 0x00010113,
+    OID_GEN_MEDIA_CONNECT_STATUS	= 0x00010114,
+    OID_GEN_MAXIMUM_SEND_PACKETS	= 0x00010115,
+    OID_GEN_VENDOR_DRIVER_VERSION	= 0x00010116,
+    OID_GEN_SUPPORTED_GUIDS		= 0x00010117,
+    OID_GEN_NETWORK_LAYER_ADDRESSES	= 0x00010118,
+    OID_GEN_TRANSPORT_HEADER_OFFSET	= 0x00010119,
+    OID_GEN_MACHINE_NAME		= 0x0001021a,
+    OID_GEN_RNDIS_CONFIG_PARAMETER	= 0x0001021b,
+    OID_GEN_VLAN_ID			= 0x0001021c,
+
+    /* Optional OIDs */
+    OID_GEN_MEDIA_CAPABILITIES		= 0x00010201,
+    OID_GEN_PHYSICAL_MEDIUM		= 0x00010202,
+
+    /* Required statistics OIDs */
+    OID_GEN_XMIT_OK			= 0x00020101,
+    OID_GEN_RCV_OK			= 0x00020102,
+    OID_GEN_XMIT_ERROR			= 0x00020103,
+    OID_GEN_RCV_ERROR			= 0x00020104,
+    OID_GEN_RCV_NO_BUFFER		= 0x00020105,
+
+    /* Optional statistics OIDs */
+    OID_GEN_DIRECTED_BYTES_XMIT		= 0x00020201,
+    OID_GEN_DIRECTED_FRAMES_XMIT	= 0x00020202,
+    OID_GEN_MULTICAST_BYTES_XMIT	= 0x00020203,
+    OID_GEN_MULTICAST_FRAMES_XMIT	= 0x00020204,
+    OID_GEN_BROADCAST_BYTES_XMIT	= 0x00020205,
+    OID_GEN_BROADCAST_FRAMES_XMIT	= 0x00020206,
+    OID_GEN_DIRECTED_BYTES_RCV		= 0x00020207,
+    OID_GEN_DIRECTED_FRAMES_RCV		= 0x00020208,
+    OID_GEN_MULTICAST_BYTES_RCV		= 0x00020209,
+    OID_GEN_MULTICAST_FRAMES_RCV	= 0x0002020a,
+    OID_GEN_BROADCAST_BYTES_RCV		= 0x0002020b,
+    OID_GEN_BROADCAST_FRAMES_RCV	= 0x0002020c,
+    OID_GEN_RCV_CRC_ERROR		= 0x0002020d,
+    OID_GEN_TRANSMIT_QUEUE_LENGTH	= 0x0002020e,
+    OID_GEN_GET_TIME_CAPS		= 0x0002020f,
+    OID_GEN_GET_NETCARD_TIME		= 0x00020210,
+    OID_GEN_NETCARD_LOAD		= 0x00020211,
+    OID_GEN_DEVICE_PROFILE		= 0x00020212,
+    OID_GEN_INIT_TIME_MS		= 0x00020213,
+    OID_GEN_RESET_COUNTS		= 0x00020214,
+    OID_GEN_MEDIA_SENSE_COUNTS		= 0x00020215,
+    OID_GEN_FRIENDLY_NAME		= 0x00020216,
+    OID_GEN_MINIPORT_INFO		= 0x00020217,
+    OID_GEN_RESET_VERIFY_PARAMETERS	= 0x00020218,
+
+    /* IEEE 802.3 (Ethernet) OIDs */
+    OID_802_3_PERMANENT_ADDRESS		= 0x01010101,
+    OID_802_3_CURRENT_ADDRESS		= 0x01010102,
+    OID_802_3_MULTICAST_LIST		= 0x01010103,
+    OID_802_3_MAXIMUM_LIST_SIZE		= 0x01010104,
+    OID_802_3_MAC_OPTIONS		= 0x01010105,
+    OID_802_3_RCV_ERROR_ALIGNMENT	= 0x01020101,
+    OID_802_3_XMIT_ONE_COLLISION	= 0x01020102,
+    OID_802_3_XMIT_MORE_COLLISIONS	= 0x01020103,
+    OID_802_3_XMIT_DEFERRED		= 0x01020201,
+    OID_802_3_XMIT_MAX_COLLISIONS	= 0x01020202,
+    OID_802_3_RCV_OVERRUN		= 0x01020203,
+    OID_802_3_XMIT_UNDERRUN		= 0x01020204,
+    OID_802_3_XMIT_HEARTBEAT_FAILURE	= 0x01020205,
+    OID_802_3_XMIT_TIMES_CRS_LOST	= 0x01020206,
+    OID_802_3_XMIT_LATE_COLLISIONS	= 0x01020207,
+};
+
+static const uint32_t oid_supported_list[] =
+{
+    /* the general stuff */
+    OID_GEN_SUPPORTED_LIST,
+    OID_GEN_HARDWARE_STATUS,
+    OID_GEN_MEDIA_SUPPORTED,
+    OID_GEN_MEDIA_IN_USE,
+    OID_GEN_MAXIMUM_FRAME_SIZE,
+    OID_GEN_LINK_SPEED,
+    OID_GEN_TRANSMIT_BLOCK_SIZE,
+    OID_GEN_RECEIVE_BLOCK_SIZE,
+    OID_GEN_VENDOR_ID,
+    OID_GEN_VENDOR_DESCRIPTION,
+    OID_GEN_VENDOR_DRIVER_VERSION,
+    OID_GEN_CURRENT_PACKET_FILTER,
+    OID_GEN_MAXIMUM_TOTAL_SIZE,
+    OID_GEN_MEDIA_CONNECT_STATUS,
+    OID_GEN_PHYSICAL_MEDIUM,
+
+    /* the statistical stuff */
+    OID_GEN_XMIT_OK,
+    OID_GEN_RCV_OK,
+    OID_GEN_XMIT_ERROR,
+    OID_GEN_RCV_ERROR,
+    OID_GEN_RCV_NO_BUFFER,
+
+    /* IEEE 802.3 */
+    /* the general stuff */
+    OID_802_3_PERMANENT_ADDRESS,
+    OID_802_3_CURRENT_ADDRESS,
+    OID_802_3_MULTICAST_LIST,
+    OID_802_3_MAC_OPTIONS,
+    OID_802_3_MAXIMUM_LIST_SIZE,
+
+    /* the statistical stuff */
+    OID_802_3_RCV_ERROR_ALIGNMENT,
+    OID_802_3_XMIT_ONE_COLLISION,
+    OID_802_3_XMIT_MORE_COLLISIONS,
+};
+
+#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA	(1 << 0)
+#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED	(1 << 1)
+#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND	(1 << 2)
+#define NDIS_MAC_OPTION_NO_LOOPBACK		(1 << 3)
+#define NDIS_MAC_OPTION_FULL_DUPLEX		(1 << 4)
+#define NDIS_MAC_OPTION_EOTX_INDICATION		(1 << 5)
+#define NDIS_MAC_OPTION_8021P_PRIORITY		(1 << 6)
+
+struct rndis_response {
+    QTAILQ_ENTRY(rndis_response) entries;
+    uint32_t length;
+    uint8_t buf[0];
+};
+
+typedef struct USBNetState {
+    USBDevice dev;
+
+    enum rndis_state rndis_state;
+    uint32_t medium;
+    uint32_t speed;
+    uint32_t media_state;
+    uint16_t filter;
+    uint32_t vendorid;
+
+    unsigned int out_ptr;
+    uint8_t out_buf[2048];
+
+    USBPacket *inpkt;
+    unsigned int in_ptr, in_len;
+    uint8_t in_buf[2048];
+
+    char usbstring_mac[13];
+    NICState *nic;
+    NICConf conf;
+    QTAILQ_HEAD(rndis_resp_head, rndis_response) rndis_resp;
+} USBNetState;
+
+static int is_rndis(USBNetState *s)
+{
+    return s->dev.config->bConfigurationValue == DEV_RNDIS_CONFIG_VALUE;
+}
+
+static int ndis_query(USBNetState *s, uint32_t oid,
+                      uint8_t *inbuf, unsigned int inlen, uint8_t *outbuf,
+                      size_t outlen)
+{
+    unsigned int i;
+
+    switch (oid) {
+    /* general oids (table 4-1) */
+    /* mandatory */
+    case OID_GEN_SUPPORTED_LIST:
+        for (i = 0; i < ARRAY_SIZE(oid_supported_list); i++)
+            ((le32 *) outbuf)[i] = cpu_to_le32(oid_supported_list[i]);
+        return sizeof(oid_supported_list);
+
+    /* mandatory */
+    case OID_GEN_HARDWARE_STATUS:
+        *((le32 *) outbuf) = cpu_to_le32(0);
+        return sizeof(le32);
+
+    /* mandatory */
+    case OID_GEN_MEDIA_SUPPORTED:
+        *((le32 *) outbuf) = cpu_to_le32(s->medium);
+        return sizeof(le32);
+
+    /* mandatory */
+    case OID_GEN_MEDIA_IN_USE:
+        *((le32 *) outbuf) = cpu_to_le32(s->medium);
+        return sizeof(le32);
+
+    /* mandatory */
+    case OID_GEN_MAXIMUM_FRAME_SIZE:
+        *((le32 *) outbuf) = cpu_to_le32(ETH_FRAME_LEN);
+        return sizeof(le32);
+
+    /* mandatory */
+    case OID_GEN_LINK_SPEED:
+        *((le32 *) outbuf) = cpu_to_le32(s->speed);
+        return sizeof(le32);
+
+    /* mandatory */
+    case OID_GEN_TRANSMIT_BLOCK_SIZE:
+        *((le32 *) outbuf) = cpu_to_le32(ETH_FRAME_LEN);
+        return sizeof(le32);
+
+    /* mandatory */
+    case OID_GEN_RECEIVE_BLOCK_SIZE:
+        *((le32 *) outbuf) = cpu_to_le32(ETH_FRAME_LEN);
+        return sizeof(le32);
+
+    /* mandatory */
+    case OID_GEN_VENDOR_ID:
+        *((le32 *) outbuf) = cpu_to_le32(s->vendorid);
+        return sizeof(le32);
+
+    /* mandatory */
+    case OID_GEN_VENDOR_DESCRIPTION:
+        pstrcpy((char *)outbuf, outlen, "QEMU USB RNDIS Net");
+        return strlen((char *)outbuf) + 1;
+
+    case OID_GEN_VENDOR_DRIVER_VERSION:
+        *((le32 *) outbuf) = cpu_to_le32(1);
+        return sizeof(le32);
+
+    /* mandatory */
+    case OID_GEN_CURRENT_PACKET_FILTER:
+        *((le32 *) outbuf) = cpu_to_le32(s->filter);
+        return sizeof(le32);
+
+    /* mandatory */
+    case OID_GEN_MAXIMUM_TOTAL_SIZE:
+        *((le32 *) outbuf) = cpu_to_le32(RNDIS_MAX_TOTAL_SIZE);
+        return sizeof(le32);
+
+    /* mandatory */
+    case OID_GEN_MEDIA_CONNECT_STATUS:
+        *((le32 *) outbuf) = cpu_to_le32(s->media_state);
+        return sizeof(le32);
+
+    case OID_GEN_PHYSICAL_MEDIUM:
+        *((le32 *) outbuf) = cpu_to_le32(0);
+        return sizeof(le32);
+
+    case OID_GEN_MAC_OPTIONS:
+        *((le32 *) outbuf) = cpu_to_le32(
+                        NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
+                        NDIS_MAC_OPTION_FULL_DUPLEX);
+        return sizeof(le32);
+
+    /* statistics OIDs (table 4-2) */
+    /* mandatory */
+    case OID_GEN_XMIT_OK:
+        *((le32 *) outbuf) = cpu_to_le32(0);
+        return sizeof(le32);
+
+    /* mandatory */
+    case OID_GEN_RCV_OK:
+        *((le32 *) outbuf) = cpu_to_le32(0);
+        return sizeof(le32);
+
+    /* mandatory */
+    case OID_GEN_XMIT_ERROR:
+        *((le32 *) outbuf) = cpu_to_le32(0);
+        return sizeof(le32);
+
+    /* mandatory */
+    case OID_GEN_RCV_ERROR:
+        *((le32 *) outbuf) = cpu_to_le32(0);
+        return sizeof(le32);
+
+    /* mandatory */
+    case OID_GEN_RCV_NO_BUFFER:
+        *((le32 *) outbuf) = cpu_to_le32(0);
+        return sizeof(le32);
+
+    /* ieee802.3 OIDs (table 4-3) */
+    /* mandatory */
+    case OID_802_3_PERMANENT_ADDRESS:
+        memcpy(outbuf, s->conf.macaddr.a, 6);
+        return 6;
+
+    /* mandatory */
+    case OID_802_3_CURRENT_ADDRESS:
+        memcpy(outbuf, s->conf.macaddr.a, 6);
+        return 6;
+
+    /* mandatory */
+    case OID_802_3_MULTICAST_LIST:
+        *((le32 *) outbuf) = cpu_to_le32(0xe0000000);
+        return sizeof(le32);
+
+    /* mandatory */
+    case OID_802_3_MAXIMUM_LIST_SIZE:
+        *((le32 *) outbuf) = cpu_to_le32(1);
+        return sizeof(le32);
+
+    case OID_802_3_MAC_OPTIONS:
+        return 0;
+
+    /* ieee802.3 statistics OIDs (table 4-4) */
+    /* mandatory */
+    case OID_802_3_RCV_ERROR_ALIGNMENT:
+        *((le32 *) outbuf) = cpu_to_le32(0);
+        return sizeof(le32);
+
+    /* mandatory */
+    case OID_802_3_XMIT_ONE_COLLISION:
+        *((le32 *) outbuf) = cpu_to_le32(0);
+        return sizeof(le32);
+
+    /* mandatory */
+    case OID_802_3_XMIT_MORE_COLLISIONS:
+        *((le32 *) outbuf) = cpu_to_le32(0);
+        return sizeof(le32);
+
+    default:
+        fprintf(stderr, "usbnet: unknown OID 0x%08x\n", oid);
+        return 0;
+    }
+    return -1;
+}
+
+static int ndis_set(USBNetState *s, uint32_t oid,
+                uint8_t *inbuf, unsigned int inlen)
+{
+    switch (oid) {
+    case OID_GEN_CURRENT_PACKET_FILTER:
+        s->filter = le32_to_cpup((le32 *) inbuf);
+        if (s->filter) {
+            s->rndis_state = RNDIS_DATA_INITIALIZED;
+        } else {
+            s->rndis_state = RNDIS_INITIALIZED;
+        }
+        return 0;
+
+    case OID_802_3_MULTICAST_LIST:
+        return 0;
+    }
+    return -1;
+}
+
+static int rndis_get_response(USBNetState *s, uint8_t *buf)
+{
+    int ret = 0;
+    struct rndis_response *r = s->rndis_resp.tqh_first;
+
+    if (!r)
+        return ret;
+
+    QTAILQ_REMOVE(&s->rndis_resp, r, entries);
+    ret = r->length;
+    memcpy(buf, r->buf, r->length);
+    g_free(r);
+
+    return ret;
+}
+
+static void *rndis_queue_response(USBNetState *s, unsigned int length)
+{
+    struct rndis_response *r =
+            g_malloc0(sizeof(struct rndis_response) + length);
+
+    QTAILQ_INSERT_TAIL(&s->rndis_resp, r, entries);
+    r->length = length;
+
+    return &r->buf[0];
+}
+
+static void rndis_clear_responsequeue(USBNetState *s)
+{
+    struct rndis_response *r;
+
+    while ((r = s->rndis_resp.tqh_first)) {
+        QTAILQ_REMOVE(&s->rndis_resp, r, entries);
+        g_free(r);
+    }
+}
+
+static int rndis_init_response(USBNetState *s, rndis_init_msg_type *buf)
+{
+    rndis_init_cmplt_type *resp =
+            rndis_queue_response(s, sizeof(rndis_init_cmplt_type));
+
+    if (!resp)
+        return USB_RET_STALL;
+
+    resp->MessageType = cpu_to_le32(RNDIS_INITIALIZE_CMPLT);
+    resp->MessageLength = cpu_to_le32(sizeof(rndis_init_cmplt_type));
+    resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
+    resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
+    resp->MajorVersion = cpu_to_le32(RNDIS_MAJOR_VERSION);
+    resp->MinorVersion = cpu_to_le32(RNDIS_MINOR_VERSION);
+    resp->DeviceFlags = cpu_to_le32(RNDIS_DF_CONNECTIONLESS);
+    resp->Medium = cpu_to_le32(RNDIS_MEDIUM_802_3);
+    resp->MaxPacketsPerTransfer = cpu_to_le32(1);
+    resp->MaxTransferSize = cpu_to_le32(ETH_FRAME_LEN +
+                    sizeof(struct rndis_packet_msg_type) + 22);
+    resp->PacketAlignmentFactor = cpu_to_le32(0);
+    resp->AFListOffset = cpu_to_le32(0);
+    resp->AFListSize = cpu_to_le32(0);
+    return 0;
+}
+
+static int rndis_query_response(USBNetState *s,
+                rndis_query_msg_type *buf, unsigned int length)
+{
+    rndis_query_cmplt_type *resp;
+    /* oid_supported_list is the largest data reply */
+    uint8_t infobuf[sizeof(oid_supported_list)];
+    uint32_t bufoffs, buflen;
+    int infobuflen;
+    unsigned int resplen;
+
+    bufoffs = le32_to_cpu(buf->InformationBufferOffset) + 8;
+    buflen = le32_to_cpu(buf->InformationBufferLength);
+    if (bufoffs + buflen > length)
+        return USB_RET_STALL;
+
+    infobuflen = ndis_query(s, le32_to_cpu(buf->OID),
+                            bufoffs + (uint8_t *) buf, buflen, infobuf,
+                            sizeof(infobuf));
+    resplen = sizeof(rndis_query_cmplt_type) +
+            ((infobuflen < 0) ? 0 : infobuflen);
+    resp = rndis_queue_response(s, resplen);
+    if (!resp)
+        return USB_RET_STALL;
+
+    resp->MessageType = cpu_to_le32(RNDIS_QUERY_CMPLT);
+    resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
+    resp->MessageLength = cpu_to_le32(resplen);
+
+    if (infobuflen < 0) {
+        /* OID not supported */
+        resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED);
+        resp->InformationBufferLength = cpu_to_le32(0);
+        resp->InformationBufferOffset = cpu_to_le32(0);
+        return 0;
+    }
+
+    resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
+    resp->InformationBufferOffset =
+            cpu_to_le32(infobuflen ? sizeof(rndis_query_cmplt_type) - 8 : 0);
+    resp->InformationBufferLength = cpu_to_le32(infobuflen);
+    memcpy(resp + 1, infobuf, infobuflen);
+
+    return 0;
+}
+
+static int rndis_set_response(USBNetState *s,
+                rndis_set_msg_type *buf, unsigned int length)
+{
+    rndis_set_cmplt_type *resp =
+            rndis_queue_response(s, sizeof(rndis_set_cmplt_type));
+    uint32_t bufoffs, buflen;
+    int ret;
+
+    if (!resp)
+        return USB_RET_STALL;
+
+    bufoffs = le32_to_cpu(buf->InformationBufferOffset) + 8;
+    buflen = le32_to_cpu(buf->InformationBufferLength);
+    if (bufoffs + buflen > length)
+        return USB_RET_STALL;
+
+    ret = ndis_set(s, le32_to_cpu(buf->OID),
+                    bufoffs + (uint8_t *) buf, buflen);
+    resp->MessageType = cpu_to_le32(RNDIS_SET_CMPLT);
+    resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
+    resp->MessageLength = cpu_to_le32(sizeof(rndis_set_cmplt_type));
+    if (ret < 0) {
+        /* OID not supported */
+        resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED);
+        return 0;
+    }
+    resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
+
+    return 0;
+}
+
+static int rndis_reset_response(USBNetState *s, rndis_reset_msg_type *buf)
+{
+    rndis_reset_cmplt_type *resp =
+            rndis_queue_response(s, sizeof(rndis_reset_cmplt_type));
+
+    if (!resp)
+        return USB_RET_STALL;
+
+    resp->MessageType = cpu_to_le32(RNDIS_RESET_CMPLT);
+    resp->MessageLength = cpu_to_le32(sizeof(rndis_reset_cmplt_type));
+    resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
+    resp->AddressingReset = cpu_to_le32(1); /* reset information */
+
+    return 0;
+}
+
+static int rndis_keepalive_response(USBNetState *s,
+                rndis_keepalive_msg_type *buf)
+{
+    rndis_keepalive_cmplt_type *resp =
+            rndis_queue_response(s, sizeof(rndis_keepalive_cmplt_type));
+
+    if (!resp)
+        return USB_RET_STALL;
+
+    resp->MessageType = cpu_to_le32(RNDIS_KEEPALIVE_CMPLT);
+    resp->MessageLength = cpu_to_le32(sizeof(rndis_keepalive_cmplt_type));
+    resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
+    resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
+
+    return 0;
+}
+
+static int rndis_parse(USBNetState *s, uint8_t *data, int length)
+{
+    uint32_t msg_type;
+    le32 *tmp = (le32 *) data;
+
+    msg_type = le32_to_cpup(tmp);
+
+    switch (msg_type) {
+    case RNDIS_INITIALIZE_MSG:
+        s->rndis_state = RNDIS_INITIALIZED;
+        return rndis_init_response(s, (rndis_init_msg_type *) data);
+
+    case RNDIS_HALT_MSG:
+        s->rndis_state = RNDIS_UNINITIALIZED;
+        return 0;
+
+    case RNDIS_QUERY_MSG:
+        return rndis_query_response(s, (rndis_query_msg_type *) data, length);
+
+    case RNDIS_SET_MSG:
+        return rndis_set_response(s, (rndis_set_msg_type *) data, length);
+
+    case RNDIS_RESET_MSG:
+        rndis_clear_responsequeue(s);
+        s->out_ptr = s->in_ptr = s->in_len = 0;
+        return rndis_reset_response(s, (rndis_reset_msg_type *) data);
+
+    case RNDIS_KEEPALIVE_MSG:
+        /* For USB: host does this every 5 seconds */
+        return rndis_keepalive_response(s, (rndis_keepalive_msg_type *) data);
+    }
+
+    return USB_RET_STALL;
+}
+
+static void usb_net_handle_reset(USBDevice *dev)
+{
+}
+
+static int usb_net_handle_control(USBDevice *dev, USBPacket *p,
+               int request, int value, int index, int length, uint8_t *data)
+{
+    USBNetState *s = (USBNetState *) dev;
+    int ret;
+
+    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
+    if (ret >= 0) {
+        return ret;
+    }
+
+    ret = 0;
+    switch(request) {
+    case ClassInterfaceOutRequest | USB_CDC_SEND_ENCAPSULATED_COMMAND:
+        if (!is_rndis(s) || value || index != 0) {
+            goto fail;
+        }
+#ifdef TRAFFIC_DEBUG
+        {
+            unsigned int i;
+            fprintf(stderr, "SEND_ENCAPSULATED_COMMAND:");
+            for (i = 0; i < length; i++) {
+                if (!(i & 15))
+                    fprintf(stderr, "\n%04x:", i);
+                fprintf(stderr, " %02x", data[i]);
+            }
+            fprintf(stderr, "\n\n");
+        }
+#endif
+        ret = rndis_parse(s, data, length);
+        break;
+
+    case ClassInterfaceRequest | USB_CDC_GET_ENCAPSULATED_RESPONSE:
+        if (!is_rndis(s) || value || index != 0) {
+            goto fail;
+        }
+        ret = rndis_get_response(s, data);
+        if (!ret) {
+            data[0] = 0;
+            ret = 1;
+        }
+#ifdef TRAFFIC_DEBUG
+        {
+            unsigned int i;
+            fprintf(stderr, "GET_ENCAPSULATED_RESPONSE:");
+            for (i = 0; i < ret; i++) {
+                if (!(i & 15))
+                    fprintf(stderr, "\n%04x:", i);
+                fprintf(stderr, " %02x", data[i]);
+            }
+            fprintf(stderr, "\n\n");
+        }
+#endif
+        break;
+
+    default:
+    fail:
+        fprintf(stderr, "usbnet: failed control transaction: "
+                        "request 0x%x value 0x%x index 0x%x length 0x%x\n",
+                        request, value, index, length);
+        ret = USB_RET_STALL;
+        break;
+    }
+    return ret;
+}
+
+static int usb_net_handle_statusin(USBNetState *s, USBPacket *p)
+{
+    le32 buf[2];
+    int ret = 8;
+
+    if (p->iov.size < 8) {
+        return USB_RET_STALL;
+    }
+
+    buf[0] = cpu_to_le32(1);
+    buf[1] = cpu_to_le32(0);
+    usb_packet_copy(p, buf, 8);
+    if (!s->rndis_resp.tqh_first)
+        ret = USB_RET_NAK;
+
+#ifdef TRAFFIC_DEBUG
+    fprintf(stderr, "usbnet: interrupt poll len %zu return %d",
+            p->iov.size, ret);
+    iov_hexdump(p->iov.iov, p->iov.niov, stderr, "usbnet", ret);
+#endif
+
+    return ret;
+}
+
+static int usb_net_handle_datain(USBNetState *s, USBPacket *p)
+{
+    int ret = USB_RET_NAK;
+
+    if (s->in_ptr > s->in_len) {
+        s->in_ptr = s->in_len = 0;
+        ret = USB_RET_NAK;
+        return ret;
+    }
+    if (!s->in_len) {
+        ret = USB_RET_NAK;
+        return ret;
+    }
+    ret = s->in_len - s->in_ptr;
+    if (ret > p->iov.size) {
+        ret = p->iov.size;
+    }
+    usb_packet_copy(p, &s->in_buf[s->in_ptr], ret);
+    s->in_ptr += ret;
+    if (s->in_ptr >= s->in_len &&
+                    (is_rndis(s) || (s->in_len & (64 - 1)) || !ret)) {
+        /* no short packet necessary */
+        s->in_ptr = s->in_len = 0;
+    }
+
+#ifdef TRAFFIC_DEBUG
+    fprintf(stderr, "usbnet: data in len %zu return %d", p->iov.size, ret);
+    iov_hexdump(p->iov.iov, p->iov.niov, stderr, "usbnet", ret);
+#endif
+
+    return ret;
+}
+
+static int usb_net_handle_dataout(USBNetState *s, USBPacket *p)
+{
+    int ret = p->iov.size;
+    int sz = sizeof(s->out_buf) - s->out_ptr;
+    struct rndis_packet_msg_type *msg =
+            (struct rndis_packet_msg_type *) s->out_buf;
+    uint32_t len;
+
+#ifdef TRAFFIC_DEBUG
+    fprintf(stderr, "usbnet: data out len %zu\n", p->iov.size);
+    iov_hexdump(p->iov.iov, p->iov.niov, stderr, "usbnet", p->iov.size);
+#endif
+
+    if (sz > ret)
+        sz = ret;
+    usb_packet_copy(p, &s->out_buf[s->out_ptr], sz);
+    s->out_ptr += sz;
+
+    if (!is_rndis(s)) {
+        if (ret < 64) {
+            qemu_send_packet(&s->nic->nc, s->out_buf, s->out_ptr);
+            s->out_ptr = 0;
+        }
+        return ret;
+    }
+    len = le32_to_cpu(msg->MessageLength);
+    if (s->out_ptr < 8 || s->out_ptr < len)
+        return ret;
+    if (le32_to_cpu(msg->MessageType) == RNDIS_PACKET_MSG) {
+        uint32_t offs = 8 + le32_to_cpu(msg->DataOffset);
+        uint32_t size = le32_to_cpu(msg->DataLength);
+        if (offs + size <= len)
+            qemu_send_packet(&s->nic->nc, s->out_buf + offs, size);
+    }
+    s->out_ptr -= len;
+    memmove(s->out_buf, &s->out_buf[len], s->out_ptr);
+
+    return ret;
+}
+
+static int usb_net_handle_data(USBDevice *dev, USBPacket *p)
+{
+    USBNetState *s = (USBNetState *) dev;
+    int ret = 0;
+
+    switch(p->pid) {
+    case USB_TOKEN_IN:
+        switch (p->ep->nr) {
+        case 1:
+            ret = usb_net_handle_statusin(s, p);
+            break;
+
+        case 2:
+            ret = usb_net_handle_datain(s, p);
+            break;
+
+        default:
+            goto fail;
+        }
+        break;
+
+    case USB_TOKEN_OUT:
+        switch (p->ep->nr) {
+        case 2:
+            ret = usb_net_handle_dataout(s, p);
+            break;
+
+        default:
+            goto fail;
+        }
+        break;
+
+    default:
+    fail:
+        ret = USB_RET_STALL;
+        break;
+    }
+    if (ret == USB_RET_STALL)
+        fprintf(stderr, "usbnet: failed data transaction: "
+                        "pid 0x%x ep 0x%x len 0x%zx\n",
+                        p->pid, p->ep->nr, p->iov.size);
+    return ret;
+}
+
+static ssize_t usbnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
+{
+    USBNetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    struct rndis_packet_msg_type *msg;
+
+    if (is_rndis(s)) {
+        msg = (struct rndis_packet_msg_type *) s->in_buf;
+        if (s->rndis_state != RNDIS_DATA_INITIALIZED) {
+            return -1;
+        }
+        if (size + sizeof(struct rndis_packet_msg_type) > sizeof(s->in_buf))
+            return -1;
+
+        memset(msg, 0, sizeof(struct rndis_packet_msg_type));
+        msg->MessageType = cpu_to_le32(RNDIS_PACKET_MSG);
+        msg->MessageLength = cpu_to_le32(size + sizeof(struct rndis_packet_msg_type));
+        msg->DataOffset = cpu_to_le32(sizeof(struct rndis_packet_msg_type) - 8);
+        msg->DataLength = cpu_to_le32(size);
+        /* msg->OOBDataOffset;
+         * msg->OOBDataLength;
+         * msg->NumOOBDataElements;
+         * msg->PerPacketInfoOffset;
+         * msg->PerPacketInfoLength;
+         * msg->VcHandle;
+         * msg->Reserved;
+         */
+        memcpy(msg + 1, buf, size);
+        s->in_len = size + sizeof(struct rndis_packet_msg_type);
+    } else {
+        if (size > sizeof(s->in_buf))
+            return -1;
+        memcpy(s->in_buf, buf, size);
+        s->in_len = size;
+    }
+    s->in_ptr = 0;
+    return size;
+}
+
+static int usbnet_can_receive(VLANClientState *nc)
+{
+    USBNetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    if (is_rndis(s) && s->rndis_state != RNDIS_DATA_INITIALIZED) {
+        return 1;
+    }
+
+    return !s->in_len;
+}
+
+static void usbnet_cleanup(VLANClientState *nc)
+{
+    USBNetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    s->nic = NULL;
+}
+
+static void usb_net_handle_destroy(USBDevice *dev)
+{
+    USBNetState *s = (USBNetState *) dev;
+
+    /* TODO: remove the nd_table[] entry */
+    rndis_clear_responsequeue(s);
+    qemu_del_vlan_client(&s->nic->nc);
+}
+
+static NetClientInfo net_usbnet_info = {
+    .type = NET_CLIENT_TYPE_NIC,
+    .size = sizeof(NICState),
+    .can_receive = usbnet_can_receive,
+    .receive = usbnet_receive,
+    .cleanup = usbnet_cleanup,
+};
+
+static int usb_net_initfn(USBDevice *dev)
+{
+    USBNetState *s = DO_UPCAST(USBNetState, dev, dev);
+
+    usb_desc_init(dev);
+
+    s->rndis_state = RNDIS_UNINITIALIZED;
+    QTAILQ_INIT(&s->rndis_resp);
+
+    s->medium = 0;	/* NDIS_MEDIUM_802_3 */
+    s->speed = 1000000; /* 100MBps, in 100Bps units */
+    s->media_state = 0;	/* NDIS_MEDIA_STATE_CONNECTED */;
+    s->filter = 0;
+    s->vendorid = 0x1234;
+
+    qemu_macaddr_default_if_unset(&s->conf.macaddr);
+    s->nic = qemu_new_nic(&net_usbnet_info, &s->conf,
+                          object_get_typename(OBJECT(s)), s->dev.qdev.id, s);
+    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
+    snprintf(s->usbstring_mac, sizeof(s->usbstring_mac),
+             "%02x%02x%02x%02x%02x%02x",
+             0x40,
+             s->conf.macaddr.a[1],
+             s->conf.macaddr.a[2],
+             s->conf.macaddr.a[3],
+             s->conf.macaddr.a[4],
+             s->conf.macaddr.a[5]);
+    usb_desc_set_string(dev, STRING_ETHADDR, s->usbstring_mac);
+
+    add_boot_device_path(s->conf.bootindex, &dev->qdev, "/ethernet at 0");
+    return 0;
+}
+
+static USBDevice *usb_net_init(USBBus *bus, const char *cmdline)
+{
+    USBDevice *dev;
+    QemuOpts *opts;
+    int idx;
+
+    opts = qemu_opts_parse(qemu_find_opts("net"), cmdline, 0);
+    if (!opts) {
+        return NULL;
+    }
+    qemu_opt_set(opts, "type", "nic");
+    qemu_opt_set(opts, "model", "usb");
+
+    idx = net_client_init(NULL, opts, 0);
+    if (idx == -1) {
+        return NULL;
+    }
+
+    dev = usb_create(bus, "usb-net");
+    if (!dev) {
+        return NULL;
+    }
+    qdev_set_nic_properties(&dev->qdev, &nd_table[idx]);
+    qdev_init_nofail(&dev->qdev);
+    return dev;
+}
+
+static const VMStateDescription vmstate_usb_net = {
+    .name = "usb-net",
+    .unmigratable = 1,
+};
+
+static Property net_properties[] = {
+    DEFINE_NIC_PROPERTIES(USBNetState, conf),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void usb_net_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+    uc->init           = usb_net_initfn;
+    uc->product_desc   = "QEMU USB Network Interface";
+    uc->usb_desc       = &desc_net;
+    uc->handle_reset   = usb_net_handle_reset;
+    uc->handle_control = usb_net_handle_control;
+    uc->handle_data    = usb_net_handle_data;
+    uc->handle_destroy = usb_net_handle_destroy;
+    dc->fw_name = "network";
+    dc->vmsd = &vmstate_usb_net;
+    dc->props = net_properties;
+}
+
+static TypeInfo net_info = {
+    .name          = "usb-net",
+    .parent        = TYPE_USB_DEVICE,
+    .instance_size = sizeof(USBNetState),
+    .class_init    = usb_net_class_initfn,
+};
+
+static void usb_net_register_types(void)
+{
+    type_register_static(&net_info);
+    usb_legacy_register("usb-net", "net", usb_net_init);
+}
+
+type_init(usb_net_register_types)
diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
new file mode 100644
index 0000000..8dcac8b
--- /dev/null
+++ b/hw/usb/dev-serial.c
@@ -0,0 +1,637 @@
+/*
+ * FTDI FT232BM Device emulation
+ *
+ * Copyright (c) 2006 CodeSourcery.
+ * Copyright (c) 2008 Samuel Thibault <samuel.thibault at ens-lyon.org>
+ * Written by Paul Brook, reused for FTDI by Samuel Thibault
+ *
+ * This code is licensed under the LGPL.
+ */
+
+#include "qemu-common.h"
+#include "qemu-error.h"
+#include "hw/usb.h"
+#include "hw/usb/desc.h"
+#include "qemu-char.h"
+
+//#define DEBUG_Serial
+
+#ifdef DEBUG_Serial
+#define DPRINTF(fmt, ...) \
+do { printf("usb-serial: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) do {} while(0)
+#endif
+
+#define RECV_BUF 384
+
+/* Commands */
+#define FTDI_RESET		0
+#define FTDI_SET_MDM_CTRL	1
+#define FTDI_SET_FLOW_CTRL	2
+#define FTDI_SET_BAUD		3
+#define FTDI_SET_DATA		4
+#define FTDI_GET_MDM_ST		5
+#define FTDI_SET_EVENT_CHR	6
+#define FTDI_SET_ERROR_CHR	7
+#define FTDI_SET_LATENCY	9
+#define FTDI_GET_LATENCY	10
+
+#define DeviceOutVendor	((USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8)
+#define DeviceInVendor	((USB_DIR_IN |USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8)
+
+/* RESET */
+
+#define FTDI_RESET_SIO	0
+#define FTDI_RESET_RX	1
+#define FTDI_RESET_TX	2
+
+/* SET_MDM_CTRL */
+
+#define FTDI_DTR	1
+#define FTDI_SET_DTR	(FTDI_DTR << 8)
+#define FTDI_RTS	2
+#define FTDI_SET_RTS	(FTDI_RTS << 8)
+
+/* SET_FLOW_CTRL */
+
+#define FTDI_RTS_CTS_HS		1
+#define FTDI_DTR_DSR_HS		2
+#define FTDI_XON_XOFF_HS	4
+
+/* SET_DATA */
+
+#define FTDI_PARITY	(0x7 << 8)
+#define FTDI_ODD	(0x1 << 8)
+#define FTDI_EVEN	(0x2 << 8)
+#define FTDI_MARK	(0x3 << 8)
+#define FTDI_SPACE	(0x4 << 8)
+
+#define FTDI_STOP	(0x3 << 11)
+#define FTDI_STOP1	(0x0 << 11)
+#define FTDI_STOP15	(0x1 << 11)
+#define FTDI_STOP2	(0x2 << 11)
+
+/* GET_MDM_ST */
+/* TODO: should be sent every 40ms */
+#define FTDI_CTS  (1<<4)        // CTS line status
+#define FTDI_DSR  (1<<5)        // DSR line status
+#define FTDI_RI   (1<<6)        // RI line status
+#define FTDI_RLSD (1<<7)        // Receive Line Signal Detect
+
+/* Status */
+
+#define FTDI_DR   (1<<0)        // Data Ready
+#define FTDI_OE   (1<<1)        // Overrun Err
+#define FTDI_PE   (1<<2)        // Parity Err
+#define FTDI_FE   (1<<3)        // Framing Err
+#define FTDI_BI   (1<<4)        // Break Interrupt
+#define FTDI_THRE (1<<5)        // Transmitter Holding Register
+#define FTDI_TEMT (1<<6)        // Transmitter Empty
+#define FTDI_FIFO (1<<7)        // Error in FIFO
+
+typedef struct {
+    USBDevice dev;
+    uint8_t recv_buf[RECV_BUF];
+    uint16_t recv_ptr;
+    uint16_t recv_used;
+    uint8_t event_chr;
+    uint8_t error_chr;
+    uint8_t event_trigger;
+    QEMUSerialSetParams params;
+    int latency;        /* ms */
+    CharDriverState *cs;
+} USBSerialState;
+
+enum {
+    STR_MANUFACTURER = 1,
+    STR_PRODUCT_SERIAL,
+    STR_PRODUCT_BRAILLE,
+    STR_SERIALNUMBER,
+};
+
+static const USBDescStrings desc_strings = {
+    [STR_MANUFACTURER]    = "QEMU " QEMU_VERSION,
+    [STR_PRODUCT_SERIAL]  = "QEMU USB SERIAL",
+    [STR_PRODUCT_BRAILLE] = "QEMU USB BRAILLE",
+    [STR_SERIALNUMBER]    = "1",
+};
+
+static const USBDescIface desc_iface0 = {
+    .bInterfaceNumber              = 0,
+    .bNumEndpoints                 = 2,
+    .bInterfaceClass               = 0xff,
+    .bInterfaceSubClass            = 0xff,
+    .bInterfaceProtocol            = 0xff,
+    .eps = (USBDescEndpoint[]) {
+        {
+            .bEndpointAddress      = USB_DIR_IN | 0x01,
+            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize        = 64,
+        },{
+            .bEndpointAddress      = USB_DIR_OUT | 0x02,
+            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize        = 64,
+        },
+    }
+};
+
+static const USBDescDevice desc_device = {
+    .bcdUSB                        = 0x0200,
+    .bMaxPacketSize0               = 8,
+    .bNumConfigurations            = 1,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 1,
+            .bConfigurationValue   = 1,
+            .bmAttributes          = 0x80,
+            .bMaxPower             = 50,
+            .nif = 1,
+            .ifs = &desc_iface0,
+        },
+    },
+};
+
+static const USBDesc desc_serial = {
+    .id = {
+        .idVendor          = 0x0403,
+        .idProduct         = 0x6001,
+        .bcdDevice         = 0x0400,
+        .iManufacturer     = STR_MANUFACTURER,
+        .iProduct          = STR_PRODUCT_SERIAL,
+        .iSerialNumber     = STR_SERIALNUMBER,
+    },
+    .full = &desc_device,
+    .str  = desc_strings,
+};
+
+static const USBDesc desc_braille = {
+    .id = {
+        .idVendor          = 0x0403,
+        .idProduct         = 0xfe72,
+        .bcdDevice         = 0x0400,
+        .iManufacturer     = STR_MANUFACTURER,
+        .iProduct          = STR_PRODUCT_BRAILLE,
+        .iSerialNumber     = STR_SERIALNUMBER,
+    },
+    .full = &desc_device,
+    .str  = desc_strings,
+};
+
+static void usb_serial_reset(USBSerialState *s)
+{
+    /* TODO: Set flow control to none */
+    s->event_chr = 0x0d;
+    s->event_trigger = 0;
+    s->recv_ptr = 0;
+    s->recv_used = 0;
+    /* TODO: purge in char driver */
+}
+
+static void usb_serial_handle_reset(USBDevice *dev)
+{
+    USBSerialState *s = (USBSerialState *)dev;
+
+    DPRINTF("Reset\n");
+
+    usb_serial_reset(s);
+    /* TODO: Reset char device, send BREAK? */
+}
+
+static uint8_t usb_get_modem_lines(USBSerialState *s)
+{
+    int flags;
+    uint8_t ret;
+
+    if (qemu_chr_fe_ioctl(s->cs, CHR_IOCTL_SERIAL_GET_TIOCM, &flags) == -ENOTSUP)
+        return FTDI_CTS|FTDI_DSR|FTDI_RLSD;
+
+    ret = 0;
+    if (flags & CHR_TIOCM_CTS)
+        ret |= FTDI_CTS;
+    if (flags & CHR_TIOCM_DSR)
+        ret |= FTDI_DSR;
+    if (flags & CHR_TIOCM_RI)
+        ret |= FTDI_RI;
+    if (flags & CHR_TIOCM_CAR)
+        ret |= FTDI_RLSD;
+
+    return ret;
+}
+
+static int usb_serial_handle_control(USBDevice *dev, USBPacket *p,
+               int request, int value, int index, int length, uint8_t *data)
+{
+    USBSerialState *s = (USBSerialState *)dev;
+    int ret;
+
+    DPRINTF("got control %x, value %x\n",request, value);
+    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
+    if (ret >= 0) {
+        return ret;
+    }
+
+    ret = 0;
+    switch (request) {
+    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
+        ret = 0;
+        break;
+
+        /* Class specific requests.  */
+    case DeviceOutVendor | FTDI_RESET:
+        switch (value) {
+        case FTDI_RESET_SIO:
+            usb_serial_reset(s);
+            break;
+        case FTDI_RESET_RX:
+            s->recv_ptr = 0;
+            s->recv_used = 0;
+            /* TODO: purge from char device */
+            break;
+        case FTDI_RESET_TX:
+            /* TODO: purge from char device */
+            break;
+        }
+        break;
+    case DeviceOutVendor | FTDI_SET_MDM_CTRL:
+    {
+        static int flags;
+        qemu_chr_fe_ioctl(s->cs,CHR_IOCTL_SERIAL_GET_TIOCM, &flags);
+        if (value & FTDI_SET_RTS) {
+            if (value & FTDI_RTS)
+                flags |= CHR_TIOCM_RTS;
+            else
+                flags &= ~CHR_TIOCM_RTS;
+        }
+        if (value & FTDI_SET_DTR) {
+            if (value & FTDI_DTR)
+                flags |= CHR_TIOCM_DTR;
+            else
+                flags &= ~CHR_TIOCM_DTR;
+        }
+        qemu_chr_fe_ioctl(s->cs,CHR_IOCTL_SERIAL_SET_TIOCM, &flags);
+        break;
+    }
+    case DeviceOutVendor | FTDI_SET_FLOW_CTRL:
+        /* TODO: ioctl */
+        break;
+    case DeviceOutVendor | FTDI_SET_BAUD: {
+        static const int subdivisors8[8] = { 0, 4, 2, 1, 3, 5, 6, 7 };
+        int subdivisor8 = subdivisors8[((value & 0xc000) >> 14)
+                                     | ((index & 1) << 2)];
+        int divisor = value & 0x3fff;
+
+        /* chip special cases */
+        if (divisor == 1 && subdivisor8 == 0)
+            subdivisor8 = 4;
+        if (divisor == 0 && subdivisor8 == 0)
+            divisor = 1;
+
+        s->params.speed = (48000000 / 2) / (8 * divisor + subdivisor8);
+        qemu_chr_fe_ioctl(s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);
+        break;
+    }
+    case DeviceOutVendor | FTDI_SET_DATA:
+        switch (value & FTDI_PARITY) {
+            case 0:
+                s->params.parity = 'N';
+                break;
+            case FTDI_ODD:
+                s->params.parity = 'O';
+                break;
+            case FTDI_EVEN:
+                s->params.parity = 'E';
+                break;
+            default:
+                DPRINTF("unsupported parity %d\n", value & FTDI_PARITY);
+                goto fail;
+        }
+        switch (value & FTDI_STOP) {
+            case FTDI_STOP1:
+                s->params.stop_bits = 1;
+                break;
+            case FTDI_STOP2:
+                s->params.stop_bits = 2;
+                break;
+            default:
+                DPRINTF("unsupported stop bits %d\n", value & FTDI_STOP);
+                goto fail;
+        }
+        qemu_chr_fe_ioctl(s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);
+        /* TODO: TX ON/OFF */
+        break;
+    case DeviceInVendor | FTDI_GET_MDM_ST:
+        data[0] = usb_get_modem_lines(s) | 1;
+        data[1] = 0;
+        ret = 2;
+        break;
+    case DeviceOutVendor | FTDI_SET_EVENT_CHR:
+        /* TODO: handle it */
+        s->event_chr = value;
+        break;
+    case DeviceOutVendor | FTDI_SET_ERROR_CHR:
+        /* TODO: handle it */
+        s->error_chr = value;
+        break;
+    case DeviceOutVendor | FTDI_SET_LATENCY:
+        s->latency = value;
+        break;
+    case DeviceInVendor | FTDI_GET_LATENCY:
+        data[0] = s->latency;
+        ret = 1;
+        break;
+    default:
+    fail:
+        DPRINTF("got unsupported/bogus control %x, value %x\n", request, value);
+        ret = USB_RET_STALL;
+        break;
+    }
+    return ret;
+}
+
+static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
+{
+    USBSerialState *s = (USBSerialState *)dev;
+    int i, ret = 0;
+    uint8_t devep = p->ep->nr;
+    struct iovec *iov;
+    uint8_t header[2];
+    int first_len, len;
+
+    switch (p->pid) {
+    case USB_TOKEN_OUT:
+        if (devep != 2)
+            goto fail;
+        for (i = 0; i < p->iov.niov; i++) {
+            iov = p->iov.iov + i;
+            qemu_chr_fe_write(s->cs, iov->iov_base, iov->iov_len);
+        }
+        break;
+
+    case USB_TOKEN_IN:
+        if (devep != 1)
+            goto fail;
+        first_len = RECV_BUF - s->recv_ptr;
+        len = p->iov.size;
+        if (len <= 2) {
+            ret = USB_RET_NAK;
+            break;
+        }
+        header[0] = usb_get_modem_lines(s) | 1;
+        /* We do not have the uart details */
+        /* handle serial break */
+        if (s->event_trigger && s->event_trigger & FTDI_BI) {
+            s->event_trigger &= ~FTDI_BI;
+            header[1] = FTDI_BI;
+            usb_packet_copy(p, header, 2);
+            ret = 2;
+            break;
+        } else {
+            header[1] = 0;
+        }
+        len -= 2;
+        if (len > s->recv_used)
+            len = s->recv_used;
+        if (!len) {
+            ret = USB_RET_NAK;
+            break;
+        }
+        if (first_len > len)
+            first_len = len;
+        usb_packet_copy(p, header, 2);
+        usb_packet_copy(p, s->recv_buf + s->recv_ptr, first_len);
+        if (len > first_len)
+            usb_packet_copy(p, s->recv_buf, len - first_len);
+        s->recv_used -= len;
+        s->recv_ptr = (s->recv_ptr + len) % RECV_BUF;
+        ret = len + 2;
+        break;
+
+    default:
+        DPRINTF("Bad token\n");
+    fail:
+        ret = USB_RET_STALL;
+        break;
+    }
+
+    return ret;
+}
+
+static void usb_serial_handle_destroy(USBDevice *dev)
+{
+    USBSerialState *s = (USBSerialState *)dev;
+
+    qemu_chr_delete(s->cs);
+}
+
+static int usb_serial_can_read(void *opaque)
+{
+    USBSerialState *s = opaque;
+    return RECV_BUF - s->recv_used;
+}
+
+static void usb_serial_read(void *opaque, const uint8_t *buf, int size)
+{
+    USBSerialState *s = opaque;
+    int first_size, start;
+
+    /* room in the buffer? */
+    if (size > (RECV_BUF - s->recv_used))
+        size = RECV_BUF - s->recv_used;
+
+    start = s->recv_ptr + s->recv_used;
+    if (start < RECV_BUF) {
+        /* copy data to end of buffer */
+        first_size = RECV_BUF - start;
+        if (first_size > size)
+            first_size = size;
+
+        memcpy(s->recv_buf + start, buf, first_size);
+
+        /* wrap around to front if needed */
+        if (size > first_size)
+            memcpy(s->recv_buf, buf + first_size, size - first_size);
+    } else {
+        start -= RECV_BUF;
+        memcpy(s->recv_buf + start, buf, size);
+    }
+    s->recv_used += size;
+}
+
+static void usb_serial_event(void *opaque, int event)
+{
+    USBSerialState *s = opaque;
+
+    switch (event) {
+        case CHR_EVENT_BREAK:
+            s->event_trigger |= FTDI_BI;
+            break;
+        case CHR_EVENT_FOCUS:
+            break;
+        case CHR_EVENT_OPENED:
+            usb_serial_reset(s);
+            /* TODO: Reset USB port */
+            break;
+    }
+}
+
+static int usb_serial_initfn(USBDevice *dev)
+{
+    USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev);
+
+    usb_desc_init(dev);
+
+    if (!s->cs) {
+        error_report("Property chardev is required");
+        return -1;
+    }
+
+    qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
+                          usb_serial_event, s);
+    usb_serial_handle_reset(dev);
+    return 0;
+}
+
+static USBDevice *usb_serial_init(USBBus *bus, const char *filename)
+{
+    USBDevice *dev;
+    CharDriverState *cdrv;
+    uint32_t vendorid = 0, productid = 0;
+    char label[32];
+    static int index;
+
+    while (*filename && *filename != ':') {
+        const char *p;
+        char *e;
+        if (strstart(filename, "vendorid=", &p)) {
+            vendorid = strtol(p, &e, 16);
+            if (e == p || (*e && *e != ',' && *e != ':')) {
+                error_report("bogus vendor ID %s", p);
+                return NULL;
+            }
+            filename = e;
+        } else if (strstart(filename, "productid=", &p)) {
+            productid = strtol(p, &e, 16);
+            if (e == p || (*e && *e != ',' && *e != ':')) {
+                error_report("bogus product ID %s", p);
+                return NULL;
+            }
+            filename = e;
+        } else {
+            error_report("unrecognized serial USB option %s", filename);
+            return NULL;
+        }
+        while(*filename == ',')
+            filename++;
+    }
+    if (!*filename) {
+        error_report("character device specification needed");
+        return NULL;
+    }
+    filename++;
+
+    snprintf(label, sizeof(label), "usbserial%d", index++);
+    cdrv = qemu_chr_new(label, filename, NULL);
+    if (!cdrv)
+        return NULL;
+
+    dev = usb_create(bus, "usb-serial");
+    if (!dev) {
+        return NULL;
+    }
+    qdev_prop_set_chr(&dev->qdev, "chardev", cdrv);
+    if (vendorid)
+        qdev_prop_set_uint16(&dev->qdev, "vendorid", vendorid);
+    if (productid)
+        qdev_prop_set_uint16(&dev->qdev, "productid", productid);
+    qdev_init_nofail(&dev->qdev);
+
+    return dev;
+}
+
+static USBDevice *usb_braille_init(USBBus *bus, const char *unused)
+{
+    USBDevice *dev;
+    CharDriverState *cdrv;
+
+    cdrv = qemu_chr_new("braille", "braille", NULL);
+    if (!cdrv)
+        return NULL;
+
+    dev = usb_create(bus, "usb-braille");
+    qdev_prop_set_chr(&dev->qdev, "chardev", cdrv);
+    qdev_init_nofail(&dev->qdev);
+
+    return dev;
+}
+
+static const VMStateDescription vmstate_usb_serial = {
+    .name = "usb-serial",
+    .unmigratable = 1,
+};
+
+static Property serial_properties[] = {
+    DEFINE_PROP_CHR("chardev", USBSerialState, cs),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void usb_serial_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+    uc->init = usb_serial_initfn;
+    uc->product_desc   = "QEMU USB Serial";
+    uc->usb_desc       = &desc_serial;
+    uc->handle_reset   = usb_serial_handle_reset;
+    uc->handle_control = usb_serial_handle_control;
+    uc->handle_data    = usb_serial_handle_data;
+    uc->handle_destroy = usb_serial_handle_destroy;
+    dc->vmsd = &vmstate_usb_serial;
+    dc->props = serial_properties;
+}
+
+static TypeInfo serial_info = {
+    .name          = "usb-serial",
+    .parent        = TYPE_USB_DEVICE,
+    .instance_size = sizeof(USBSerialState),
+    .class_init    = usb_serial_class_initfn,
+};
+
+static Property braille_properties[] = {
+    DEFINE_PROP_CHR("chardev", USBSerialState, cs),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void usb_braille_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+    uc->init           = usb_serial_initfn;
+    uc->product_desc   = "QEMU USB Braille";
+    uc->usb_desc       = &desc_braille;
+    uc->handle_reset   = usb_serial_handle_reset;
+    uc->handle_control = usb_serial_handle_control;
+    uc->handle_data    = usb_serial_handle_data;
+    uc->handle_destroy = usb_serial_handle_destroy;
+    dc->vmsd = &vmstate_usb_serial;
+    dc->props = braille_properties;
+}
+
+static TypeInfo braille_info = {
+    .name          = "usb-braille",
+    .parent        = TYPE_USB_DEVICE,
+    .instance_size = sizeof(USBSerialState),
+    .class_init    = usb_braille_class_initfn,
+};
+
+static void usb_serial_register_types(void)
+{
+    type_register_static(&serial_info);
+    usb_legacy_register("usb-serial", "serial", usb_serial_init);
+    type_register_static(&braille_info);
+    usb_legacy_register("usb-braille", "braille", usb_braille_init);
+}
+
+type_init(usb_serial_register_types)
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
new file mode 100644
index 0000000..8e66675
--- /dev/null
+++ b/hw/usb/dev-smartcard-reader.c
@@ -0,0 +1,1365 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * CCID Device emulation
+ *
+ * Written by Alon Levy, with contributions from Robert Relyea.
+ *
+ * Based on usb-serial.c, see its copyright and attributions below.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.1 or later.
+ * See the COPYING file in the top-level directory.
+ * ------- (original copyright & attribution for usb-serial.c below) --------
+ * Copyright (c) 2006 CodeSourcery.
+ * Copyright (c) 2008 Samuel Thibault <samuel.thibault at ens-lyon.org>
+ * Written by Paul Brook, reused for FTDI by Samuel Thibault,
+ */
+
+/*
+ * References:
+ *
+ * CCID Specification Revision 1.1 April 22nd 2005
+ *  "Universal Serial Bus, Device Class: Smart Card"
+ *  Specification for Integrated Circuit(s) Cards Interface Devices
+ *
+ * Endianness note: from the spec (1.3)
+ *  "Fields that are larger than a byte are stored in little endian"
+ *
+ * KNOWN BUGS
+ * 1. remove/insert can sometimes result in removed state instead of inserted.
+ * This is a result of the following:
+ *  symptom: dmesg shows ERMOTEIO (-121), pcscd shows -99. This can happen
+ *  when a short packet is sent, as seen in uhci-usb.c, resulting from a urb
+ *  from the guest requesting SPD and us returning a smaller packet.
+ *  Not sure which messages trigger this.
+ */
+
+#include "qemu-common.h"
+#include "qemu-error.h"
+#include "hw/usb.h"
+#include "hw/usb/desc.h"
+#include "monitor.h"
+
+#include "hw/ccid.h"
+
+#define DPRINTF(s, lvl, fmt, ...) \
+do { \
+    if (lvl <= s->debug) { \
+        printf("usb-ccid: " fmt , ## __VA_ARGS__); \
+    } \
+} while (0)
+
+#define D_WARN 1
+#define D_INFO 2
+#define D_MORE_INFO 3
+#define D_VERBOSE 4
+
+#define CCID_DEV_NAME "usb-ccid"
+
+/*
+ * The two options for variable sized buffers:
+ * make them constant size, for large enough constant,
+ * or handle the migration complexity - VMState doesn't handle this case.
+ * sizes are expected never to be exceeded, unless guest misbehaves.
+ */
+#define BULK_OUT_DATA_SIZE 65536
+#define PENDING_ANSWERS_NUM 128
+
+#define BULK_IN_BUF_SIZE 384
+#define BULK_IN_PENDING_NUM 8
+
+#define InterfaceOutClass \
+    ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)<<8)
+
+#define InterfaceInClass  \
+    ((USB_DIR_IN  | USB_TYPE_CLASS | USB_RECIP_INTERFACE)<<8)
+
+#define CCID_MAX_PACKET_SIZE                64
+
+#define CCID_CONTROL_ABORT                  0x1
+#define CCID_CONTROL_GET_CLOCK_FREQUENCIES  0x2
+#define CCID_CONTROL_GET_DATA_RATES         0x3
+
+#define CCID_PRODUCT_DESCRIPTION        "QEMU USB CCID"
+#define CCID_VENDOR_DESCRIPTION         "QEMU " QEMU_VERSION
+#define CCID_INTERFACE_NAME             "CCID Interface"
+#define CCID_SERIAL_NUMBER_STRING       "1"
+/*
+ * Using Gemplus Vendor and Product id
+ * Effect on various drivers:
+ *  usbccid.sys (winxp, others untested) is a class driver so it doesn't care.
+ *  linux has a number of class drivers, but openct filters based on
+ *   vendor/product (/etc/openct.conf under fedora), hence Gemplus.
+ */
+#define CCID_VENDOR_ID                  0x08e6
+#define CCID_PRODUCT_ID                 0x4433
+#define CCID_DEVICE_VERSION             0x0000
+
+/*
+ * BULK_OUT messages from PC to Reader
+ * Defined in CCID Rev 1.1 6.1 (page 26)
+ */
+#define CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn              0x62
+#define CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff             0x63
+#define CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus           0x65
+#define CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock                0x6f
+#define CCID_MESSAGE_TYPE_PC_to_RDR_GetParameters           0x6c
+#define CCID_MESSAGE_TYPE_PC_to_RDR_ResetParameters         0x6d
+#define CCID_MESSAGE_TYPE_PC_to_RDR_SetParameters           0x61
+#define CCID_MESSAGE_TYPE_PC_to_RDR_Escape                  0x6b
+#define CCID_MESSAGE_TYPE_PC_to_RDR_IccClock                0x6e
+#define CCID_MESSAGE_TYPE_PC_to_RDR_T0APDU                  0x6a
+#define CCID_MESSAGE_TYPE_PC_to_RDR_Secure                  0x69
+#define CCID_MESSAGE_TYPE_PC_to_RDR_Mechanical              0x71
+#define CCID_MESSAGE_TYPE_PC_to_RDR_Abort                   0x72
+#define CCID_MESSAGE_TYPE_PC_to_RDR_SetDataRateAndClockFrequency 0x73
+
+/*
+ * BULK_IN messages from Reader to PC
+ * Defined in CCID Rev 1.1 6.2 (page 48)
+ */
+#define CCID_MESSAGE_TYPE_RDR_to_PC_DataBlock               0x80
+#define CCID_MESSAGE_TYPE_RDR_to_PC_SlotStatus              0x81
+#define CCID_MESSAGE_TYPE_RDR_to_PC_Parameters              0x82
+#define CCID_MESSAGE_TYPE_RDR_to_PC_Escape                  0x83
+#define CCID_MESSAGE_TYPE_RDR_to_PC_DataRateAndClockFrequency 0x84
+
+/*
+ * INTERRUPT_IN messages from Reader to PC
+ * Defined in CCID Rev 1.1 6.3 (page 56)
+ */
+#define CCID_MESSAGE_TYPE_RDR_to_PC_NotifySlotChange        0x50
+#define CCID_MESSAGE_TYPE_RDR_to_PC_HardwareError           0x51
+
+/*
+ * Endpoints for CCID - addresses are up to us to decide.
+ * To support slot insertion and removal we must have an interrupt in ep
+ * in addition we need a bulk in and bulk out ep
+ * 5.2, page 20
+ */
+#define CCID_INT_IN_EP       1
+#define CCID_BULK_IN_EP      2
+#define CCID_BULK_OUT_EP     3
+
+/* bmSlotICCState masks */
+#define SLOT_0_STATE_MASK    1
+#define SLOT_0_CHANGED_MASK  2
+
+/* Status codes that go in bStatus (see 6.2.6) */
+enum {
+    ICC_STATUS_PRESENT_ACTIVE = 0,
+    ICC_STATUS_PRESENT_INACTIVE,
+    ICC_STATUS_NOT_PRESENT
+};
+
+enum {
+    COMMAND_STATUS_NO_ERROR = 0,
+    COMMAND_STATUS_FAILED,
+    COMMAND_STATUS_TIME_EXTENSION_REQUIRED
+};
+
+/* Error codes that go in bError (see 6.2.6) */
+enum {
+    ERROR_CMD_NOT_SUPPORTED = 0,
+    ERROR_CMD_ABORTED       = -1,
+    ERROR_ICC_MUTE          = -2,
+    ERROR_XFR_PARITY_ERROR  = -3,
+    ERROR_XFR_OVERRUN       = -4,
+    ERROR_HW_ERROR          = -5,
+};
+
+/* 6.2.6 RDR_to_PC_SlotStatus definitions */
+enum {
+    CLOCK_STATUS_RUNNING = 0,
+    /*
+     * 0 - Clock Running, 1 - Clock stopped in State L, 2 - H,
+     * 3 - unknown state. rest are RFU
+     */
+};
+
+typedef struct QEMU_PACKED CCID_Header {
+    uint8_t     bMessageType;
+    uint32_t    dwLength;
+    uint8_t     bSlot;
+    uint8_t     bSeq;
+} CCID_Header;
+
+typedef struct QEMU_PACKED CCID_BULK_IN {
+    CCID_Header hdr;
+    uint8_t     bStatus;        /* Only used in BULK_IN */
+    uint8_t     bError;         /* Only used in BULK_IN */
+} CCID_BULK_IN;
+
+typedef struct QEMU_PACKED CCID_SlotStatus {
+    CCID_BULK_IN b;
+    uint8_t     bClockStatus;
+} CCID_SlotStatus;
+
+typedef struct QEMU_PACKED CCID_Parameter {
+    CCID_BULK_IN b;
+    uint8_t     bProtocolNum;
+    uint8_t     abProtocolDataStructure[0];
+} CCID_Parameter;
+
+typedef struct QEMU_PACKED CCID_DataBlock {
+    CCID_BULK_IN b;
+    uint8_t      bChainParameter;
+    uint8_t      abData[0];
+} CCID_DataBlock;
+
+/* 6.1.4 PC_to_RDR_XfrBlock */
+typedef struct QEMU_PACKED CCID_XferBlock {
+    CCID_Header  hdr;
+    uint8_t      bBWI; /* Block Waiting Timeout */
+    uint16_t     wLevelParameter; /* XXX currently unused */
+    uint8_t      abData[0];
+} CCID_XferBlock;
+
+typedef struct QEMU_PACKED CCID_IccPowerOn {
+    CCID_Header hdr;
+    uint8_t     bPowerSelect;
+    uint16_t    abRFU;
+} CCID_IccPowerOn;
+
+typedef struct QEMU_PACKED CCID_IccPowerOff {
+    CCID_Header hdr;
+    uint16_t    abRFU;
+} CCID_IccPowerOff;
+
+typedef struct QEMU_PACKED CCID_SetParameters {
+    CCID_Header hdr;
+    uint8_t     bProtocolNum;
+    uint16_t   abRFU;
+    uint8_t    abProtocolDataStructure[0];
+} CCID_SetParameters;
+
+typedef struct CCID_Notify_Slot_Change {
+    uint8_t     bMessageType; /* CCID_MESSAGE_TYPE_RDR_to_PC_NotifySlotChange */
+    uint8_t     bmSlotICCState;
+} CCID_Notify_Slot_Change;
+
+/* used for DataBlock response to XferBlock */
+typedef struct Answer {
+    uint8_t slot;
+    uint8_t seq;
+} Answer;
+
+/* pending BULK_IN messages */
+typedef struct BulkIn {
+    uint8_t  data[BULK_IN_BUF_SIZE];
+    uint32_t len;
+    uint32_t pos;
+} BulkIn;
+
+enum {
+    MIGRATION_NONE,
+    MIGRATION_MIGRATED,
+};
+
+typedef struct CCIDBus {
+    BusState qbus;
+} CCIDBus;
+
+#define MAX_PROTOCOL_SIZE   7
+
+/*
+ * powered - defaults to true, changed by PowerOn/PowerOff messages
+ */
+typedef struct USBCCIDState {
+    USBDevice dev;
+    USBEndpoint *intr;
+    CCIDBus bus;
+    CCIDCardState *card;
+    BulkIn bulk_in_pending[BULK_IN_PENDING_NUM]; /* circular */
+    uint32_t bulk_in_pending_start;
+    uint32_t bulk_in_pending_end; /* first free */
+    uint32_t bulk_in_pending_num;
+    BulkIn *current_bulk_in;
+    uint8_t  bulk_out_data[BULK_OUT_DATA_SIZE];
+    uint32_t bulk_out_pos;
+    uint64_t last_answer_error;
+    Answer pending_answers[PENDING_ANSWERS_NUM];
+    uint32_t pending_answers_start;
+    uint32_t pending_answers_end;
+    uint32_t pending_answers_num;
+    uint8_t  bError;
+    uint8_t  bmCommandStatus;
+    uint8_t  bProtocolNum;
+    uint8_t  abProtocolDataStructure[MAX_PROTOCOL_SIZE];
+    uint32_t ulProtocolDataStructureSize;
+    uint32_t state_vmstate;
+    uint32_t migration_target_ip;
+    uint16_t migration_target_port;
+    uint8_t  migration_state;
+    uint8_t  bmSlotICCState;
+    uint8_t  powered;
+    uint8_t  notify_slot_change;
+    uint8_t  debug;
+} USBCCIDState;
+
+/*
+ * CCID Spec chapter 4: CCID uses a standard device descriptor per Chapter 9,
+ * "USB Device Framework", section 9.6.1, in the Universal Serial Bus
+ * Specification.
+ *
+ * This device implemented based on the spec and with an Athena Smart Card
+ * Reader as reference:
+ *   0dc3:1004 Athena Smartcard Solutions, Inc.
+ */
+
+static const uint8_t qemu_ccid_descriptor[] = {
+        /* Smart Card Device Class Descriptor */
+        0x36,       /* u8  bLength; */
+        0x21,       /* u8  bDescriptorType; Functional */
+        0x10, 0x01, /* u16 bcdCCID; CCID Specification Release Number. */
+        0x00,       /*
+                     * u8  bMaxSlotIndex; The index of the highest available
+                     * slot on this device. All slots are consecutive starting
+                     * at 00h.
+                     */
+        0x07,       /* u8  bVoltageSupport; 01h - 5.0v, 02h - 3.0, 03 - 1.8 */
+
+        0x03, 0x00, /* u32 dwProtocols; RRRR PPPP. RRRR = 0000h.*/
+        0x00, 0x00, /* PPPP: 0001h = Protocol T=0, 0002h = Protocol T=1 */
+                    /* u32 dwDefaultClock; in kHZ (0x0fa0 is 4 MHz) */
+        0xa0, 0x0f, 0x00, 0x00,
+                    /* u32 dwMaximumClock; */
+        0x00, 0x00, 0x01, 0x00,
+        0x00,       /* u8 bNumClockSupported;                 *
+                     *    0 means just the default and max.   */
+                    /* u32 dwDataRate ;bps. 9600 == 00002580h */
+        0x80, 0x25, 0x00, 0x00,
+                    /* u32 dwMaxDataRate ; 11520 bps == 0001C200h */
+        0x00, 0xC2, 0x01, 0x00,
+        0x00,       /* u8  bNumDataRatesSupported; 00 means all rates between
+                     *     default and max */
+                    /* u32 dwMaxIFSD;                                  *
+                     *     maximum IFSD supported by CCID for protocol *
+                     *     T=1 (Maximum seen from various cards)       */
+        0xfe, 0x00, 0x00, 0x00,
+                    /* u32 dwSyncProtocols; 1 - 2-wire, 2 - 3-wire, 4 - I2C */
+        0x00, 0x00, 0x00, 0x00,
+                    /* u32 dwMechanical;  0 - no special characteristics. */
+        0x00, 0x00, 0x00, 0x00,
+                    /*
+                     * u32 dwFeatures;
+                     * 0 - No special characteristics
+                     * + 2 Automatic parameter configuration based on ATR data
+                     * + 4 Automatic activation of ICC on inserting
+                     * + 8 Automatic ICC voltage selection
+                     * + 10 Automatic ICC clock frequency change
+                     * + 20 Automatic baud rate change
+                     * + 40 Automatic parameters negotiation made by the CCID
+                     * + 80 automatic PPS made by the CCID
+                     * 100 CCID can set ICC in clock stop mode
+                     * 200 NAD value other then 00 accepted (T=1 protocol)
+                     * + 400 Automatic IFSD exchange as first exchange (T=1)
+                     * One of the following only:
+                     * + 10000 TPDU level exchanges with CCID
+                     * 20000 Short APDU level exchange with CCID
+                     * 40000 Short and Extended APDU level exchange with CCID
+                     *
+                     * + 100000 USB Wake up signaling supported on card
+                     * insertion and removal. Must set bit 5 in bmAttributes
+                     * in Configuration descriptor if 100000 is set.
+                     */
+        0xfe, 0x04, 0x11, 0x00,
+                    /*
+                     * u32 dwMaxCCIDMessageLength; For extended APDU in
+                     * [261 + 10 , 65544 + 10]. Otherwise the minimum is
+                     * wMaxPacketSize of the Bulk-OUT endpoint
+                     */
+        0x12, 0x00, 0x01, 0x00,
+        0xFF,       /*
+                     * u8  bClassGetResponse; Significant only for CCID that
+                     * offers an APDU level for exchanges. Indicates the
+                     * default class value used by the CCID when it sends a
+                     * Get Response command to perform the transportation of
+                     * an APDU by T=0 protocol
+                     * FFh indicates that the CCID echos the class of the APDU.
+                     */
+        0xFF,       /*
+                     * u8  bClassEnvelope; EAPDU only. Envelope command for
+                     * T=0
+                     */
+        0x00, 0x00, /*
+                     * u16 wLcdLayout; XXYY Number of lines (XX) and chars per
+                     * line for LCD display used for PIN entry. 0000 - no LCD
+                     */
+        0x01,       /*
+                     * u8  bPINSupport; 01h PIN Verification,
+                     *                  02h PIN Modification
+                     */
+        0x01,       /* u8  bMaxCCIDBusySlots; */
+};
+
+enum {
+    STR_MANUFACTURER = 1,
+    STR_PRODUCT,
+    STR_SERIALNUMBER,
+    STR_INTERFACE,
+};
+
+static const USBDescStrings desc_strings = {
+    [STR_MANUFACTURER]  = "QEMU " QEMU_VERSION,
+    [STR_PRODUCT]       = "QEMU USB CCID",
+    [STR_SERIALNUMBER]  = "1",
+    [STR_INTERFACE]     = "CCID Interface",
+};
+
+static const USBDescIface desc_iface0 = {
+    .bInterfaceNumber              = 0,
+    .bNumEndpoints                 = 3,
+    .bInterfaceClass               = 0x0b,
+    .bInterfaceSubClass            = 0x00,
+    .bInterfaceProtocol            = 0x00,
+    .iInterface                    = STR_INTERFACE,
+    .ndesc                         = 1,
+    .descs = (USBDescOther[]) {
+        {
+            /* smartcard descriptor */
+            .data = qemu_ccid_descriptor,
+        },
+    },
+    .eps = (USBDescEndpoint[]) {
+        {
+            .bEndpointAddress      = USB_DIR_IN | CCID_INT_IN_EP,
+            .bmAttributes          = USB_ENDPOINT_XFER_INT,
+            .bInterval             = 255,
+            .wMaxPacketSize        = 64,
+        },{
+            .bEndpointAddress      = USB_DIR_IN | CCID_BULK_IN_EP,
+            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize        = 64,
+        },{
+            .bEndpointAddress      = USB_DIR_OUT | CCID_BULK_OUT_EP,
+            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize        = 64,
+        },
+    }
+};
+
+static const USBDescDevice desc_device = {
+    .bcdUSB                        = 0x0110,
+    .bMaxPacketSize0               = 64,
+    .bNumConfigurations            = 1,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 1,
+            .bConfigurationValue   = 1,
+            .bmAttributes          = 0xe0,
+            .bMaxPower             = 50,
+            .nif = 1,
+            .ifs = &desc_iface0,
+        },
+    },
+};
+
+static const USBDesc desc_ccid = {
+    .id = {
+        .idVendor          = CCID_VENDOR_ID,
+        .idProduct         = CCID_PRODUCT_ID,
+        .bcdDevice         = CCID_DEVICE_VERSION,
+        .iManufacturer     = STR_MANUFACTURER,
+        .iProduct          = STR_PRODUCT,
+        .iSerialNumber     = STR_SERIALNUMBER,
+    },
+    .full = &desc_device,
+    .str  = desc_strings,
+};
+
+static const uint8_t *ccid_card_get_atr(CCIDCardState *card, uint32_t *len)
+{
+    CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
+    if (cc->get_atr) {
+        return cc->get_atr(card, len);
+    }
+    return NULL;
+}
+
+static void ccid_card_apdu_from_guest(CCIDCardState *card,
+                                      const uint8_t *apdu,
+                                      uint32_t len)
+{
+    CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
+    if (cc->apdu_from_guest) {
+        cc->apdu_from_guest(card, apdu, len);
+    }
+}
+
+static int ccid_card_exitfn(CCIDCardState *card)
+{
+    CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
+    if (cc->exitfn) {
+        return cc->exitfn(card);
+    }
+    return 0;
+}
+
+static int ccid_card_initfn(CCIDCardState *card)
+{
+    CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
+    if (cc->initfn) {
+        return cc->initfn(card);
+    }
+    return 0;
+}
+
+static bool ccid_has_pending_answers(USBCCIDState *s)
+{
+    return s->pending_answers_num > 0;
+}
+
+static void ccid_clear_pending_answers(USBCCIDState *s)
+{
+    s->pending_answers_num = 0;
+    s->pending_answers_start = 0;
+    s->pending_answers_end = 0;
+}
+
+static void ccid_print_pending_answers(USBCCIDState *s)
+{
+    Answer *answer;
+    int i, count;
+
+    DPRINTF(s, D_VERBOSE, "usb-ccid: pending answers:");
+    if (!ccid_has_pending_answers(s)) {
+        DPRINTF(s, D_VERBOSE, " empty\n");
+        return;
+    }
+    for (i = s->pending_answers_start, count = s->pending_answers_num ;
+         count > 0; count--, i++) {
+        answer = &s->pending_answers[i % PENDING_ANSWERS_NUM];
+        if (count == 1) {
+            DPRINTF(s, D_VERBOSE, "%d:%d\n", answer->slot, answer->seq);
+        } else {
+            DPRINTF(s, D_VERBOSE, "%d:%d,", answer->slot, answer->seq);
+        }
+    }
+}
+
+static void ccid_add_pending_answer(USBCCIDState *s, CCID_Header *hdr)
+{
+    Answer *answer;
+
+    assert(s->pending_answers_num < PENDING_ANSWERS_NUM);
+    s->pending_answers_num++;
+    answer =
+        &s->pending_answers[(s->pending_answers_end++) % PENDING_ANSWERS_NUM];
+    answer->slot = hdr->bSlot;
+    answer->seq = hdr->bSeq;
+    ccid_print_pending_answers(s);
+}
+
+static void ccid_remove_pending_answer(USBCCIDState *s,
+    uint8_t *slot, uint8_t *seq)
+{
+    Answer *answer;
+
+    assert(s->pending_answers_num > 0);
+    s->pending_answers_num--;
+    answer =
+        &s->pending_answers[(s->pending_answers_start++) % PENDING_ANSWERS_NUM];
+    *slot = answer->slot;
+    *seq = answer->seq;
+    ccid_print_pending_answers(s);
+}
+
+static void ccid_bulk_in_clear(USBCCIDState *s)
+{
+    s->bulk_in_pending_start = 0;
+    s->bulk_in_pending_end = 0;
+    s->bulk_in_pending_num = 0;
+}
+
+static void ccid_bulk_in_release(USBCCIDState *s)
+{
+    assert(s->current_bulk_in != NULL);
+    s->current_bulk_in->pos = 0;
+    s->current_bulk_in = NULL;
+}
+
+static void ccid_bulk_in_get(USBCCIDState *s)
+{
+    if (s->current_bulk_in != NULL || s->bulk_in_pending_num == 0) {
+        return;
+    }
+    assert(s->bulk_in_pending_num > 0);
+    s->bulk_in_pending_num--;
+    s->current_bulk_in =
+        &s->bulk_in_pending[(s->bulk_in_pending_start++) % BULK_IN_PENDING_NUM];
+}
+
+static void *ccid_reserve_recv_buf(USBCCIDState *s, uint16_t len)
+{
+    BulkIn *bulk_in;
+
+    DPRINTF(s, D_VERBOSE, "%s: QUEUE: reserve %d bytes\n", __func__, len);
+
+    /* look for an existing element */
+    if (len > BULK_IN_BUF_SIZE) {
+        DPRINTF(s, D_WARN, "usb-ccid.c: %s: len larger then max (%d>%d). "
+                           "discarding message.\n",
+                           __func__, len, BULK_IN_BUF_SIZE);
+        return NULL;
+    }
+    if (s->bulk_in_pending_num >= BULK_IN_PENDING_NUM) {
+        DPRINTF(s, D_WARN, "usb-ccid.c: %s: No free bulk_in buffers. "
+                           "discarding message.\n", __func__);
+        return NULL;
+    }
+    bulk_in =
+        &s->bulk_in_pending[(s->bulk_in_pending_end++) % BULK_IN_PENDING_NUM];
+    s->bulk_in_pending_num++;
+    bulk_in->len = len;
+    return bulk_in->data;
+}
+
+static void ccid_reset(USBCCIDState *s)
+{
+    ccid_bulk_in_clear(s);
+    ccid_clear_pending_answers(s);
+}
+
+static void ccid_detach(USBCCIDState *s)
+{
+    ccid_reset(s);
+}
+
+static void ccid_handle_reset(USBDevice *dev)
+{
+    USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
+
+    DPRINTF(s, 1, "Reset\n");
+
+    ccid_reset(s);
+}
+
+static int ccid_handle_control(USBDevice *dev, USBPacket *p, int request,
+                               int value, int index, int length, uint8_t *data)
+{
+    USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
+    int ret = 0;
+
+    DPRINTF(s, 1, "got control %x, value %x\n", request, value);
+    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
+    if (ret >= 0) {
+        return ret;
+    }
+
+    switch (request) {
+        /* Class specific requests.  */
+    case InterfaceOutClass | CCID_CONTROL_ABORT:
+        DPRINTF(s, 1, "ccid_control abort UNIMPLEMENTED\n");
+        ret = USB_RET_STALL;
+        break;
+    case InterfaceInClass | CCID_CONTROL_GET_CLOCK_FREQUENCIES:
+        DPRINTF(s, 1, "ccid_control get clock frequencies UNIMPLEMENTED\n");
+        ret = USB_RET_STALL;
+        break;
+    case InterfaceInClass | CCID_CONTROL_GET_DATA_RATES:
+        DPRINTF(s, 1, "ccid_control get data rates UNIMPLEMENTED\n");
+        ret = USB_RET_STALL;
+        break;
+    default:
+        DPRINTF(s, 1, "got unsupported/bogus control %x, value %x\n",
+                request, value);
+        ret = USB_RET_STALL;
+        break;
+    }
+    return ret;
+}
+
+static bool ccid_card_inserted(USBCCIDState *s)
+{
+    return s->bmSlotICCState & SLOT_0_STATE_MASK;
+}
+
+static uint8_t ccid_card_status(USBCCIDState *s)
+{
+    return ccid_card_inserted(s)
+            ? (s->powered ?
+                ICC_STATUS_PRESENT_ACTIVE
+              : ICC_STATUS_PRESENT_INACTIVE
+              )
+            : ICC_STATUS_NOT_PRESENT;
+}
+
+static uint8_t ccid_calc_status(USBCCIDState *s)
+{
+    /*
+     * page 55, 6.2.6, calculation of bStatus from bmICCStatus and
+     * bmCommandStatus
+     */
+    uint8_t ret = ccid_card_status(s) | (s->bmCommandStatus << 6);
+    DPRINTF(s, D_VERBOSE, "status = %d\n", ret);
+    return ret;
+}
+
+static void ccid_reset_error_status(USBCCIDState *s)
+{
+    s->bError = ERROR_CMD_NOT_SUPPORTED;
+    s->bmCommandStatus = COMMAND_STATUS_NO_ERROR;
+}
+
+static void ccid_write_slot_status(USBCCIDState *s, CCID_Header *recv)
+{
+    CCID_SlotStatus *h = ccid_reserve_recv_buf(s, sizeof(CCID_SlotStatus));
+    if (h == NULL) {
+        return;
+    }
+    h->b.hdr.bMessageType = CCID_MESSAGE_TYPE_RDR_to_PC_SlotStatus;
+    h->b.hdr.dwLength = 0;
+    h->b.hdr.bSlot = recv->bSlot;
+    h->b.hdr.bSeq = recv->bSeq;
+    h->b.bStatus = ccid_calc_status(s);
+    h->b.bError = s->bError;
+    h->bClockStatus = CLOCK_STATUS_RUNNING;
+    ccid_reset_error_status(s);
+}
+
+static void ccid_write_parameters(USBCCIDState *s, CCID_Header *recv)
+{
+    CCID_Parameter *h;
+    uint32_t len = s->ulProtocolDataStructureSize;
+
+    h = ccid_reserve_recv_buf(s, sizeof(CCID_Parameter) + len);
+    if (h == NULL) {
+        return;
+    }
+    h->b.hdr.bMessageType = CCID_MESSAGE_TYPE_RDR_to_PC_Parameters;
+    h->b.hdr.dwLength = 0;
+    h->b.hdr.bSlot = recv->bSlot;
+    h->b.hdr.bSeq = recv->bSeq;
+    h->b.bStatus = ccid_calc_status(s);
+    h->b.bError = s->bError;
+    h->bProtocolNum = s->bProtocolNum;
+    memcpy(h->abProtocolDataStructure, s->abProtocolDataStructure, len);
+    ccid_reset_error_status(s);
+}
+
+static void ccid_write_data_block(USBCCIDState *s, uint8_t slot, uint8_t seq,
+                                  const uint8_t *data, uint32_t len)
+{
+    CCID_DataBlock *p = ccid_reserve_recv_buf(s, sizeof(*p) + len);
+
+    if (p == NULL) {
+        return;
+    }
+    p->b.hdr.bMessageType = CCID_MESSAGE_TYPE_RDR_to_PC_DataBlock;
+    p->b.hdr.dwLength = cpu_to_le32(len);
+    p->b.hdr.bSlot = slot;
+    p->b.hdr.bSeq = seq;
+    p->b.bStatus = ccid_calc_status(s);
+    p->b.bError = s->bError;
+    if (p->b.bError) {
+        DPRINTF(s, D_VERBOSE, "error %d", p->b.bError);
+    }
+    memcpy(p->abData, data, len);
+    ccid_reset_error_status(s);
+}
+
+static void ccid_write_data_block_answer(USBCCIDState *s,
+    const uint8_t *data, uint32_t len)
+{
+    uint8_t seq;
+    uint8_t slot;
+
+    if (!ccid_has_pending_answers(s)) {
+        abort();
+    }
+    ccid_remove_pending_answer(s, &slot, &seq);
+    ccid_write_data_block(s, slot, seq, data, len);
+}
+
+static void ccid_write_data_block_atr(USBCCIDState *s, CCID_Header *recv)
+{
+    const uint8_t *atr = NULL;
+    uint32_t len = 0;
+
+    if (s->card) {
+        atr = ccid_card_get_atr(s->card, &len);
+    }
+    ccid_write_data_block(s, recv->bSlot, recv->bSeq, atr, len);
+}
+
+static void ccid_set_parameters(USBCCIDState *s, CCID_Header *recv)
+{
+    CCID_SetParameters *ph = (CCID_SetParameters *) recv;
+    uint32_t len = 0;
+    if ((ph->bProtocolNum & 3) == 0) {
+        len = 5;
+    }
+    if ((ph->bProtocolNum & 3) == 1) {
+        len = 7;
+    }
+    if (len == 0) {
+        s->bmCommandStatus = COMMAND_STATUS_FAILED;
+        s->bError = 7; /* Protocol invalid or not supported */
+        return;
+    }
+    s->bProtocolNum = ph->bProtocolNum;
+    memcpy(s->abProtocolDataStructure, ph->abProtocolDataStructure, len);
+    s->ulProtocolDataStructureSize = len;
+    DPRINTF(s, 1, "%s: using len %d\n", __func__, len);
+}
+
+/*
+ * must be 5 bytes for T=0, 7 bytes for T=1
+ * See page 52
+ */
+static const uint8_t abDefaultProtocolDataStructure[7] = {
+    0x77, 0x00, 0x00, 0x00, 0x00, 0xfe /*IFSC*/, 0x00 /*NAD*/ };
+
+static void ccid_reset_parameters(USBCCIDState *s)
+{
+   uint32_t len = sizeof(abDefaultProtocolDataStructure);
+
+   s->bProtocolNum = 1; /* T=1 */
+   s->ulProtocolDataStructureSize = len;
+   memcpy(s->abProtocolDataStructure, abDefaultProtocolDataStructure, len);
+}
+
+static void ccid_report_error_failed(USBCCIDState *s, uint8_t error)
+{
+    s->bmCommandStatus = COMMAND_STATUS_FAILED;
+    s->bError = error;
+}
+
+/* NOTE: only a single slot is supported (SLOT_0) */
+static void ccid_on_slot_change(USBCCIDState *s, bool full)
+{
+    /* RDR_to_PC_NotifySlotChange, 6.3.1 page 56 */
+    uint8_t current = s->bmSlotICCState;
+    if (full) {
+        s->bmSlotICCState |= SLOT_0_STATE_MASK;
+    } else {
+        s->bmSlotICCState &= ~SLOT_0_STATE_MASK;
+    }
+    if (current != s->bmSlotICCState) {
+        s->bmSlotICCState |= SLOT_0_CHANGED_MASK;
+    }
+    s->notify_slot_change = true;
+    usb_wakeup(s->intr);
+}
+
+static void ccid_write_data_block_error(
+    USBCCIDState *s, uint8_t slot, uint8_t seq)
+{
+    ccid_write_data_block(s, slot, seq, NULL, 0);
+}
+
+static void ccid_on_apdu_from_guest(USBCCIDState *s, CCID_XferBlock *recv)
+{
+    uint32_t len;
+
+    if (ccid_card_status(s) != ICC_STATUS_PRESENT_ACTIVE) {
+        DPRINTF(s, 1,
+                "usb-ccid: not sending apdu to client, no card connected\n");
+        ccid_write_data_block_error(s, recv->hdr.bSlot, recv->hdr.bSeq);
+        return;
+    }
+    len = le32_to_cpu(recv->hdr.dwLength);
+    DPRINTF(s, 1, "%s: seq %d, len %d\n", __func__,
+                recv->hdr.bSeq, len);
+    ccid_add_pending_answer(s, (CCID_Header *)recv);
+    if (s->card) {
+        ccid_card_apdu_from_guest(s->card, recv->abData, len);
+    } else {
+        DPRINTF(s, D_WARN, "warning: discarded apdu\n");
+    }
+}
+
+/*
+ * Handle a single USB_TOKEN_OUT, return value returned to guest.
+ * Return value:
+ *  0             - all ok
+ *  USB_RET_STALL - failed to handle packet
+ */
+static int ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
+{
+    CCID_Header *ccid_header;
+
+    if (p->iov.size + s->bulk_out_pos > BULK_OUT_DATA_SIZE) {
+        return USB_RET_STALL;
+    }
+    ccid_header = (CCID_Header *)s->bulk_out_data;
+    usb_packet_copy(p, s->bulk_out_data + s->bulk_out_pos, p->iov.size);
+    s->bulk_out_pos += p->iov.size;
+    if (p->iov.size == CCID_MAX_PACKET_SIZE) {
+        DPRINTF(s, D_VERBOSE,
+            "usb-ccid: bulk_in: expecting more packets (%zd/%d)\n",
+            p->iov.size, ccid_header->dwLength);
+        return 0;
+    }
+    if (s->bulk_out_pos < 10) {
+        DPRINTF(s, 1,
+                "%s: bad USB_TOKEN_OUT length, should be at least 10 bytes\n",
+                __func__);
+    } else {
+        DPRINTF(s, D_MORE_INFO, "%s %x\n", __func__, ccid_header->bMessageType);
+        switch (ccid_header->bMessageType) {
+        case CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus:
+            ccid_write_slot_status(s, ccid_header);
+            break;
+        case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn:
+            DPRINTF(s, 1, "PowerOn: %d\n",
+                ((CCID_IccPowerOn *)(ccid_header))->bPowerSelect);
+            s->powered = true;
+            if (!ccid_card_inserted(s)) {
+                ccid_report_error_failed(s, ERROR_ICC_MUTE);
+            }
+            /* atr is written regardless of error. */
+            ccid_write_data_block_atr(s, ccid_header);
+            break;
+        case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff:
+            DPRINTF(s, 1, "PowerOff\n");
+            ccid_reset_error_status(s);
+            s->powered = false;
+            ccid_write_slot_status(s, ccid_header);
+            break;
+        case CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock:
+            ccid_on_apdu_from_guest(s, (CCID_XferBlock *)s->bulk_out_data);
+            break;
+        case CCID_MESSAGE_TYPE_PC_to_RDR_SetParameters:
+            ccid_reset_error_status(s);
+            ccid_set_parameters(s, ccid_header);
+            ccid_write_parameters(s, ccid_header);
+            break;
+        case CCID_MESSAGE_TYPE_PC_to_RDR_ResetParameters:
+            ccid_reset_error_status(s);
+            ccid_reset_parameters(s);
+            ccid_write_parameters(s, ccid_header);
+            break;
+        case CCID_MESSAGE_TYPE_PC_to_RDR_GetParameters:
+            ccid_reset_error_status(s);
+            ccid_write_parameters(s, ccid_header);
+            break;
+        default:
+            DPRINTF(s, 1,
+                "handle_data: ERROR: unhandled message type %Xh\n",
+                ccid_header->bMessageType);
+            /*
+             * The caller is expecting the device to respond, tell it we
+             * don't support the operation.
+             */
+            ccid_report_error_failed(s, ERROR_CMD_NOT_SUPPORTED);
+            ccid_write_slot_status(s, ccid_header);
+            break;
+        }
+    }
+    s->bulk_out_pos = 0;
+    return 0;
+}
+
+static int ccid_bulk_in_copy_to_guest(USBCCIDState *s, USBPacket *p)
+{
+    int ret = 0;
+
+    assert(p->iov.size > 0);
+    ccid_bulk_in_get(s);
+    if (s->current_bulk_in != NULL) {
+        ret = MIN(s->current_bulk_in->len - s->current_bulk_in->pos,
+                  p->iov.size);
+        usb_packet_copy(p, s->current_bulk_in->data +
+                        s->current_bulk_in->pos, ret);
+        s->current_bulk_in->pos += ret;
+        if (s->current_bulk_in->pos == s->current_bulk_in->len) {
+            ccid_bulk_in_release(s);
+        }
+    } else {
+        /* return when device has no data - usb 2.0 spec Table 8-4 */
+        ret = USB_RET_NAK;
+    }
+    if (ret > 0) {
+        DPRINTF(s, D_MORE_INFO,
+                "%s: %zd/%d req/act to guest (BULK_IN)\n",
+                __func__, p->iov.size, ret);
+    }
+    if (ret != USB_RET_NAK && ret < p->iov.size) {
+        DPRINTF(s, 1,
+                "%s: returning short (EREMOTEIO) %d < %zd\n",
+                __func__, ret, p->iov.size);
+    }
+    return ret;
+}
+
+static int ccid_handle_data(USBDevice *dev, USBPacket *p)
+{
+    USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
+    int ret = 0;
+    uint8_t buf[2];
+
+    switch (p->pid) {
+    case USB_TOKEN_OUT:
+        ret = ccid_handle_bulk_out(s, p);
+        break;
+
+    case USB_TOKEN_IN:
+        switch (p->ep->nr) {
+        case CCID_BULK_IN_EP:
+            if (!p->iov.size) {
+                ret = USB_RET_NAK;
+            } else {
+                ret = ccid_bulk_in_copy_to_guest(s, p);
+            }
+            break;
+        case CCID_INT_IN_EP:
+            if (s->notify_slot_change) {
+                /* page 56, RDR_to_PC_NotifySlotChange */
+                buf[0] = CCID_MESSAGE_TYPE_RDR_to_PC_NotifySlotChange;
+                buf[1] = s->bmSlotICCState;
+                usb_packet_copy(p, buf, 2);
+                ret = 2;
+                s->notify_slot_change = false;
+                s->bmSlotICCState &= ~SLOT_0_CHANGED_MASK;
+                DPRINTF(s, D_INFO,
+                        "handle_data: int_in: notify_slot_change %X, "
+                        "requested len %zd\n",
+                        s->bmSlotICCState, p->iov.size);
+            }
+            break;
+        default:
+            DPRINTF(s, 1, "Bad endpoint\n");
+            ret = USB_RET_STALL;
+            break;
+        }
+        break;
+    default:
+        DPRINTF(s, 1, "Bad token\n");
+        ret = USB_RET_STALL;
+        break;
+    }
+
+    return ret;
+}
+
+static void ccid_handle_destroy(USBDevice *dev)
+{
+    USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
+
+    ccid_bulk_in_clear(s);
+}
+
+static void ccid_flush_pending_answers(USBCCIDState *s)
+{
+    while (ccid_has_pending_answers(s)) {
+        ccid_write_data_block_answer(s, NULL, 0);
+    }
+}
+
+static Answer *ccid_peek_next_answer(USBCCIDState *s)
+{
+    return s->pending_answers_num == 0
+        ? NULL
+        : &s->pending_answers[s->pending_answers_start % PENDING_ANSWERS_NUM];
+}
+
+static struct BusInfo ccid_bus_info = {
+    .name = "ccid-bus",
+    .size = sizeof(CCIDBus),
+    .props = (Property[]) {
+        DEFINE_PROP_UINT32("slot", struct CCIDCardState, slot, 0),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
+void ccid_card_send_apdu_to_guest(CCIDCardState *card,
+                                  uint8_t *apdu, uint32_t len)
+{
+    USBCCIDState *s = DO_UPCAST(USBCCIDState, dev.qdev,
+                                card->qdev.parent_bus->parent);
+    Answer *answer;
+
+    if (!ccid_has_pending_answers(s)) {
+        DPRINTF(s, 1, "CCID ERROR: got an APDU without pending answers\n");
+        return;
+    }
+    s->bmCommandStatus = COMMAND_STATUS_NO_ERROR;
+    answer = ccid_peek_next_answer(s);
+    if (answer == NULL) {
+        abort();
+    }
+    DPRINTF(s, 1, "APDU returned to guest %d (answer seq %d, slot %d)\n",
+        len, answer->seq, answer->slot);
+    ccid_write_data_block_answer(s, apdu, len);
+}
+
+void ccid_card_card_removed(CCIDCardState *card)
+{
+    USBCCIDState *s =
+        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
+
+    ccid_on_slot_change(s, false);
+    ccid_flush_pending_answers(s);
+    ccid_reset(s);
+}
+
+int ccid_card_ccid_attach(CCIDCardState *card)
+{
+    USBCCIDState *s =
+        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
+
+    DPRINTF(s, 1, "CCID Attach\n");
+    if (s->migration_state == MIGRATION_MIGRATED) {
+        s->migration_state = MIGRATION_NONE;
+    }
+    return 0;
+}
+
+void ccid_card_ccid_detach(CCIDCardState *card)
+{
+    USBCCIDState *s =
+        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
+
+    DPRINTF(s, 1, "CCID Detach\n");
+    if (ccid_card_inserted(s)) {
+        ccid_on_slot_change(s, false);
+    }
+    ccid_detach(s);
+}
+
+void ccid_card_card_error(CCIDCardState *card, uint64_t error)
+{
+    USBCCIDState *s =
+        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
+
+    s->bmCommandStatus = COMMAND_STATUS_FAILED;
+    s->last_answer_error = error;
+    DPRINTF(s, 1, "VSC_Error: %" PRIX64 "\n", s->last_answer_error);
+    /* TODO: these errors should be more verbose and propagated to the guest.*/
+    /*
+     * We flush all pending answers on CardRemove message in ccid-card-passthru,
+     * so check that first to not trigger abort
+     */
+    if (ccid_has_pending_answers(s)) {
+        ccid_write_data_block_answer(s, NULL, 0);
+    }
+}
+
+void ccid_card_card_inserted(CCIDCardState *card)
+{
+    USBCCIDState *s =
+        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
+
+    s->bmCommandStatus = COMMAND_STATUS_NO_ERROR;
+    ccid_flush_pending_answers(s);
+    ccid_on_slot_change(s, true);
+}
+
+static int ccid_card_exit(DeviceState *qdev)
+{
+    int ret = 0;
+    CCIDCardState *card = CCID_CARD(qdev);
+    USBCCIDState *s =
+        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
+
+    if (ccid_card_inserted(s)) {
+        ccid_card_card_removed(card);
+    }
+    ret = ccid_card_exitfn(card);
+    s->card = NULL;
+    return ret;
+}
+
+static int ccid_card_init(DeviceState *qdev)
+{
+    CCIDCardState *card = CCID_CARD(qdev);
+    USBCCIDState *s =
+        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
+    int ret = 0;
+
+    if (card->slot != 0) {
+        error_report("Warning: usb-ccid supports one slot, can't add %d",
+                card->slot);
+        return -1;
+    }
+    if (s->card != NULL) {
+        error_report("Warning: usb-ccid card already full, not adding");
+        return -1;
+    }
+    ret = ccid_card_initfn(card);
+    if (ret == 0) {
+        s->card = card;
+    }
+    return ret;
+}
+
+static int ccid_initfn(USBDevice *dev)
+{
+    USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
+
+    usb_desc_init(dev);
+    qbus_create_inplace(&s->bus.qbus, &ccid_bus_info, &dev->qdev, NULL);
+    s->intr = usb_ep_get(dev, USB_TOKEN_IN, CCID_INT_IN_EP);
+    s->bus.qbus.allow_hotplug = 1;
+    s->card = NULL;
+    s->migration_state = MIGRATION_NONE;
+    s->migration_target_ip = 0;
+    s->migration_target_port = 0;
+    s->dev.speed = USB_SPEED_FULL;
+    s->dev.speedmask = USB_SPEED_MASK_FULL;
+    s->notify_slot_change = false;
+    s->powered = true;
+    s->pending_answers_num = 0;
+    s->last_answer_error = 0;
+    s->bulk_in_pending_start = 0;
+    s->bulk_in_pending_end = 0;
+    s->current_bulk_in = NULL;
+    ccid_reset_error_status(s);
+    s->bulk_out_pos = 0;
+    ccid_reset_parameters(s);
+    ccid_reset(s);
+    return 0;
+}
+
+static int ccid_post_load(void *opaque, int version_id)
+{
+    USBCCIDState *s = opaque;
+
+    /*
+     * This must be done after usb_device_attach, which sets state to ATTACHED,
+     * while it must be DEFAULT in order to accept packets (like it is after
+     * reset, but reset will reset our addr and call our reset handler which
+     * may change state, and we don't want to do that when migrating).
+     */
+    s->dev.state = s->state_vmstate;
+    return 0;
+}
+
+static void ccid_pre_save(void *opaque)
+{
+    USBCCIDState *s = opaque;
+
+    s->state_vmstate = s->dev.state;
+    if (s->dev.attached) {
+        /*
+         * Migrating an open device, ignore reconnection CHR_EVENT to avoid an
+         * erroneous detach.
+         */
+        s->migration_state = MIGRATION_MIGRATED;
+    }
+}
+
+static VMStateDescription bulk_in_vmstate = {
+    .name = "CCID BulkIn state",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_BUFFER(data, BulkIn),
+        VMSTATE_UINT32(len, BulkIn),
+        VMSTATE_UINT32(pos, BulkIn),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static VMStateDescription answer_vmstate = {
+    .name = "CCID Answer state",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(slot, Answer),
+        VMSTATE_UINT8(seq, Answer),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static VMStateDescription usb_device_vmstate = {
+    .name = "usb_device",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(addr, USBDevice),
+        VMSTATE_BUFFER(setup_buf, USBDevice),
+        VMSTATE_BUFFER(data_buf, USBDevice),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static VMStateDescription ccid_vmstate = {
+    .name = CCID_DEV_NAME,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .post_load = ccid_post_load,
+    .pre_save = ccid_pre_save,
+    .fields = (VMStateField[]) {
+        VMSTATE_STRUCT(dev, USBCCIDState, 1, usb_device_vmstate, USBDevice),
+        VMSTATE_UINT8(debug, USBCCIDState),
+        VMSTATE_BUFFER(bulk_out_data, USBCCIDState),
+        VMSTATE_UINT32(bulk_out_pos, USBCCIDState),
+        VMSTATE_UINT8(bmSlotICCState, USBCCIDState),
+        VMSTATE_UINT8(powered, USBCCIDState),
+        VMSTATE_UINT8(notify_slot_change, USBCCIDState),
+        VMSTATE_UINT64(last_answer_error, USBCCIDState),
+        VMSTATE_UINT8(bError, USBCCIDState),
+        VMSTATE_UINT8(bmCommandStatus, USBCCIDState),
+        VMSTATE_UINT8(bProtocolNum, USBCCIDState),
+        VMSTATE_BUFFER(abProtocolDataStructure, USBCCIDState),
+        VMSTATE_UINT32(ulProtocolDataStructureSize, USBCCIDState),
+        VMSTATE_STRUCT_ARRAY(bulk_in_pending, USBCCIDState,
+                       BULK_IN_PENDING_NUM, 1, bulk_in_vmstate, BulkIn),
+        VMSTATE_UINT32(bulk_in_pending_start, USBCCIDState),
+        VMSTATE_UINT32(bulk_in_pending_end, USBCCIDState),
+        VMSTATE_STRUCT_ARRAY(pending_answers, USBCCIDState,
+                        PENDING_ANSWERS_NUM, 1, answer_vmstate, Answer),
+        VMSTATE_UINT32(pending_answers_num, USBCCIDState),
+        VMSTATE_UINT8(migration_state, USBCCIDState),
+        VMSTATE_UINT32(state_vmstate, USBCCIDState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static Property ccid_properties[] = {
+    DEFINE_PROP_UINT8("debug", USBCCIDState, debug, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ccid_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+    uc->init           = ccid_initfn;
+    uc->product_desc   = "QEMU USB CCID";
+    uc->usb_desc       = &desc_ccid;
+    uc->handle_reset   = ccid_handle_reset;
+    uc->handle_control = ccid_handle_control;
+    uc->handle_data    = ccid_handle_data;
+    uc->handle_destroy = ccid_handle_destroy;
+    dc->desc = "CCID Rev 1.1 smartcard reader";
+    dc->vmsd = &ccid_vmstate;
+    dc->props = ccid_properties;
+}
+
+static TypeInfo ccid_info = {
+    .name          = CCID_DEV_NAME,
+    .parent        = TYPE_USB_DEVICE,
+    .instance_size = sizeof(USBCCIDState),
+    .class_init    = ccid_class_initfn,
+};
+
+static void ccid_card_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *k = DEVICE_CLASS(klass);
+    k->bus_info = &ccid_bus_info;
+    k->init = ccid_card_init;
+    k->exit = ccid_card_exit;
+}
+
+static TypeInfo ccid_card_type_info = {
+    .name = TYPE_CCID_CARD,
+    .parent = TYPE_DEVICE,
+    .instance_size = sizeof(CCIDCardState),
+    .abstract = true,
+    .class_size = sizeof(CCIDCardClass),
+    .class_init = ccid_card_class_init,
+};
+
+static void ccid_register_types(void)
+{
+    type_register_static(&ccid_card_type_info);
+    type_register_static(&ccid_info);
+    usb_legacy_register(CCID_DEV_NAME, "ccid", NULL);
+}
+
+type_init(ccid_register_types)
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
new file mode 100644
index 0000000..6ffaf70
--- /dev/null
+++ b/hw/usb/dev-storage.c
@@ -0,0 +1,677 @@
+/*
+ * USB Mass Storage Device emulation
+ *
+ * Copyright (c) 2006 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the LGPL.
+ */
+
+#include "qemu-common.h"
+#include "qemu-option.h"
+#include "qemu-config.h"
+#include "hw/usb.h"
+#include "hw/usb/desc.h"
+#include "hw/scsi.h"
+#include "console.h"
+#include "monitor.h"
+#include "sysemu.h"
+#include "blockdev.h"
+
+//#define DEBUG_MSD
+
+#ifdef DEBUG_MSD
+#define DPRINTF(fmt, ...) \
+do { printf("usb-msd: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) do {} while(0)
+#endif
+
+/* USB requests.  */
+#define MassStorageReset  0xff
+#define GetMaxLun         0xfe
+
+enum USBMSDMode {
+    USB_MSDM_CBW, /* Command Block.  */
+    USB_MSDM_DATAOUT, /* Transfer data to device.  */
+    USB_MSDM_DATAIN, /* Transfer data from device.  */
+    USB_MSDM_CSW /* Command Status.  */
+};
+
+struct usb_msd_csw {
+    uint32_t sig;
+    uint32_t tag;
+    uint32_t residue;
+    uint8_t status;
+};
+
+typedef struct {
+    USBDevice dev;
+    enum USBMSDMode mode;
+    uint32_t scsi_len;
+    uint8_t *scsi_buf;
+    uint32_t data_len;
+    uint32_t residue;
+    struct usb_msd_csw csw;
+    SCSIRequest *req;
+    SCSIBus bus;
+    BlockConf conf;
+    char *serial;
+    SCSIDevice *scsi_dev;
+    uint32_t removable;
+    /* For async completion.  */
+    USBPacket *packet;
+} MSDState;
+
+struct usb_msd_cbw {
+    uint32_t sig;
+    uint32_t tag;
+    uint32_t data_len;
+    uint8_t flags;
+    uint8_t lun;
+    uint8_t cmd_len;
+    uint8_t cmd[16];
+};
+
+enum {
+    STR_MANUFACTURER = 1,
+    STR_PRODUCT,
+    STR_SERIALNUMBER,
+    STR_CONFIG_FULL,
+    STR_CONFIG_HIGH,
+};
+
+static const USBDescStrings desc_strings = {
+    [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
+    [STR_PRODUCT]      = "QEMU USB HARDDRIVE",
+    [STR_SERIALNUMBER] = "1",
+    [STR_CONFIG_FULL]  = "Full speed config (usb 1.1)",
+    [STR_CONFIG_HIGH]  = "High speed config (usb 2.0)",
+};
+
+static const USBDescIface desc_iface_full = {
+    .bInterfaceNumber              = 0,
+    .bNumEndpoints                 = 2,
+    .bInterfaceClass               = USB_CLASS_MASS_STORAGE,
+    .bInterfaceSubClass            = 0x06, /* SCSI */
+    .bInterfaceProtocol            = 0x50, /* Bulk */
+    .eps = (USBDescEndpoint[]) {
+        {
+            .bEndpointAddress      = USB_DIR_IN | 0x01,
+            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize        = 64,
+        },{
+            .bEndpointAddress      = USB_DIR_OUT | 0x02,
+            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize        = 64,
+        },
+    }
+};
+
+static const USBDescDevice desc_device_full = {
+    .bcdUSB                        = 0x0200,
+    .bMaxPacketSize0               = 8,
+    .bNumConfigurations            = 1,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 1,
+            .bConfigurationValue   = 1,
+            .iConfiguration        = STR_CONFIG_FULL,
+            .bmAttributes          = 0xc0,
+            .nif = 1,
+            .ifs = &desc_iface_full,
+        },
+    },
+};
+
+static const USBDescIface desc_iface_high = {
+    .bInterfaceNumber              = 0,
+    .bNumEndpoints                 = 2,
+    .bInterfaceClass               = USB_CLASS_MASS_STORAGE,
+    .bInterfaceSubClass            = 0x06, /* SCSI */
+    .bInterfaceProtocol            = 0x50, /* Bulk */
+    .eps = (USBDescEndpoint[]) {
+        {
+            .bEndpointAddress      = USB_DIR_IN | 0x01,
+            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize        = 512,
+        },{
+            .bEndpointAddress      = USB_DIR_OUT | 0x02,
+            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize        = 512,
+        },
+    }
+};
+
+static const USBDescDevice desc_device_high = {
+    .bcdUSB                        = 0x0200,
+    .bMaxPacketSize0               = 64,
+    .bNumConfigurations            = 1,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 1,
+            .bConfigurationValue   = 1,
+            .iConfiguration        = STR_CONFIG_HIGH,
+            .bmAttributes          = 0xc0,
+            .nif = 1,
+            .ifs = &desc_iface_high,
+        },
+    },
+};
+
+static const USBDesc desc = {
+    .id = {
+        .idVendor          = 0x46f4, /* CRC16() of "QEMU" */
+        .idProduct         = 0x0001,
+        .bcdDevice         = 0,
+        .iManufacturer     = STR_MANUFACTURER,
+        .iProduct          = STR_PRODUCT,
+        .iSerialNumber     = STR_SERIALNUMBER,
+    },
+    .full = &desc_device_full,
+    .high = &desc_device_high,
+    .str  = desc_strings,
+};
+
+static void usb_msd_copy_data(MSDState *s, USBPacket *p)
+{
+    uint32_t len;
+    len = p->iov.size - p->result;
+    if (len > s->scsi_len)
+        len = s->scsi_len;
+    usb_packet_copy(p, s->scsi_buf, len);
+    s->scsi_len -= len;
+    s->scsi_buf += len;
+    s->data_len -= len;
+    if (s->scsi_len == 0 || s->data_len == 0) {
+        scsi_req_continue(s->req);
+    }
+}
+
+static void usb_msd_send_status(MSDState *s, USBPacket *p)
+{
+    int len;
+
+    DPRINTF("Command status %d tag 0x%x, len %zd\n",
+            s->csw.status, s->csw.tag, p->iov.size);
+
+    assert(s->csw.sig == 0x53425355);
+    len = MIN(sizeof(s->csw), p->iov.size);
+    usb_packet_copy(p, &s->csw, len);
+    memset(&s->csw, 0, sizeof(s->csw));
+}
+
+static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
+{
+    MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
+    USBPacket *p = s->packet;
+
+    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);
+    if (p) {
+        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);
+        }
+    }
+}
+
+static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t resid)
+{
+    MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
+    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 = s->residue;
+    s->csw.status = status != 0;
+
+    if (s->packet) {
+        if (s->data_len == 0 && s->mode == USB_MSDM_DATAOUT) {
+            /* A deferred packet with no write data remaining must be
+               the status read packet.  */
+            usb_msd_send_status(s, p);
+            s->mode = USB_MSDM_CBW;
+        } else {
+            if (s->data_len) {
+                int len = (p->iov.size - p->result);
+                usb_packet_skip(p, len);
+                s->data_len -= len;
+            }
+            if (s->data_len == 0) {
+                s->mode = USB_MSDM_CSW;
+            }
+        }
+        s->packet = NULL;
+        usb_packet_complete(&s->dev, p);
+    } else if (s->data_len == 0) {
+        s->mode = USB_MSDM_CSW;
+    }
+    scsi_req_unref(req);
+    s->req = NULL;
+}
+
+static void usb_msd_request_cancelled(SCSIRequest *req)
+{
+    MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
+
+    if (req == s->req) {
+        scsi_req_unref(s->req);
+        s->req = NULL;
+        s->packet = NULL;
+        s->scsi_len = 0;
+    }
+}
+
+static void usb_msd_handle_reset(USBDevice *dev)
+{
+    MSDState *s = (MSDState *)dev;
+
+    DPRINTF("Reset\n");
+    if (s->req) {
+        scsi_req_cancel(s->req);
+    }
+    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->mode = USB_MSDM_CBW;
+}
+
+static int usb_msd_handle_control(USBDevice *dev, USBPacket *p,
+               int request, int value, int index, int length, uint8_t *data)
+{
+    MSDState *s = (MSDState *)dev;
+    int ret;
+
+    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
+    if (ret >= 0) {
+        return ret;
+    }
+
+    ret = 0;
+    switch (request) {
+    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
+        ret = 0;
+        break;
+        /* Class specific requests.  */
+    case ClassInterfaceOutRequest | MassStorageReset:
+        /* Reset state ready for the next CBW.  */
+        s->mode = USB_MSDM_CBW;
+        ret = 0;
+        break;
+    case ClassInterfaceRequest | GetMaxLun:
+        data[0] = 0;
+        ret = 1;
+        break;
+    default:
+        ret = USB_RET_STALL;
+        break;
+    }
+    return ret;
+}
+
+static void usb_msd_cancel_io(USBDevice *dev, USBPacket *p)
+{
+    MSDState *s = DO_UPCAST(MSDState, dev, dev);
+
+    if (s->req) {
+        scsi_req_cancel(s->req);
+    }
+}
+
+static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
+{
+    MSDState *s = (MSDState *)dev;
+    uint32_t tag;
+    int ret = 0;
+    struct usb_msd_cbw cbw;
+    uint8_t devep = p->ep->nr;
+
+    switch (p->pid) {
+    case USB_TOKEN_OUT:
+        if (devep != 2)
+            goto fail;
+
+        switch (s->mode) {
+        case USB_MSDM_CBW:
+            if (p->iov.size != 31) {
+                fprintf(stderr, "usb-msd: Bad CBW size");
+                goto fail;
+            }
+            usb_packet_copy(p, &cbw, 31);
+            if (le32_to_cpu(cbw.sig) != 0x43425355) {
+                fprintf(stderr, "usb-msd: Bad signature %08x\n",
+                        le32_to_cpu(cbw.sig));
+                goto fail;
+            }
+            DPRINTF("Command on LUN %d\n", cbw.lun);
+            if (cbw.lun != 0) {
+                fprintf(stderr, "usb-msd: Bad LUN %d\n", cbw.lun);
+                goto fail;
+            }
+            tag = le32_to_cpu(cbw.tag);
+            s->data_len = le32_to_cpu(cbw.data_len);
+            if (s->data_len == 0) {
+                s->mode = USB_MSDM_CSW;
+            } else if (cbw.flags & 0x80) {
+                s->mode = USB_MSDM_DATAIN;
+            } else {
+                s->mode = USB_MSDM_DATAOUT;
+            }
+            DPRINTF("Command tag 0x%x flags %08x len %d data %d\n",
+                    tag, cbw.flags, cbw.cmd_len, s->data_len);
+            s->residue = 0;
+            s->scsi_len = 0;
+            s->req = scsi_req_new(s->scsi_dev, tag, 0, cbw.cmd, NULL);
+            scsi_req_enqueue(s->req);
+            if (s->req && s->req->cmd.xfer != SCSI_XFER_NONE) {
+                scsi_req_continue(s->req);
+            }
+            ret = p->result;
+            break;
+
+        case USB_MSDM_DATAOUT:
+            DPRINTF("Data out %zd/%d\n", p->iov.size, s->data_len);
+            if (p->iov.size > s->data_len) {
+                goto fail;
+            }
+
+            if (s->scsi_len) {
+                usb_msd_copy_data(s, p);
+            }
+            if (s->residue) {
+                int len = p->iov.size - p->result;
+                if (len) {
+                    usb_packet_skip(p, len);
+                    s->data_len -= len;
+                    if (s->data_len == 0) {
+                        s->mode = USB_MSDM_CSW;
+                    }
+                }
+            }
+            if (p->result < p->iov.size) {
+                DPRINTF("Deferring packet %p\n", p);
+                s->packet = p;
+                ret = USB_RET_ASYNC;
+            } else {
+                ret = p->result;
+            }
+            break;
+
+        default:
+            DPRINTF("Unexpected write (len %zd)\n", p->iov.size);
+            goto fail;
+        }
+        break;
+
+    case USB_TOKEN_IN:
+        if (devep != 1)
+            goto fail;
+
+        switch (s->mode) {
+        case USB_MSDM_DATAOUT:
+            if (s->data_len != 0 || p->iov.size < 13) {
+                goto fail;
+            }
+            /* Waiting for SCSI write to complete.  */
+            s->packet = p;
+            ret = USB_RET_ASYNC;
+            break;
+
+        case USB_MSDM_CSW:
+            if (p->iov.size < 13) {
+                goto fail;
+            }
+
+            if (s->req) {
+                /* still in flight */
+                s->packet = p;
+                ret = USB_RET_ASYNC;
+            } else {
+                usb_msd_send_status(s, p);
+                s->mode = USB_MSDM_CBW;
+                ret = 13;
+            }
+            break;
+
+        case USB_MSDM_DATAIN:
+            DPRINTF("Data in %zd/%d, scsi_len %d\n",
+                    p->iov.size, s->data_len, s->scsi_len);
+            if (s->scsi_len) {
+                usb_msd_copy_data(s, p);
+            }
+            if (s->residue) {
+                int len = p->iov.size - p->result;
+                if (len) {
+                    usb_packet_skip(p, len);
+                    s->data_len -= len;
+                    if (s->data_len == 0) {
+                        s->mode = USB_MSDM_CSW;
+                    }
+                }
+            }
+            if (p->result < p->iov.size) {
+                DPRINTF("Deferring packet %p\n", p);
+                s->packet = p;
+                ret = USB_RET_ASYNC;
+            } else {
+                ret = p->result;
+            }
+            break;
+
+        default:
+            DPRINTF("Unexpected read (len %zd)\n", p->iov.size);
+            goto fail;
+        }
+        break;
+
+    default:
+        DPRINTF("Bad token\n");
+    fail:
+        ret = USB_RET_STALL;
+        break;
+    }
+
+    return ret;
+}
+
+static void usb_msd_password_cb(void *opaque, int err)
+{
+    MSDState *s = opaque;
+
+    if (!err)
+        err = usb_device_attach(&s->dev);
+
+    if (err)
+        qdev_unplug(&s->dev.qdev);
+}
+
+static const struct SCSIBusInfo usb_msd_scsi_info = {
+    .tcq = false,
+    .max_target = 0,
+    .max_lun = 0,
+
+    .transfer_data = usb_msd_transfer_data,
+    .complete = usb_msd_command_complete,
+    .cancel = usb_msd_request_cancelled
+};
+
+static int usb_msd_initfn(USBDevice *dev)
+{
+    MSDState *s = DO_UPCAST(MSDState, dev, dev);
+    BlockDriverState *bs = s->conf.bs;
+    DriveInfo *dinfo;
+
+    if (!bs) {
+        error_report("drive property not set");
+        return -1;
+    }
+
+    /*
+     * Hack alert: this pretends to be a block device, but it's really
+     * a SCSI bus that can serve only a single device, which it
+     * creates automatically.  But first it needs to detach from its
+     * blockdev, or else scsi_bus_legacy_add_drive() dies when it
+     * attaches again.
+     *
+     * The hack is probably a bad idea.
+     */
+    bdrv_detach_dev(bs, &s->dev.qdev);
+    s->conf.bs = NULL;
+
+    if (!s->serial) {
+        /* try to fall back to value set with legacy -drive serial=... */
+        dinfo = drive_get_by_blockdev(bs);
+        if (*dinfo->serial) {
+            s->serial = strdup(dinfo->serial);
+        }
+    }
+    if (s->serial) {
+        usb_desc_set_string(dev, STR_SERIALNUMBER, s->serial);
+    }
+
+    usb_desc_init(dev);
+    scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info);
+    s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable,
+                                            s->conf.bootindex);
+    if (!s->scsi_dev) {
+        return -1;
+    }
+    s->bus.qbus.allow_hotplug = 0;
+    usb_msd_handle_reset(dev);
+
+    if (bdrv_key_required(bs)) {
+        if (cur_mon) {
+            monitor_read_bdrv_key_start(cur_mon, bs, usb_msd_password_cb, s);
+            s->dev.auto_attach = 0;
+        } else {
+            autostart = 0;
+        }
+    }
+
+    return 0;
+}
+
+static USBDevice *usb_msd_init(USBBus *bus, const char *filename)
+{
+    static int nr=0;
+    char id[8];
+    QemuOpts *opts;
+    DriveInfo *dinfo;
+    USBDevice *dev;
+    const char *p1;
+    char fmt[32];
+
+    /* parse -usbdevice disk: syntax into drive opts */
+    snprintf(id, sizeof(id), "usb%d", nr++);
+    opts = qemu_opts_create(qemu_find_opts("drive"), id, 0);
+
+    p1 = strchr(filename, ':');
+    if (p1++) {
+        const char *p2;
+
+        if (strstart(filename, "format=", &p2)) {
+            int len = MIN(p1 - p2, sizeof(fmt));
+            pstrcpy(fmt, len, p2);
+            qemu_opt_set(opts, "format", fmt);
+        } else if (*filename != ':') {
+            printf("unrecognized USB mass-storage option %s\n", filename);
+            return NULL;
+        }
+        filename = p1;
+    }
+    if (!*filename) {
+        printf("block device specification needed\n");
+        return NULL;
+    }
+    qemu_opt_set(opts, "file", filename);
+    qemu_opt_set(opts, "if", "none");
+
+    /* create host drive */
+    dinfo = drive_init(opts, 0);
+    if (!dinfo) {
+        qemu_opts_del(opts);
+        return NULL;
+    }
+
+    /* create guest device */
+    dev = usb_create(bus, "usb-storage");
+    if (!dev) {
+        return NULL;
+    }
+    if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
+        qdev_free(&dev->qdev);
+        return NULL;
+    }
+    if (qdev_init(&dev->qdev) < 0)
+        return NULL;
+
+    return dev;
+}
+
+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_END_OF_LIST()
+    }
+};
+
+static Property msd_properties[] = {
+    DEFINE_BLOCK_PROPERTIES(MSDState, conf),
+    DEFINE_PROP_STRING("serial", MSDState, serial),
+    DEFINE_PROP_BIT("removable", MSDState, removable, 0, false),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void usb_msd_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+    uc->init           = usb_msd_initfn;
+    uc->product_desc   = "QEMU USB MSD";
+    uc->usb_desc       = &desc;
+    uc->cancel_packet  = usb_msd_cancel_io;
+    uc->handle_attach  = usb_desc_attach;
+    uc->handle_reset   = usb_msd_handle_reset;
+    uc->handle_control = usb_msd_handle_control;
+    uc->handle_data    = usb_msd_handle_data;
+    dc->fw_name = "storage";
+    dc->vmsd = &vmstate_usb_msd;
+    dc->props = msd_properties;
+}
+
+static TypeInfo msd_info = {
+    .name          = "usb-storage",
+    .parent        = TYPE_USB_DEVICE,
+    .instance_size = sizeof(MSDState),
+    .class_init    = usb_msd_class_initfn,
+};
+
+static void usb_msd_register_types(void)
+{
+    type_register_static(&msd_info);
+    usb_legacy_register("usb-storage", "disk", usb_msd_init);
+}
+
+type_init(usb_msd_register_types)
diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c
new file mode 100644
index 0000000..c1cfd74
--- /dev/null
+++ b/hw/usb/dev-wacom.c
@@ -0,0 +1,381 @@
+/*
+ * Wacom PenPartner USB tablet emulation.
+ *
+ * Copyright (c) 2006 Openedhand Ltd.
+ * Author: Andrzej Zaborowski <balrog at zabor.org>
+ *
+ * Based on hw/usb-hid.c:
+ * Copyright (c) 2005 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw/hw.h"
+#include "console.h"
+#include "hw/usb.h"
+#include "hw/usb/desc.h"
+
+/* Interface requests */
+#define WACOM_GET_REPORT	0x2101
+#define WACOM_SET_REPORT	0x2109
+
+/* HID interface requests */
+#define HID_GET_REPORT		0xa101
+#define HID_GET_IDLE		0xa102
+#define HID_GET_PROTOCOL	0xa103
+#define HID_SET_IDLE		0x210a
+#define HID_SET_PROTOCOL	0x210b
+
+typedef struct USBWacomState {
+    USBDevice dev;
+    QEMUPutMouseEntry *eh_entry;
+    int dx, dy, dz, buttons_state;
+    int x, y;
+    int mouse_grabbed;
+    enum {
+        WACOM_MODE_HID = 1,
+        WACOM_MODE_WACOM = 2,
+    } mode;
+    uint8_t idle;
+    int changed;
+} USBWacomState;
+
+enum {
+    STR_MANUFACTURER = 1,
+    STR_PRODUCT,
+    STR_SERIALNUMBER,
+};
+
+static const USBDescStrings desc_strings = {
+    [STR_MANUFACTURER]     = "QEMU " QEMU_VERSION,
+    [STR_PRODUCT]          = "Wacom PenPartner",
+    [STR_SERIALNUMBER]     = "1",
+};
+
+static const USBDescIface desc_iface_wacom = {
+    .bInterfaceNumber              = 0,
+    .bNumEndpoints                 = 1,
+    .bInterfaceClass               = USB_CLASS_HID,
+    .bInterfaceSubClass            = 0x01, /* boot */
+    .bInterfaceProtocol            = 0x02,
+    .ndesc                         = 1,
+    .descs = (USBDescOther[]) {
+        {
+            /* HID descriptor */
+            .data = (uint8_t[]) {
+                0x09,          /*  u8  bLength */
+                0x21,          /*  u8  bDescriptorType */
+                0x01, 0x10,    /*  u16 HID_class */
+                0x00,          /*  u8  country_code */
+                0x01,          /*  u8  num_descriptors */
+                0x22,          /*  u8  type: Report */
+                0x6e, 0,       /*  u16 len */
+            },
+        },
+    },
+    .eps = (USBDescEndpoint[]) {
+        {
+            .bEndpointAddress      = USB_DIR_IN | 0x01,
+            .bmAttributes          = USB_ENDPOINT_XFER_INT,
+            .wMaxPacketSize        = 8,
+            .bInterval             = 0x0a,
+        },
+    },
+};
+
+static const USBDescDevice desc_device_wacom = {
+    .bcdUSB                        = 0x0110,
+    .bMaxPacketSize0               = 8,
+    .bNumConfigurations            = 1,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 1,
+            .bConfigurationValue   = 1,
+            .bmAttributes          = 0x80,
+            .bMaxPower             = 40,
+            .nif = 1,
+            .ifs = &desc_iface_wacom,
+        },
+    },
+};
+
+static const USBDesc desc_wacom = {
+    .id = {
+        .idVendor          = 0x056a,
+        .idProduct         = 0x0000,
+        .bcdDevice         = 0x4210,
+        .iManufacturer     = STR_MANUFACTURER,
+        .iProduct          = STR_PRODUCT,
+        .iSerialNumber     = STR_SERIALNUMBER,
+    },
+    .full = &desc_device_wacom,
+    .str  = desc_strings,
+};
+
+static void usb_mouse_event(void *opaque,
+                            int dx1, int dy1, int dz1, int buttons_state)
+{
+    USBWacomState *s = opaque;
+
+    s->dx += dx1;
+    s->dy += dy1;
+    s->dz += dz1;
+    s->buttons_state = buttons_state;
+    s->changed = 1;
+}
+
+static void usb_wacom_event(void *opaque,
+                            int x, int y, int dz, int buttons_state)
+{
+    USBWacomState *s = opaque;
+
+    /* scale to Penpartner resolution */
+    s->x = (x * 5040 / 0x7FFF);
+    s->y = (y * 3780 / 0x7FFF);
+    s->dz += dz;
+    s->buttons_state = buttons_state;
+    s->changed = 1;
+}
+
+static inline int int_clamp(int val, int vmin, int vmax)
+{
+    if (val < vmin)
+        return vmin;
+    else if (val > vmax)
+        return vmax;
+    else
+        return val;
+}
+
+static int usb_mouse_poll(USBWacomState *s, uint8_t *buf, int len)
+{
+    int dx, dy, dz, b, l;
+
+    if (!s->mouse_grabbed) {
+        s->eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, s, 0,
+                        "QEMU PenPartner tablet");
+        qemu_activate_mouse_event_handler(s->eh_entry);
+        s->mouse_grabbed = 1;
+    }
+
+    dx = int_clamp(s->dx, -128, 127);
+    dy = int_clamp(s->dy, -128, 127);
+    dz = int_clamp(s->dz, -128, 127);
+
+    s->dx -= dx;
+    s->dy -= dy;
+    s->dz -= dz;
+
+    b = 0;
+    if (s->buttons_state & MOUSE_EVENT_LBUTTON)
+        b |= 0x01;
+    if (s->buttons_state & MOUSE_EVENT_RBUTTON)
+        b |= 0x02;
+    if (s->buttons_state & MOUSE_EVENT_MBUTTON)
+        b |= 0x04;
+
+    buf[0] = b;
+    buf[1] = dx;
+    buf[2] = dy;
+    l = 3;
+    if (len >= 4) {
+        buf[3] = dz;
+        l = 4;
+    }
+    return l;
+}
+
+static int usb_wacom_poll(USBWacomState *s, uint8_t *buf, int len)
+{
+    int b;
+
+    if (!s->mouse_grabbed) {
+        s->eh_entry = qemu_add_mouse_event_handler(usb_wacom_event, s, 1,
+                        "QEMU PenPartner tablet");
+        qemu_activate_mouse_event_handler(s->eh_entry);
+        s->mouse_grabbed = 1;
+    }
+
+    b = 0;
+    if (s->buttons_state & MOUSE_EVENT_LBUTTON)
+        b |= 0x01;
+    if (s->buttons_state & MOUSE_EVENT_RBUTTON)
+        b |= 0x40;
+    if (s->buttons_state & MOUSE_EVENT_MBUTTON)
+        b |= 0x20; /* eraser */
+
+    if (len < 7)
+        return 0;
+
+    buf[0] = s->mode;
+    buf[5] = 0x00 | (b & 0xf0);
+    buf[1] = s->x & 0xff;
+    buf[2] = s->x >> 8;
+    buf[3] = s->y & 0xff;
+    buf[4] = s->y >> 8;
+    if (b & 0x3f) {
+        buf[6] = 0;
+    } else {
+        buf[6] = (unsigned char) -127;
+    }
+
+    return 7;
+}
+
+static void usb_wacom_handle_reset(USBDevice *dev)
+{
+    USBWacomState *s = (USBWacomState *) dev;
+
+    s->dx = 0;
+    s->dy = 0;
+    s->dz = 0;
+    s->x = 0;
+    s->y = 0;
+    s->buttons_state = 0;
+    s->mode = WACOM_MODE_HID;
+}
+
+static int usb_wacom_handle_control(USBDevice *dev, USBPacket *p,
+               int request, int value, int index, int length, uint8_t *data)
+{
+    USBWacomState *s = (USBWacomState *) dev;
+    int ret;
+
+    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
+    if (ret >= 0) {
+        return ret;
+    }
+
+    ret = 0;
+    switch (request) {
+    case WACOM_SET_REPORT:
+        if (s->mouse_grabbed) {
+            qemu_remove_mouse_event_handler(s->eh_entry);
+            s->mouse_grabbed = 0;
+        }
+        s->mode = data[0];
+        ret = 0;
+        break;
+    case WACOM_GET_REPORT:
+        data[0] = 0;
+        data[1] = s->mode;
+        ret = 2;
+        break;
+    /* USB HID requests */
+    case HID_GET_REPORT:
+        if (s->mode == WACOM_MODE_HID)
+            ret = usb_mouse_poll(s, data, length);
+        else if (s->mode == WACOM_MODE_WACOM)
+            ret = usb_wacom_poll(s, data, length);
+        break;
+    case HID_GET_IDLE:
+        ret = 1;
+        data[0] = s->idle;
+        break;
+    case HID_SET_IDLE:
+        s->idle = (uint8_t) (value >> 8);
+        ret = 0;
+        break;
+    default:
+        ret = USB_RET_STALL;
+        break;
+    }
+    return ret;
+}
+
+static int usb_wacom_handle_data(USBDevice *dev, USBPacket *p)
+{
+    USBWacomState *s = (USBWacomState *) dev;
+    uint8_t buf[p->iov.size];
+    int ret = 0;
+
+    switch (p->pid) {
+    case USB_TOKEN_IN:
+        if (p->ep->nr == 1) {
+            if (!(s->changed || s->idle))
+                return USB_RET_NAK;
+            s->changed = 0;
+            if (s->mode == WACOM_MODE_HID)
+                ret = usb_mouse_poll(s, buf, p->iov.size);
+            else if (s->mode == WACOM_MODE_WACOM)
+                ret = usb_wacom_poll(s, buf, p->iov.size);
+            usb_packet_copy(p, buf, ret);
+            break;
+        }
+        /* Fall through.  */
+    case USB_TOKEN_OUT:
+    default:
+        ret = USB_RET_STALL;
+        break;
+    }
+    return ret;
+}
+
+static void usb_wacom_handle_destroy(USBDevice *dev)
+{
+    USBWacomState *s = (USBWacomState *) dev;
+
+    if (s->mouse_grabbed) {
+        qemu_remove_mouse_event_handler(s->eh_entry);
+        s->mouse_grabbed = 0;
+    }
+}
+
+static int usb_wacom_initfn(USBDevice *dev)
+{
+    USBWacomState *s = DO_UPCAST(USBWacomState, dev, dev);
+    usb_desc_init(dev);
+    s->changed = 1;
+    return 0;
+}
+
+static const VMStateDescription vmstate_usb_wacom = {
+    .name = "usb-wacom",
+    .unmigratable = 1,
+};
+
+static void usb_wacom_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+    uc->product_desc   = "QEMU PenPartner Tablet";
+    uc->usb_desc       = &desc_wacom;
+    uc->init           = usb_wacom_initfn;
+    uc->handle_reset   = usb_wacom_handle_reset;
+    uc->handle_control = usb_wacom_handle_control;
+    uc->handle_data    = usb_wacom_handle_data;
+    uc->handle_destroy = usb_wacom_handle_destroy;
+    dc->desc = "QEMU PenPartner Tablet";
+    dc->vmsd = &vmstate_usb_wacom;
+}
+
+static TypeInfo wacom_info = {
+    .name          = "usb-wacom-tablet",
+    .parent        = TYPE_USB_DEVICE,
+    .instance_size = sizeof(USBWacomState),
+    .class_init    = usb_wacom_class_init,
+};
+
+static void usb_wacom_register_types(void)
+{
+    type_register_static(&wacom_info);
+    usb_legacy_register("usb-wacom-tablet", "wacom-tablet", NULL);
+}
+
+type_init(usb_wacom_register_types)
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
new file mode 100644
index 0000000..58811d3
--- /dev/null
+++ b/hw/usb/hcd-ehci.c
@@ -0,0 +1,2345 @@
+/*
+ * QEMU USB EHCI Emulation
+ *
+ * Copyright(c) 2008  Emutex Ltd. (address at hidden)
+ *
+ * EHCI project was started by Mark Burkley, with contributions by
+ * Niels de Vos.  David S. Ahern continued working on it.  Kevin Wolf,
+ * Jan Kiszka and Vincent Palatin contributed bugfixes.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or(at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw/hw.h"
+#include "qemu-timer.h"
+#include "hw/usb.h"
+#include "hw/pci.h"
+#include "monitor.h"
+#include "trace.h"
+#include "dma.h"
+
+#define EHCI_DEBUG   0
+
+#if EHCI_DEBUG
+#define DPRINTF printf
+#else
+#define DPRINTF(...)
+#endif
+
+/* internal processing - reset HC to try and recover */
+#define USB_RET_PROCERR   (-99)
+
+#define MMIO_SIZE        0x1000
+
+/* Capability Registers Base Address - section 2.2 */
+#define CAPREGBASE       0x0000
+#define CAPLENGTH        CAPREGBASE + 0x0000  // 1-byte, 0x0001 reserved
+#define HCIVERSION       CAPREGBASE + 0x0002  // 2-bytes, i/f version #
+#define HCSPARAMS        CAPREGBASE + 0x0004  // 4-bytes, structural params
+#define HCCPARAMS        CAPREGBASE + 0x0008  // 4-bytes, capability params
+#define EECP             HCCPARAMS + 1
+#define HCSPPORTROUTE1   CAPREGBASE + 0x000c
+#define HCSPPORTROUTE2   CAPREGBASE + 0x0010
+
+#define OPREGBASE        0x0020        // Operational Registers Base Address
+
+#define USBCMD           OPREGBASE + 0x0000
+#define USBCMD_RUNSTOP   (1 << 0)      // run / Stop
+#define USBCMD_HCRESET   (1 << 1)      // HC Reset
+#define USBCMD_FLS       (3 << 2)      // Frame List Size
+#define USBCMD_FLS_SH    2             // Frame List Size Shift
+#define USBCMD_PSE       (1 << 4)      // Periodic Schedule Enable
+#define USBCMD_ASE       (1 << 5)      // Asynch Schedule Enable
+#define USBCMD_IAAD      (1 << 6)      // Int Asynch Advance Doorbell
+#define USBCMD_LHCR      (1 << 7)      // Light Host Controller Reset
+#define USBCMD_ASPMC     (3 << 8)      // Async Sched Park Mode Count
+#define USBCMD_ASPME     (1 << 11)     // Async Sched Park Mode Enable
+#define USBCMD_ITC       (0x7f << 16)  // Int Threshold Control
+#define USBCMD_ITC_SH    16            // Int Threshold Control Shift
+
+#define USBSTS           OPREGBASE + 0x0004
+#define USBSTS_RO_MASK   0x0000003f
+#define USBSTS_INT       (1 << 0)      // USB Interrupt
+#define USBSTS_ERRINT    (1 << 1)      // Error Interrupt
+#define USBSTS_PCD       (1 << 2)      // Port Change Detect
+#define USBSTS_FLR       (1 << 3)      // Frame List Rollover
+#define USBSTS_HSE       (1 << 4)      // Host System Error
+#define USBSTS_IAA       (1 << 5)      // Interrupt on Async Advance
+#define USBSTS_HALT      (1 << 12)     // HC Halted
+#define USBSTS_REC       (1 << 13)     // Reclamation
+#define USBSTS_PSS       (1 << 14)     // Periodic Schedule Status
+#define USBSTS_ASS       (1 << 15)     // Asynchronous Schedule Status
+
+/*
+ *  Interrupt enable bits correspond to the interrupt active bits in USBSTS
+ *  so no need to redefine here.
+ */
+#define USBINTR              OPREGBASE + 0x0008
+#define USBINTR_MASK         0x0000003f
+
+#define FRINDEX              OPREGBASE + 0x000c
+#define CTRLDSSEGMENT        OPREGBASE + 0x0010
+#define PERIODICLISTBASE     OPREGBASE + 0x0014
+#define ASYNCLISTADDR        OPREGBASE + 0x0018
+#define ASYNCLISTADDR_MASK   0xffffffe0
+
+#define CONFIGFLAG           OPREGBASE + 0x0040
+
+#define PORTSC               (OPREGBASE + 0x0044)
+#define PORTSC_BEGIN         PORTSC
+#define PORTSC_END           (PORTSC + 4 * NB_PORTS)
+/*
+ * Bits that are reserved or are read-only are masked out of values
+ * written to us by software
+ */
+#define PORTSC_RO_MASK       0x007001c0
+#define PORTSC_RWC_MASK      0x0000002a
+#define PORTSC_WKOC_E        (1 << 22)    // Wake on Over Current Enable
+#define PORTSC_WKDS_E        (1 << 21)    // Wake on Disconnect Enable
+#define PORTSC_WKCN_E        (1 << 20)    // Wake on Connect Enable
+#define PORTSC_PTC           (15 << 16)   // Port Test Control
+#define PORTSC_PTC_SH        16           // Port Test Control shift
+#define PORTSC_PIC           (3 << 14)    // Port Indicator Control
+#define PORTSC_PIC_SH        14           // Port Indicator Control Shift
+#define PORTSC_POWNER        (1 << 13)    // Port Owner
+#define PORTSC_PPOWER        (1 << 12)    // Port Power
+#define PORTSC_LINESTAT      (3 << 10)    // Port Line Status
+#define PORTSC_LINESTAT_SH   10           // Port Line Status Shift
+#define PORTSC_PRESET        (1 << 8)     // Port Reset
+#define PORTSC_SUSPEND       (1 << 7)     // Port Suspend
+#define PORTSC_FPRES         (1 << 6)     // Force Port Resume
+#define PORTSC_OCC           (1 << 5)     // Over Current Change
+#define PORTSC_OCA           (1 << 4)     // Over Current Active
+#define PORTSC_PEDC          (1 << 3)     // Port Enable/Disable Change
+#define PORTSC_PED           (1 << 2)     // Port Enable/Disable
+#define PORTSC_CSC           (1 << 1)     // Connect Status Change
+#define PORTSC_CONNECT       (1 << 0)     // Current Connect Status
+
+#define FRAME_TIMER_FREQ 1000
+#define FRAME_TIMER_NS   (1000000000 / FRAME_TIMER_FREQ)
+
+#define NB_MAXINTRATE    8        // Max rate at which controller issues ints
+#define NB_PORTS         6        // Number of downstream ports
+#define BUFF_SIZE        5*4096   // Max bytes to transfer per transaction
+#define MAX_ITERATIONS   20       // Max number of QH before we break the loop
+#define MAX_QH           100      // Max allowable queue heads in a chain
+
+/*  Internal periodic / asynchronous schedule state machine states
+ */
+typedef enum {
+    EST_INACTIVE = 1000,
+    EST_ACTIVE,
+    EST_EXECUTING,
+    EST_SLEEPING,
+    /*  The following states are internal to the state machine function
+    */
+    EST_WAITLISTHEAD,
+    EST_FETCHENTRY,
+    EST_FETCHQH,
+    EST_FETCHITD,
+    EST_FETCHSITD,
+    EST_ADVANCEQUEUE,
+    EST_FETCHQTD,
+    EST_EXECUTE,
+    EST_WRITEBACK,
+    EST_HORIZONTALQH
+} EHCI_STATES;
+
+/* macros for accessing fields within next link pointer entry */
+#define NLPTR_GET(x)             ((x) & 0xffffffe0)
+#define NLPTR_TYPE_GET(x)        (((x) >> 1) & 3)
+#define NLPTR_TBIT(x)            ((x) & 1)  // 1=invalid, 0=valid
+
+/* link pointer types */
+#define NLPTR_TYPE_ITD           0     // isoc xfer descriptor
+#define NLPTR_TYPE_QH            1     // queue head
+#define NLPTR_TYPE_STITD         2     // split xaction, isoc xfer descriptor
+#define NLPTR_TYPE_FSTN          3     // frame span traversal node
+
+
+/*  EHCI spec version 1.0 Section 3.3
+ */
+typedef struct EHCIitd {
+    uint32_t next;
+
+    uint32_t transact[8];
+#define ITD_XACT_ACTIVE          (1 << 31)
+#define ITD_XACT_DBERROR         (1 << 30)
+#define ITD_XACT_BABBLE          (1 << 29)
+#define ITD_XACT_XACTERR         (1 << 28)
+#define ITD_XACT_LENGTH_MASK     0x0fff0000
+#define ITD_XACT_LENGTH_SH       16
+#define ITD_XACT_IOC             (1 << 15)
+#define ITD_XACT_PGSEL_MASK      0x00007000
+#define ITD_XACT_PGSEL_SH        12
+#define ITD_XACT_OFFSET_MASK     0x00000fff
+
+    uint32_t bufptr[7];
+#define ITD_BUFPTR_MASK          0xfffff000
+#define ITD_BUFPTR_SH            12
+#define ITD_BUFPTR_EP_MASK       0x00000f00
+#define ITD_BUFPTR_EP_SH         8
+#define ITD_BUFPTR_DEVADDR_MASK  0x0000007f
+#define ITD_BUFPTR_DEVADDR_SH    0
+#define ITD_BUFPTR_DIRECTION     (1 << 11)
+#define ITD_BUFPTR_MAXPKT_MASK   0x000007ff
+#define ITD_BUFPTR_MAXPKT_SH     0
+#define ITD_BUFPTR_MULT_MASK     0x00000003
+#define ITD_BUFPTR_MULT_SH       0
+} EHCIitd;
+
+/*  EHCI spec version 1.0 Section 3.4
+ */
+typedef struct EHCIsitd {
+    uint32_t next;                  // Standard next link pointer
+    uint32_t epchar;
+#define SITD_EPCHAR_IO              (1 << 31)
+#define SITD_EPCHAR_PORTNUM_MASK    0x7f000000
+#define SITD_EPCHAR_PORTNUM_SH      24
+#define SITD_EPCHAR_HUBADD_MASK     0x007f0000
+#define SITD_EPCHAR_HUBADDR_SH      16
+#define SITD_EPCHAR_EPNUM_MASK      0x00000f00
+#define SITD_EPCHAR_EPNUM_SH        8
+#define SITD_EPCHAR_DEVADDR_MASK    0x0000007f
+
+    uint32_t uframe;
+#define SITD_UFRAME_CMASK_MASK      0x0000ff00
+#define SITD_UFRAME_CMASK_SH        8
+#define SITD_UFRAME_SMASK_MASK      0x000000ff
+
+    uint32_t results;
+#define SITD_RESULTS_IOC              (1 << 31)
+#define SITD_RESULTS_PGSEL            (1 << 30)
+#define SITD_RESULTS_TBYTES_MASK      0x03ff0000
+#define SITD_RESULTS_TYBYTES_SH       16
+#define SITD_RESULTS_CPROGMASK_MASK   0x0000ff00
+#define SITD_RESULTS_CPROGMASK_SH     8
+#define SITD_RESULTS_ACTIVE           (1 << 7)
+#define SITD_RESULTS_ERR              (1 << 6)
+#define SITD_RESULTS_DBERR            (1 << 5)
+#define SITD_RESULTS_BABBLE           (1 << 4)
+#define SITD_RESULTS_XACTERR          (1 << 3)
+#define SITD_RESULTS_MISSEDUF         (1 << 2)
+#define SITD_RESULTS_SPLITXSTATE      (1 << 1)
+
+    uint32_t bufptr[2];
+#define SITD_BUFPTR_MASK              0xfffff000
+#define SITD_BUFPTR_CURROFF_MASK      0x00000fff
+#define SITD_BUFPTR_TPOS_MASK         0x00000018
+#define SITD_BUFPTR_TPOS_SH           3
+#define SITD_BUFPTR_TCNT_MASK         0x00000007
+
+    uint32_t backptr;                 // Standard next link pointer
+} EHCIsitd;
+
+/*  EHCI spec version 1.0 Section 3.5
+ */
+typedef struct EHCIqtd {
+    uint32_t next;                    // Standard next link pointer
+    uint32_t altnext;                 // Standard next link pointer
+    uint32_t token;
+#define QTD_TOKEN_DTOGGLE             (1 << 31)
+#define QTD_TOKEN_TBYTES_MASK         0x7fff0000
+#define QTD_TOKEN_TBYTES_SH           16
+#define QTD_TOKEN_IOC                 (1 << 15)
+#define QTD_TOKEN_CPAGE_MASK          0x00007000
+#define QTD_TOKEN_CPAGE_SH            12
+#define QTD_TOKEN_CERR_MASK           0x00000c00
+#define QTD_TOKEN_CERR_SH             10
+#define QTD_TOKEN_PID_MASK            0x00000300
+#define QTD_TOKEN_PID_SH              8
+#define QTD_TOKEN_ACTIVE              (1 << 7)
+#define QTD_TOKEN_HALT                (1 << 6)
+#define QTD_TOKEN_DBERR               (1 << 5)
+#define QTD_TOKEN_BABBLE              (1 << 4)
+#define QTD_TOKEN_XACTERR             (1 << 3)
+#define QTD_TOKEN_MISSEDUF            (1 << 2)
+#define QTD_TOKEN_SPLITXSTATE         (1 << 1)
+#define QTD_TOKEN_PING                (1 << 0)
+
+    uint32_t bufptr[5];               // Standard buffer pointer
+#define QTD_BUFPTR_MASK               0xfffff000
+#define QTD_BUFPTR_SH                 12
+} EHCIqtd;
+
+/*  EHCI spec version 1.0 Section 3.6
+ */
+typedef struct EHCIqh {
+    uint32_t next;                    // Standard next link pointer
+
+    /* endpoint characteristics */
+    uint32_t epchar;
+#define QH_EPCHAR_RL_MASK             0xf0000000
+#define QH_EPCHAR_RL_SH               28
+#define QH_EPCHAR_C                   (1 << 27)
+#define QH_EPCHAR_MPLEN_MASK          0x07FF0000
+#define QH_EPCHAR_MPLEN_SH            16
+#define QH_EPCHAR_H                   (1 << 15)
+#define QH_EPCHAR_DTC                 (1 << 14)
+#define QH_EPCHAR_EPS_MASK            0x00003000
+#define QH_EPCHAR_EPS_SH              12
+#define EHCI_QH_EPS_FULL              0
+#define EHCI_QH_EPS_LOW               1
+#define EHCI_QH_EPS_HIGH              2
+#define EHCI_QH_EPS_RESERVED          3
+
+#define QH_EPCHAR_EP_MASK             0x00000f00
+#define QH_EPCHAR_EP_SH               8
+#define QH_EPCHAR_I                   (1 << 7)
+#define QH_EPCHAR_DEVADDR_MASK        0x0000007f
+#define QH_EPCHAR_DEVADDR_SH          0
+
+    /* endpoint capabilities */
+    uint32_t epcap;
+#define QH_EPCAP_MULT_MASK            0xc0000000
+#define QH_EPCAP_MULT_SH              30
+#define QH_EPCAP_PORTNUM_MASK         0x3f800000
+#define QH_EPCAP_PORTNUM_SH           23
+#define QH_EPCAP_HUBADDR_MASK         0x007f0000
+#define QH_EPCAP_HUBADDR_SH           16
+#define QH_EPCAP_CMASK_MASK           0x0000ff00
+#define QH_EPCAP_CMASK_SH             8
+#define QH_EPCAP_SMASK_MASK           0x000000ff
+#define QH_EPCAP_SMASK_SH             0
+
+    uint32_t current_qtd;             // Standard next link pointer
+    uint32_t next_qtd;                // Standard next link pointer
+    uint32_t altnext_qtd;
+#define QH_ALTNEXT_NAKCNT_MASK        0x0000001e
+#define QH_ALTNEXT_NAKCNT_SH          1
+
+    uint32_t token;                   // Same as QTD token
+    uint32_t bufptr[5];               // Standard buffer pointer
+#define BUFPTR_CPROGMASK_MASK         0x000000ff
+#define BUFPTR_FRAMETAG_MASK          0x0000001f
+#define BUFPTR_SBYTES_MASK            0x00000fe0
+#define BUFPTR_SBYTES_SH              5
+} EHCIqh;
+
+/*  EHCI spec version 1.0 Section 3.7
+ */
+typedef struct EHCIfstn {
+    uint32_t next;                    // Standard next link pointer
+    uint32_t backptr;                 // Standard next link pointer
+} EHCIfstn;
+
+typedef struct EHCIQueue EHCIQueue;
+typedef struct EHCIState EHCIState;
+
+enum async_state {
+    EHCI_ASYNC_NONE = 0,
+    EHCI_ASYNC_INFLIGHT,
+    EHCI_ASYNC_FINISHED,
+};
+
+struct EHCIQueue {
+    EHCIState *ehci;
+    QTAILQ_ENTRY(EHCIQueue) next;
+    uint32_t seen;
+    uint64_t ts;
+
+    /* 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;
+};
+
+typedef QTAILQ_HEAD(EHCIQueueHead, EHCIQueue) EHCIQueueHead;
+
+struct EHCIState {
+    PCIDevice dev;
+    USBBus bus;
+    qemu_irq irq;
+    MemoryRegion mem;
+    int companion_count;
+
+    /* properties */
+    uint32_t freq;
+    uint32_t maxframes;
+
+    /*
+     *  EHCI spec version 1.0 Section 2.3
+     *  Host Controller Operational Registers
+     */
+    union {
+        uint8_t mmio[MMIO_SIZE];
+        struct {
+            uint8_t cap[OPREGBASE];
+            uint32_t usbcmd;
+            uint32_t usbsts;
+            uint32_t usbintr;
+            uint32_t frindex;
+            uint32_t ctrldssegment;
+            uint32_t periodiclistbase;
+            uint32_t asynclistaddr;
+            uint32_t notused[9];
+            uint32_t configflag;
+            uint32_t portsc[NB_PORTS];
+        };
+    };
+
+    /*
+     *  Internal states, shadow registers, etc
+     */
+    uint32_t sofv;
+    QEMUTimer *frame_timer;
+    int attach_poll_counter;
+    int astate;                        // Current state in asynchronous schedule
+    int pstate;                        // Current state in periodic schedule
+    USBPort ports[NB_PORTS];
+    USBPort *companion_ports[NB_PORTS];
+    uint32_t usbsts_pending;
+    EHCIQueueHead aqueues;
+    EHCIQueueHead pqueues;
+
+    uint32_t a_fetch_addr;   // which address to look at next
+    uint32_t p_fetch_addr;   // which address to look at next
+
+    USBPacket ipacket;
+    QEMUSGList isgl;
+    int isoch_pause;
+
+    uint64_t last_run_ns;
+};
+
+#define SET_LAST_RUN_CLOCK(s) \
+    (s)->last_run_ns = qemu_get_clock_ns(vm_clock);
+
+/* nifty macros from Arnon's EHCI version  */
+#define get_field(data, field) \
+    (((data) & field##_MASK) >> field##_SH)
+
+#define set_field(data, newval, field) do { \
+    uint32_t val = *data; \
+    val &= ~ field##_MASK; \
+    val |= ((newval) << field##_SH) & field##_MASK; \
+    *data = val; \
+    } while(0)
+
+static const char *ehci_state_names[] = {
+    [EST_INACTIVE]     = "INACTIVE",
+    [EST_ACTIVE]       = "ACTIVE",
+    [EST_EXECUTING]    = "EXECUTING",
+    [EST_SLEEPING]     = "SLEEPING",
+    [EST_WAITLISTHEAD] = "WAITLISTHEAD",
+    [EST_FETCHENTRY]   = "FETCH ENTRY",
+    [EST_FETCHQH]      = "FETCH QH",
+    [EST_FETCHITD]     = "FETCH ITD",
+    [EST_ADVANCEQUEUE] = "ADVANCEQUEUE",
+    [EST_FETCHQTD]     = "FETCH QTD",
+    [EST_EXECUTE]      = "EXECUTE",
+    [EST_WRITEBACK]    = "WRITEBACK",
+    [EST_HORIZONTALQH] = "HORIZONTALQH",
+};
+
+static const char *ehci_mmio_names[] = {
+    [CAPLENGTH]         = "CAPLENGTH",
+    [HCIVERSION]        = "HCIVERSION",
+    [HCSPARAMS]         = "HCSPARAMS",
+    [HCCPARAMS]         = "HCCPARAMS",
+    [USBCMD]            = "USBCMD",
+    [USBSTS]            = "USBSTS",
+    [USBINTR]           = "USBINTR",
+    [FRINDEX]           = "FRINDEX",
+    [PERIODICLISTBASE]  = "P-LIST BASE",
+    [ASYNCLISTADDR]     = "A-LIST ADDR",
+    [PORTSC_BEGIN]      = "PORTSC #0",
+    [PORTSC_BEGIN + 4]  = "PORTSC #1",
+    [PORTSC_BEGIN + 8]  = "PORTSC #2",
+    [PORTSC_BEGIN + 12] = "PORTSC #3",
+    [PORTSC_BEGIN + 16] = "PORTSC #4",
+    [PORTSC_BEGIN + 20] = "PORTSC #5",
+    [CONFIGFLAG]        = "CONFIGFLAG",
+};
+
+static const char *nr2str(const char **n, size_t len, uint32_t nr)
+{
+    if (nr < len && n[nr] != NULL) {
+        return n[nr];
+    } else {
+        return "unknown";
+    }
+}
+
+static const char *state2str(uint32_t state)
+{
+    return nr2str(ehci_state_names, ARRAY_SIZE(ehci_state_names), state);
+}
+
+static const char *addr2str(target_phys_addr_t addr)
+{
+    return nr2str(ehci_mmio_names, ARRAY_SIZE(ehci_mmio_names), addr);
+}
+
+static void ehci_trace_usbsts(uint32_t mask, int state)
+{
+    /* interrupts */
+    if (mask & USBSTS_INT) {
+        trace_usb_ehci_usbsts("INT", state);
+    }
+    if (mask & USBSTS_ERRINT) {
+        trace_usb_ehci_usbsts("ERRINT", state);
+    }
+    if (mask & USBSTS_PCD) {
+        trace_usb_ehci_usbsts("PCD", state);
+    }
+    if (mask & USBSTS_FLR) {
+        trace_usb_ehci_usbsts("FLR", state);
+    }
+    if (mask & USBSTS_HSE) {
+        trace_usb_ehci_usbsts("HSE", state);
+    }
+    if (mask & USBSTS_IAA) {
+        trace_usb_ehci_usbsts("IAA", state);
+    }
+
+    /* status */
+    if (mask & USBSTS_HALT) {
+        trace_usb_ehci_usbsts("HALT", state);
+    }
+    if (mask & USBSTS_REC) {
+        trace_usb_ehci_usbsts("REC", state);
+    }
+    if (mask & USBSTS_PSS) {
+        trace_usb_ehci_usbsts("PSS", state);
+    }
+    if (mask & USBSTS_ASS) {
+        trace_usb_ehci_usbsts("ASS", state);
+    }
+}
+
+static inline void ehci_set_usbsts(EHCIState *s, int mask)
+{
+    if ((s->usbsts & mask) == mask) {
+        return;
+    }
+    ehci_trace_usbsts(mask, 1);
+    s->usbsts |= mask;
+}
+
+static inline void ehci_clear_usbsts(EHCIState *s, int mask)
+{
+    if ((s->usbsts & mask) == 0) {
+        return;
+    }
+    ehci_trace_usbsts(mask, 0);
+    s->usbsts &= ~mask;
+}
+
+static inline void ehci_set_interrupt(EHCIState *s, int intr)
+{
+    int level = 0;
+
+    // TODO honour interrupt threshold requests
+
+    ehci_set_usbsts(s, intr);
+
+    if ((s->usbsts & USBINTR_MASK) & s->usbintr) {
+        level = 1;
+    }
+
+    qemu_set_irq(s->irq, level);
+}
+
+static inline void ehci_record_interrupt(EHCIState *s, int intr)
+{
+    s->usbsts_pending |= intr;
+}
+
+static inline void ehci_commit_interrupt(EHCIState *s)
+{
+    if (!s->usbsts_pending) {
+        return;
+    }
+    ehci_set_interrupt(s, s->usbsts_pending);
+    s->usbsts_pending = 0;
+}
+
+static void ehci_set_state(EHCIState *s, int async, int state)
+{
+    if (async) {
+        trace_usb_ehci_state("async", state2str(state));
+        s->astate = state;
+    } else {
+        trace_usb_ehci_state("periodic", state2str(state));
+        s->pstate = state;
+    }
+}
+
+static int ehci_get_state(EHCIState *s, int async)
+{
+    return async ? s->astate : s->pstate;
+}
+
+static void ehci_set_fetch_addr(EHCIState *s, int async, uint32_t addr)
+{
+    if (async) {
+        s->a_fetch_addr = addr;
+    } else {
+        s->p_fetch_addr = addr;
+    }
+}
+
+static int ehci_get_fetch_addr(EHCIState *s, int async)
+{
+    return async ? s->a_fetch_addr : s->p_fetch_addr;
+}
+
+static void ehci_trace_qh(EHCIQueue *q, target_phys_addr_t addr, EHCIqh *qh)
+{
+    /* need three here due to argument count limits */
+    trace_usb_ehci_qh_ptrs(q, addr, qh->next,
+                           qh->current_qtd, qh->next_qtd, qh->altnext_qtd);
+    trace_usb_ehci_qh_fields(addr,
+                             get_field(qh->epchar, QH_EPCHAR_RL),
+                             get_field(qh->epchar, QH_EPCHAR_MPLEN),
+                             get_field(qh->epchar, QH_EPCHAR_EPS),
+                             get_field(qh->epchar, QH_EPCHAR_EP),
+                             get_field(qh->epchar, QH_EPCHAR_DEVADDR));
+    trace_usb_ehci_qh_bits(addr,
+                           (bool)(qh->epchar & QH_EPCHAR_C),
+                           (bool)(qh->epchar & QH_EPCHAR_H),
+                           (bool)(qh->epchar & QH_EPCHAR_DTC),
+                           (bool)(qh->epchar & QH_EPCHAR_I));
+}
+
+static void ehci_trace_qtd(EHCIQueue *q, target_phys_addr_t addr, EHCIqtd *qtd)
+{
+    /* need three here due to argument count limits */
+    trace_usb_ehci_qtd_ptrs(q, addr, qtd->next, qtd->altnext);
+    trace_usb_ehci_qtd_fields(addr,
+                              get_field(qtd->token, QTD_TOKEN_TBYTES),
+                              get_field(qtd->token, QTD_TOKEN_CPAGE),
+                              get_field(qtd->token, QTD_TOKEN_CERR),
+                              get_field(qtd->token, QTD_TOKEN_PID));
+    trace_usb_ehci_qtd_bits(addr,
+                            (bool)(qtd->token & QTD_TOKEN_IOC),
+                            (bool)(qtd->token & QTD_TOKEN_ACTIVE),
+                            (bool)(qtd->token & QTD_TOKEN_HALT),
+                            (bool)(qtd->token & QTD_TOKEN_BABBLE),
+                            (bool)(qtd->token & QTD_TOKEN_XACTERR));
+}
+
+static void ehci_trace_itd(EHCIState *s, target_phys_addr_t addr, EHCIitd *itd)
+{
+    trace_usb_ehci_itd(addr, itd->next,
+                       get_field(itd->bufptr[1], ITD_BUFPTR_MAXPKT),
+                       get_field(itd->bufptr[2], ITD_BUFPTR_MULT),
+                       get_field(itd->bufptr[0], ITD_BUFPTR_EP),
+                       get_field(itd->bufptr[0], ITD_BUFPTR_DEVADDR));
+}
+
+static void ehci_trace_sitd(EHCIState *s, target_phys_addr_t addr,
+                            EHCIsitd *sitd)
+{
+    trace_usb_ehci_sitd(addr, sitd->next,
+                        (bool)(sitd->results & SITD_RESULTS_ACTIVE));
+}
+
+/* queue management */
+
+static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async)
+{
+    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
+    EHCIQueue *q;
+
+    q = g_malloc0(sizeof(*q));
+    q->ehci = ehci;
+    QTAILQ_INSERT_HEAD(head, q, next);
+    trace_usb_ehci_queue_action(q, "alloc");
+    return q;
+}
+
+static void ehci_free_queue(EHCIQueue *q, int async)
+{
+    EHCIQueueHead *head = async ? &q->ehci->aqueues : &q->ehci->pqueues;
+    trace_usb_ehci_queue_action(q, "free");
+    if (q->async == EHCI_ASYNC_INFLIGHT) {
+        usb_cancel_packet(&q->packet);
+    }
+    QTAILQ_REMOVE(head, q, next);
+    g_free(q);
+}
+
+static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr,
+                                        int async)
+{
+    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
+    EHCIQueue *q;
+
+    QTAILQ_FOREACH(q, head, next) {
+        if (addr == q->qhaddr) {
+            return q;
+        }
+    }
+    return NULL;
+}
+
+static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
+{
+    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
+    EHCIQueue *q, *tmp;
+
+    QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
+        if (q->seen) {
+            q->seen = 0;
+            q->ts = ehci->last_run_ns;
+            continue;
+        }
+        if (!flush && ehci->last_run_ns < q->ts + 250000000) {
+            /* allow 0.25 sec idle */
+            continue;
+        }
+        ehci_free_queue(q, async);
+    }
+}
+
+static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async)
+{
+    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
+    EHCIQueue *q, *tmp;
+
+    QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
+        if (!usb_packet_is_inflight(&q->packet) ||
+            q->packet.ep->dev != dev) {
+            continue;
+        }
+        ehci_free_queue(q, async);
+    }
+}
+
+static void ehci_queues_rip_all(EHCIState *ehci, int async)
+{
+    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
+    EHCIQueue *q, *tmp;
+
+    QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
+        ehci_free_queue(q, async);
+    }
+}
+
+/* Attach or detach a device on root hub */
+
+static void ehci_attach(USBPort *port)
+{
+    EHCIState *s = port->opaque;
+    uint32_t *portsc = &s->portsc[port->index];
+
+    trace_usb_ehci_port_attach(port->index, port->dev->product_desc);
+
+    if (*portsc & PORTSC_POWNER) {
+        USBPort *companion = s->companion_ports[port->index];
+        companion->dev = port->dev;
+        companion->ops->attach(companion);
+        return;
+    }
+
+    *portsc |= PORTSC_CONNECT;
+    *portsc |= PORTSC_CSC;
+
+    ehci_set_interrupt(s, USBSTS_PCD);
+}
+
+static void ehci_detach(USBPort *port)
+{
+    EHCIState *s = port->opaque;
+    uint32_t *portsc = &s->portsc[port->index];
+
+    trace_usb_ehci_port_detach(port->index);
+
+    if (*portsc & PORTSC_POWNER) {
+        USBPort *companion = s->companion_ports[port->index];
+        companion->ops->detach(companion);
+        companion->dev = NULL;
+        /*
+         * EHCI spec 4.2.2: "When a disconnect occurs... On the event,
+         * the port ownership is returned immediately to the EHCI controller."
+         */
+        *portsc &= ~PORTSC_POWNER;
+        return;
+    }
+
+    ehci_queues_rip_device(s, port->dev, 0);
+    ehci_queues_rip_device(s, port->dev, 1);
+
+    *portsc &= ~(PORTSC_CONNECT|PORTSC_PED);
+    *portsc |= PORTSC_CSC;
+
+    ehci_set_interrupt(s, USBSTS_PCD);
+}
+
+static void ehci_child_detach(USBPort *port, USBDevice *child)
+{
+    EHCIState *s = port->opaque;
+    uint32_t portsc = s->portsc[port->index];
+
+    if (portsc & PORTSC_POWNER) {
+        USBPort *companion = s->companion_ports[port->index];
+        companion->ops->child_detach(companion, child);
+        companion->dev = NULL;
+        return;
+    }
+
+    ehci_queues_rip_device(s, child, 0);
+    ehci_queues_rip_device(s, child, 1);
+}
+
+static void ehci_wakeup(USBPort *port)
+{
+    EHCIState *s = port->opaque;
+    uint32_t portsc = s->portsc[port->index];
+
+    if (portsc & PORTSC_POWNER) {
+        USBPort *companion = s->companion_ports[port->index];
+        if (companion->ops->wakeup) {
+            companion->ops->wakeup(companion);
+        }
+    }
+}
+
+static int ehci_register_companion(USBBus *bus, USBPort *ports[],
+                                   uint32_t portcount, uint32_t firstport)
+{
+    EHCIState *s = container_of(bus, EHCIState, bus);
+    uint32_t i;
+
+    if (firstport + portcount > NB_PORTS) {
+        qerror_report(QERR_INVALID_PARAMETER_VALUE, "firstport",
+                      "firstport on masterbus");
+        error_printf_unless_qmp(
+            "firstport value of %u makes companion take ports %u - %u, which "
+            "is outside of the valid range of 0 - %u\n", firstport, firstport,
+            firstport + portcount - 1, NB_PORTS - 1);
+        return -1;
+    }
+
+    for (i = 0; i < portcount; i++) {
+        if (s->companion_ports[firstport + i]) {
+            qerror_report(QERR_INVALID_PARAMETER_VALUE, "masterbus",
+                          "an USB masterbus");
+            error_printf_unless_qmp(
+                "port %u on masterbus %s already has a companion assigned\n",
+                firstport + i, bus->qbus.name);
+            return -1;
+        }
+    }
+
+    for (i = 0; i < portcount; i++) {
+        s->companion_ports[firstport + i] = ports[i];
+        s->ports[firstport + i].speedmask |=
+            USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL;
+        /* Ensure devs attached before the initial reset go to the companion */
+        s->portsc[firstport + i] = PORTSC_POWNER;
+    }
+
+    s->companion_count++;
+    s->mmio[0x05] = (s->companion_count << 4) | portcount;
+
+    return 0;
+}
+
+static USBDevice *ehci_find_device(EHCIState *ehci, uint8_t addr)
+{
+    USBDevice *dev;
+    USBPort *port;
+    int i;
+
+    for (i = 0; i < NB_PORTS; i++) {
+        port = &ehci->ports[i];
+        if (!(ehci->portsc[i] & PORTSC_PED)) {
+            DPRINTF("Port %d not enabled\n", i);
+            continue;
+        }
+        dev = usb_find_device(port, addr);
+        if (dev != NULL) {
+            return dev;
+        }
+    }
+    return NULL;
+}
+
+/* 4.1 host controller initialization */
+static void ehci_reset(void *opaque)
+{
+    EHCIState *s = opaque;
+    int i;
+    USBDevice *devs[NB_PORTS];
+
+    trace_usb_ehci_reset();
+
+    /*
+     * Do the detach before touching portsc, so that it correctly gets send to
+     * us or to our companion based on PORTSC_POWNER before the reset.
+     */
+    for(i = 0; i < NB_PORTS; i++) {
+        devs[i] = s->ports[i].dev;
+        if (devs[i] && devs[i]->attached) {
+            usb_detach(&s->ports[i]);
+        }
+    }
+
+    memset(&s->mmio[OPREGBASE], 0x00, MMIO_SIZE - OPREGBASE);
+
+    s->usbcmd = NB_MAXINTRATE << USBCMD_ITC_SH;
+    s->usbsts = USBSTS_HALT;
+
+    s->astate = EST_INACTIVE;
+    s->pstate = EST_INACTIVE;
+    s->isoch_pause = -1;
+    s->attach_poll_counter = 0;
+
+    for(i = 0; i < NB_PORTS; i++) {
+        if (s->companion_ports[i]) {
+            s->portsc[i] = PORTSC_POWNER | PORTSC_PPOWER;
+        } else {
+            s->portsc[i] = PORTSC_PPOWER;
+        }
+        if (devs[i] && devs[i]->attached) {
+            usb_attach(&s->ports[i]);
+            usb_device_reset(devs[i]);
+        }
+    }
+    ehci_queues_rip_all(s, 0);
+    ehci_queues_rip_all(s, 1);
+    qemu_del_timer(s->frame_timer);
+}
+
+static uint32_t ehci_mem_readb(void *ptr, target_phys_addr_t addr)
+{
+    EHCIState *s = ptr;
+    uint32_t val;
+
+    val = s->mmio[addr];
+
+    return val;
+}
+
+static uint32_t ehci_mem_readw(void *ptr, target_phys_addr_t addr)
+{
+    EHCIState *s = ptr;
+    uint32_t val;
+
+    val = s->mmio[addr] | (s->mmio[addr+1] << 8);
+
+    return val;
+}
+
+static uint32_t ehci_mem_readl(void *ptr, target_phys_addr_t addr)
+{
+    EHCIState *s = ptr;
+    uint32_t val;
+
+    val = s->mmio[addr] | (s->mmio[addr+1] << 8) |
+          (s->mmio[addr+2] << 16) | (s->mmio[addr+3] << 24);
+
+    trace_usb_ehci_mmio_readl(addr, addr2str(addr), val);
+    return val;
+}
+
+static void ehci_mem_writeb(void *ptr, target_phys_addr_t addr, uint32_t val)
+{
+    fprintf(stderr, "EHCI doesn't handle byte writes to MMIO\n");
+    exit(1);
+}
+
+static void ehci_mem_writew(void *ptr, target_phys_addr_t addr, uint32_t val)
+{
+    fprintf(stderr, "EHCI doesn't handle 16-bit writes to MMIO\n");
+    exit(1);
+}
+
+static void handle_port_owner_write(EHCIState *s, int port, uint32_t owner)
+{
+    USBDevice *dev = s->ports[port].dev;
+    uint32_t *portsc = &s->portsc[port];
+    uint32_t orig;
+
+    if (s->companion_ports[port] == NULL)
+        return;
+
+    owner = owner & PORTSC_POWNER;
+    orig  = *portsc & PORTSC_POWNER;
+
+    if (!(owner ^ orig)) {
+        return;
+    }
+
+    if (dev && dev->attached) {
+        usb_detach(&s->ports[port]);
+    }
+
+    *portsc &= ~PORTSC_POWNER;
+    *portsc |= owner;
+
+    if (dev && dev->attached) {
+        usb_attach(&s->ports[port]);
+    }
+}
+
+static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
+{
+    uint32_t *portsc = &s->portsc[port];
+    USBDevice *dev = s->ports[port].dev;
+
+    /* Clear rwc bits */
+    *portsc &= ~(val & PORTSC_RWC_MASK);
+    /* The guest may clear, but not set the PED bit */
+    *portsc &= val | ~PORTSC_PED;
+    /* POWNER is masked out by RO_MASK as it is RO when we've no companion */
+    handle_port_owner_write(s, port, val);
+    /* And finally apply RO_MASK */
+    val &= PORTSC_RO_MASK;
+
+    if ((val & PORTSC_PRESET) && !(*portsc & PORTSC_PRESET)) {
+        trace_usb_ehci_port_reset(port, 1);
+    }
+
+    if (!(val & PORTSC_PRESET) &&(*portsc & PORTSC_PRESET)) {
+        trace_usb_ehci_port_reset(port, 0);
+        if (dev && dev->attached) {
+            usb_port_reset(&s->ports[port]);
+            *portsc &= ~PORTSC_CSC;
+        }
+
+        /*
+         *  Table 2.16 Set the enable bit(and enable bit change) to indicate
+         *  to SW that this port has a high speed device attached
+         */
+        if (dev && dev->attached && (dev->speedmask & USB_SPEED_MASK_HIGH)) {
+            val |= PORTSC_PED;
+        }
+    }
+
+    *portsc &= ~PORTSC_RO_MASK;
+    *portsc |= val;
+}
+
+static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
+{
+    EHCIState *s = ptr;
+    uint32_t *mmio = (uint32_t *)(&s->mmio[addr]);
+    uint32_t old = *mmio;
+    int i;
+
+    trace_usb_ehci_mmio_writel(addr, addr2str(addr), val);
+
+    /* Only aligned reads are allowed on OHCI */
+    if (addr & 3) {
+        fprintf(stderr, "usb-ehci: Mis-aligned write to addr 0x"
+                TARGET_FMT_plx "\n", addr);
+        return;
+    }
+
+    if (addr >= PORTSC && addr < PORTSC + 4 * NB_PORTS) {
+        handle_port_status_write(s, (addr-PORTSC)/4, val);
+        trace_usb_ehci_mmio_change(addr, addr2str(addr), *mmio, old);
+        return;
+    }
+
+    if (addr < OPREGBASE) {
+        fprintf(stderr, "usb-ehci: write attempt to read-only register"
+                TARGET_FMT_plx "\n", addr);
+        return;
+    }
+
+
+    /* Do any register specific pre-write processing here.  */
+    switch(addr) {
+    case USBCMD:
+        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);
+            ehci_queues_rip_all(s, 0);
+            ehci_queues_rip_all(s, 1);
+            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)) {
+            fprintf(stderr, "attempt to set frame list size -- value %d\n",
+                    val & USBCMD_FLS);
+            val &= ~USBCMD_FLS;
+        }
+        break;
+
+    case USBSTS:
+        val &= USBSTS_RO_MASK;              // bits 6 thru 31 are RO
+        ehci_clear_usbsts(s, val);          // bits 0 thru 5 are R/WC
+        val = s->usbsts;
+        ehci_set_interrupt(s, 0);
+        break;
+
+    case USBINTR:
+        val &= USBINTR_MASK;
+        break;
+
+    case FRINDEX:
+        s->sofv = val >> 3;
+        break;
+
+    case CONFIGFLAG:
+        val &= 0x1;
+        if (val) {
+            for(i = 0; i < NB_PORTS; i++)
+                handle_port_owner_write(s, i, 0);
+        }
+        break;
+
+    case PERIODICLISTBASE:
+        if ((s->usbcmd & USBCMD_PSE) && (s->usbcmd & USBCMD_RUNSTOP)) {
+            fprintf(stderr,
+              "ehci: PERIODIC list base register set while periodic schedule\n"
+              "      is enabled and HC is enabled\n");
+        }
+        break;
+
+    case ASYNCLISTADDR:
+        if ((s->usbcmd & USBCMD_ASE) && (s->usbcmd & USBCMD_RUNSTOP)) {
+            fprintf(stderr,
+              "ehci: ASYNC list address register set while async schedule\n"
+              "      is enabled and HC is enabled\n");
+        }
+        break;
+    }
+
+    *mmio = val;
+    trace_usb_ehci_mmio_change(addr, addr2str(addr), *mmio, old);
+}
+
+
+// TODO : Put in common header file, duplication from usb-ohci.c
+
+/* Get an array of dwords from main memory */
+static inline int get_dwords(EHCIState *ehci, uint32_t addr,
+                             uint32_t *buf, int num)
+{
+    int i;
+
+    for(i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
+        pci_dma_read(&ehci->dev, addr, buf, sizeof(*buf));
+        *buf = le32_to_cpu(*buf);
+    }
+
+    return 1;
+}
+
+/* Put an array of dwords in to main memory */
+static inline int put_dwords(EHCIState *ehci, uint32_t addr,
+                             uint32_t *buf, int num)
+{
+    int i;
+
+    for(i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
+        uint32_t tmp = cpu_to_le32(*buf);
+        pci_dma_write(&ehci->dev, addr, &tmp, sizeof(tmp));
+    }
+
+    return 1;
+}
+
+// 4.10.2
+
+static int ehci_qh_do_overlay(EHCIQueue *q)
+{
+    int i;
+    int dtoggle;
+    int ping;
+    int eps;
+    int reload;
+
+    // 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;
+
+
+    eps = get_field(q->qh.epchar, QH_EPCHAR_EPS);
+    if (eps == EHCI_QH_EPS_HIGH) {
+        q->qh.token &= ~QTD_TOKEN_PING;
+        q->qh.token |= ping;
+    }
+
+    reload = get_field(q->qh.epchar, QH_EPCHAR_RL);
+    set_field(&q->qh.altnext_qtd, reload, QH_ALTNEXT_NAKCNT);
+
+    for (i = 0; i < 5; i++) {
+        q->qh.bufptr[i] = q->qtd.bufptr[i];
+    }
+
+    if (!(q->qh.epchar & QH_EPCHAR_DTC)) {
+        // preserve QH DT bit
+        q->qh.token &= ~QTD_TOKEN_DTOGGLE;
+        q->qh.token |= dtoggle;
+    }
+
+    q->qh.bufptr[1] &= ~BUFPTR_CPROGMASK_MASK;
+    q->qh.bufptr[2] &= ~BUFPTR_FRAMETAG_MASK;
+
+    put_dwords(q->ehci, NLPTR_GET(q->qhaddr), (uint32_t *) &q->qh,
+               sizeof(EHCIqh) >> 2);
+
+    return 0;
+}
+
+static int ehci_init_transfer(EHCIQueue *q)
+{
+    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);
+
+    while (bytes > 0) {
+        if (cpage > 4) {
+            fprintf(stderr, "cpage out of range (%d)\n", cpage);
+            return USB_RET_PROCERR;
+        }
+
+        page  = q->qh.bufptr[cpage] & QTD_BUFPTR_MASK;
+        page += offset;
+        plen  = bytes;
+        if (plen > 4096 - offset) {
+            plen = 4096 - offset;
+            offset = 0;
+            cpage++;
+        }
+
+        qemu_sglist_add(&q->sgl, page, plen);
+        bytes -= plen;
+    }
+    return 0;
+}
+
+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);
+        offset = q->qh.bufptr[0] & ~QTD_BUFPTR_MASK;
+
+        offset += status;
+        cpage  += offset >> QTD_BUFPTR_SH;
+        offset &= ~QTD_BUFPTR_MASK;
+
+        set_field(&q->qh.token, cpage, QTD_TOKEN_CPAGE);
+        q->qh.bufptr[0] &= QTD_BUFPTR_MASK;
+        q->qh.bufptr[0] |= offset;
+    }
+}
+
+static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
+{
+    EHCIQueue *q;
+    EHCIState *s = port->opaque;
+    uint32_t portsc = s->portsc[port->index];
+
+    if (portsc & PORTSC_POWNER) {
+        USBPort *companion = s->companion_ports[port->index];
+        companion->ops->complete(companion, 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;
+}
+
+static void ehci_execute_complete(EHCIQueue *q)
+{
+    assert(q->async != EHCI_ASYNC_INFLIGHT);
+    q->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) {
+        case USB_RET_IOERROR:
+        case USB_RET_NODEV:
+            q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_XACTERR);
+            set_field(&q->qh.token, 0, QTD_TOKEN_CERR);
+            ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
+            break;
+        case USB_RET_STALL:
+            q->qh.token |= QTD_TOKEN_HALT;
+            ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
+            break;
+        case USB_RET_NAK:
+            set_field(&q->qh.altnext_qtd, 0, QH_ALTNEXT_NAKCNT);
+            return; /* We're not done yet with this transaction */
+        case USB_RET_BABBLE:
+            q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_BABBLE);
+            ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
+            break;
+        default:
+            /* should not be triggerable */
+            fprintf(stderr, "USB invalid response %d to handle\n", q->usb_status);
+            assert(0);
+            break;
+        }
+    } else if ((q->usb_status > q->tbytes) && (q->pid == USB_TOKEN_IN)) {
+        q->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;
+        } else {
+            q->tbytes = 0;
+        }
+
+        DPRINTF("updating tbytes to %d\n", q->tbytes);
+        set_field(&q->qh.token, q->tbytes, QTD_TOKEN_TBYTES);
+    }
+    ehci_finish_transfer(q, q->usb_status);
+    usb_packet_unmap(&q->packet);
+
+    q->qh.token ^= QTD_TOKEN_DTOGGLE;
+    q->qh.token &= ~QTD_TOKEN_ACTIVE;
+
+    if (q->qh.token & QTD_TOKEN_IOC) {
+        ehci_record_interrupt(q->ehci, USBSTS_INT);
+    }
+}
+
+// 4.10.3
+
+static int ehci_execute(EHCIQueue *q)
+{
+    USBDevice *dev;
+    USBEndpoint *ep;
+    int ret;
+    int endp;
+    int devadr;
+
+    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) {
+        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;
+    }
+
+    if (ehci_init_transfer(q) != 0) {
+        return USB_RET_PROCERR;
+    }
+
+    endp = get_field(q->qh.epchar, QH_EPCHAR_EP);
+    devadr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR);
+
+    /* TODO: associating device with ehci port */
+    dev = ehci_find_device(q->ehci, devadr);
+    ep = usb_ep_get(dev, q->pid, endp);
+
+    usb_packet_setup(&q->packet, q->pid, ep);
+    usb_packet_map(&q->packet, &q->sgl);
+
+    ret = usb_handle_packet(dev, &q->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,
+            q->packet.iov.size, q->tbytes, endp, ret);
+
+    if (ret > BUFF_SIZE) {
+        fprintf(stderr, "ret from usb_handle_packet > BUFF_SIZE\n");
+        return USB_RET_PROCERR;
+    }
+
+    return ret;
+}
+
+/*  4.7.2
+ */
+
+static int ehci_process_itd(EHCIState *ehci,
+                            EHCIitd *itd)
+{
+    USBDevice *dev;
+    USBEndpoint *ep;
+    int ret;
+    uint32_t i, len, pid, dir, devaddr, endp;
+    uint32_t pg, off, ptr1, ptr2, max, mult;
+
+    dir =(itd->bufptr[1] & ITD_BUFPTR_DIRECTION);
+    devaddr = get_field(itd->bufptr[0], ITD_BUFPTR_DEVADDR);
+    endp = get_field(itd->bufptr[0], ITD_BUFPTR_EP);
+    max = get_field(itd->bufptr[1], ITD_BUFPTR_MAXPKT);
+    mult = get_field(itd->bufptr[2], ITD_BUFPTR_MULT);
+
+    for(i = 0; i < 8; i++) {
+        if (itd->transact[i] & ITD_XACT_ACTIVE) {
+            pg   = get_field(itd->transact[i], ITD_XACT_PGSEL);
+            off  = itd->transact[i] & ITD_XACT_OFFSET_MASK;
+            ptr1 = (itd->bufptr[pg] & ITD_BUFPTR_MASK);
+            ptr2 = (itd->bufptr[pg+1] & ITD_BUFPTR_MASK);
+            len  = get_field(itd->transact[i], ITD_XACT_LENGTH);
+
+            if (len > max * mult) {
+                len = max * mult;
+            }
+
+            if (len > BUFF_SIZE) {
+                return USB_RET_PROCERR;
+            }
+
+            pci_dma_sglist_init(&ehci->isgl, &ehci->dev, 2);
+            if (off + len > 4096) {
+                /* transfer crosses page border */
+                uint32_t len2 = off + len - 4096;
+                uint32_t len1 = len - len2;
+                qemu_sglist_add(&ehci->isgl, ptr1 + off, len1);
+                qemu_sglist_add(&ehci->isgl, ptr2, len2);
+            } else {
+                qemu_sglist_add(&ehci->isgl, ptr1 + off, len);
+            }
+
+            pid = dir ? USB_TOKEN_IN : USB_TOKEN_OUT;
+
+            dev = ehci_find_device(ehci, devaddr);
+            ep = usb_ep_get(dev, pid, endp);
+            if (ep->type == USB_ENDPOINT_XFER_ISOC) {
+                usb_packet_setup(&ehci->ipacket, pid, ep);
+                usb_packet_map(&ehci->ipacket, &ehci->isgl);
+                ret = usb_handle_packet(dev, &ehci->ipacket);
+                assert(ret != USB_RET_ASYNC);
+                usb_packet_unmap(&ehci->ipacket);
+            } else {
+                DPRINTF("ISOCH: attempt to addess non-iso endpoint\n");
+                ret = USB_RET_NAK;
+            }
+            qemu_sglist_destroy(&ehci->isgl);
+
+            if (ret < 0) {
+                switch (ret) {
+                default:
+                    fprintf(stderr, "Unexpected iso usb result: %d\n", ret);
+                    /* Fall through */
+                case USB_RET_IOERROR:
+                case USB_RET_NODEV:
+                    /* 3.3.2: XACTERR is only allowed on IN transactions */
+                    if (dir) {
+                        itd->transact[i] |= ITD_XACT_XACTERR;
+                        ehci_record_interrupt(ehci, USBSTS_ERRINT);
+                    }
+                    break;
+                case USB_RET_BABBLE:
+                    itd->transact[i] |= ITD_XACT_BABBLE;
+                    ehci_record_interrupt(ehci, USBSTS_ERRINT);
+                    break;
+                case USB_RET_NAK:
+                    /* no data for us, so do a zero-length transfer */
+                    ret = 0;
+                    break;
+                }
+            }
+            if (ret >= 0) {
+                if (!dir) {
+                    /* OUT */
+                    set_field(&itd->transact[i], len - ret, ITD_XACT_LENGTH);
+                } else {
+                    /* IN */
+                    set_field(&itd->transact[i], ret, ITD_XACT_LENGTH);
+                }
+            }
+            if (itd->transact[i] & ITD_XACT_IOC) {
+                ehci_record_interrupt(ehci, USBSTS_INT);
+            }
+            itd->transact[i] &= ~ITD_XACT_ACTIVE;
+        }
+    }
+    return 0;
+}
+
+/*  This state is the entry point for asynchronous schedule
+ *  processing.  Entry here consitutes a EHCI start event state (4.8.5)
+ */
+static int ehci_state_waitlisthead(EHCIState *ehci,  int async)
+{
+    EHCIqh qh;
+    int i = 0;
+    int again = 0;
+    uint32_t entry = ehci->asynclistaddr;
+
+    /* set reclamation flag at start event (4.8.6) */
+    if (async) {
+        ehci_set_usbsts(ehci, USBSTS_REC);
+    }
+
+    ehci_queues_rip_unused(ehci, async, 0);
+
+    /*  Find the head of the list (4.9.1.1) */
+    for(i = 0; i < MAX_QH; i++) {
+        get_dwords(ehci, NLPTR_GET(entry), (uint32_t *) &qh,
+                   sizeof(EHCIqh) >> 2);
+        ehci_trace_qh(NULL, NLPTR_GET(entry), &qh);
+
+        if (qh.epchar & QH_EPCHAR_H) {
+            if (async) {
+                entry |= (NLPTR_TYPE_QH << 1);
+            }
+
+            ehci_set_fetch_addr(ehci, async, entry);
+            ehci_set_state(ehci, async, EST_FETCHENTRY);
+            again = 1;
+            goto out;
+        }
+
+        entry = qh.next;
+        if (entry == ehci->asynclistaddr) {
+            break;
+        }
+    }
+
+    /* no head found for list. */
+
+    ehci_set_state(ehci, async, EST_ACTIVE);
+
+out:
+    return again;
+}
+
+
+/*  This state is the entry point for periodic schedule processing as
+ *  well as being a continuation state for async processing.
+ */
+static int ehci_state_fetchentry(EHCIState *ehci, int async)
+{
+    int again = 0;
+    uint32_t entry = ehci_get_fetch_addr(ehci, async);
+
+    if (NLPTR_TBIT(entry)) {
+        ehci_set_state(ehci, async, EST_ACTIVE);
+        goto out;
+    }
+
+    /* section 4.8, only QH in async schedule */
+    if (async && (NLPTR_TYPE_GET(entry) != NLPTR_TYPE_QH)) {
+        fprintf(stderr, "non queue head request in async schedule\n");
+        return -1;
+    }
+
+    switch (NLPTR_TYPE_GET(entry)) {
+    case NLPTR_TYPE_QH:
+        ehci_set_state(ehci, async, EST_FETCHQH);
+        again = 1;
+        break;
+
+    case NLPTR_TYPE_ITD:
+        ehci_set_state(ehci, async, EST_FETCHITD);
+        again = 1;
+        break;
+
+    case NLPTR_TYPE_STITD:
+        ehci_set_state(ehci, async, EST_FETCHSITD);
+        again = 1;
+        break;
+
+    default:
+        /* TODO: handle FSTN type */
+        fprintf(stderr, "FETCHENTRY: entry at %X is of type %d "
+                "which is not supported yet\n", entry, NLPTR_TYPE_GET(entry));
+        return -1;
+    }
+
+out:
+    return again;
+}
+
+static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
+{
+    uint32_t entry;
+    EHCIQueue *q;
+
+    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->qhaddr = entry;
+    q->seen++;
+
+    if (q->seen > 1) {
+        /* we are going in circles -- stop processing */
+        ehci_set_state(ehci, async, EST_ACTIVE);
+        q = NULL;
+        goto out;
+    }
+
+    get_dwords(ehci, NLPTR_GET(q->qhaddr),
+               (uint32_t *) &q->qh, sizeof(EHCIqh) >> 2);
+    ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &q->qh);
+
+    if (q->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) {
+        /* I/O finished -- continue processing queue */
+        trace_usb_ehci_queue_action(q, "resume");
+        ehci_set_state(ehci, async, EST_EXECUTING);
+        goto out;
+    }
+
+    if (async && (q->qh.epchar & QH_EPCHAR_H)) {
+
+        /*  EHCI spec version 1.0 Section 4.8.3 & 4.10.1 */
+        if (ehci->usbsts & USBSTS_REC) {
+            ehci_clear_usbsts(ehci, USBSTS_REC);
+        } else {
+            DPRINTF("FETCHQH:  QH 0x%08x. H-bit set, reclamation status reset"
+                       " - done processing\n", q->qhaddr);
+            ehci_set_state(ehci, async, EST_ACTIVE);
+            q = NULL;
+            goto out;
+        }
+    }
+
+#if EHCI_DEBUG
+    if (q->qhaddr != q->qh.next) {
+    DPRINTF("FETCHQH:  QH 0x%08x (h %x halt %x active %x) next 0x%08x\n",
+               q->qhaddr,
+               q->qh.epchar & QH_EPCHAR_H,
+               q->qh.token & QTD_TOKEN_HALT,
+               q->qh.token & QTD_TOKEN_ACTIVE,
+               q->qh.next);
+    }
+#endif
+
+    if (q->qh.token & QTD_TOKEN_HALT) {
+        ehci_set_state(ehci, async, EST_HORIZONTALQH);
+
+    } else if ((q->qh.token & QTD_TOKEN_ACTIVE) &&
+               (NLPTR_TBIT(q->qh.current_qtd) == 0)) {
+        q->qtdaddr = q->qh.current_qtd;
+        ehci_set_state(ehci, async, EST_FETCHQTD);
+
+    } else {
+        /*  EHCI spec version 1.0 Section 4.10.2 */
+        ehci_set_state(ehci, async, EST_ADVANCEQUEUE);
+    }
+
+out:
+    return q;
+}
+
+static int ehci_state_fetchitd(EHCIState *ehci, int async)
+{
+    uint32_t entry;
+    EHCIitd itd;
+
+    assert(!async);
+    entry = ehci_get_fetch_addr(ehci, async);
+
+    get_dwords(ehci, NLPTR_GET(entry), (uint32_t *) &itd,
+               sizeof(EHCIitd) >> 2);
+    ehci_trace_itd(ehci, entry, &itd);
+
+    if (ehci_process_itd(ehci, &itd) != 0) {
+        return -1;
+    }
+
+    put_dwords(ehci, NLPTR_GET(entry), (uint32_t *) &itd,
+               sizeof(EHCIitd) >> 2);
+    ehci_set_fetch_addr(ehci, async, itd.next);
+    ehci_set_state(ehci, async, EST_FETCHENTRY);
+
+    return 1;
+}
+
+static int ehci_state_fetchsitd(EHCIState *ehci, int async)
+{
+    uint32_t entry;
+    EHCIsitd sitd;
+
+    assert(!async);
+    entry = ehci_get_fetch_addr(ehci, async);
+
+    get_dwords(ehci, NLPTR_GET(entry), (uint32_t *)&sitd,
+               sizeof(EHCIsitd) >> 2);
+    ehci_trace_sitd(ehci, entry, &sitd);
+
+    if (!(sitd.results & SITD_RESULTS_ACTIVE)) {
+        /* siTD is not active, nothing to do */;
+    } else {
+        /* TODO: split transfers are not implemented */
+        fprintf(stderr, "WARNING: Skipping active siTD\n");
+    }
+
+    ehci_set_fetch_addr(ehci, async, sitd.next);
+    ehci_set_state(ehci, async, EST_FETCHENTRY);
+    return 1;
+}
+
+/* Section 4.10.2 - paragraph 3 */
+static int ehci_state_advqueue(EHCIQueue *q, int async)
+{
+#if 0
+    /* TO-DO: 4.10.2 - paragraph 2
+     * if I-bit is set to 1 and QH is not active
+     * go to horizontal QH
+     */
+    if (I-bit set) {
+        ehci_set_state(ehci, async, EST_HORIZONTALQH);
+        goto out;
+    }
+#endif
+
+    /*
+     * want data and alt-next qTD is valid
+     */
+    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);
+
+    /*
+     *  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);
+
+    /*
+     *  no valid qTD, try next QH
+     */
+    } else {
+        ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+    }
+
+    return 1;
+}
+
+/* Section 4.10.2 - paragraph 4 */
+static int ehci_state_fetchqtd(EHCIQueue *q, int async)
+{
+    int again = 0;
+
+    get_dwords(q->ehci, NLPTR_GET(q->qtdaddr), (uint32_t *) &q->qtd,
+               sizeof(EHCIqtd) >> 2);
+    ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), &q->qtd);
+
+    if (q->qtd.token & QTD_TOKEN_ACTIVE) {
+        ehci_set_state(q->ehci, async, EST_EXECUTE);
+        again = 1;
+    } else {
+        ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+        again = 1;
+    }
+
+    return again;
+}
+
+static int ehci_state_horizqh(EHCIQueue *q, int async)
+{
+    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);
+        again = 1;
+    } else {
+        ehci_set_state(q->ehci, async, EST_ACTIVE);
+    }
+
+    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)
+{
+    int again = 0;
+
+    if (ehci_qh_do_overlay(q) != 0) {
+        return -1;
+    }
+
+    // TODO verify enough time remains in the uframe as in 4.4.1.1
+    // 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) {
+        int transactCtr = get_field(q->qh.epcap, QH_EPCAP_MULT);
+        if (!transactCtr) {
+            ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+            again = 1;
+            goto out;
+        }
+    }
+
+    if (async) {
+        ehci_set_usbsts(q->ehci, USBSTS_REC);
+    }
+
+    q->usb_status = ehci_execute(q);
+    if (q->usb_status == USB_RET_PROCERR) {
+        again = -1;
+        goto out;
+    }
+    if (q->usb_status == USB_RET_ASYNC) {
+        ehci_flush_qh(q);
+        trace_usb_ehci_queue_action(q, "suspend");
+        q->async = EHCI_ASYNC_INFLIGHT;
+        ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+        again = 1;
+        goto out;
+    }
+
+    ehci_set_state(q->ehci, async, EST_EXECUTING);
+    again = 1;
+
+out:
+    return again;
+}
+
+static int ehci_state_executing(EHCIQueue *q, int async)
+{
+    int again = 0;
+
+    ehci_execute_complete(q);
+    if (q->usb_status == USB_RET_ASYNC) {
+        goto out;
+    }
+    if (q->usb_status == USB_RET_PROCERR) {
+        again = -1;
+        goto out;
+    }
+
+    // 4.10.3
+    if (!async) {
+        int transactCtr = get_field(q->qh.epcap, QH_EPCAP_MULT);
+        transactCtr--;
+        set_field(&q->qh.epcap, transactCtr, QH_EPCAP_MULT);
+        // 4.10.3, bottom of page 82, should exit this state when transaction
+        // counter decrements to 0
+    }
+
+    /* 4.10.5 */
+    if (q->usb_status == USB_RET_NAK) {
+        ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+    } else {
+        ehci_set_state(q->ehci, async, EST_WRITEBACK);
+    }
+
+    again = 1;
+
+out:
+    ehci_flush_qh(q);
+    return again;
+}
+
+
+static int ehci_state_writeback(EHCIQueue *q, int async)
+{
+    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,
+               sizeof(EHCIqtd) >> 2);
+
+    /*
+     * EHCI specs say go horizontal here.
+     *
+     * We can also advance the queue here for performance reasons.  We
+     * need to take care to only take that shortcut in case we've
+     * processed the qtd just written back without errors, i.e. halt
+     * bit is clear.
+     */
+    if (q->qh.token & QTD_TOKEN_HALT) {
+        ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+        again = 1;
+    } else {
+        ehci_set_state(q->ehci, async, EST_ADVANCEQUEUE);
+        again = 1;
+    }
+    return again;
+}
+
+/*
+ * This is the state machine that is common to both async and periodic
+ */
+
+static void ehci_advance_state(EHCIState *ehci,
+                               int async)
+{
+    EHCIQueue *q = NULL;
+    int again;
+    int iter = 0;
+
+    do {
+        if (ehci_get_state(ehci, async) == EST_FETCHQH) {
+            iter++;
+            /* if we are roaming a lot of QH without executing a qTD
+             * something is wrong with the linked list. TO-DO: why is
+             * this hack needed?
+             */
+            assert(iter < MAX_ITERATIONS);
+#if 0
+            if (iter > MAX_ITERATIONS) {
+                DPRINTF("\n*** advance_state: bailing on MAX ITERATIONS***\n");
+                ehci_set_state(ehci, async, EST_ACTIVE);
+                break;
+            }
+#endif
+        }
+        switch(ehci_get_state(ehci, async)) {
+        case EST_WAITLISTHEAD:
+            again = ehci_state_waitlisthead(ehci, async);
+            break;
+
+        case EST_FETCHENTRY:
+            again = ehci_state_fetchentry(ehci, async);
+            break;
+
+        case EST_FETCHQH:
+            q = ehci_state_fetchqh(ehci, async);
+            again = q ? 1 : 0;
+            break;
+
+        case EST_FETCHITD:
+            again = ehci_state_fetchitd(ehci, async);
+            break;
+
+        case EST_FETCHSITD:
+            again = ehci_state_fetchsitd(ehci, async);
+            break;
+
+        case EST_ADVANCEQUEUE:
+            again = ehci_state_advqueue(q, async);
+            break;
+
+        case EST_FETCHQTD:
+            again = ehci_state_fetchqtd(q, async);
+            break;
+
+        case EST_HORIZONTALQH:
+            again = ehci_state_horizqh(q, async);
+            break;
+
+        case EST_EXECUTE:
+            iter = 0;
+            again = ehci_state_execute(q, async);
+            break;
+
+        case EST_EXECUTING:
+            assert(q != NULL);
+            again = ehci_state_executing(q, async);
+            break;
+
+        case EST_WRITEBACK:
+            assert(q != NULL);
+            again = ehci_state_writeback(q, async);
+            break;
+
+        default:
+            fprintf(stderr, "Bad state!\n");
+            again = -1;
+            assert(0);
+            break;
+        }
+
+        if (again < 0) {
+            fprintf(stderr, "processing error - resetting ehci HC\n");
+            ehci_reset(ehci);
+            again = 0;
+            assert(0);
+        }
+    }
+    while (again);
+
+    ehci_commit_interrupt(ehci);
+}
+
+static void ehci_advance_async_state(EHCIState *ehci)
+{
+    const int async = 1;
+
+    switch(ehci_get_state(ehci, async)) {
+    case EST_INACTIVE:
+        if (!(ehci->usbcmd & USBCMD_ASE)) {
+            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->usbcmd & USBCMD_ASE)) {
+            ehci_queues_rip_all(ehci, async);
+            ehci_clear_usbsts(ehci, USBSTS_ASS);
+            ehci_set_state(ehci, async, EST_INACTIVE);
+            break;
+        }
+
+        /* make sure guest has acknowledged the doorbell interrupt */
+        /* TO-DO: is this really needed? */
+        if (ehci->usbsts & USBSTS_IAA) {
+            DPRINTF("IAA status bit still set.\n");
+            break;
+        }
+
+        /* check that address register has been set */
+        if (ehci->asynclistaddr == 0) {
+            break;
+        }
+
+        ehci_set_state(ehci, async, EST_WAITLISTHEAD);
+        ehci_advance_state(ehci, async);
+
+        /* If the doorbell is set, the guest wants to make a change to the
+         * schedule. The host controller needs to release cached data.
+         * (section 4.8.2)
+         */
+        if (ehci->usbcmd & USBCMD_IAAD) {
+            /* Remove all unseen qhs from the async qhs queue */
+            ehci_queues_rip_unused(ehci, async, 1);
+            DPRINTF("ASYNC: doorbell request acknowledged\n");
+            ehci->usbcmd &= ~USBCMD_IAAD;
+            ehci_set_interrupt(ehci, USBSTS_IAA);
+        }
+        break;
+
+    default:
+        /* this should only be due to a developer mistake */
+        fprintf(stderr, "ehci: Bad asynchronous state %d. "
+                "Resetting to active\n", ehci->astate);
+        assert(0);
+    }
+}
+
+static void ehci_advance_periodic_state(EHCIState *ehci)
+{
+    uint32_t entry;
+    uint32_t list;
+    const int async = 0;
+
+    // 4.6
+
+    switch(ehci_get_state(ehci, async)) {
+    case EST_INACTIVE:
+        if ( !(ehci->frindex & 7) && (ehci->usbcmd & USBCMD_PSE)) {
+            ehci_set_usbsts(ehci, USBSTS_PSS);
+            ehci_set_state(ehci, async, EST_ACTIVE);
+            // No break, fall through to ACTIVE
+        } else
+            break;
+
+    case EST_ACTIVE:
+        if ( !(ehci->frindex & 7) && !(ehci->usbcmd & USBCMD_PSE)) {
+            ehci_queues_rip_all(ehci, async);
+            ehci_clear_usbsts(ehci, USBSTS_PSS);
+            ehci_set_state(ehci, async, EST_INACTIVE);
+            break;
+        }
+
+        list = ehci->periodiclistbase & 0xfffff000;
+        /* check that register has been set */
+        if (list == 0) {
+            break;
+        }
+        list |= ((ehci->frindex & 0x1ff8) >> 1);
+
+        pci_dma_read(&ehci->dev, list, &entry, sizeof entry);
+        entry = le32_to_cpu(entry);
+
+        DPRINTF("PERIODIC state adv fr=%d.  [%08X] -> %08X\n",
+                ehci->frindex / 8, list, entry);
+        ehci_set_fetch_addr(ehci, async,entry);
+        ehci_set_state(ehci, async, EST_FETCHENTRY);
+        ehci_advance_state(ehci, async);
+        ehci_queues_rip_unused(ehci, async, 0);
+        break;
+
+    default:
+        /* this should only be due to a developer mistake */
+        fprintf(stderr, "ehci: Bad periodic state %d. "
+                "Resetting to active\n", ehci->pstate);
+        assert(0);
+    }
+}
+
+static void ehci_frame_timer(void *opaque)
+{
+    EHCIState *ehci = opaque;
+    int64_t expire_time, t_now;
+    uint64_t ns_elapsed;
+    int frames;
+    int i;
+    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++) {
+        if ( !(ehci->usbsts & USBSTS_HALT)) {
+            if (ehci->isoch_pause <= 0) {
+                ehci->frindex += 8;
+            }
+
+            if (ehci->frindex > 0x00001fff) {
+                ehci->frindex = 0;
+                ehci_set_interrupt(ehci, USBSTS_FLR);
+            }
+
+            ehci->sofv = (ehci->frindex - 1) >> 3;
+            ehci->sofv &= 0x000003ff;
+        }
+
+        if (frames - i > ehci->maxframes) {
+            skipped_frames++;
+        } else {
+            ehci_advance_periodic_state(ehci);
+        }
+
+        ehci->last_run_ns += FRAME_TIMER_NS;
+    }
+
+#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
+     */
+    ehci_advance_async_state(ehci);
+
+    qemu_mod_timer(ehci->frame_timer, expire_time);
+}
+
+
+static const MemoryRegionOps ehci_mem_ops = {
+    .old_mmio = {
+        .read = { ehci_mem_readb, ehci_mem_readw, ehci_mem_readl },
+        .write = { ehci_mem_writeb, ehci_mem_writew, ehci_mem_writel },
+    },
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static int usb_ehci_initfn(PCIDevice *dev);
+
+static USBPortOps ehci_port_ops = {
+    .attach = ehci_attach,
+    .detach = ehci_detach,
+    .child_detach = ehci_child_detach,
+    .wakeup = ehci_wakeup,
+    .complete = ehci_async_complete_packet,
+};
+
+static USBBusOps ehci_bus_ops = {
+    .register_companion = ehci_register_companion,
+};
+
+static const VMStateDescription vmstate_ehci = {
+    .name = "ehci",
+    .unmigratable = 1,
+};
+
+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(),
+};
+
+static void ehci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = usb_ehci_initfn;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82801D; /* ich4 */
+    k->revision = 0x10;
+    k->class_id = PCI_CLASS_SERIAL_USB;
+    dc->vmsd = &vmstate_ehci;
+    dc->props = ehci_properties;
+}
+
+static TypeInfo ehci_info = {
+    .name          = "usb-ehci",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(EHCIState),
+    .class_init    = ehci_class_init,
+};
+
+static void ich9_ehci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = usb_ehci_initfn;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82801I_EHCI1;
+    k->revision = 0x03;
+    k->class_id = PCI_CLASS_SERIAL_USB;
+    dc->vmsd = &vmstate_ehci;
+    dc->props = ehci_properties;
+}
+
+static TypeInfo ich9_ehci_info = {
+    .name          = "ich9-usb-ehci1",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(EHCIState),
+    .class_init    = ich9_ehci_class_init,
+};
+
+static int usb_ehci_initfn(PCIDevice *dev)
+{
+    EHCIState *s = DO_UPCAST(EHCIState, dev, dev);
+    uint8_t *pci_conf = s->dev.config;
+    int i;
+
+    pci_set_byte(&pci_conf[PCI_CLASS_PROG], 0x20);
+
+    /* capabilities pointer */
+    pci_set_byte(&pci_conf[PCI_CAPABILITY_LIST], 0x00);
+    //pci_set_byte(&pci_conf[PCI_CAPABILITY_LIST], 0x50);
+
+    pci_set_byte(&pci_conf[PCI_INTERRUPT_PIN], 4); /* interrupt pin D */
+    pci_set_byte(&pci_conf[PCI_MIN_GNT], 0);
+    pci_set_byte(&pci_conf[PCI_MAX_LAT], 0);
+
+    // pci_conf[0x50] = 0x01; // power management caps
+
+    pci_set_byte(&pci_conf[USB_SBRN], USB_RELEASE_2); // release number (2.1.4)
+    pci_set_byte(&pci_conf[0x61], 0x20);  // frame length adjustment (2.1.5)
+    pci_set_word(&pci_conf[0x62], 0x00);  // port wake up capability (2.1.6)
+
+    pci_conf[0x64] = 0x00;
+    pci_conf[0x65] = 0x00;
+    pci_conf[0x66] = 0x00;
+    pci_conf[0x67] = 0x00;
+    pci_conf[0x68] = 0x01;
+    pci_conf[0x69] = 0x00;
+    pci_conf[0x6a] = 0x00;
+    pci_conf[0x6b] = 0x00;  // USBLEGSUP
+    pci_conf[0x6c] = 0x00;
+    pci_conf[0x6d] = 0x00;
+    pci_conf[0x6e] = 0x00;
+    pci_conf[0x6f] = 0xc0;  // USBLEFCTLSTS
+
+    // 2.2 host controller interface version
+    s->mmio[0x00] = (uint8_t) OPREGBASE;
+    s->mmio[0x01] = 0x00;
+    s->mmio[0x02] = 0x00;
+    s->mmio[0x03] = 0x01;        // HC version
+    s->mmio[0x04] = NB_PORTS;    // Number of downstream ports
+    s->mmio[0x05] = 0x00;        // No companion ports at present
+    s->mmio[0x06] = 0x00;
+    s->mmio[0x07] = 0x00;
+    s->mmio[0x08] = 0x80;        // We can cache whole frame, not 64-bit capable
+    s->mmio[0x09] = 0x68;        // EECP
+    s->mmio[0x0a] = 0x00;
+    s->mmio[0x0b] = 0x00;
+
+    s->irq = s->dev.irq[3];
+
+    usb_bus_new(&s->bus, &ehci_bus_ops, &s->dev.qdev);
+    for(i = 0; i < NB_PORTS; i++) {
+        usb_register_port(&s->bus, &s->ports[i], s, i, &ehci_port_ops,
+                          USB_SPEED_MASK_HIGH);
+        s->ports[i].dev = 0;
+    }
+
+    s->frame_timer = qemu_new_timer_ns(vm_clock, ehci_frame_timer, s);
+    QTAILQ_INIT(&s->aqueues);
+    QTAILQ_INIT(&s->pqueues);
+
+    qemu_register_reset(ehci_reset, s);
+
+    memory_region_init_io(&s->mem, &ehci_mem_ops, s, "ehci", MMIO_SIZE);
+    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem);
+
+    return 0;
+}
+
+static void ehci_register_types(void)
+{
+    type_register_static(&ehci_info);
+    type_register_static(&ich9_ehci_info);
+}
+
+type_init(ehci_register_types)
+
+/*
+ * vim: expandtab ts=4
+ */
diff --git a/hw/usb/hcd-musb.c b/hw/usb/hcd-musb.c
new file mode 100644
index 0000000..fa9385e
--- /dev/null
+++ b/hw/usb/hcd-musb.c
@@ -0,0 +1,1544 @@
+/*
+ * "Inventra" High-speed Dual-Role Controller (MUSB-HDRC), Mentor Graphics,
+ * USB2.0 OTG compliant core used in various chips.
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Written by Andrzej Zaborowski <andrew at openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * 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/>.
+ *
+ * Only host-mode and non-DMA accesses are currently supported.
+ */
+#include "qemu-common.h"
+#include "qemu-timer.h"
+#include "hw/usb.h"
+#include "hw/irq.h"
+#include "hw/hw.h"
+
+/* Common USB registers */
+#define MUSB_HDRC_FADDR		0x00	/* 8-bit */
+#define MUSB_HDRC_POWER		0x01	/* 8-bit */
+
+#define MUSB_HDRC_INTRTX	0x02	/* 16-bit */
+#define MUSB_HDRC_INTRRX	0x04
+#define MUSB_HDRC_INTRTXE	0x06  
+#define MUSB_HDRC_INTRRXE	0x08  
+#define MUSB_HDRC_INTRUSB	0x0a	/* 8 bit */
+#define MUSB_HDRC_INTRUSBE	0x0b	/* 8 bit */
+#define MUSB_HDRC_FRAME		0x0c	/* 16-bit */
+#define MUSB_HDRC_INDEX		0x0e	/* 8 bit */
+#define MUSB_HDRC_TESTMODE	0x0f	/* 8 bit */
+
+/* Per-EP registers in indexed mode */
+#define MUSB_HDRC_EP_IDX	0x10	/* 8-bit */
+
+/* EP FIFOs */
+#define MUSB_HDRC_FIFO		0x20
+
+/* Additional Control Registers */
+#define	MUSB_HDRC_DEVCTL	0x60	/* 8 bit */
+
+/* These are indexed */
+#define MUSB_HDRC_TXFIFOSZ	0x62	/* 8 bit (see masks) */
+#define MUSB_HDRC_RXFIFOSZ	0x63	/* 8 bit (see masks) */
+#define MUSB_HDRC_TXFIFOADDR	0x64	/* 16 bit offset shifted right 3 */
+#define MUSB_HDRC_RXFIFOADDR	0x66	/* 16 bit offset shifted right 3 */
+
+/* Some more registers */
+#define MUSB_HDRC_VCTRL		0x68	/* 8 bit */
+#define MUSB_HDRC_HWVERS	0x6c	/* 8 bit */
+
+/* Added in HDRC 1.9(?) & MHDRC 1.4 */
+/* ULPI pass-through */
+#define MUSB_HDRC_ULPI_VBUSCTL	0x70
+#define MUSB_HDRC_ULPI_REGDATA	0x74
+#define MUSB_HDRC_ULPI_REGADDR	0x75
+#define MUSB_HDRC_ULPI_REGCTL	0x76
+
+/* Extended config & PHY control */
+#define MUSB_HDRC_ENDCOUNT	0x78	/* 8 bit */
+#define MUSB_HDRC_DMARAMCFG	0x79	/* 8 bit */
+#define MUSB_HDRC_PHYWAIT	0x7a	/* 8 bit */
+#define MUSB_HDRC_PHYVPLEN	0x7b	/* 8 bit */
+#define MUSB_HDRC_HS_EOF1	0x7c	/* 8 bit, units of 546.1 us */
+#define MUSB_HDRC_FS_EOF1	0x7d	/* 8 bit, units of 533.3 ns */
+#define MUSB_HDRC_LS_EOF1	0x7e	/* 8 bit, units of 1.067 us */
+
+/* Per-EP BUSCTL registers */
+#define MUSB_HDRC_BUSCTL	0x80
+
+/* Per-EP registers in flat mode */
+#define MUSB_HDRC_EP		0x100
+
+/* offsets to registers in flat model */
+#define MUSB_HDRC_TXMAXP	0x00	/* 16 bit apparently */
+#define MUSB_HDRC_TXCSR		0x02	/* 16 bit apparently */
+#define MUSB_HDRC_CSR0		MUSB_HDRC_TXCSR		/* re-used for EP0 */
+#define MUSB_HDRC_RXMAXP	0x04	/* 16 bit apparently */
+#define MUSB_HDRC_RXCSR		0x06	/* 16 bit apparently */
+#define MUSB_HDRC_RXCOUNT	0x08	/* 16 bit apparently */
+#define MUSB_HDRC_COUNT0	MUSB_HDRC_RXCOUNT	/* re-used for EP0 */
+#define MUSB_HDRC_TXTYPE	0x0a	/* 8 bit apparently */
+#define MUSB_HDRC_TYPE0		MUSB_HDRC_TXTYPE	/* re-used for EP0 */
+#define MUSB_HDRC_TXINTERVAL	0x0b	/* 8 bit apparently */
+#define MUSB_HDRC_NAKLIMIT0	MUSB_HDRC_TXINTERVAL	/* re-used for EP0 */
+#define MUSB_HDRC_RXTYPE	0x0c	/* 8 bit apparently */
+#define MUSB_HDRC_RXINTERVAL	0x0d	/* 8 bit apparently */
+#define MUSB_HDRC_FIFOSIZE	0x0f	/* 8 bit apparently */
+#define MUSB_HDRC_CONFIGDATA	MGC_O_HDRC_FIFOSIZE	/* re-used for EP0 */
+
+/* "Bus control" registers */
+#define MUSB_HDRC_TXFUNCADDR	0x00
+#define MUSB_HDRC_TXHUBADDR	0x02
+#define MUSB_HDRC_TXHUBPORT	0x03
+
+#define MUSB_HDRC_RXFUNCADDR	0x04
+#define MUSB_HDRC_RXHUBADDR	0x06
+#define MUSB_HDRC_RXHUBPORT	0x07
+
+/*
+ * MUSBHDRC Register bit masks
+ */
+
+/* POWER */
+#define MGC_M_POWER_ISOUPDATE		0x80 
+#define	MGC_M_POWER_SOFTCONN		0x40
+#define	MGC_M_POWER_HSENAB		0x20
+#define	MGC_M_POWER_HSMODE		0x10
+#define MGC_M_POWER_RESET		0x08
+#define MGC_M_POWER_RESUME		0x04
+#define MGC_M_POWER_SUSPENDM		0x02
+#define MGC_M_POWER_ENSUSPEND		0x01
+
+/* INTRUSB */
+#define MGC_M_INTR_SUSPEND		0x01
+#define MGC_M_INTR_RESUME		0x02
+#define MGC_M_INTR_RESET		0x04
+#define MGC_M_INTR_BABBLE		0x04
+#define MGC_M_INTR_SOF			0x08 
+#define MGC_M_INTR_CONNECT		0x10
+#define MGC_M_INTR_DISCONNECT		0x20
+#define MGC_M_INTR_SESSREQ		0x40
+#define MGC_M_INTR_VBUSERROR		0x80	/* FOR SESSION END */
+#define MGC_M_INTR_EP0			0x01	/* FOR EP0 INTERRUPT */
+
+/* DEVCTL */
+#define MGC_M_DEVCTL_BDEVICE		0x80   
+#define MGC_M_DEVCTL_FSDEV		0x40
+#define MGC_M_DEVCTL_LSDEV		0x20
+#define MGC_M_DEVCTL_VBUS		0x18
+#define MGC_S_DEVCTL_VBUS		3
+#define MGC_M_DEVCTL_HM			0x04
+#define MGC_M_DEVCTL_HR			0x02
+#define MGC_M_DEVCTL_SESSION		0x01
+
+/* TESTMODE */
+#define MGC_M_TEST_FORCE_HOST		0x80
+#define MGC_M_TEST_FIFO_ACCESS		0x40
+#define MGC_M_TEST_FORCE_FS		0x20
+#define MGC_M_TEST_FORCE_HS		0x10
+#define MGC_M_TEST_PACKET		0x08
+#define MGC_M_TEST_K			0x04
+#define MGC_M_TEST_J			0x02
+#define MGC_M_TEST_SE0_NAK		0x01
+
+/* CSR0 */
+#define	MGC_M_CSR0_FLUSHFIFO		0x0100
+#define MGC_M_CSR0_TXPKTRDY		0x0002
+#define MGC_M_CSR0_RXPKTRDY		0x0001
+
+/* CSR0 in Peripheral mode */
+#define MGC_M_CSR0_P_SVDSETUPEND	0x0080
+#define MGC_M_CSR0_P_SVDRXPKTRDY	0x0040
+#define MGC_M_CSR0_P_SENDSTALL		0x0020
+#define MGC_M_CSR0_P_SETUPEND		0x0010
+#define MGC_M_CSR0_P_DATAEND		0x0008
+#define MGC_M_CSR0_P_SENTSTALL		0x0004
+
+/* CSR0 in Host mode */
+#define MGC_M_CSR0_H_NO_PING		0x0800
+#define MGC_M_CSR0_H_WR_DATATOGGLE	0x0400	/* set to allow setting: */
+#define MGC_M_CSR0_H_DATATOGGLE		0x0200	/* data toggle control */
+#define	MGC_M_CSR0_H_NAKTIMEOUT		0x0080
+#define MGC_M_CSR0_H_STATUSPKT		0x0040
+#define MGC_M_CSR0_H_REQPKT		0x0020
+#define MGC_M_CSR0_H_ERROR		0x0010
+#define MGC_M_CSR0_H_SETUPPKT		0x0008
+#define MGC_M_CSR0_H_RXSTALL		0x0004
+
+/* CONFIGDATA */
+#define MGC_M_CONFIGDATA_MPRXE		0x80	/* auto bulk pkt combining */
+#define MGC_M_CONFIGDATA_MPTXE		0x40	/* auto bulk pkt splitting */
+#define MGC_M_CONFIGDATA_BIGENDIAN	0x20
+#define MGC_M_CONFIGDATA_HBRXE		0x10	/* HB-ISO for RX */
+#define MGC_M_CONFIGDATA_HBTXE		0x08	/* HB-ISO for TX */
+#define MGC_M_CONFIGDATA_DYNFIFO	0x04	/* dynamic FIFO sizing */
+#define MGC_M_CONFIGDATA_SOFTCONE	0x02	/* SoftConnect */
+#define MGC_M_CONFIGDATA_UTMIDW		0x01	/* Width, 0 => 8b, 1 => 16b */
+
+/* TXCSR in Peripheral and Host mode */
+#define MGC_M_TXCSR_AUTOSET		0x8000
+#define MGC_M_TXCSR_ISO			0x4000
+#define MGC_M_TXCSR_MODE		0x2000
+#define MGC_M_TXCSR_DMAENAB		0x1000
+#define MGC_M_TXCSR_FRCDATATOG		0x0800
+#define MGC_M_TXCSR_DMAMODE		0x0400
+#define MGC_M_TXCSR_CLRDATATOG		0x0040
+#define MGC_M_TXCSR_FLUSHFIFO		0x0008
+#define MGC_M_TXCSR_FIFONOTEMPTY	0x0002
+#define MGC_M_TXCSR_TXPKTRDY		0x0001
+
+/* TXCSR in Peripheral mode */
+#define MGC_M_TXCSR_P_INCOMPTX		0x0080
+#define MGC_M_TXCSR_P_SENTSTALL		0x0020
+#define MGC_M_TXCSR_P_SENDSTALL		0x0010
+#define MGC_M_TXCSR_P_UNDERRUN		0x0004
+
+/* TXCSR in Host mode */
+#define MGC_M_TXCSR_H_WR_DATATOGGLE	0x0200
+#define MGC_M_TXCSR_H_DATATOGGLE	0x0100
+#define MGC_M_TXCSR_H_NAKTIMEOUT	0x0080
+#define MGC_M_TXCSR_H_RXSTALL		0x0020
+#define MGC_M_TXCSR_H_ERROR		0x0004
+
+/* RXCSR in Peripheral and Host mode */
+#define MGC_M_RXCSR_AUTOCLEAR		0x8000
+#define MGC_M_RXCSR_DMAENAB		0x2000
+#define MGC_M_RXCSR_DISNYET		0x1000
+#define MGC_M_RXCSR_DMAMODE		0x0800
+#define MGC_M_RXCSR_INCOMPRX		0x0100
+#define MGC_M_RXCSR_CLRDATATOG		0x0080
+#define MGC_M_RXCSR_FLUSHFIFO		0x0010
+#define MGC_M_RXCSR_DATAERROR		0x0008
+#define MGC_M_RXCSR_FIFOFULL		0x0002
+#define MGC_M_RXCSR_RXPKTRDY		0x0001
+
+/* RXCSR in Peripheral mode */
+#define MGC_M_RXCSR_P_ISO		0x4000
+#define MGC_M_RXCSR_P_SENTSTALL		0x0040
+#define MGC_M_RXCSR_P_SENDSTALL		0x0020
+#define MGC_M_RXCSR_P_OVERRUN		0x0004
+
+/* RXCSR in Host mode */
+#define MGC_M_RXCSR_H_AUTOREQ		0x4000
+#define MGC_M_RXCSR_H_WR_DATATOGGLE	0x0400
+#define MGC_M_RXCSR_H_DATATOGGLE	0x0200
+#define MGC_M_RXCSR_H_RXSTALL		0x0040
+#define MGC_M_RXCSR_H_REQPKT		0x0020
+#define MGC_M_RXCSR_H_ERROR		0x0004
+
+/* HUBADDR */
+#define MGC_M_HUBADDR_MULTI_TT		0x80
+
+/* ULPI: Added in HDRC 1.9(?) & MHDRC 1.4 */
+#define MGC_M_ULPI_VBCTL_USEEXTVBUSIND	0x02
+#define MGC_M_ULPI_VBCTL_USEEXTVBUS	0x01
+#define MGC_M_ULPI_REGCTL_INT_ENABLE	0x08
+#define MGC_M_ULPI_REGCTL_READNOTWRITE	0x04
+#define MGC_M_ULPI_REGCTL_COMPLETE	0x02
+#define MGC_M_ULPI_REGCTL_REG		0x01
+
+/* #define MUSB_DEBUG */
+
+#ifdef MUSB_DEBUG
+#define TRACE(fmt,...) fprintf(stderr, "%s@%d: " fmt "\n", __FUNCTION__, \
+                               __LINE__, ##__VA_ARGS__)
+#else
+#define TRACE(...)
+#endif
+
+
+static void musb_attach(USBPort *port);
+static void musb_detach(USBPort *port);
+static void musb_child_detach(USBPort *port, USBDevice *child);
+static void musb_schedule_cb(USBPort *port, USBPacket *p);
+static void musb_async_cancel_device(MUSBState *s, USBDevice *dev);
+
+static USBPortOps musb_port_ops = {
+    .attach = musb_attach,
+    .detach = musb_detach,
+    .child_detach = musb_child_detach,
+    .complete = musb_schedule_cb,
+};
+
+static USBBusOps musb_bus_ops = {
+};
+
+typedef struct MUSBPacket MUSBPacket;
+typedef struct MUSBEndPoint MUSBEndPoint;
+
+struct MUSBPacket {
+    USBPacket p;
+    MUSBEndPoint *ep;
+    int dir;
+};
+
+struct MUSBEndPoint {
+    uint16_t faddr[2];
+    uint8_t haddr[2];
+    uint8_t hport[2];
+    uint16_t csr[2];
+    uint16_t maxp[2];
+    uint16_t rxcount;
+    uint8_t type[2];
+    uint8_t interval[2];
+    uint8_t config;
+    uint8_t fifosize;
+    int timeout[2];	/* Always in microframes */
+
+    uint8_t *buf[2];
+    int fifolen[2];
+    int fifostart[2];
+    int fifoaddr[2];
+    MUSBPacket packey[2];
+    int status[2];
+    int ext_size[2];
+
+    /* For callbacks' use */
+    int epnum;
+    int interrupt[2];
+    MUSBState *musb;
+    USBCallback *delayed_cb[2];
+    QEMUTimer *intv_timer[2];
+};
+
+struct MUSBState {
+    qemu_irq irqs[musb_irq_max];
+    USBBus bus;
+    USBPort port;
+
+    int idx;
+    uint8_t devctl;
+    uint8_t power;
+    uint8_t faddr;
+
+    uint8_t intr;
+    uint8_t mask;
+    uint16_t tx_intr;
+    uint16_t tx_mask;
+    uint16_t rx_intr;
+    uint16_t rx_mask;
+
+    int setup_len;
+    int session;
+
+    uint8_t buf[0x8000];
+
+        /* Duplicating the world since 2008!...  probably we should have 32
+         * logical, single endpoints instead.  */
+    MUSBEndPoint ep[16];
+};
+
+void musb_reset(MUSBState *s)
+{
+    int i;
+
+    s->faddr = 0x00;
+    s->devctl = 0;
+    s->power = MGC_M_POWER_HSENAB;
+    s->tx_intr = 0x0000;
+    s->rx_intr = 0x0000;
+    s->tx_mask = 0xffff;
+    s->rx_mask = 0xffff;
+    s->intr = 0x00;
+    s->mask = 0x06;
+    s->idx = 0;
+
+    s->setup_len = 0;
+    s->session = 0;
+    memset(s->buf, 0, sizeof(s->buf));
+
+    /* TODO: _DW */
+    s->ep[0].config = MGC_M_CONFIGDATA_SOFTCONE | MGC_M_CONFIGDATA_DYNFIFO;
+    for (i = 0; i < 16; i ++) {
+        s->ep[i].fifosize = 64;
+        s->ep[i].maxp[0] = 0x40;
+        s->ep[i].maxp[1] = 0x40;
+        s->ep[i].musb = s;
+        s->ep[i].epnum = i;
+        usb_packet_init(&s->ep[i].packey[0].p);
+        usb_packet_init(&s->ep[i].packey[1].p);
+    }
+}
+
+struct MUSBState *musb_init(DeviceState *parent_device, int gpio_base)
+{
+    MUSBState *s = g_malloc0(sizeof(*s));
+    int i;
+
+    for (i = 0; i < musb_irq_max; i++) {
+        s->irqs[i] = qdev_get_gpio_in(parent_device, gpio_base + i);
+    }
+
+    musb_reset(s);
+
+    usb_bus_new(&s->bus, &musb_bus_ops, parent_device);
+    usb_register_port(&s->bus, &s->port, s, 0, &musb_port_ops,
+                      USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
+
+    return s;
+}
+
+static void musb_vbus_set(MUSBState *s, int level)
+{
+    if (level)
+        s->devctl |= 3 << MGC_S_DEVCTL_VBUS;
+    else
+        s->devctl &= ~MGC_M_DEVCTL_VBUS;
+
+    qemu_set_irq(s->irqs[musb_set_vbus], level);
+}
+
+static void musb_intr_set(MUSBState *s, int line, int level)
+{
+    if (!level) {
+        s->intr &= ~(1 << line);
+        qemu_irq_lower(s->irqs[line]);
+    } else if (s->mask & (1 << line)) {
+        s->intr |= 1 << line;
+        qemu_irq_raise(s->irqs[line]);
+    }
+}
+
+static void musb_tx_intr_set(MUSBState *s, int line, int level)
+{
+    if (!level) {
+        s->tx_intr &= ~(1 << line);
+        if (!s->tx_intr)
+            qemu_irq_lower(s->irqs[musb_irq_tx]);
+    } else if (s->tx_mask & (1 << line)) {
+        s->tx_intr |= 1 << line;
+        qemu_irq_raise(s->irqs[musb_irq_tx]);
+    }
+}
+
+static void musb_rx_intr_set(MUSBState *s, int line, int level)
+{
+    if (line) {
+        if (!level) {
+            s->rx_intr &= ~(1 << line);
+            if (!s->rx_intr)
+                qemu_irq_lower(s->irqs[musb_irq_rx]);
+        } else if (s->rx_mask & (1 << line)) {
+            s->rx_intr |= 1 << line;
+            qemu_irq_raise(s->irqs[musb_irq_rx]);
+        }
+    } else
+        musb_tx_intr_set(s, line, level);
+}
+
+uint32_t musb_core_intr_get(MUSBState *s)
+{
+    return (s->rx_intr << 15) | s->tx_intr;
+}
+
+void musb_core_intr_clear(MUSBState *s, uint32_t mask)
+{
+    if (s->rx_intr) {
+        s->rx_intr &= mask >> 15;
+        if (!s->rx_intr)
+            qemu_irq_lower(s->irqs[musb_irq_rx]);
+    }
+
+    if (s->tx_intr) {
+        s->tx_intr &= mask & 0xffff;
+        if (!s->tx_intr)
+            qemu_irq_lower(s->irqs[musb_irq_tx]);
+    }
+}
+
+void musb_set_size(MUSBState *s, int epnum, int size, int is_tx)
+{
+    s->ep[epnum].ext_size[!is_tx] = size;
+    s->ep[epnum].fifostart[0] = 0;
+    s->ep[epnum].fifostart[1] = 0;
+    s->ep[epnum].fifolen[0] = 0;
+    s->ep[epnum].fifolen[1] = 0;
+}
+
+static void musb_session_update(MUSBState *s, int prev_dev, int prev_sess)
+{
+    int detect_prev = prev_dev && prev_sess;
+    int detect = !!s->port.dev && s->session;
+
+    if (detect && !detect_prev) {
+        /* Let's skip the ID pin sense and VBUS sense formalities and
+         * and signal a successful SRP directly.  This should work at least
+         * for the Linux driver stack.  */
+        musb_intr_set(s, musb_irq_connect, 1);
+
+        if (s->port.dev->speed == USB_SPEED_LOW) {
+            s->devctl &= ~MGC_M_DEVCTL_FSDEV;
+            s->devctl |= MGC_M_DEVCTL_LSDEV;
+        } else {
+            s->devctl |= MGC_M_DEVCTL_FSDEV;
+            s->devctl &= ~MGC_M_DEVCTL_LSDEV;
+        }
+
+        /* A-mode?  */
+        s->devctl &= ~MGC_M_DEVCTL_BDEVICE;
+
+        /* Host-mode bit?  */
+        s->devctl |= MGC_M_DEVCTL_HM;
+#if 1
+        musb_vbus_set(s, 1);
+#endif
+    } else if (!detect && detect_prev) {
+#if 1
+        musb_vbus_set(s, 0);
+#endif
+    }
+}
+
+/* Attach or detach a device on our only port.  */
+static void musb_attach(USBPort *port)
+{
+    MUSBState *s = (MUSBState *) port->opaque;
+
+    musb_intr_set(s, musb_irq_vbus_request, 1);
+    musb_session_update(s, 0, s->session);
+}
+
+static void musb_detach(USBPort *port)
+{
+    MUSBState *s = (MUSBState *) port->opaque;
+
+    musb_async_cancel_device(s, port->dev);
+
+    musb_intr_set(s, musb_irq_disconnect, 1);
+    musb_session_update(s, 1, s->session);
+}
+
+static void musb_child_detach(USBPort *port, USBDevice *child)
+{
+    MUSBState *s = (MUSBState *) port->opaque;
+
+    musb_async_cancel_device(s, child);
+}
+
+static void musb_cb_tick0(void *opaque)
+{
+    MUSBEndPoint *ep = (MUSBEndPoint *) opaque;
+
+    ep->delayed_cb[0](&ep->packey[0].p, opaque);
+}
+
+static void musb_cb_tick1(void *opaque)
+{
+    MUSBEndPoint *ep = (MUSBEndPoint *) opaque;
+
+    ep->delayed_cb[1](&ep->packey[1].p, opaque);
+}
+
+#define musb_cb_tick	(dir ? musb_cb_tick1 : musb_cb_tick0)
+
+static void musb_schedule_cb(USBPort *port, USBPacket *packey)
+{
+    MUSBPacket *p = container_of(packey, MUSBPacket, p);
+    MUSBEndPoint *ep = p->ep;
+    int dir = p->dir;
+    int timeout = 0;
+
+    if (ep->status[dir] == USB_RET_NAK)
+        timeout = ep->timeout[dir];
+    else if (ep->interrupt[dir])
+        timeout = 8;
+    else
+        return musb_cb_tick(ep);
+
+    if (!ep->intv_timer[dir])
+        ep->intv_timer[dir] = qemu_new_timer_ns(vm_clock, musb_cb_tick, ep);
+
+    qemu_mod_timer(ep->intv_timer[dir], qemu_get_clock_ns(vm_clock) +
+                   muldiv64(timeout, get_ticks_per_sec(), 8000));
+}
+
+static int musb_timeout(int ttype, int speed, int val)
+{
+#if 1
+    return val << 3;
+#endif
+
+    switch (ttype) {
+    case USB_ENDPOINT_XFER_CONTROL:
+        if (val < 2)
+            return 0;
+        else if (speed == USB_SPEED_HIGH)
+            return 1 << (val - 1);
+        else
+            return 8 << (val - 1);
+
+    case USB_ENDPOINT_XFER_INT:
+        if (speed == USB_SPEED_HIGH)
+            if (val < 2)
+                return 0;
+            else
+                return 1 << (val - 1);
+        else
+            return val << 3;
+
+    case USB_ENDPOINT_XFER_BULK:
+    case USB_ENDPOINT_XFER_ISOC:
+        if (val < 2)
+            return 0;
+        else if (speed == USB_SPEED_HIGH)
+            return 1 << (val - 1);
+        else
+            return 8 << (val - 1);
+        /* TODO: what with low-speed Bulk and Isochronous?  */
+    }
+
+    hw_error("bad interval\n");
+}
+
+static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
+                int epnum, int pid, int len, USBCallback cb, int dir)
+{
+    USBDevice *dev;
+    USBEndpoint *uep;
+    int ret;
+    int idx = epnum && dir;
+    int ttype;
+
+    /* ep->type[0,1] contains:
+     * in bits 7:6 the speed (0 - invalid, 1 - high, 2 - full, 3 - slow)
+     * in bits 5:4 the transfer type (BULK / INT)
+     * in bits 3:0 the EP num
+     */
+    ttype = epnum ? (ep->type[idx] >> 4) & 3 : 0;
+
+    ep->timeout[dir] = musb_timeout(ttype,
+                    ep->type[idx] >> 6, ep->interval[idx]);
+    ep->interrupt[dir] = ttype == USB_ENDPOINT_XFER_INT;
+    ep->delayed_cb[dir] = cb;
+
+    /* A wild guess on the FADDR semantics... */
+    dev = usb_find_device(&s->port, ep->faddr[idx]);
+    uep = usb_ep_get(dev, pid, ep->type[idx] & 0xf);
+    usb_packet_setup(&ep->packey[dir].p, pid, uep);
+    usb_packet_addbuf(&ep->packey[dir].p, ep->buf[idx], len);
+    ep->packey[dir].ep = ep;
+    ep->packey[dir].dir = dir;
+
+    ret = usb_handle_packet(dev, &ep->packey[dir].p);
+
+    if (ret == USB_RET_ASYNC) {
+        ep->status[dir] = len;
+        return;
+    }
+
+    ep->status[dir] = ret;
+    musb_schedule_cb(&s->port, &ep->packey[dir].p);
+}
+
+static void musb_tx_packet_complete(USBPacket *packey, void *opaque)
+{
+    /* Unfortunately we can't use packey->devep because that's the remote
+     * endpoint number and may be different than our local.  */
+    MUSBEndPoint *ep = (MUSBEndPoint *) opaque;
+    int epnum = ep->epnum;
+    MUSBState *s = ep->musb;
+
+    ep->fifostart[0] = 0;
+    ep->fifolen[0] = 0;
+#ifdef CLEAR_NAK
+    if (ep->status[0] != USB_RET_NAK) {
+#endif
+        if (epnum)
+            ep->csr[0] &= ~(MGC_M_TXCSR_FIFONOTEMPTY | MGC_M_TXCSR_TXPKTRDY);
+        else
+            ep->csr[0] &= ~MGC_M_CSR0_TXPKTRDY;
+#ifdef CLEAR_NAK
+    }
+#endif
+
+    /* Clear all of the error bits first */
+    if (epnum)
+        ep->csr[0] &= ~(MGC_M_TXCSR_H_ERROR | MGC_M_TXCSR_H_RXSTALL |
+                        MGC_M_TXCSR_H_NAKTIMEOUT);
+    else
+        ep->csr[0] &= ~(MGC_M_CSR0_H_ERROR | MGC_M_CSR0_H_RXSTALL |
+                        MGC_M_CSR0_H_NAKTIMEOUT | MGC_M_CSR0_H_NO_PING);
+
+    if (ep->status[0] == USB_RET_STALL) {
+        /* Command not supported by target! */
+        ep->status[0] = 0;
+
+        if (epnum)
+            ep->csr[0] |= MGC_M_TXCSR_H_RXSTALL;
+        else
+            ep->csr[0] |= MGC_M_CSR0_H_RXSTALL;
+    }
+
+    if (ep->status[0] == USB_RET_NAK) {
+        ep->status[0] = 0;
+
+        /* NAK timeouts are only generated in Bulk transfers and
+         * Data-errors in Isochronous.  */
+        if (ep->interrupt[0]) {
+            return;
+        }
+
+        if (epnum)
+            ep->csr[0] |= MGC_M_TXCSR_H_NAKTIMEOUT;
+        else
+            ep->csr[0] |= MGC_M_CSR0_H_NAKTIMEOUT;
+    }
+
+    if (ep->status[0] < 0) {
+        if (ep->status[0] == USB_RET_BABBLE)
+            musb_intr_set(s, musb_irq_rst_babble, 1);
+
+        /* Pretend we've tried three times already and failed (in
+         * case of USB_TOKEN_SETUP).  */
+        if (epnum)
+            ep->csr[0] |= MGC_M_TXCSR_H_ERROR;
+        else
+            ep->csr[0] |= MGC_M_CSR0_H_ERROR;
+
+        musb_tx_intr_set(s, epnum, 1);
+        return;
+    }
+    /* TODO: check len for over/underruns of an OUT packet?  */
+
+#ifdef SETUPLEN_HACK
+    if (!epnum && ep->packey[0].pid == USB_TOKEN_SETUP)
+        s->setup_len = ep->packey[0].data[6];
+#endif
+
+    /* In DMA mode: if no error, assert DMA request for this EP,
+     * and skip the interrupt.  */
+    musb_tx_intr_set(s, epnum, 1);
+}
+
+static void musb_rx_packet_complete(USBPacket *packey, void *opaque)
+{
+    /* Unfortunately we can't use packey->devep because that's the remote
+     * endpoint number and may be different than our local.  */
+    MUSBEndPoint *ep = (MUSBEndPoint *) opaque;
+    int epnum = ep->epnum;
+    MUSBState *s = ep->musb;
+
+    ep->fifostart[1] = 0;
+    ep->fifolen[1] = 0;
+
+#ifdef CLEAR_NAK
+    if (ep->status[1] != USB_RET_NAK) {
+#endif
+        ep->csr[1] &= ~MGC_M_RXCSR_H_REQPKT;
+        if (!epnum)
+            ep->csr[0] &= ~MGC_M_CSR0_H_REQPKT;
+#ifdef CLEAR_NAK
+    }
+#endif
+
+    /* Clear all of the imaginable error bits first */
+    ep->csr[1] &= ~(MGC_M_RXCSR_H_ERROR | MGC_M_RXCSR_H_RXSTALL |
+                    MGC_M_RXCSR_DATAERROR);
+    if (!epnum)
+        ep->csr[0] &= ~(MGC_M_CSR0_H_ERROR | MGC_M_CSR0_H_RXSTALL |
+                        MGC_M_CSR0_H_NAKTIMEOUT | MGC_M_CSR0_H_NO_PING);
+
+    if (ep->status[1] == USB_RET_STALL) {
+        ep->status[1] = 0;
+        packey->result = 0;
+
+        ep->csr[1] |= MGC_M_RXCSR_H_RXSTALL;
+        if (!epnum)
+            ep->csr[0] |= MGC_M_CSR0_H_RXSTALL;
+    }
+
+    if (ep->status[1] == USB_RET_NAK) {
+        ep->status[1] = 0;
+
+        /* NAK timeouts are only generated in Bulk transfers and
+         * Data-errors in Isochronous.  */
+        if (ep->interrupt[1])
+            return musb_packet(s, ep, epnum, USB_TOKEN_IN,
+                            packey->iov.size, musb_rx_packet_complete, 1);
+
+        ep->csr[1] |= MGC_M_RXCSR_DATAERROR;
+        if (!epnum)
+            ep->csr[0] |= MGC_M_CSR0_H_NAKTIMEOUT;
+    }
+
+    if (ep->status[1] < 0) {
+        if (ep->status[1] == USB_RET_BABBLE) {
+            musb_intr_set(s, musb_irq_rst_babble, 1);
+            return;
+        }
+
+        /* Pretend we've tried three times already and failed (in
+         * case of a control transfer).  */
+        ep->csr[1] |= MGC_M_RXCSR_H_ERROR;
+        if (!epnum)
+            ep->csr[0] |= MGC_M_CSR0_H_ERROR;
+
+        musb_rx_intr_set(s, epnum, 1);
+        return;
+    }
+    /* TODO: check len for over/underruns of an OUT packet?  */
+    /* TODO: perhaps make use of e->ext_size[1] here.  */
+
+    packey->result = ep->status[1];
+
+    if (!(ep->csr[1] & (MGC_M_RXCSR_H_RXSTALL | MGC_M_RXCSR_DATAERROR))) {
+        ep->csr[1] |= MGC_M_RXCSR_FIFOFULL | MGC_M_RXCSR_RXPKTRDY;
+        if (!epnum)
+            ep->csr[0] |= MGC_M_CSR0_RXPKTRDY;
+
+        ep->rxcount = packey->result; /* XXX: MIN(packey->len, ep->maxp[1]); */
+        /* In DMA mode: assert DMA request for this EP */
+    }
+
+    /* Only if DMA has not been asserted */
+    musb_rx_intr_set(s, epnum, 1);
+}
+
+static void musb_async_cancel_device(MUSBState *s, USBDevice *dev)
+{
+    int ep, dir;
+
+    for (ep = 0; ep < 16; ep++) {
+        for (dir = 0; dir < 2; dir++) {
+            if (!usb_packet_is_inflight(&s->ep[ep].packey[dir].p) ||
+                s->ep[ep].packey[dir].p.ep->dev != dev) {
+                continue;
+            }
+            usb_cancel_packet(&s->ep[ep].packey[dir].p);
+            /* status updates needed here? */
+        }
+    }
+}
+
+static void musb_tx_rdy(MUSBState *s, int epnum)
+{
+    MUSBEndPoint *ep = s->ep + epnum;
+    int pid;
+    int total, valid = 0;
+    TRACE("start %d, len %d",  ep->fifostart[0], ep->fifolen[0] );
+    ep->fifostart[0] += ep->fifolen[0];
+    ep->fifolen[0] = 0;
+
+    /* XXX: how's the total size of the packet retrieved exactly in
+     * the generic case?  */
+    total = ep->maxp[0] & 0x3ff;
+
+    if (ep->ext_size[0]) {
+        total = ep->ext_size[0];
+        ep->ext_size[0] = 0;
+        valid = 1;
+    }
+
+    /* If the packet is not fully ready yet, wait for a next segment.  */
+    if (epnum && (ep->fifostart[0]) < total)
+        return;
+
+    if (!valid)
+        total = ep->fifostart[0];
+
+    pid = USB_TOKEN_OUT;
+    if (!epnum && (ep->csr[0] & MGC_M_CSR0_H_SETUPPKT)) {
+        pid = USB_TOKEN_SETUP;
+        if (total != 8) {
+            TRACE("illegal SETUPPKT length of %i bytes", total);
+        }
+        /* Controller should retry SETUP packets three times on errors
+         * but it doesn't make sense for us to do that.  */
+    }
+
+    return musb_packet(s, ep, epnum, pid,
+                    total, musb_tx_packet_complete, 0);
+}
+
+static void musb_rx_req(MUSBState *s, int epnum)
+{
+    MUSBEndPoint *ep = s->ep + epnum;
+    int total;
+
+    /* If we already have a packet, which didn't fit into the
+     * 64 bytes of the FIFO, only move the FIFO start and return. (Obsolete) */
+    if (ep->packey[1].p.pid == USB_TOKEN_IN && ep->status[1] >= 0 &&
+                    (ep->fifostart[1]) + ep->rxcount <
+                    ep->packey[1].p.iov.size) {
+        TRACE("0x%08x, %d",  ep->fifostart[1], ep->rxcount );
+        ep->fifostart[1] += ep->rxcount;
+        ep->fifolen[1] = 0;
+
+        ep->rxcount = MIN(ep->packey[0].p.iov.size - (ep->fifostart[1]),
+                        ep->maxp[1]);
+
+        ep->csr[1] &= ~MGC_M_RXCSR_H_REQPKT;
+        if (!epnum)
+            ep->csr[0] &= ~MGC_M_CSR0_H_REQPKT;
+
+        /* Clear all of the error bits first */
+        ep->csr[1] &= ~(MGC_M_RXCSR_H_ERROR | MGC_M_RXCSR_H_RXSTALL |
+                        MGC_M_RXCSR_DATAERROR);
+        if (!epnum)
+            ep->csr[0] &= ~(MGC_M_CSR0_H_ERROR | MGC_M_CSR0_H_RXSTALL |
+                            MGC_M_CSR0_H_NAKTIMEOUT | MGC_M_CSR0_H_NO_PING);
+
+        ep->csr[1] |= MGC_M_RXCSR_FIFOFULL | MGC_M_RXCSR_RXPKTRDY;
+        if (!epnum)
+            ep->csr[0] |= MGC_M_CSR0_RXPKTRDY;
+        musb_rx_intr_set(s, epnum, 1);
+        return;
+    }
+
+    /* The driver sets maxp[1] to 64 or less because it knows the hardware
+     * FIFO is this deep.  Bigger packets get split in
+     * usb_generic_handle_packet but we can also do the splitting locally
+     * for performance.  It turns out we can also have a bigger FIFO and
+     * ignore the limit set in ep->maxp[1].  The Linux MUSB driver deals
+     * OK with single packets of even 32KB and we avoid splitting, however
+     * usb_msd.c sometimes sends a packet bigger than what Linux expects
+     * (e.g. 8192 bytes instead of 4096) and we get an OVERRUN.  Splitting
+     * hides this overrun from Linux.  Up to 4096 everything is fine
+     * though.  Currently this is disabled.
+     *
+     * XXX: mind ep->fifosize.  */
+    total = MIN(ep->maxp[1] & 0x3ff, sizeof(s->buf));
+
+#ifdef SETUPLEN_HACK
+    /* Why should *we* do that instead of Linux?  */
+    if (!epnum) {
+        if (ep->packey[0].p.devaddr == 2) {
+            total = MIN(s->setup_len, 8);
+        } else {
+            total = MIN(s->setup_len, 64);
+        }
+        s->setup_len -= total;
+    }
+#endif
+
+    return musb_packet(s, ep, epnum, USB_TOKEN_IN,
+                    total, musb_rx_packet_complete, 1);
+}
+
+static uint8_t musb_read_fifo(MUSBEndPoint *ep)
+{
+    uint8_t value;
+    if (ep->fifolen[1] >= 64) {
+        /* We have a FIFO underrun */
+        TRACE("EP%d FIFO is now empty, stop reading", ep->epnum);
+        return 0x00000000;
+    }
+    /* In DMA mode clear RXPKTRDY and set REQPKT automatically
+     * (if AUTOREQ is set) */
+
+    ep->csr[1] &= ~MGC_M_RXCSR_FIFOFULL;
+    value=ep->buf[1][ep->fifostart[1] + ep->fifolen[1] ++];
+    TRACE("EP%d 0x%02x, %d", ep->epnum, value, ep->fifolen[1] );
+    return value;
+}
+
+static void musb_write_fifo(MUSBEndPoint *ep, uint8_t value)
+{
+    TRACE("EP%d = %02x", ep->epnum, value);
+    if (ep->fifolen[0] >= 64) {
+        /* We have a FIFO overrun */
+        TRACE("EP%d FIFO exceeded 64 bytes, stop feeding data", ep->epnum);
+        return;
+     }
+
+     ep->buf[0][ep->fifostart[0] + ep->fifolen[0] ++] = value;
+     ep->csr[0] |= MGC_M_TXCSR_FIFONOTEMPTY;
+}
+
+static void musb_ep_frame_cancel(MUSBEndPoint *ep, int dir)
+{
+    if (ep->intv_timer[dir])
+        qemu_del_timer(ep->intv_timer[dir]);
+}
+
+/* Bus control */
+static uint8_t musb_busctl_readb(void *opaque, int ep, int addr)
+{
+    MUSBState *s = (MUSBState *) opaque;
+
+    switch (addr) {
+    /* For USB2.0 HS hubs only */
+    case MUSB_HDRC_TXHUBADDR:
+        return s->ep[ep].haddr[0];
+    case MUSB_HDRC_TXHUBPORT:
+        return s->ep[ep].hport[0];
+    case MUSB_HDRC_RXHUBADDR:
+        return s->ep[ep].haddr[1];
+    case MUSB_HDRC_RXHUBPORT:
+        return s->ep[ep].hport[1];
+
+    default:
+        TRACE("unknown register 0x%02x", addr);
+        return 0x00;
+    };
+}
+
+static void musb_busctl_writeb(void *opaque, int ep, int addr, uint8_t value)
+{
+    MUSBState *s = (MUSBState *) opaque;
+
+    switch (addr) {
+    case MUSB_HDRC_TXFUNCADDR:
+        s->ep[ep].faddr[0] = value;
+        break;
+    case MUSB_HDRC_RXFUNCADDR:
+        s->ep[ep].faddr[1] = value;
+        break;
+    case MUSB_HDRC_TXHUBADDR:
+        s->ep[ep].haddr[0] = value;
+        break;
+    case MUSB_HDRC_TXHUBPORT:
+        s->ep[ep].hport[0] = value;
+        break;
+    case MUSB_HDRC_RXHUBADDR:
+        s->ep[ep].haddr[1] = value;
+        break;
+    case MUSB_HDRC_RXHUBPORT:
+        s->ep[ep].hport[1] = value;
+        break;
+
+    default:
+        TRACE("unknown register 0x%02x", addr);
+        break;
+    };
+}
+
+static uint16_t musb_busctl_readh(void *opaque, int ep, int addr)
+{
+    MUSBState *s = (MUSBState *) opaque;
+
+    switch (addr) {
+    case MUSB_HDRC_TXFUNCADDR:
+        return s->ep[ep].faddr[0];
+    case MUSB_HDRC_RXFUNCADDR:
+        return s->ep[ep].faddr[1];
+
+    default:
+        return musb_busctl_readb(s, ep, addr) |
+                (musb_busctl_readb(s, ep, addr | 1) << 8);
+    };
+}
+
+static void musb_busctl_writeh(void *opaque, int ep, int addr, uint16_t value)
+{
+    MUSBState *s = (MUSBState *) opaque;
+
+    switch (addr) {
+    case MUSB_HDRC_TXFUNCADDR:
+        s->ep[ep].faddr[0] = value;
+        break;
+    case MUSB_HDRC_RXFUNCADDR:
+        s->ep[ep].faddr[1] = value;
+        break;
+
+    default:
+        musb_busctl_writeb(s, ep, addr, value & 0xff);
+        musb_busctl_writeb(s, ep, addr | 1, value >> 8);
+    };
+}
+
+/* Endpoint control */
+static uint8_t musb_ep_readb(void *opaque, int ep, int addr)
+{
+    MUSBState *s = (MUSBState *) opaque;
+
+    switch (addr) {
+    case MUSB_HDRC_TXTYPE:
+        return s->ep[ep].type[0];
+    case MUSB_HDRC_TXINTERVAL:
+        return s->ep[ep].interval[0];
+    case MUSB_HDRC_RXTYPE:
+        return s->ep[ep].type[1];
+    case MUSB_HDRC_RXINTERVAL:
+        return s->ep[ep].interval[1];
+    case (MUSB_HDRC_FIFOSIZE & ~1):
+        return 0x00;
+    case MUSB_HDRC_FIFOSIZE:
+        return ep ? s->ep[ep].fifosize : s->ep[ep].config;
+    case MUSB_HDRC_RXCOUNT:
+        return s->ep[ep].rxcount;
+
+    default:
+        TRACE("unknown register 0x%02x", addr);
+        return 0x00;
+    };
+}
+
+static void musb_ep_writeb(void *opaque, int ep, int addr, uint8_t value)
+{
+    MUSBState *s = (MUSBState *) opaque;
+
+    switch (addr) {
+    case MUSB_HDRC_TXTYPE:
+        s->ep[ep].type[0] = value;
+        break;
+    case MUSB_HDRC_TXINTERVAL:
+        s->ep[ep].interval[0] = value;
+        musb_ep_frame_cancel(&s->ep[ep], 0);
+        break;
+    case MUSB_HDRC_RXTYPE:
+        s->ep[ep].type[1] = value;
+        break;
+    case MUSB_HDRC_RXINTERVAL:
+        s->ep[ep].interval[1] = value;
+        musb_ep_frame_cancel(&s->ep[ep], 1);
+        break;
+    case (MUSB_HDRC_FIFOSIZE & ~1):
+        break;
+    case MUSB_HDRC_FIFOSIZE:
+        TRACE("somebody messes with fifosize (now %i bytes)", value);
+        s->ep[ep].fifosize = value;
+        break;
+    default:
+        TRACE("unknown register 0x%02x", addr);
+        break;
+    };
+}
+
+static uint16_t musb_ep_readh(void *opaque, int ep, int addr)
+{
+    MUSBState *s = (MUSBState *) opaque;
+    uint16_t ret;
+
+    switch (addr) {
+    case MUSB_HDRC_TXMAXP:
+        return s->ep[ep].maxp[0];
+    case MUSB_HDRC_TXCSR:
+        return s->ep[ep].csr[0];
+    case MUSB_HDRC_RXMAXP:
+        return s->ep[ep].maxp[1];
+    case MUSB_HDRC_RXCSR:
+        ret = s->ep[ep].csr[1];
+
+        /* TODO: This and other bits probably depend on
+         * ep->csr[1] & MGC_M_RXCSR_AUTOCLEAR.  */
+        if (s->ep[ep].csr[1] & MGC_M_RXCSR_AUTOCLEAR)
+            s->ep[ep].csr[1] &= ~MGC_M_RXCSR_RXPKTRDY;
+
+        return ret;
+    case MUSB_HDRC_RXCOUNT:
+        return s->ep[ep].rxcount;
+
+    default:
+        return musb_ep_readb(s, ep, addr) |
+                (musb_ep_readb(s, ep, addr | 1) << 8);
+    };
+}
+
+static void musb_ep_writeh(void *opaque, int ep, int addr, uint16_t value)
+{
+    MUSBState *s = (MUSBState *) opaque;
+
+    switch (addr) {
+    case MUSB_HDRC_TXMAXP:
+        s->ep[ep].maxp[0] = value;
+        break;
+    case MUSB_HDRC_TXCSR:
+        if (ep) {
+            s->ep[ep].csr[0] &= value & 0xa6;
+            s->ep[ep].csr[0] |= value & 0xff59;
+        } else {
+            s->ep[ep].csr[0] &= value & 0x85;
+            s->ep[ep].csr[0] |= value & 0xf7a;
+        }
+
+        musb_ep_frame_cancel(&s->ep[ep], 0);
+
+        if ((ep && (value & MGC_M_TXCSR_FLUSHFIFO)) ||
+                        (!ep && (value & MGC_M_CSR0_FLUSHFIFO))) {
+            s->ep[ep].fifolen[0] = 0;
+            s->ep[ep].fifostart[0] = 0;
+            if (ep)
+                s->ep[ep].csr[0] &=
+                        ~(MGC_M_TXCSR_FIFONOTEMPTY | MGC_M_TXCSR_TXPKTRDY);
+            else
+                s->ep[ep].csr[0] &=
+                        ~(MGC_M_CSR0_TXPKTRDY | MGC_M_CSR0_RXPKTRDY);
+        }
+        if (
+                        (ep &&
+#ifdef CLEAR_NAK
+                         (value & MGC_M_TXCSR_TXPKTRDY) &&
+                         !(value & MGC_M_TXCSR_H_NAKTIMEOUT)) ||
+#else
+                         (value & MGC_M_TXCSR_TXPKTRDY)) ||
+#endif
+                        (!ep &&
+#ifdef CLEAR_NAK
+                         (value & MGC_M_CSR0_TXPKTRDY) &&
+                         !(value & MGC_M_CSR0_H_NAKTIMEOUT)))
+#else
+                         (value & MGC_M_CSR0_TXPKTRDY)))
+#endif
+            musb_tx_rdy(s, ep);
+        if (!ep &&
+                        (value & MGC_M_CSR0_H_REQPKT) &&
+#ifdef CLEAR_NAK
+                        !(value & (MGC_M_CSR0_H_NAKTIMEOUT |
+                                        MGC_M_CSR0_RXPKTRDY)))
+#else
+                        !(value & MGC_M_CSR0_RXPKTRDY))
+#endif
+            musb_rx_req(s, ep);
+        break;
+
+    case MUSB_HDRC_RXMAXP:
+        s->ep[ep].maxp[1] = value;
+        break;
+    case MUSB_HDRC_RXCSR:
+        /* (DMA mode only) */
+        if (
+                (value & MGC_M_RXCSR_H_AUTOREQ) &&
+                !(value & MGC_M_RXCSR_RXPKTRDY) &&
+                (s->ep[ep].csr[1] & MGC_M_RXCSR_RXPKTRDY))
+            value |= MGC_M_RXCSR_H_REQPKT;
+
+        s->ep[ep].csr[1] &= 0x102 | (value & 0x4d);
+        s->ep[ep].csr[1] |= value & 0xfeb0;
+
+        musb_ep_frame_cancel(&s->ep[ep], 1);
+
+        if (value & MGC_M_RXCSR_FLUSHFIFO) {
+            s->ep[ep].fifolen[1] = 0;
+            s->ep[ep].fifostart[1] = 0;
+            s->ep[ep].csr[1] &= ~(MGC_M_RXCSR_FIFOFULL | MGC_M_RXCSR_RXPKTRDY);
+            /* If double buffering and we have two packets ready, flush
+             * only the first one and set up the fifo at the second packet.  */
+        }
+#ifdef CLEAR_NAK
+        if ((value & MGC_M_RXCSR_H_REQPKT) && !(value & MGC_M_RXCSR_DATAERROR))
+#else
+        if (value & MGC_M_RXCSR_H_REQPKT)
+#endif
+            musb_rx_req(s, ep);
+        break;
+    case MUSB_HDRC_RXCOUNT:
+        s->ep[ep].rxcount = value;
+        break;
+
+    default:
+        musb_ep_writeb(s, ep, addr, value & 0xff);
+        musb_ep_writeb(s, ep, addr | 1, value >> 8);
+    };
+}
+
+/* Generic control */
+static uint32_t musb_readb(void *opaque, target_phys_addr_t addr)
+{
+    MUSBState *s = (MUSBState *) opaque;
+    int ep, i;
+    uint8_t ret;
+
+    switch (addr) {
+    case MUSB_HDRC_FADDR:
+        return s->faddr;
+    case MUSB_HDRC_POWER:
+        return s->power;
+    case MUSB_HDRC_INTRUSB:
+        ret = s->intr;
+        for (i = 0; i < sizeof(ret) * 8; i ++)
+            if (ret & (1 << i))
+                musb_intr_set(s, i, 0);
+        return ret;
+    case MUSB_HDRC_INTRUSBE:
+        return s->mask;
+    case MUSB_HDRC_INDEX:
+        return s->idx;
+    case MUSB_HDRC_TESTMODE:
+        return 0x00;
+
+    case MUSB_HDRC_EP_IDX ... (MUSB_HDRC_EP_IDX + 0xf):
+        return musb_ep_readb(s, s->idx, addr & 0xf);
+
+    case MUSB_HDRC_DEVCTL:
+        return s->devctl;
+
+    case MUSB_HDRC_TXFIFOSZ:
+    case MUSB_HDRC_RXFIFOSZ:
+    case MUSB_HDRC_VCTRL:
+        /* TODO */
+        return 0x00;
+
+    case MUSB_HDRC_HWVERS:
+        return (1 << 10) | 400;
+
+    case (MUSB_HDRC_VCTRL | 1):
+    case (MUSB_HDRC_HWVERS | 1):
+    case (MUSB_HDRC_DEVCTL | 1):
+        return 0x00;
+
+    case MUSB_HDRC_BUSCTL ... (MUSB_HDRC_BUSCTL + 0x7f):
+        ep = (addr >> 3) & 0xf;
+        return musb_busctl_readb(s, ep, addr & 0x7);
+
+    case MUSB_HDRC_EP ... (MUSB_HDRC_EP + 0xff):
+        ep = (addr >> 4) & 0xf;
+        return musb_ep_readb(s, ep, addr & 0xf);
+
+    case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
+        ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
+        return musb_read_fifo(s->ep + ep);
+
+    default:
+        TRACE("unknown register 0x%02x", (int) addr);
+        return 0x00;
+    };
+}
+
+static void musb_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    MUSBState *s = (MUSBState *) opaque;
+    int ep;
+
+    switch (addr) {
+    case MUSB_HDRC_FADDR:
+        s->faddr = value & 0x7f;
+        break;
+    case MUSB_HDRC_POWER:
+        s->power = (value & 0xef) | (s->power & 0x10);
+        /* MGC_M_POWER_RESET is also read-only in Peripheral Mode */
+        if ((value & MGC_M_POWER_RESET) && s->port.dev) {
+            usb_device_reset(s->port.dev);
+            /* Negotiate high-speed operation if MGC_M_POWER_HSENAB is set.  */
+            if ((value & MGC_M_POWER_HSENAB) &&
+                            s->port.dev->speed == USB_SPEED_HIGH)
+                s->power |= MGC_M_POWER_HSMODE;	/* Success */
+            /* Restart frame counting.  */
+        }
+        if (value & MGC_M_POWER_SUSPENDM) {
+            /* When all transfers finish, suspend and if MGC_M_POWER_ENSUSPEND
+             * is set, also go into low power mode.  Frame counting stops.  */
+            /* XXX: Cleared when the interrupt register is read */
+        }
+        if (value & MGC_M_POWER_RESUME) {
+            /* Wait 20ms and signal resuming on the bus.  Frame counting
+             * restarts.  */
+        }
+        break;
+    case MUSB_HDRC_INTRUSB:
+        break;
+    case MUSB_HDRC_INTRUSBE:
+        s->mask = value & 0xff;
+        break;
+    case MUSB_HDRC_INDEX:
+        s->idx = value & 0xf;
+        break;
+    case MUSB_HDRC_TESTMODE:
+        break;
+
+    case MUSB_HDRC_EP_IDX ... (MUSB_HDRC_EP_IDX + 0xf):
+        musb_ep_writeb(s, s->idx, addr & 0xf, value);
+        break;
+
+    case MUSB_HDRC_DEVCTL:
+        s->session = !!(value & MGC_M_DEVCTL_SESSION);
+        musb_session_update(s,
+                        !!s->port.dev,
+                        !!(s->devctl & MGC_M_DEVCTL_SESSION));
+
+        /* It seems this is the only R/W bit in this register?  */
+        s->devctl &= ~MGC_M_DEVCTL_SESSION;
+        s->devctl |= value & MGC_M_DEVCTL_SESSION;
+        break;
+
+    case MUSB_HDRC_TXFIFOSZ:
+    case MUSB_HDRC_RXFIFOSZ:
+    case MUSB_HDRC_VCTRL:
+        /* TODO */
+        break;
+
+    case (MUSB_HDRC_VCTRL | 1):
+    case (MUSB_HDRC_DEVCTL | 1):
+        break;
+
+    case MUSB_HDRC_BUSCTL ... (MUSB_HDRC_BUSCTL + 0x7f):
+        ep = (addr >> 3) & 0xf;
+        musb_busctl_writeb(s, ep, addr & 0x7, value);
+        break;
+
+    case MUSB_HDRC_EP ... (MUSB_HDRC_EP + 0xff):
+        ep = (addr >> 4) & 0xf;
+        musb_ep_writeb(s, ep, addr & 0xf, value);
+        break;
+
+    case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
+        ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
+        musb_write_fifo(s->ep + ep, value & 0xff);
+        break;
+
+    default:
+        TRACE("unknown register 0x%02x", (int) addr);
+        break;
+    };
+}
+
+static uint32_t musb_readh(void *opaque, target_phys_addr_t addr)
+{
+    MUSBState *s = (MUSBState *) opaque;
+    int ep, i;
+    uint16_t ret;
+
+    switch (addr) {
+    case MUSB_HDRC_INTRTX:
+        ret = s->tx_intr;
+        /* Auto clear */
+        for (i = 0; i < sizeof(ret) * 8; i ++)
+            if (ret & (1 << i))
+                musb_tx_intr_set(s, i, 0);
+        return ret;
+    case MUSB_HDRC_INTRRX:
+        ret = s->rx_intr;
+        /* Auto clear */
+        for (i = 0; i < sizeof(ret) * 8; i ++)
+            if (ret & (1 << i))
+                musb_rx_intr_set(s, i, 0);
+        return ret;
+    case MUSB_HDRC_INTRTXE:
+        return s->tx_mask;
+    case MUSB_HDRC_INTRRXE:
+        return s->rx_mask;
+
+    case MUSB_HDRC_FRAME:
+        /* TODO */
+        return 0x0000;
+    case MUSB_HDRC_TXFIFOADDR:
+        return s->ep[s->idx].fifoaddr[0];
+    case MUSB_HDRC_RXFIFOADDR:
+        return s->ep[s->idx].fifoaddr[1];
+
+    case MUSB_HDRC_EP_IDX ... (MUSB_HDRC_EP_IDX + 0xf):
+        return musb_ep_readh(s, s->idx, addr & 0xf);
+
+    case MUSB_HDRC_BUSCTL ... (MUSB_HDRC_BUSCTL + 0x7f):
+        ep = (addr >> 3) & 0xf;
+        return musb_busctl_readh(s, ep, addr & 0x7);
+
+    case MUSB_HDRC_EP ... (MUSB_HDRC_EP + 0xff):
+        ep = (addr >> 4) & 0xf;
+        return musb_ep_readh(s, ep, addr & 0xf);
+
+    case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
+        ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
+        return (musb_read_fifo(s->ep + ep) | musb_read_fifo(s->ep + ep) << 8);
+
+    default:
+        return musb_readb(s, addr) | (musb_readb(s, addr | 1) << 8);
+    };
+}
+
+static void musb_writeh(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    MUSBState *s = (MUSBState *) opaque;
+    int ep;
+
+    switch (addr) {
+    case MUSB_HDRC_INTRTXE:
+        s->tx_mask = value;
+        /* XXX: the masks seem to apply on the raising edge like with
+         * edge-triggered interrupts, thus no need to update.  I may be
+         * wrong though.  */
+        break;
+    case MUSB_HDRC_INTRRXE:
+        s->rx_mask = value;
+        break;
+
+    case MUSB_HDRC_FRAME:
+        /* TODO */
+        break;
+    case MUSB_HDRC_TXFIFOADDR:
+        s->ep[s->idx].fifoaddr[0] = value;
+        s->ep[s->idx].buf[0] =
+                s->buf + ((value << 3) & 0x7ff );
+        break;
+    case MUSB_HDRC_RXFIFOADDR:
+        s->ep[s->idx].fifoaddr[1] = value;
+        s->ep[s->idx].buf[1] =
+                s->buf + ((value << 3) & 0x7ff);
+        break;
+
+    case MUSB_HDRC_EP_IDX ... (MUSB_HDRC_EP_IDX + 0xf):
+        musb_ep_writeh(s, s->idx, addr & 0xf, value);
+        break;
+
+    case MUSB_HDRC_BUSCTL ... (MUSB_HDRC_BUSCTL + 0x7f):
+        ep = (addr >> 3) & 0xf;
+        musb_busctl_writeh(s, ep, addr & 0x7, value);
+        break;
+
+    case MUSB_HDRC_EP ... (MUSB_HDRC_EP + 0xff):
+        ep = (addr >> 4) & 0xf;
+        musb_ep_writeh(s, ep, addr & 0xf, value);
+        break;
+
+    case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
+        ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
+        musb_write_fifo(s->ep + ep, value & 0xff);
+        musb_write_fifo(s->ep + ep, (value >> 8) & 0xff);
+        break;
+
+    default:
+        musb_writeb(s, addr, value & 0xff);
+        musb_writeb(s, addr | 1, value >> 8);
+    };
+}
+
+static uint32_t musb_readw(void *opaque, target_phys_addr_t addr)
+{
+    MUSBState *s = (MUSBState *) opaque;
+    int ep;
+
+    switch (addr) {
+    case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
+        ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
+        return ( musb_read_fifo(s->ep + ep)       |
+                 musb_read_fifo(s->ep + ep) << 8  |
+                 musb_read_fifo(s->ep + ep) << 16 |
+                 musb_read_fifo(s->ep + ep) << 24 );
+    default:
+        TRACE("unknown register 0x%02x", (int) addr);
+        return 0x00000000;
+    };
+}
+
+static void musb_writew(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    MUSBState *s = (MUSBState *) opaque;
+    int ep;
+
+    switch (addr) {
+    case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
+        ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
+        musb_write_fifo(s->ep + ep, value & 0xff);
+        musb_write_fifo(s->ep + ep, (value >> 8 ) & 0xff);
+        musb_write_fifo(s->ep + ep, (value >> 16) & 0xff);
+        musb_write_fifo(s->ep + ep, (value >> 24) & 0xff);
+            break;
+    default:
+        TRACE("unknown register 0x%02x", (int) addr);
+        break;
+    };
+}
+
+CPUReadMemoryFunc * const musb_read[] = {
+    musb_readb,
+    musb_readh,
+    musb_readw,
+};
+
+CPUWriteMemoryFunc * const musb_write[] = {
+    musb_writeb,
+    musb_writeh,
+    musb_writew,
+};
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
new file mode 100644
index 0000000..dd79cef
--- /dev/null
+++ b/hw/usb/hcd-ohci.c
@@ -0,0 +1,1898 @@
+/*
+ * QEMU USB OHCI Emulation
+ * Copyright (c) 2004 Gianni Tedesco
+ * Copyright (c) 2006 CodeSourcery
+ * Copyright (c) 2006 Openedhand Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * TODO:
+ *  o Isochronous transfers
+ *  o Allocate bandwidth in frames properly
+ *  o Disable timers when nothing needs to be done, or remove timer usage
+ *    all together.
+ *  o Handle unrecoverable errors properly
+ *  o BIOS work to boot from USB storage
+*/
+
+#include "hw/hw.h"
+#include "qemu-timer.h"
+#include "hw/usb.h"
+#include "hw/pci.h"
+#include "hw/usb-ohci.h"
+#include "hw/sysbus.h"
+#include "hw/qdev-addr.h"
+
+//#define DEBUG_OHCI
+/* Dump packet contents.  */
+//#define DEBUG_PACKET
+//#define DEBUG_ISOCH
+/* This causes frames to occur 1000x slower */
+//#define OHCI_TIME_WARP 1
+
+#ifdef DEBUG_OHCI
+#define DPRINTF printf
+#else
+#define DPRINTF(...)
+#endif
+
+/* Number of Downstream Ports on the root hub.  */
+
+#define OHCI_MAX_PORTS 15
+
+static int64_t usb_frame_time;
+static int64_t usb_bit_time;
+
+typedef struct OHCIPort {
+    USBPort port;
+    uint32_t ctrl;
+} OHCIPort;
+
+typedef struct {
+    USBBus bus;
+    qemu_irq irq;
+    MemoryRegion mem;
+    int num_ports;
+    const char *name;
+
+    QEMUTimer *eof_timer;
+    int64_t sof_time;
+
+    /* OHCI state */
+    /* Control partition */
+    uint32_t ctl, status;
+    uint32_t intr_status;
+    uint32_t intr;
+
+    /* memory pointer partition */
+    uint32_t hcca;
+    uint32_t ctrl_head, ctrl_cur;
+    uint32_t bulk_head, bulk_cur;
+    uint32_t per_cur;
+    uint32_t done;
+    int done_count;
+
+    /* Frame counter partition */
+    uint32_t fsmps:15;
+    uint32_t fit:1;
+    uint32_t fi:14;
+    uint32_t frt:1;
+    uint16_t frame_number;
+    uint16_t padding;
+    uint32_t pstart;
+    uint32_t lst;
+
+    /* Root Hub partition */
+    uint32_t rhdesc_a, rhdesc_b;
+    uint32_t rhstatus;
+    OHCIPort rhport[OHCI_MAX_PORTS];
+
+    /* PXA27x Non-OHCI events */
+    uint32_t hstatus;
+    uint32_t hmask;
+    uint32_t hreset;
+    uint32_t htest;
+
+    /* SM501 local memory offset */
+    target_phys_addr_t localmem_base;
+
+    /* Active packets.  */
+    uint32_t old_ctl;
+    USBPacket usb_packet;
+    uint8_t usb_buf[8192];
+    uint32_t async_td;
+    int async_complete;
+
+} OHCIState;
+
+/* Host Controller Communications Area */
+struct ohci_hcca {
+    uint32_t intr[32];
+    uint16_t frame, pad;
+    uint32_t done;
+};
+
+static void ohci_bus_stop(OHCIState *ohci);
+static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev);
+
+/* Bitfields for the first word of an Endpoint Desciptor.  */
+#define OHCI_ED_FA_SHIFT  0
+#define OHCI_ED_FA_MASK   (0x7f<<OHCI_ED_FA_SHIFT)
+#define OHCI_ED_EN_SHIFT  7
+#define OHCI_ED_EN_MASK   (0xf<<OHCI_ED_EN_SHIFT)
+#define OHCI_ED_D_SHIFT   11
+#define OHCI_ED_D_MASK    (3<<OHCI_ED_D_SHIFT)
+#define OHCI_ED_S         (1<<13)
+#define OHCI_ED_K         (1<<14)
+#define OHCI_ED_F         (1<<15)
+#define OHCI_ED_MPS_SHIFT 16
+#define OHCI_ED_MPS_MASK  (0x7ff<<OHCI_ED_MPS_SHIFT)
+
+/* Flags in the head field of an Endpoint Desciptor.  */
+#define OHCI_ED_H         1
+#define OHCI_ED_C         2
+
+/* Bitfields for the first word of a Transfer Desciptor.  */
+#define OHCI_TD_R         (1<<18)
+#define OHCI_TD_DP_SHIFT  19
+#define OHCI_TD_DP_MASK   (3<<OHCI_TD_DP_SHIFT)
+#define OHCI_TD_DI_SHIFT  21
+#define OHCI_TD_DI_MASK   (7<<OHCI_TD_DI_SHIFT)
+#define OHCI_TD_T0        (1<<24)
+#define OHCI_TD_T1        (1<<25)
+#define OHCI_TD_EC_SHIFT  26
+#define OHCI_TD_EC_MASK   (3<<OHCI_TD_EC_SHIFT)
+#define OHCI_TD_CC_SHIFT  28
+#define OHCI_TD_CC_MASK   (0xf<<OHCI_TD_CC_SHIFT)
+
+/* Bitfields for the first word of an Isochronous Transfer Desciptor.  */
+/* CC & DI - same as in the General Transfer Desciptor */
+#define OHCI_TD_SF_SHIFT  0
+#define OHCI_TD_SF_MASK   (0xffff<<OHCI_TD_SF_SHIFT)
+#define OHCI_TD_FC_SHIFT  24
+#define OHCI_TD_FC_MASK   (7<<OHCI_TD_FC_SHIFT)
+
+/* Isochronous Transfer Desciptor - Offset / PacketStatusWord */
+#define OHCI_TD_PSW_CC_SHIFT 12
+#define OHCI_TD_PSW_CC_MASK  (0xf<<OHCI_TD_PSW_CC_SHIFT)
+#define OHCI_TD_PSW_SIZE_SHIFT 0
+#define OHCI_TD_PSW_SIZE_MASK  (0xfff<<OHCI_TD_PSW_SIZE_SHIFT)
+
+#define OHCI_PAGE_MASK    0xfffff000
+#define OHCI_OFFSET_MASK  0xfff
+
+#define OHCI_DPTR_MASK    0xfffffff0
+
+#define OHCI_BM(val, field) \
+  (((val) & OHCI_##field##_MASK) >> OHCI_##field##_SHIFT)
+
+#define OHCI_SET_BM(val, field, newval) do { \
+    val &= ~OHCI_##field##_MASK; \
+    val |= ((newval) << OHCI_##field##_SHIFT) & OHCI_##field##_MASK; \
+    } while(0)
+
+/* endpoint descriptor */
+struct ohci_ed {
+    uint32_t flags;
+    uint32_t tail;
+    uint32_t head;
+    uint32_t next;
+};
+
+/* General transfer descriptor */
+struct ohci_td {
+    uint32_t flags;
+    uint32_t cbp;
+    uint32_t next;
+    uint32_t be;
+};
+
+/* Isochronous transfer descriptor */
+struct ohci_iso_td {
+    uint32_t flags;
+    uint32_t bp;
+    uint32_t next;
+    uint32_t be;
+    uint16_t offset[8];
+};
+
+#define USB_HZ                      12000000
+
+/* OHCI Local stuff */
+#define OHCI_CTL_CBSR         ((1<<0)|(1<<1))
+#define OHCI_CTL_PLE          (1<<2)
+#define OHCI_CTL_IE           (1<<3)
+#define OHCI_CTL_CLE          (1<<4)
+#define OHCI_CTL_BLE          (1<<5)
+#define OHCI_CTL_HCFS         ((1<<6)|(1<<7))
+#define  OHCI_USB_RESET       0x00
+#define  OHCI_USB_RESUME      0x40
+#define  OHCI_USB_OPERATIONAL 0x80
+#define  OHCI_USB_SUSPEND     0xc0
+#define OHCI_CTL_IR           (1<<8)
+#define OHCI_CTL_RWC          (1<<9)
+#define OHCI_CTL_RWE          (1<<10)
+
+#define OHCI_STATUS_HCR       (1<<0)
+#define OHCI_STATUS_CLF       (1<<1)
+#define OHCI_STATUS_BLF       (1<<2)
+#define OHCI_STATUS_OCR       (1<<3)
+#define OHCI_STATUS_SOC       ((1<<6)|(1<<7))
+
+#define OHCI_INTR_SO          (1<<0) /* Scheduling overrun */
+#define OHCI_INTR_WD          (1<<1) /* HcDoneHead writeback */
+#define OHCI_INTR_SF          (1<<2) /* Start of frame */
+#define OHCI_INTR_RD          (1<<3) /* Resume detect */
+#define OHCI_INTR_UE          (1<<4) /* Unrecoverable error */
+#define OHCI_INTR_FNO         (1<<5) /* Frame number overflow */
+#define OHCI_INTR_RHSC        (1<<6) /* Root hub status change */
+#define OHCI_INTR_OC          (1<<30) /* Ownership change */
+#define OHCI_INTR_MIE         (1<<31) /* Master Interrupt Enable */
+
+#define OHCI_HCCA_SIZE        0x100
+#define OHCI_HCCA_MASK        0xffffff00
+
+#define OHCI_EDPTR_MASK       0xfffffff0
+
+#define OHCI_FMI_FI           0x00003fff
+#define OHCI_FMI_FSMPS        0xffff0000
+#define OHCI_FMI_FIT          0x80000000
+
+#define OHCI_FR_RT            (1<<31)
+
+#define OHCI_LS_THRESH        0x628
+
+#define OHCI_RHA_RW_MASK      0x00000000 /* Mask of supported features.  */
+#define OHCI_RHA_PSM          (1<<8)
+#define OHCI_RHA_NPS          (1<<9)
+#define OHCI_RHA_DT           (1<<10)
+#define OHCI_RHA_OCPM         (1<<11)
+#define OHCI_RHA_NOCP         (1<<12)
+#define OHCI_RHA_POTPGT_MASK  0xff000000
+
+#define OHCI_RHS_LPS          (1<<0)
+#define OHCI_RHS_OCI          (1<<1)
+#define OHCI_RHS_DRWE         (1<<15)
+#define OHCI_RHS_LPSC         (1<<16)
+#define OHCI_RHS_OCIC         (1<<17)
+#define OHCI_RHS_CRWE         (1<<31)
+
+#define OHCI_PORT_CCS         (1<<0)
+#define OHCI_PORT_PES         (1<<1)
+#define OHCI_PORT_PSS         (1<<2)
+#define OHCI_PORT_POCI        (1<<3)
+#define OHCI_PORT_PRS         (1<<4)
+#define OHCI_PORT_PPS         (1<<8)
+#define OHCI_PORT_LSDA        (1<<9)
+#define OHCI_PORT_CSC         (1<<16)
+#define OHCI_PORT_PESC        (1<<17)
+#define OHCI_PORT_PSSC        (1<<18)
+#define OHCI_PORT_OCIC        (1<<19)
+#define OHCI_PORT_PRSC        (1<<20)
+#define OHCI_PORT_WTC         (OHCI_PORT_CSC|OHCI_PORT_PESC|OHCI_PORT_PSSC \
+                               |OHCI_PORT_OCIC|OHCI_PORT_PRSC)
+
+#define OHCI_TD_DIR_SETUP     0x0
+#define OHCI_TD_DIR_OUT       0x1
+#define OHCI_TD_DIR_IN        0x2
+#define OHCI_TD_DIR_RESERVED  0x3
+
+#define OHCI_CC_NOERROR             0x0
+#define OHCI_CC_CRC                 0x1
+#define OHCI_CC_BITSTUFFING         0x2
+#define OHCI_CC_DATATOGGLEMISMATCH  0x3
+#define OHCI_CC_STALL               0x4
+#define OHCI_CC_DEVICENOTRESPONDING 0x5
+#define OHCI_CC_PIDCHECKFAILURE     0x6
+#define OHCI_CC_UNDEXPETEDPID       0x7
+#define OHCI_CC_DATAOVERRUN         0x8
+#define OHCI_CC_DATAUNDERRUN        0x9
+#define OHCI_CC_BUFFEROVERRUN       0xc
+#define OHCI_CC_BUFFERUNDERRUN      0xd
+
+#define OHCI_HRESET_FSBIR       (1 << 0)
+
+/* Update IRQ levels */
+static inline void ohci_intr_update(OHCIState *ohci)
+{
+    int level = 0;
+
+    if ((ohci->intr & OHCI_INTR_MIE) &&
+        (ohci->intr_status & ohci->intr))
+        level = 1;
+
+    qemu_set_irq(ohci->irq, level);
+}
+
+/* Set an interrupt */
+static inline void ohci_set_interrupt(OHCIState *ohci, uint32_t intr)
+{
+    ohci->intr_status |= intr;
+    ohci_intr_update(ohci);
+}
+
+/* Attach or detach a device on a root hub port.  */
+static void ohci_attach(USBPort *port1)
+{
+    OHCIState *s = port1->opaque;
+    OHCIPort *port = &s->rhport[port1->index];
+    uint32_t old_state = port->ctrl;
+
+    /* set connect status */
+    port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
+
+    /* update speed */
+    if (port->port.dev->speed == USB_SPEED_LOW) {
+        port->ctrl |= OHCI_PORT_LSDA;
+    } else {
+        port->ctrl &= ~OHCI_PORT_LSDA;
+    }
+
+    /* notify of remote-wakeup */
+    if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
+        ohci_set_interrupt(s, OHCI_INTR_RD);
+    }
+
+    DPRINTF("usb-ohci: Attached port %d\n", port1->index);
+
+    if (old_state != port->ctrl) {
+        ohci_set_interrupt(s, OHCI_INTR_RHSC);
+    }
+}
+
+static void ohci_detach(USBPort *port1)
+{
+    OHCIState *s = port1->opaque;
+    OHCIPort *port = &s->rhport[port1->index];
+    uint32_t old_state = port->ctrl;
+
+    ohci_async_cancel_device(s, port1->dev);
+
+    /* set connect status */
+    if (port->ctrl & OHCI_PORT_CCS) {
+        port->ctrl &= ~OHCI_PORT_CCS;
+        port->ctrl |= OHCI_PORT_CSC;
+    }
+    /* disable port */
+    if (port->ctrl & OHCI_PORT_PES) {
+        port->ctrl &= ~OHCI_PORT_PES;
+        port->ctrl |= OHCI_PORT_PESC;
+    }
+    DPRINTF("usb-ohci: Detached port %d\n", port1->index);
+
+    if (old_state != port->ctrl) {
+        ohci_set_interrupt(s, OHCI_INTR_RHSC);
+    }
+}
+
+static void ohci_wakeup(USBPort *port1)
+{
+    OHCIState *s = port1->opaque;
+    OHCIPort *port = &s->rhport[port1->index];
+    uint32_t intr = 0;
+    if (port->ctrl & OHCI_PORT_PSS) {
+        DPRINTF("usb-ohci: port %d: wakeup\n", port1->index);
+        port->ctrl |= OHCI_PORT_PSSC;
+        port->ctrl &= ~OHCI_PORT_PSS;
+        intr = OHCI_INTR_RHSC;
+    }
+    /* Note that the controller can be suspended even if this port is not */
+    if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
+        DPRINTF("usb-ohci: remote-wakeup: SUSPEND->RESUME\n");
+        /* This is the one state transition the controller can do by itself */
+        s->ctl &= ~OHCI_CTL_HCFS;
+        s->ctl |= OHCI_USB_RESUME;
+        /* In suspend mode only ResumeDetected is possible, not RHSC:
+         * see the OHCI spec 5.1.2.3.
+         */
+        intr = OHCI_INTR_RD;
+    }
+    ohci_set_interrupt(s, intr);
+}
+
+static void ohci_child_detach(USBPort *port1, USBDevice *child)
+{
+    OHCIState *s = port1->opaque;
+
+    ohci_async_cancel_device(s, child);
+}
+
+static USBDevice *ohci_find_device(OHCIState *ohci, uint8_t addr)
+{
+    USBDevice *dev;
+    int i;
+
+    for (i = 0; i < ohci->num_ports; i++) {
+        if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0) {
+            continue;
+        }
+        dev = usb_find_device(&ohci->rhport[i].port, addr);
+        if (dev != NULL) {
+            return dev;
+        }
+    }
+    return NULL;
+}
+
+/* Reset the controller */
+static void ohci_reset(void *opaque)
+{
+    OHCIState *ohci = opaque;
+    OHCIPort *port;
+    int i;
+
+    ohci_bus_stop(ohci);
+    ohci->ctl = 0;
+    ohci->old_ctl = 0;
+    ohci->status = 0;
+    ohci->intr_status = 0;
+    ohci->intr = OHCI_INTR_MIE;
+
+    ohci->hcca = 0;
+    ohci->ctrl_head = ohci->ctrl_cur = 0;
+    ohci->bulk_head = ohci->bulk_cur = 0;
+    ohci->per_cur = 0;
+    ohci->done = 0;
+    ohci->done_count = 7;
+
+    /* FSMPS is marked TBD in OCHI 1.0, what gives ffs?
+     * I took the value linux sets ...
+     */
+    ohci->fsmps = 0x2778;
+    ohci->fi = 0x2edf;
+    ohci->fit = 0;
+    ohci->frt = 0;
+    ohci->frame_number = 0;
+    ohci->pstart = 0;
+    ohci->lst = OHCI_LS_THRESH;
+
+    ohci->rhdesc_a = OHCI_RHA_NPS | ohci->num_ports;
+    ohci->rhdesc_b = 0x0; /* Impl. specific */
+    ohci->rhstatus = 0;
+
+    for (i = 0; i < ohci->num_ports; i++)
+      {
+        port = &ohci->rhport[i];
+        port->ctrl = 0;
+        if (port->port.dev && port->port.dev->attached) {
+            usb_port_reset(&port->port);
+        }
+      }
+    if (ohci->async_td) {
+        usb_cancel_packet(&ohci->usb_packet);
+        ohci->async_td = 0;
+    }
+    DPRINTF("usb-ohci: Reset %s\n", ohci->name);
+}
+
+/* Get an array of dwords from main memory */
+static inline int get_dwords(OHCIState *ohci,
+                             uint32_t addr, uint32_t *buf, int num)
+{
+    int i;
+
+    addr += ohci->localmem_base;
+
+    for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
+        cpu_physical_memory_read(addr, buf, sizeof(*buf));
+        *buf = le32_to_cpu(*buf);
+    }
+
+    return 1;
+}
+
+/* Put an array of dwords in to main memory */
+static inline int put_dwords(OHCIState *ohci,
+                             uint32_t addr, uint32_t *buf, int num)
+{
+    int i;
+
+    addr += ohci->localmem_base;
+
+    for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
+        uint32_t tmp = cpu_to_le32(*buf);
+        cpu_physical_memory_write(addr, &tmp, sizeof(tmp));
+    }
+
+    return 1;
+}
+
+/* Get an array of words from main memory */
+static inline int get_words(OHCIState *ohci,
+                            uint32_t addr, uint16_t *buf, int num)
+{
+    int i;
+
+    addr += ohci->localmem_base;
+
+    for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
+        cpu_physical_memory_read(addr, buf, sizeof(*buf));
+        *buf = le16_to_cpu(*buf);
+    }
+
+    return 1;
+}
+
+/* Put an array of words in to main memory */
+static inline int put_words(OHCIState *ohci,
+                            uint32_t addr, uint16_t *buf, int num)
+{
+    int i;
+
+    addr += ohci->localmem_base;
+
+    for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
+        uint16_t tmp = cpu_to_le16(*buf);
+        cpu_physical_memory_write(addr, &tmp, sizeof(tmp));
+    }
+
+    return 1;
+}
+
+static inline int ohci_read_ed(OHCIState *ohci,
+                               uint32_t addr, struct ohci_ed *ed)
+{
+    return get_dwords(ohci, addr, (uint32_t *)ed, sizeof(*ed) >> 2);
+}
+
+static inline int ohci_read_td(OHCIState *ohci,
+                               uint32_t addr, struct ohci_td *td)
+{
+    return get_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2);
+}
+
+static inline int ohci_read_iso_td(OHCIState *ohci,
+                                   uint32_t addr, struct ohci_iso_td *td)
+{
+    return (get_dwords(ohci, addr, (uint32_t *)td, 4) &&
+            get_words(ohci, addr + 16, td->offset, 8));
+}
+
+static inline int ohci_read_hcca(OHCIState *ohci,
+                                 uint32_t addr, struct ohci_hcca *hcca)
+{
+    cpu_physical_memory_read(addr + ohci->localmem_base, hcca, sizeof(*hcca));
+    return 1;
+}
+
+static inline int ohci_put_ed(OHCIState *ohci,
+                              uint32_t addr, struct ohci_ed *ed)
+{
+    return put_dwords(ohci, addr, (uint32_t *)ed, sizeof(*ed) >> 2);
+}
+
+static inline int ohci_put_td(OHCIState *ohci,
+                              uint32_t addr, struct ohci_td *td)
+{
+    return put_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2);
+}
+
+static inline int ohci_put_iso_td(OHCIState *ohci,
+                                  uint32_t addr, struct ohci_iso_td *td)
+{
+    return (put_dwords(ohci, addr, (uint32_t *)td, 4) &&
+            put_words(ohci, addr + 16, td->offset, 8));
+}
+
+static inline int ohci_put_hcca(OHCIState *ohci,
+                                uint32_t addr, struct ohci_hcca *hcca)
+{
+    cpu_physical_memory_write(addr + ohci->localmem_base, hcca, sizeof(*hcca));
+    return 1;
+}
+
+/* Read/Write the contents of a TD from/to main memory.  */
+static void ohci_copy_td(OHCIState *ohci, struct ohci_td *td,
+                         uint8_t *buf, int len, int write)
+{
+    uint32_t ptr;
+    uint32_t n;
+
+    ptr = td->cbp;
+    n = 0x1000 - (ptr & 0xfff);
+    if (n > len)
+        n = len;
+    cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, n, write);
+    if (n == len)
+        return;
+    ptr = td->be & ~0xfffu;
+    buf += n;
+    cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, len - n, write);
+}
+
+/* Read/Write the contents of an ISO TD from/to main memory.  */
+static void ohci_copy_iso_td(OHCIState *ohci,
+                             uint32_t start_addr, uint32_t end_addr,
+                             uint8_t *buf, int len, int write)
+{
+    uint32_t ptr;
+    uint32_t n;
+
+    ptr = start_addr;
+    n = 0x1000 - (ptr & 0xfff);
+    if (n > len)
+        n = len;
+    cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, n, write);
+    if (n == len)
+        return;
+    ptr = end_addr & ~0xfffu;
+    buf += n;
+    cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, len - n, write);
+}
+
+static void ohci_process_lists(OHCIState *ohci, int completion);
+
+static void ohci_async_complete_packet(USBPort *port, USBPacket *packet)
+{
+    OHCIState *ohci = container_of(packet, OHCIState, usb_packet);
+#ifdef DEBUG_PACKET
+    DPRINTF("Async packet complete\n");
+#endif
+    ohci->async_complete = 1;
+    ohci_process_lists(ohci, 1);
+}
+
+#define USUB(a, b) ((int16_t)((uint16_t)(a) - (uint16_t)(b)))
+
+static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
+                               int completion)
+{
+    int dir;
+    size_t len = 0;
+#ifdef DEBUG_ISOCH
+    const char *str = NULL;
+#endif
+    int pid;
+    int ret;
+    int i;
+    USBDevice *dev;
+    USBEndpoint *ep;
+    struct ohci_iso_td iso_td;
+    uint32_t addr;
+    uint16_t starting_frame;
+    int16_t relative_frame_number;
+    int frame_count;
+    uint32_t start_offset, next_offset, end_offset = 0;
+    uint32_t start_addr, end_addr;
+
+    addr = ed->head & OHCI_DPTR_MASK;
+
+    if (!ohci_read_iso_td(ohci, addr, &iso_td)) {
+        printf("usb-ohci: ISO_TD read error at %x\n", addr);
+        return 0;
+    }
+
+    starting_frame = OHCI_BM(iso_td.flags, TD_SF);
+    frame_count = OHCI_BM(iso_td.flags, TD_FC);
+    relative_frame_number = USUB(ohci->frame_number, starting_frame); 
+
+#ifdef DEBUG_ISOCH
+    printf("--- ISO_TD ED head 0x%.8x tailp 0x%.8x\n"
+           "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n"
+           "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n"
+           "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n"
+           "frame_number 0x%.8x starting_frame 0x%.8x\n"
+           "frame_count  0x%.8x relative %d\n"
+           "di 0x%.8x cc 0x%.8x\n",
+           ed->head & OHCI_DPTR_MASK, ed->tail & OHCI_DPTR_MASK,
+           iso_td.flags, iso_td.bp, iso_td.next, iso_td.be,
+           iso_td.offset[0], iso_td.offset[1], iso_td.offset[2], iso_td.offset[3],
+           iso_td.offset[4], iso_td.offset[5], iso_td.offset[6], iso_td.offset[7],
+           ohci->frame_number, starting_frame, 
+           frame_count, relative_frame_number,         
+           OHCI_BM(iso_td.flags, TD_DI), OHCI_BM(iso_td.flags, TD_CC));
+#endif
+
+    if (relative_frame_number < 0) {
+        DPRINTF("usb-ohci: ISO_TD R=%d < 0\n", relative_frame_number);
+        return 1;
+    } else if (relative_frame_number > frame_count) {
+        /* ISO TD expired - retire the TD to the Done Queue and continue with
+           the next ISO TD of the same ED */
+        DPRINTF("usb-ohci: ISO_TD R=%d > FC=%d\n", relative_frame_number, 
+               frame_count);
+        OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_DATAOVERRUN);
+        ed->head &= ~OHCI_DPTR_MASK;
+        ed->head |= (iso_td.next & OHCI_DPTR_MASK);
+        iso_td.next = ohci->done;
+        ohci->done = addr;
+        i = OHCI_BM(iso_td.flags, TD_DI);
+        if (i < ohci->done_count)
+            ohci->done_count = i;
+        ohci_put_iso_td(ohci, addr, &iso_td);
+        return 0;
+    }
+
+    dir = OHCI_BM(ed->flags, ED_D);
+    switch (dir) {
+    case OHCI_TD_DIR_IN:
+#ifdef DEBUG_ISOCH
+        str = "in";
+#endif
+        pid = USB_TOKEN_IN;
+        break;
+    case OHCI_TD_DIR_OUT:
+#ifdef DEBUG_ISOCH
+        str = "out";
+#endif
+        pid = USB_TOKEN_OUT;
+        break;
+    case OHCI_TD_DIR_SETUP:
+#ifdef DEBUG_ISOCH
+        str = "setup";
+#endif
+        pid = USB_TOKEN_SETUP;
+        break;
+    default:
+        printf("usb-ohci: Bad direction %d\n", dir);
+        return 1;
+    }
+
+    if (!iso_td.bp || !iso_td.be) {
+        printf("usb-ohci: ISO_TD bp 0x%.8x be 0x%.8x\n", iso_td.bp, iso_td.be);
+        return 1;
+    }
+
+    start_offset = iso_td.offset[relative_frame_number];
+    next_offset = iso_td.offset[relative_frame_number + 1];
+
+    if (!(OHCI_BM(start_offset, TD_PSW_CC) & 0xe) || 
+        ((relative_frame_number < frame_count) && 
+         !(OHCI_BM(next_offset, TD_PSW_CC) & 0xe))) {
+        printf("usb-ohci: ISO_TD cc != not accessed 0x%.8x 0x%.8x\n",
+               start_offset, next_offset);
+        return 1;
+    }
+
+    if ((relative_frame_number < frame_count) && (start_offset > next_offset)) {
+        printf("usb-ohci: ISO_TD start_offset=0x%.8x > next_offset=0x%.8x\n",
+                start_offset, next_offset);
+        return 1;
+    }
+
+    if ((start_offset & 0x1000) == 0) {
+        start_addr = (iso_td.bp & OHCI_PAGE_MASK) |
+            (start_offset & OHCI_OFFSET_MASK);
+    } else {
+        start_addr = (iso_td.be & OHCI_PAGE_MASK) |
+            (start_offset & OHCI_OFFSET_MASK);
+    }
+
+    if (relative_frame_number < frame_count) {
+        end_offset = next_offset - 1;
+        if ((end_offset & 0x1000) == 0) {
+            end_addr = (iso_td.bp & OHCI_PAGE_MASK) |
+                (end_offset & OHCI_OFFSET_MASK);
+        } else {
+            end_addr = (iso_td.be & OHCI_PAGE_MASK) |
+                (end_offset & OHCI_OFFSET_MASK);
+        }
+    } else {
+        /* Last packet in the ISO TD */
+        end_addr = iso_td.be;
+    }
+
+    if ((start_addr & OHCI_PAGE_MASK) != (end_addr & OHCI_PAGE_MASK)) {
+        len = (end_addr & OHCI_OFFSET_MASK) + 0x1001
+            - (start_addr & OHCI_OFFSET_MASK);
+    } else {
+        len = end_addr - start_addr + 1;
+    }
+
+    if (len && dir != OHCI_TD_DIR_IN) {
+        ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, len, 0);
+    }
+
+    if (completion) {
+        ret = ohci->usb_packet.result;
+    } else {
+        dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
+        ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
+        usb_packet_setup(&ohci->usb_packet, pid, ep);
+        usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
+        ret = usb_handle_packet(dev, &ohci->usb_packet);
+        if (ret == USB_RET_ASYNC) {
+            return 1;
+        }
+    }
+
+#ifdef DEBUG_ISOCH
+    printf("so 0x%.8x eo 0x%.8x\nsa 0x%.8x ea 0x%.8x\ndir %s len %zu ret %d\n",
+           start_offset, end_offset, start_addr, end_addr, str, len, ret);
+#endif
+
+    /* Writeback */
+    if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) {
+        /* IN transfer succeeded */
+        ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, ret, 1);
+        OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
+                    OHCI_CC_NOERROR);
+        OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ret);
+    } else if (dir == OHCI_TD_DIR_OUT && ret == len) {
+        /* OUT transfer succeeded */
+        OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
+                    OHCI_CC_NOERROR);
+        OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 0);
+    } else {
+        if (ret > (ssize_t) len) {
+            printf("usb-ohci: DataOverrun %d > %zu\n", ret, len);
+            OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
+                        OHCI_CC_DATAOVERRUN);
+            OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
+                        len);
+        } else if (ret >= 0) {
+            printf("usb-ohci: DataUnderrun %d\n", ret);
+            OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
+                        OHCI_CC_DATAUNDERRUN);
+        } else {
+            switch (ret) {
+            case USB_RET_IOERROR:
+            case USB_RET_NODEV:
+                OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
+                            OHCI_CC_DEVICENOTRESPONDING);
+                OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
+                            0);
+                break;
+            case USB_RET_NAK:
+            case USB_RET_STALL:
+                printf("usb-ohci: got NAK/STALL %d\n", ret);
+                OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
+                            OHCI_CC_STALL);
+                OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
+                            0);
+                break;
+            default:
+                printf("usb-ohci: Bad device response %d\n", ret);
+                OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
+                            OHCI_CC_UNDEXPETEDPID);
+                break;
+            }
+        }
+    }
+
+    if (relative_frame_number == frame_count) {
+        /* Last data packet of ISO TD - retire the TD to the Done Queue */
+        OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_NOERROR);
+        ed->head &= ~OHCI_DPTR_MASK;
+        ed->head |= (iso_td.next & OHCI_DPTR_MASK);
+        iso_td.next = ohci->done;
+        ohci->done = addr;
+        i = OHCI_BM(iso_td.flags, TD_DI);
+        if (i < ohci->done_count)
+            ohci->done_count = i;
+    }
+    ohci_put_iso_td(ohci, addr, &iso_td);
+    return 1;
+}
+
+/* Service a transport descriptor.
+   Returns nonzero to terminate processing of this endpoint.  */
+
+static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
+{
+    int dir;
+    size_t len = 0, pktlen = 0;
+#ifdef DEBUG_PACKET
+    const char *str = NULL;
+#endif
+    int pid;
+    int ret;
+    int i;
+    USBDevice *dev;
+    USBEndpoint *ep;
+    struct ohci_td td;
+    uint32_t addr;
+    int flag_r;
+    int completion;
+
+    addr = ed->head & OHCI_DPTR_MASK;
+    /* See if this TD has already been submitted to the device.  */
+    completion = (addr == ohci->async_td);
+    if (completion && !ohci->async_complete) {
+#ifdef DEBUG_PACKET
+        DPRINTF("Skipping async TD\n");
+#endif
+        return 1;
+    }
+    if (!ohci_read_td(ohci, addr, &td)) {
+        fprintf(stderr, "usb-ohci: TD read error at %x\n", addr);
+        return 0;
+    }
+
+    dir = OHCI_BM(ed->flags, ED_D);
+    switch (dir) {
+    case OHCI_TD_DIR_OUT:
+    case OHCI_TD_DIR_IN:
+        /* Same value.  */
+        break;
+    default:
+        dir = OHCI_BM(td.flags, TD_DP);
+        break;
+    }
+
+    switch (dir) {
+    case OHCI_TD_DIR_IN:
+#ifdef DEBUG_PACKET
+        str = "in";
+#endif
+        pid = USB_TOKEN_IN;
+        break;
+    case OHCI_TD_DIR_OUT:
+#ifdef DEBUG_PACKET
+        str = "out";
+#endif
+        pid = USB_TOKEN_OUT;
+        break;
+    case OHCI_TD_DIR_SETUP:
+#ifdef DEBUG_PACKET
+        str = "setup";
+#endif
+        pid = USB_TOKEN_SETUP;
+        break;
+    default:
+        fprintf(stderr, "usb-ohci: Bad direction\n");
+        return 1;
+    }
+    if (td.cbp && td.be) {
+        if ((td.cbp & 0xfffff000) != (td.be & 0xfffff000)) {
+            len = (td.be & 0xfff) + 0x1001 - (td.cbp & 0xfff);
+        } else {
+            len = (td.be - td.cbp) + 1;
+        }
+
+        pktlen = len;
+        if (len && dir != OHCI_TD_DIR_IN) {
+            /* The endpoint may not allow us to transfer it all now */
+            pktlen = (ed->flags & OHCI_ED_MPS_MASK) >> OHCI_ED_MPS_SHIFT;
+            if (pktlen > len) {
+                pktlen = len;
+            }
+            if (!completion) {
+                ohci_copy_td(ohci, &td, ohci->usb_buf, pktlen, 0);
+            }
+        }
+    }
+
+    flag_r = (td.flags & OHCI_TD_R) != 0;
+#ifdef DEBUG_PACKET
+    DPRINTF(" TD @ 0x%.8x %" PRId64 " of %" PRId64
+            " bytes %s r=%d cbp=0x%.8x be=0x%.8x\n",
+            addr, (int64_t)pktlen, (int64_t)len, str, flag_r, td.cbp, td.be);
+
+    if (pktlen > 0 && dir != OHCI_TD_DIR_IN) {
+        DPRINTF("  data:");
+        for (i = 0; i < pktlen; i++) {
+            printf(" %.2x", ohci->usb_buf[i]);
+        }
+        DPRINTF("\n");
+    }
+#endif
+    if (completion) {
+        ret = ohci->usb_packet.result;
+        ohci->async_td = 0;
+        ohci->async_complete = 0;
+    } else {
+        if (ohci->async_td) {
+            /* ??? The hardware should allow one active packet per
+               endpoint.  We only allow one active packet per controller.
+               This should be sufficient as long as devices respond in a
+               timely manner.
+            */
+#ifdef DEBUG_PACKET
+            DPRINTF("Too many pending packets\n");
+#endif
+            return 1;
+        }
+        dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
+        ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
+        usb_packet_setup(&ohci->usb_packet, pid, ep);
+        usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen);
+        ret = usb_handle_packet(dev, &ohci->usb_packet);
+#ifdef DEBUG_PACKET
+        DPRINTF("ret=%d\n", ret);
+#endif
+        if (ret == USB_RET_ASYNC) {
+            ohci->async_td = addr;
+            return 1;
+        }
+    }
+    if (ret >= 0) {
+        if (dir == OHCI_TD_DIR_IN) {
+            ohci_copy_td(ohci, &td, ohci->usb_buf, ret, 1);
+#ifdef DEBUG_PACKET
+            DPRINTF("  data:");
+            for (i = 0; i < ret; i++)
+                printf(" %.2x", ohci->usb_buf[i]);
+            DPRINTF("\n");
+#endif
+        } else {
+            ret = pktlen;
+        }
+    }
+
+    /* Writeback */
+    if (ret == pktlen || (dir == OHCI_TD_DIR_IN && ret >= 0 && flag_r)) {
+        /* Transmission succeeded.  */
+        if (ret == len) {
+            td.cbp = 0;
+        } else {
+            if ((td.cbp & 0xfff) + ret > 0xfff) {
+                td.cbp = (td.be & ~0xfff) + ((td.cbp + ret) & 0xfff);
+            } else {
+                td.cbp += ret;
+            }
+        }
+        td.flags |= OHCI_TD_T1;
+        td.flags ^= OHCI_TD_T0;
+        OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_NOERROR);
+        OHCI_SET_BM(td.flags, TD_EC, 0);
+
+        if ((dir != OHCI_TD_DIR_IN) && (ret != len)) {
+            /* Partial packet transfer: TD not ready to retire yet */
+            goto exit_no_retire;
+        }
+
+        /* Setting ED_C is part of the TD retirement process */
+        ed->head &= ~OHCI_ED_C;
+        if (td.flags & OHCI_TD_T0)
+            ed->head |= OHCI_ED_C;
+    } else {
+        if (ret >= 0) {
+            DPRINTF("usb-ohci: Underrun\n");
+            OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAUNDERRUN);
+        } else {
+            switch (ret) {
+            case USB_RET_IOERROR:
+            case USB_RET_NODEV:
+                OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING);
+            case USB_RET_NAK:
+                DPRINTF("usb-ohci: got NAK\n");
+                return 1;
+            case USB_RET_STALL:
+                DPRINTF("usb-ohci: got STALL\n");
+                OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_STALL);
+                break;
+            case USB_RET_BABBLE:
+                DPRINTF("usb-ohci: got BABBLE\n");
+                OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAOVERRUN);
+                break;
+            default:
+                fprintf(stderr, "usb-ohci: Bad device response %d\n", ret);
+                OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_UNDEXPETEDPID);
+                OHCI_SET_BM(td.flags, TD_EC, 3);
+                break;
+            }
+        }
+        ed->head |= OHCI_ED_H;
+    }
+
+    /* Retire this TD */
+    ed->head &= ~OHCI_DPTR_MASK;
+    ed->head |= td.next & OHCI_DPTR_MASK;
+    td.next = ohci->done;
+    ohci->done = addr;
+    i = OHCI_BM(td.flags, TD_DI);
+    if (i < ohci->done_count)
+        ohci->done_count = i;
+exit_no_retire:
+    ohci_put_td(ohci, addr, &td);
+    return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR;
+}
+
+/* Service an endpoint list.  Returns nonzero if active TD were found.  */
+static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion)
+{
+    struct ohci_ed ed;
+    uint32_t next_ed;
+    uint32_t cur;
+    int active;
+
+    active = 0;
+
+    if (head == 0)
+        return 0;
+
+    for (cur = head; cur; cur = next_ed) {
+        if (!ohci_read_ed(ohci, cur, &ed)) {
+            fprintf(stderr, "usb-ohci: ED read error at %x\n", cur);
+            return 0;
+        }
+
+        next_ed = ed.next & OHCI_DPTR_MASK;
+
+        if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K)) {
+            uint32_t addr;
+            /* Cancel pending packets for ED that have been paused.  */
+            addr = ed.head & OHCI_DPTR_MASK;
+            if (ohci->async_td && addr == ohci->async_td) {
+                usb_cancel_packet(&ohci->usb_packet);
+                ohci->async_td = 0;
+            }
+            continue;
+        }
+
+        while ((ed.head & OHCI_DPTR_MASK) != ed.tail) {
+#ifdef DEBUG_PACKET
+            DPRINTF("ED @ 0x%.8x fa=%u en=%u d=%u s=%u k=%u f=%u mps=%u "
+                    "h=%u c=%u\n  head=0x%.8x tailp=0x%.8x next=0x%.8x\n", cur,
+                    OHCI_BM(ed.flags, ED_FA), OHCI_BM(ed.flags, ED_EN),
+                    OHCI_BM(ed.flags, ED_D), (ed.flags & OHCI_ED_S)!= 0,
+                    (ed.flags & OHCI_ED_K) != 0, (ed.flags & OHCI_ED_F) != 0,
+                    OHCI_BM(ed.flags, ED_MPS), (ed.head & OHCI_ED_H) != 0,
+                    (ed.head & OHCI_ED_C) != 0, ed.head & OHCI_DPTR_MASK,
+                    ed.tail & OHCI_DPTR_MASK, ed.next & OHCI_DPTR_MASK);
+#endif
+            active = 1;
+
+            if ((ed.flags & OHCI_ED_F) == 0) {
+                if (ohci_service_td(ohci, &ed))
+                    break;
+            } else {
+                /* Handle isochronous endpoints */
+                if (ohci_service_iso_td(ohci, &ed, completion))
+                    break;
+            }
+        }
+
+        ohci_put_ed(ohci, cur, &ed);
+    }
+
+    return active;
+}
+
+/* Generate a SOF event, and set a timer for EOF */
+static void ohci_sof(OHCIState *ohci)
+{
+    ohci->sof_time = qemu_get_clock_ns(vm_clock);
+    qemu_mod_timer(ohci->eof_timer, ohci->sof_time + usb_frame_time);
+    ohci_set_interrupt(ohci, OHCI_INTR_SF);
+}
+
+/* Process Control and Bulk lists.  */
+static void ohci_process_lists(OHCIState *ohci, int completion)
+{
+    if ((ohci->ctl & OHCI_CTL_CLE) && (ohci->status & OHCI_STATUS_CLF)) {
+        if (ohci->ctrl_cur && ohci->ctrl_cur != ohci->ctrl_head) {
+            DPRINTF("usb-ohci: head %x, cur %x\n",
+                    ohci->ctrl_head, ohci->ctrl_cur);
+        }
+        if (!ohci_service_ed_list(ohci, ohci->ctrl_head, completion)) {
+            ohci->ctrl_cur = 0;
+            ohci->status &= ~OHCI_STATUS_CLF;
+        }
+    }
+
+    if ((ohci->ctl & OHCI_CTL_BLE) && (ohci->status & OHCI_STATUS_BLF)) {
+        if (!ohci_service_ed_list(ohci, ohci->bulk_head, completion)) {
+            ohci->bulk_cur = 0;
+            ohci->status &= ~OHCI_STATUS_BLF;
+        }
+    }
+}
+
+/* Do frame processing on frame boundary */
+static void ohci_frame_boundary(void *opaque)
+{
+    OHCIState *ohci = opaque;
+    struct ohci_hcca hcca;
+
+    ohci_read_hcca(ohci, ohci->hcca, &hcca);
+
+    /* Process all the lists at the end of the frame */
+    if (ohci->ctl & OHCI_CTL_PLE) {
+        int n;
+
+        n = ohci->frame_number & 0x1f;
+        ohci_service_ed_list(ohci, le32_to_cpu(hcca.intr[n]), 0);
+    }
+
+    /* Cancel all pending packets if either of the lists has been disabled.  */
+    if (ohci->async_td &&
+        ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) {
+        usb_cancel_packet(&ohci->usb_packet);
+        ohci->async_td = 0;
+    }
+    ohci->old_ctl = ohci->ctl;
+    ohci_process_lists(ohci, 0);
+
+    /* Frame boundary, so do EOF stuf here */
+    ohci->frt = ohci->fit;
+
+    /* Increment frame number and take care of endianness. */
+    ohci->frame_number = (ohci->frame_number + 1) & 0xffff;
+    hcca.frame = cpu_to_le16(ohci->frame_number);
+
+    if (ohci->done_count == 0 && !(ohci->intr_status & OHCI_INTR_WD)) {
+        if (!ohci->done)
+            abort();
+        if (ohci->intr & ohci->intr_status)
+            ohci->done |= 1;
+        hcca.done = cpu_to_le32(ohci->done);
+        ohci->done = 0;
+        ohci->done_count = 7;
+        ohci_set_interrupt(ohci, OHCI_INTR_WD);
+    }
+
+    if (ohci->done_count != 7 && ohci->done_count != 0)
+        ohci->done_count--;
+
+    /* Do SOF stuff here */
+    ohci_sof(ohci);
+
+    /* Writeback HCCA */
+    ohci_put_hcca(ohci, ohci->hcca, &hcca);
+}
+
+/* Start sending SOF tokens across the USB bus, lists are processed in
+ * next frame
+ */
+static int ohci_bus_start(OHCIState *ohci)
+{
+    ohci->eof_timer = qemu_new_timer_ns(vm_clock,
+                    ohci_frame_boundary,
+                    ohci);
+
+    if (ohci->eof_timer == NULL) {
+        fprintf(stderr, "usb-ohci: %s: qemu_new_timer_ns failed\n", ohci->name);
+        /* TODO: Signal unrecoverable error */
+        return 0;
+    }
+
+    DPRINTF("usb-ohci: %s: USB Operational\n", ohci->name);
+
+    ohci_sof(ohci);
+
+    return 1;
+}
+
+/* Stop sending SOF tokens on the bus */
+static void ohci_bus_stop(OHCIState *ohci)
+{
+    if (ohci->eof_timer)
+        qemu_del_timer(ohci->eof_timer);
+    ohci->eof_timer = NULL;
+}
+
+/* Sets a flag in a port status register but only set it if the port is
+ * connected, if not set ConnectStatusChange flag. If flag is enabled
+ * return 1.
+ */
+static int ohci_port_set_if_connected(OHCIState *ohci, int i, uint32_t val)
+{
+    int ret = 1;
+
+    /* writing a 0 has no effect */
+    if (val == 0)
+        return 0;
+
+    /* If CurrentConnectStatus is cleared we set
+     * ConnectStatusChange
+     */
+    if (!(ohci->rhport[i].ctrl & OHCI_PORT_CCS)) {
+        ohci->rhport[i].ctrl |= OHCI_PORT_CSC;
+        if (ohci->rhstatus & OHCI_RHS_DRWE) {
+            /* TODO: CSC is a wakeup event */
+        }
+        return 0;
+    }
+
+    if (ohci->rhport[i].ctrl & val)
+        ret = 0;
+
+    /* set the bit */
+    ohci->rhport[i].ctrl |= val;
+
+    return ret;
+}
+
+/* Set the frame interval - frame interval toggle is manipulated by the hcd only */
+static void ohci_set_frame_interval(OHCIState *ohci, uint16_t val)
+{
+    val &= OHCI_FMI_FI;
+
+    if (val != ohci->fi) {
+        DPRINTF("usb-ohci: %s: FrameInterval = 0x%x (%u)\n",
+            ohci->name, ohci->fi, ohci->fi);
+    }
+
+    ohci->fi = val;
+}
+
+static void ohci_port_power(OHCIState *ohci, int i, int p)
+{
+    if (p) {
+        ohci->rhport[i].ctrl |= OHCI_PORT_PPS;
+    } else {
+        ohci->rhport[i].ctrl &= ~(OHCI_PORT_PPS|
+                    OHCI_PORT_CCS|
+                    OHCI_PORT_PSS|
+                    OHCI_PORT_PRS);
+    }
+}
+
+/* Set HcControlRegister */
+static void ohci_set_ctl(OHCIState *ohci, uint32_t val)
+{
+    uint32_t old_state;
+    uint32_t new_state;
+
+    old_state = ohci->ctl & OHCI_CTL_HCFS;
+    ohci->ctl = val;
+    new_state = ohci->ctl & OHCI_CTL_HCFS;
+
+    /* no state change */
+    if (old_state == new_state)
+        return;
+
+    switch (new_state) {
+    case OHCI_USB_OPERATIONAL:
+        ohci_bus_start(ohci);
+        break;
+    case OHCI_USB_SUSPEND:
+        ohci_bus_stop(ohci);
+        DPRINTF("usb-ohci: %s: USB Suspended\n", ohci->name);
+        break;
+    case OHCI_USB_RESUME:
+        DPRINTF("usb-ohci: %s: USB Resume\n", ohci->name);
+        break;
+    case OHCI_USB_RESET:
+        ohci_reset(ohci);
+        DPRINTF("usb-ohci: %s: USB Reset\n", ohci->name);
+        break;
+    }
+}
+
+static uint32_t ohci_get_frame_remaining(OHCIState *ohci)
+{
+    uint16_t fr;
+    int64_t tks;
+
+    if ((ohci->ctl & OHCI_CTL_HCFS) != OHCI_USB_OPERATIONAL)
+        return (ohci->frt << 31);
+
+    /* Being in USB operational state guarnatees sof_time was
+     * set already.
+     */
+    tks = qemu_get_clock_ns(vm_clock) - ohci->sof_time;
+
+    /* avoid muldiv if possible */
+    if (tks >= usb_frame_time)
+        return (ohci->frt << 31);
+
+    tks = muldiv64(1, tks, usb_bit_time);
+    fr = (uint16_t)(ohci->fi - tks);
+
+    return (ohci->frt << 31) | fr;
+}
+
+
+/* Set root hub status */
+static void ohci_set_hub_status(OHCIState *ohci, uint32_t val)
+{
+    uint32_t old_state;
+
+    old_state = ohci->rhstatus;
+
+    /* write 1 to clear OCIC */
+    if (val & OHCI_RHS_OCIC)
+        ohci->rhstatus &= ~OHCI_RHS_OCIC;
+
+    if (val & OHCI_RHS_LPS) {
+        int i;
+
+        for (i = 0; i < ohci->num_ports; i++)
+            ohci_port_power(ohci, i, 0);
+        DPRINTF("usb-ohci: powered down all ports\n");
+    }
+
+    if (val & OHCI_RHS_LPSC) {
+        int i;
+
+        for (i = 0; i < ohci->num_ports; i++)
+            ohci_port_power(ohci, i, 1);
+        DPRINTF("usb-ohci: powered up all ports\n");
+    }
+
+    if (val & OHCI_RHS_DRWE)
+        ohci->rhstatus |= OHCI_RHS_DRWE;
+
+    if (val & OHCI_RHS_CRWE)
+        ohci->rhstatus &= ~OHCI_RHS_DRWE;
+
+    if (old_state != ohci->rhstatus)
+        ohci_set_interrupt(ohci, OHCI_INTR_RHSC);
+}
+
+/* Set root hub port status */
+static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val)
+{
+    uint32_t old_state;
+    OHCIPort *port;
+
+    port = &ohci->rhport[portnum];
+    old_state = port->ctrl;
+
+    /* Write to clear CSC, PESC, PSSC, OCIC, PRSC */
+    if (val & OHCI_PORT_WTC)
+        port->ctrl &= ~(val & OHCI_PORT_WTC);
+
+    if (val & OHCI_PORT_CCS)
+        port->ctrl &= ~OHCI_PORT_PES;
+
+    ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PES);
+
+    if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PSS)) {
+        DPRINTF("usb-ohci: port %d: SUSPEND\n", portnum);
+    }
+
+    if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PRS)) {
+        DPRINTF("usb-ohci: port %d: RESET\n", portnum);
+        usb_device_reset(port->port.dev);
+        port->ctrl &= ~OHCI_PORT_PRS;
+        /* ??? Should this also set OHCI_PORT_PESC.  */
+        port->ctrl |= OHCI_PORT_PES | OHCI_PORT_PRSC;
+    }
+
+    /* Invert order here to ensure in ambiguous case, device is
+     * powered up...
+     */
+    if (val & OHCI_PORT_LSDA)
+        ohci_port_power(ohci, portnum, 0);
+    if (val & OHCI_PORT_PPS)
+        ohci_port_power(ohci, portnum, 1);
+
+    if (old_state != port->ctrl)
+        ohci_set_interrupt(ohci, OHCI_INTR_RHSC);
+
+    return;
+}
+
+static uint64_t ohci_mem_read(void *opaque,
+                              target_phys_addr_t addr,
+                              unsigned size)
+{
+    OHCIState *ohci = opaque;
+    uint32_t retval;
+
+    /* Only aligned reads are allowed on OHCI */
+    if (addr & 3) {
+        fprintf(stderr, "usb-ohci: Mis-aligned read\n");
+        return 0xffffffff;
+    } else if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) {
+        /* HcRhPortStatus */
+        retval = ohci->rhport[(addr - 0x54) >> 2].ctrl | OHCI_PORT_PPS;
+    } else {
+        switch (addr >> 2) {
+        case 0: /* HcRevision */
+            retval = 0x10;
+            break;
+
+        case 1: /* HcControl */
+            retval = ohci->ctl;
+            break;
+
+        case 2: /* HcCommandStatus */
+            retval = ohci->status;
+            break;
+
+        case 3: /* HcInterruptStatus */
+            retval = ohci->intr_status;
+            break;
+
+        case 4: /* HcInterruptEnable */
+        case 5: /* HcInterruptDisable */
+            retval = ohci->intr;
+            break;
+
+        case 6: /* HcHCCA */
+            retval = ohci->hcca;
+            break;
+
+        case 7: /* HcPeriodCurrentED */
+            retval = ohci->per_cur;
+            break;
+
+        case 8: /* HcControlHeadED */
+            retval = ohci->ctrl_head;
+            break;
+
+        case 9: /* HcControlCurrentED */
+            retval = ohci->ctrl_cur;
+            break;
+
+        case 10: /* HcBulkHeadED */
+            retval = ohci->bulk_head;
+            break;
+
+        case 11: /* HcBulkCurrentED */
+            retval = ohci->bulk_cur;
+            break;
+
+        case 12: /* HcDoneHead */
+            retval = ohci->done;
+            break;
+
+        case 13: /* HcFmInterretval */
+            retval = (ohci->fit << 31) | (ohci->fsmps << 16) | (ohci->fi);
+            break;
+
+        case 14: /* HcFmRemaining */
+            retval = ohci_get_frame_remaining(ohci);
+            break;
+
+        case 15: /* HcFmNumber */
+            retval = ohci->frame_number;
+            break;
+
+        case 16: /* HcPeriodicStart */
+            retval = ohci->pstart;
+            break;
+
+        case 17: /* HcLSThreshold */
+            retval = ohci->lst;
+            break;
+
+        case 18: /* HcRhDescriptorA */
+            retval = ohci->rhdesc_a;
+            break;
+
+        case 19: /* HcRhDescriptorB */
+            retval = ohci->rhdesc_b;
+            break;
+
+        case 20: /* HcRhStatus */
+            retval = ohci->rhstatus;
+            break;
+
+        /* PXA27x specific registers */
+        case 24: /* HcStatus */
+            retval = ohci->hstatus & ohci->hmask;
+            break;
+
+        case 25: /* HcHReset */
+            retval = ohci->hreset;
+            break;
+
+        case 26: /* HcHInterruptEnable */
+            retval = ohci->hmask;
+            break;
+
+        case 27: /* HcHInterruptTest */
+            retval = ohci->htest;
+            break;
+
+        default:
+            fprintf(stderr, "ohci_read: Bad offset %x\n", (int)addr);
+            retval = 0xffffffff;
+        }
+    }
+
+    return retval;
+}
+
+static void ohci_mem_write(void *opaque,
+                           target_phys_addr_t addr,
+                           uint64_t val,
+                           unsigned size)
+{
+    OHCIState *ohci = opaque;
+
+    /* Only aligned reads are allowed on OHCI */
+    if (addr & 3) {
+        fprintf(stderr, "usb-ohci: Mis-aligned write\n");
+        return;
+    }
+
+    if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) {
+        /* HcRhPortStatus */
+        ohci_port_set_status(ohci, (addr - 0x54) >> 2, val);
+        return;
+    }
+
+    switch (addr >> 2) {
+    case 1: /* HcControl */
+        ohci_set_ctl(ohci, val);
+        break;
+
+    case 2: /* HcCommandStatus */
+        /* SOC is read-only */
+        val = (val & ~OHCI_STATUS_SOC);
+
+        /* Bits written as '0' remain unchanged in the register */
+        ohci->status |= val;
+
+        if (ohci->status & OHCI_STATUS_HCR)
+            ohci_reset(ohci);
+        break;
+
+    case 3: /* HcInterruptStatus */
+        ohci->intr_status &= ~val;
+        ohci_intr_update(ohci);
+        break;
+
+    case 4: /* HcInterruptEnable */
+        ohci->intr |= val;
+        ohci_intr_update(ohci);
+        break;
+
+    case 5: /* HcInterruptDisable */
+        ohci->intr &= ~val;
+        ohci_intr_update(ohci);
+        break;
+
+    case 6: /* HcHCCA */
+        ohci->hcca = val & OHCI_HCCA_MASK;
+        break;
+
+    case 7: /* HcPeriodCurrentED */
+        /* Ignore writes to this read-only register, Linux does them */
+        break;
+
+    case 8: /* HcControlHeadED */
+        ohci->ctrl_head = val & OHCI_EDPTR_MASK;
+        break;
+
+    case 9: /* HcControlCurrentED */
+        ohci->ctrl_cur = val & OHCI_EDPTR_MASK;
+        break;
+
+    case 10: /* HcBulkHeadED */
+        ohci->bulk_head = val & OHCI_EDPTR_MASK;
+        break;
+
+    case 11: /* HcBulkCurrentED */
+        ohci->bulk_cur = val & OHCI_EDPTR_MASK;
+        break;
+
+    case 13: /* HcFmInterval */
+        ohci->fsmps = (val & OHCI_FMI_FSMPS) >> 16;
+        ohci->fit = (val & OHCI_FMI_FIT) >> 31;
+        ohci_set_frame_interval(ohci, val);
+        break;
+
+    case 15: /* HcFmNumber */
+        break;
+
+    case 16: /* HcPeriodicStart */
+        ohci->pstart = val & 0xffff;
+        break;
+
+    case 17: /* HcLSThreshold */
+        ohci->lst = val & 0xffff;
+        break;
+
+    case 18: /* HcRhDescriptorA */
+        ohci->rhdesc_a &= ~OHCI_RHA_RW_MASK;
+        ohci->rhdesc_a |= val & OHCI_RHA_RW_MASK;
+        break;
+
+    case 19: /* HcRhDescriptorB */
+        break;
+
+    case 20: /* HcRhStatus */
+        ohci_set_hub_status(ohci, val);
+        break;
+
+    /* PXA27x specific registers */
+    case 24: /* HcStatus */
+        ohci->hstatus &= ~(val & ohci->hmask);
+
+    case 25: /* HcHReset */
+        ohci->hreset = val & ~OHCI_HRESET_FSBIR;
+        if (val & OHCI_HRESET_FSBIR)
+            ohci_reset(ohci);
+        break;
+
+    case 26: /* HcHInterruptEnable */
+        ohci->hmask = val;
+        break;
+
+    case 27: /* HcHInterruptTest */
+        ohci->htest = val;
+        break;
+
+    default:
+        fprintf(stderr, "ohci_write: Bad offset %x\n", (int)addr);
+        break;
+    }
+}
+
+static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev)
+{
+    if (ohci->async_td &&
+        usb_packet_is_inflight(&ohci->usb_packet) &&
+        ohci->usb_packet.ep->dev == dev) {
+        usb_cancel_packet(&ohci->usb_packet);
+        ohci->async_td = 0;
+    }
+}
+
+static const MemoryRegionOps ohci_mem_ops = {
+    .read = ohci_mem_read,
+    .write = ohci_mem_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static USBPortOps ohci_port_ops = {
+    .attach = ohci_attach,
+    .detach = ohci_detach,
+    .child_detach = ohci_child_detach,
+    .wakeup = ohci_wakeup,
+    .complete = ohci_async_complete_packet,
+};
+
+static USBBusOps ohci_bus_ops = {
+};
+
+static int usb_ohci_init(OHCIState *ohci, DeviceState *dev,
+                         int num_ports, uint32_t localmem_base,
+                         char *masterbus, uint32_t firstport)
+{
+    int i;
+
+    if (usb_frame_time == 0) {
+#ifdef OHCI_TIME_WARP
+        usb_frame_time = get_ticks_per_sec();
+        usb_bit_time = muldiv64(1, get_ticks_per_sec(), USB_HZ/1000);
+#else
+        usb_frame_time = muldiv64(1, get_ticks_per_sec(), 1000);
+        if (get_ticks_per_sec() >= USB_HZ) {
+            usb_bit_time = muldiv64(1, get_ticks_per_sec(), USB_HZ);
+        } else {
+            usb_bit_time = 1;
+        }
+#endif
+        DPRINTF("usb-ohci: usb_bit_time=%" PRId64 " usb_frame_time=%" PRId64 "\n",
+                usb_frame_time, usb_bit_time);
+    }
+
+    ohci->num_ports = num_ports;
+    if (masterbus) {
+        USBPort *ports[OHCI_MAX_PORTS];
+        for(i = 0; i < num_ports; i++) {
+            ports[i] = &ohci->rhport[i].port;
+        }
+        if (usb_register_companion(masterbus, ports, num_ports,
+                firstport, ohci, &ohci_port_ops,
+                USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL) != 0) {
+            return -1;
+        }
+    } else {
+        usb_bus_new(&ohci->bus, &ohci_bus_ops, dev);
+        for (i = 0; i < num_ports; i++) {
+            usb_register_port(&ohci->bus, &ohci->rhport[i].port,
+                              ohci, i, &ohci_port_ops,
+                              USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
+        }
+    }
+
+    memory_region_init_io(&ohci->mem, &ohci_mem_ops, ohci, "ohci", 256);
+    ohci->localmem_base = localmem_base;
+
+    ohci->name = object_get_typename(OBJECT(dev));
+    usb_packet_init(&ohci->usb_packet);
+
+    ohci->async_td = 0;
+    qemu_register_reset(ohci_reset, ohci);
+
+    return 0;
+}
+
+typedef struct {
+    PCIDevice pci_dev;
+    OHCIState state;
+    char *masterbus;
+    uint32_t num_ports;
+    uint32_t firstport;
+} OHCIPCIState;
+
+static int usb_ohci_initfn_pci(struct PCIDevice *dev)
+{
+    OHCIPCIState *ohci = DO_UPCAST(OHCIPCIState, pci_dev, dev);
+
+    ohci->pci_dev.config[PCI_CLASS_PROG] = 0x10; /* OHCI */
+    ohci->pci_dev.config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */
+
+    if (usb_ohci_init(&ohci->state, &dev->qdev, ohci->num_ports, 0,
+                      ohci->masterbus, ohci->firstport) != 0) {
+        return -1;
+    }
+    ohci->state.irq = ohci->pci_dev.irq[0];
+
+    /* TODO: avoid cast below by using dev */
+    pci_register_bar(&ohci->pci_dev, 0, 0, &ohci->state.mem);
+    return 0;
+}
+
+void usb_ohci_init_pci(struct PCIBus *bus, int devfn)
+{
+    pci_create_simple(bus, devfn, "pci-ohci");
+}
+
+typedef struct {
+    SysBusDevice busdev;
+    OHCIState ohci;
+    uint32_t num_ports;
+    target_phys_addr_t dma_offset;
+} OHCISysBusState;
+
+static int ohci_init_pxa(SysBusDevice *dev)
+{
+    OHCISysBusState *s = FROM_SYSBUS(OHCISysBusState, dev);
+
+    /* Cannot fail as we pass NULL for masterbus */
+    usb_ohci_init(&s->ohci, &dev->qdev, s->num_ports, s->dma_offset, NULL, 0);
+    sysbus_init_irq(dev, &s->ohci.irq);
+    sysbus_init_mmio(dev, &s->ohci.mem);
+
+    return 0;
+}
+
+static Property ohci_pci_properties[] = {
+    DEFINE_PROP_STRING("masterbus", OHCIPCIState, masterbus),
+    DEFINE_PROP_UINT32("num-ports", OHCIPCIState, num_ports, 3),
+    DEFINE_PROP_UINT32("firstport", OHCIPCIState, firstport, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ohci_pci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = usb_ohci_initfn_pci;
+    k->vendor_id = PCI_VENDOR_ID_APPLE;
+    k->device_id = PCI_DEVICE_ID_APPLE_IPID_USB;
+    k->class_id = PCI_CLASS_SERIAL_USB;
+    dc->desc = "Apple USB Controller";
+    dc->props = ohci_pci_properties;
+}
+
+static TypeInfo ohci_pci_info = {
+    .name          = "pci-ohci",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(OHCIPCIState),
+    .class_init    = ohci_pci_class_init,
+};
+
+static Property ohci_sysbus_properties[] = {
+    DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3),
+    DEFINE_PROP_TADDR("dma-offset", OHCISysBusState, dma_offset, 3),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ohci_sysbus_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sbc->init = ohci_init_pxa;
+    dc->desc = "OHCI USB Controller";
+    dc->props = ohci_sysbus_properties;
+}
+
+static TypeInfo ohci_sysbus_info = {
+    .name          = "sysbus-ohci",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(OHCISysBusState),
+    .class_init    = ohci_sysbus_class_init,
+};
+
+static void ohci_register_types(void)
+{
+    type_register_static(&ohci_pci_info);
+    type_register_static(&ohci_sysbus_info);
+}
+
+type_init(ohci_register_types)
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
new file mode 100644
index 0000000..7c2e9b3
--- /dev/null
+++ b/hw/usb/hcd-uhci.c
@@ -0,0 +1,1408 @@
+/*
+ * USB UHCI controller emulation
+ *
+ * Copyright (c) 2005 Fabrice Bellard
+ *
+ * Copyright (c) 2008 Max Krasnyansky
+ *     Magor rewrite of the UHCI data structures parser and frame processor
+ *     Support for fully async operation and multiple outstanding transactions
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw/hw.h"
+#include "hw/usb.h"
+#include "hw/pci.h"
+#include "qemu-timer.h"
+#include "hw/usb-uhci.h"
+#include "iov.h"
+#include "dma.h"
+
+//#define DEBUG
+//#define DEBUG_DUMP_DATA
+
+#define UHCI_CMD_FGR      (1 << 4)
+#define UHCI_CMD_EGSM     (1 << 3)
+#define UHCI_CMD_GRESET   (1 << 2)
+#define UHCI_CMD_HCRESET  (1 << 1)
+#define UHCI_CMD_RS       (1 << 0)
+
+#define UHCI_STS_HCHALTED (1 << 5)
+#define UHCI_STS_HCPERR   (1 << 4)
+#define UHCI_STS_HSERR    (1 << 3)
+#define UHCI_STS_RD       (1 << 2)
+#define UHCI_STS_USBERR   (1 << 1)
+#define UHCI_STS_USBINT   (1 << 0)
+
+#define TD_CTRL_SPD     (1 << 29)
+#define TD_CTRL_ERROR_SHIFT  27
+#define TD_CTRL_IOS     (1 << 25)
+#define TD_CTRL_IOC     (1 << 24)
+#define TD_CTRL_ACTIVE  (1 << 23)
+#define TD_CTRL_STALL   (1 << 22)
+#define TD_CTRL_BABBLE  (1 << 20)
+#define TD_CTRL_NAK     (1 << 19)
+#define TD_CTRL_TIMEOUT (1 << 18)
+
+#define UHCI_PORT_SUSPEND (1 << 12)
+#define UHCI_PORT_RESET (1 << 9)
+#define UHCI_PORT_LSDA  (1 << 8)
+#define UHCI_PORT_RD    (1 << 6)
+#define UHCI_PORT_ENC   (1 << 3)
+#define UHCI_PORT_EN    (1 << 2)
+#define UHCI_PORT_CSC   (1 << 1)
+#define UHCI_PORT_CCS   (1 << 0)
+
+#define UHCI_PORT_READ_ONLY    (0x1bb)
+#define UHCI_PORT_WRITE_CLEAR  (UHCI_PORT_CSC | UHCI_PORT_ENC)
+
+#define FRAME_TIMER_FREQ 1000
+
+#define FRAME_MAX_LOOPS  256
+
+#define NB_PORTS 2
+
+#ifdef DEBUG
+#define DPRINTF printf
+
+static const char *pid2str(int pid)
+{
+    switch (pid) {
+    case USB_TOKEN_SETUP: return "SETUP";
+    case USB_TOKEN_IN:    return "IN";
+    case USB_TOKEN_OUT:   return "OUT";
+    }
+    return "?";
+}
+
+#else
+#define DPRINTF(...)
+#endif
+
+typedef struct UHCIState UHCIState;
+typedef struct UHCIAsync UHCIAsync;
+typedef struct UHCIQueue UHCIQueue;
+
+/* 
+ * Pending async transaction.
+ * 'packet' must be the first field because completion
+ * handler does "(UHCIAsync *) pkt" cast.
+ */
+
+struct UHCIAsync {
+    USBPacket packet;
+    QEMUSGList sgl;
+    UHCIQueue *queue;
+    QTAILQ_ENTRY(UHCIAsync) next;
+    uint32_t  td;
+    uint8_t   isoc;
+    uint8_t   done;
+};
+
+struct UHCIQueue {
+    uint32_t  token;
+    UHCIState *uhci;
+    QTAILQ_ENTRY(UHCIQueue) next;
+    QTAILQ_HEAD(, UHCIAsync) asyncs;
+    int8_t    valid;
+};
+
+typedef struct UHCIPort {
+    USBPort port;
+    uint16_t ctrl;
+} UHCIPort;
+
+struct UHCIState {
+    PCIDevice dev;
+    MemoryRegion io_bar;
+    USBBus bus; /* Note unused when we're a companion controller */
+    uint16_t cmd; /* cmd register */
+    uint16_t status;
+    uint16_t intr; /* interrupt enable register */
+    uint16_t frnum; /* frame number */
+    uint32_t fl_base_addr; /* frame list base address */
+    uint8_t sof_timing;
+    uint8_t status2; /* bit 0 and 1 are used to generate UHCI_STS_USBINT */
+    int64_t expire_time;
+    QEMUTimer *frame_timer;
+    UHCIPort ports[NB_PORTS];
+
+    /* Interrupts that should be raised at the end of the current frame.  */
+    uint32_t pending_int_mask;
+
+    /* Active packets */
+    QTAILQ_HEAD(, UHCIQueue) queues;
+    uint8_t num_ports_vmstate;
+
+    /* Properties */
+    char *masterbus;
+    uint32_t firstport;
+};
+
+typedef struct UHCI_TD {
+    uint32_t link;
+    uint32_t ctrl; /* see TD_CTRL_xxx */
+    uint32_t token;
+    uint32_t buffer;
+} UHCI_TD;
+
+typedef struct UHCI_QH {
+    uint32_t link;
+    uint32_t el_link;
+} UHCI_QH;
+
+static inline int32_t uhci_queue_token(UHCI_TD *td)
+{
+    /* covers ep, dev, pid -> identifies the endpoint */
+    return td->token & 0x7ffff;
+}
+
+static UHCIQueue *uhci_queue_get(UHCIState *s, UHCI_TD *td)
+{
+    uint32_t token = uhci_queue_token(td);
+    UHCIQueue *queue;
+
+    QTAILQ_FOREACH(queue, &s->queues, next) {
+        if (queue->token == token) {
+            return queue;
+        }
+    }
+
+    queue = g_new0(UHCIQueue, 1);
+    queue->uhci = s;
+    queue->token = token;
+    QTAILQ_INIT(&queue->asyncs);
+    QTAILQ_INSERT_HEAD(&s->queues, queue, next);
+    return queue;
+}
+
+static void uhci_queue_free(UHCIQueue *queue)
+{
+    UHCIState *s = queue->uhci;
+
+    QTAILQ_REMOVE(&s->queues, queue, next);
+    g_free(queue);
+}
+
+static UHCIAsync *uhci_async_alloc(UHCIQueue *queue)
+{
+    UHCIAsync *async = g_new0(UHCIAsync, 1);
+
+    async->queue = queue;
+    usb_packet_init(&async->packet);
+    pci_dma_sglist_init(&async->sgl, &queue->uhci->dev, 1);
+
+    return async;
+}
+
+static void uhci_async_free(UHCIAsync *async)
+{
+    usb_packet_cleanup(&async->packet);
+    qemu_sglist_destroy(&async->sgl);
+    g_free(async);
+}
+
+static void uhci_async_link(UHCIAsync *async)
+{
+    UHCIQueue *queue = async->queue;
+    QTAILQ_INSERT_TAIL(&queue->asyncs, async, next);
+}
+
+static void uhci_async_unlink(UHCIAsync *async)
+{
+    UHCIQueue *queue = async->queue;
+    QTAILQ_REMOVE(&queue->asyncs, async, next);
+}
+
+static void uhci_async_cancel(UHCIAsync *async)
+{
+    DPRINTF("uhci: cancel td 0x%x token 0x%x done %u\n",
+           async->td, async->token, async->done);
+
+    if (!async->done)
+        usb_cancel_packet(&async->packet);
+    uhci_async_free(async);
+}
+
+/*
+ * Mark all outstanding async packets as invalid.
+ * This is used for canceling them when TDs are removed by the HCD.
+ */
+static void uhci_async_validate_begin(UHCIState *s)
+{
+    UHCIQueue *queue;
+
+    QTAILQ_FOREACH(queue, &s->queues, next) {
+        queue->valid--;
+    }
+}
+
+/*
+ * Cancel async packets that are no longer valid
+ */
+static void uhci_async_validate_end(UHCIState *s)
+{
+    UHCIQueue *queue, *n;
+    UHCIAsync *async;
+
+    QTAILQ_FOREACH_SAFE(queue, &s->queues, next, n) {
+        if (queue->valid > 0) {
+            continue;
+        }
+        while (!QTAILQ_EMPTY(&queue->asyncs)) {
+            async = QTAILQ_FIRST(&queue->asyncs);
+            uhci_async_unlink(async);
+            uhci_async_cancel(async);
+        }
+        uhci_queue_free(queue);
+    }
+}
+
+static void uhci_async_cancel_device(UHCIState *s, USBDevice *dev)
+{
+    UHCIQueue *queue;
+    UHCIAsync *curr, *n;
+
+    QTAILQ_FOREACH(queue, &s->queues, next) {
+        QTAILQ_FOREACH_SAFE(curr, &queue->asyncs, next, n) {
+            if (!usb_packet_is_inflight(&curr->packet) ||
+                curr->packet.ep->dev != dev) {
+                continue;
+            }
+            uhci_async_unlink(curr);
+            uhci_async_cancel(curr);
+        }
+    }
+}
+
+static void uhci_async_cancel_all(UHCIState *s)
+{
+    UHCIQueue *queue;
+    UHCIAsync *curr, *n;
+
+    QTAILQ_FOREACH(queue, &s->queues, next) {
+        QTAILQ_FOREACH_SAFE(curr, &queue->asyncs, next, n) {
+            uhci_async_unlink(curr);
+            uhci_async_cancel(curr);
+        }
+    }
+}
+
+static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t addr, UHCI_TD *td)
+{
+    uint32_t token = uhci_queue_token(td);
+    UHCIQueue *queue;
+    UHCIAsync *async;
+
+    QTAILQ_FOREACH(queue, &s->queues, next) {
+        if (queue->token == token) {
+            break;
+        }
+    }
+    if (queue == NULL) {
+        return NULL;
+    }
+
+    QTAILQ_FOREACH(async, &queue->asyncs, next) {
+        if (async->td == addr) {
+            return async;
+        }
+    }
+
+    return NULL;
+}
+
+static void uhci_update_irq(UHCIState *s)
+{
+    int level;
+    if (((s->status2 & 1) && (s->intr & (1 << 2))) ||
+        ((s->status2 & 2) && (s->intr & (1 << 3))) ||
+        ((s->status & UHCI_STS_USBERR) && (s->intr & (1 << 0))) ||
+        ((s->status & UHCI_STS_RD) && (s->intr & (1 << 1))) ||
+        (s->status & UHCI_STS_HSERR) ||
+        (s->status & UHCI_STS_HCPERR)) {
+        level = 1;
+    } else {
+        level = 0;
+    }
+    qemu_set_irq(s->dev.irq[3], level);
+}
+
+static void uhci_reset(void *opaque)
+{
+    UHCIState *s = opaque;
+    uint8_t *pci_conf;
+    int i;
+    UHCIPort *port;
+
+    DPRINTF("uhci: full reset\n");
+
+    pci_conf = s->dev.config;
+
+    pci_conf[0x6a] = 0x01; /* usb clock */
+    pci_conf[0x6b] = 0x00;
+    s->cmd = 0;
+    s->status = 0;
+    s->status2 = 0;
+    s->intr = 0;
+    s->fl_base_addr = 0;
+    s->sof_timing = 64;
+
+    for(i = 0; i < NB_PORTS; i++) {
+        port = &s->ports[i];
+        port->ctrl = 0x0080;
+        if (port->port.dev && port->port.dev->attached) {
+            usb_port_reset(&port->port);
+        }
+    }
+
+    uhci_async_cancel_all(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,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_UINT16(ctrl, UHCIPort),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_uhci = {
+    .name = "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),
+        VMSTATE_STRUCT_ARRAY(ports, UHCIState, NB_PORTS, 1,
+                             vmstate_uhci_port, UHCIPort),
+        VMSTATE_UINT16(cmd, UHCIState),
+        VMSTATE_UINT16(status, UHCIState),
+        VMSTATE_UINT16(intr, UHCIState),
+        VMSTATE_UINT16(frnum, UHCIState),
+        VMSTATE_UINT32(fl_base_addr, UHCIState),
+        VMSTATE_UINT8(sof_timing, UHCIState),
+        VMSTATE_UINT8(status2, UHCIState),
+        VMSTATE_TIMER(frame_timer, UHCIState),
+        VMSTATE_INT64_V(expire_time, UHCIState, 2),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void uhci_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+    UHCIState *s = opaque;
+
+    addr &= 0x1f;
+    switch(addr) {
+    case 0x0c:
+        s->sof_timing = val;
+        break;
+    }
+}
+
+static uint32_t uhci_ioport_readb(void *opaque, uint32_t addr)
+{
+    UHCIState *s = opaque;
+    uint32_t val;
+
+    addr &= 0x1f;
+    switch(addr) {
+    case 0x0c:
+        val = s->sof_timing;
+        break;
+    default:
+        val = 0xff;
+        break;
+    }
+    return val;
+}
+
+static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
+{
+    UHCIState *s = opaque;
+
+    addr &= 0x1f;
+    DPRINTF("uhci: writew port=0x%04x val=0x%04x\n", addr, val);
+
+    switch(addr) {
+    case 0x00:
+        if ((val & UHCI_CMD_RS) && !(s->cmd & UHCI_CMD_RS)) {
+            /* start frame processing */
+            s->expire_time = qemu_get_clock_ns(vm_clock) +
+                (get_ticks_per_sec() / FRAME_TIMER_FREQ);
+            qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
+            s->status &= ~UHCI_STS_HCHALTED;
+        } else if (!(val & UHCI_CMD_RS)) {
+            s->status |= UHCI_STS_HCHALTED;
+        }
+        if (val & UHCI_CMD_GRESET) {
+            UHCIPort *port;
+            int i;
+
+            /* send reset on the USB bus */
+            for(i = 0; i < NB_PORTS; i++) {
+                port = &s->ports[i];
+                usb_device_reset(port->port.dev);
+            }
+            uhci_reset(s);
+            return;
+        }
+        if (val & UHCI_CMD_HCRESET) {
+            uhci_reset(s);
+            return;
+        }
+        s->cmd = val;
+        break;
+    case 0x02:
+        s->status &= ~val;
+        /* XXX: the chip spec is not coherent, so we add a hidden
+           register to distinguish between IOC and SPD */
+        if (val & UHCI_STS_USBINT)
+            s->status2 = 0;
+        uhci_update_irq(s);
+        break;
+    case 0x04:
+        s->intr = val;
+        uhci_update_irq(s);
+        break;
+    case 0x06:
+        if (s->status & UHCI_STS_HCHALTED)
+            s->frnum = val & 0x7ff;
+        break;
+    case 0x10 ... 0x1f:
+        {
+            UHCIPort *port;
+            USBDevice *dev;
+            int n;
+
+            n = (addr >> 1) & 7;
+            if (n >= NB_PORTS)
+                return;
+            port = &s->ports[n];
+            dev = port->port.dev;
+            if (dev && dev->attached) {
+                /* port reset */
+                if ( (val & UHCI_PORT_RESET) &&
+                     !(port->ctrl & UHCI_PORT_RESET) ) {
+                    usb_device_reset(dev);
+                }
+            }
+            port->ctrl &= UHCI_PORT_READ_ONLY;
+            port->ctrl |= (val & ~UHCI_PORT_READ_ONLY);
+            /* some bits are reset when a '1' is written to them */
+            port->ctrl &= ~(val & UHCI_PORT_WRITE_CLEAR);
+        }
+        break;
+    }
+}
+
+static uint32_t uhci_ioport_readw(void *opaque, uint32_t addr)
+{
+    UHCIState *s = opaque;
+    uint32_t val;
+
+    addr &= 0x1f;
+    switch(addr) {
+    case 0x00:
+        val = s->cmd;
+        break;
+    case 0x02:
+        val = s->status;
+        break;
+    case 0x04:
+        val = s->intr;
+        break;
+    case 0x06:
+        val = s->frnum;
+        break;
+    case 0x10 ... 0x1f:
+        {
+            UHCIPort *port;
+            int n;
+            n = (addr >> 1) & 7;
+            if (n >= NB_PORTS)
+                goto read_default;
+            port = &s->ports[n];
+            val = port->ctrl;
+        }
+        break;
+    default:
+    read_default:
+        val = 0xff7f; /* disabled port */
+        break;
+    }
+
+    DPRINTF("uhci: readw port=0x%04x val=0x%04x\n", addr, val);
+
+    return val;
+}
+
+static void uhci_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
+{
+    UHCIState *s = opaque;
+
+    addr &= 0x1f;
+    DPRINTF("uhci: writel port=0x%04x val=0x%08x\n", addr, val);
+
+    switch(addr) {
+    case 0x08:
+        s->fl_base_addr = val & ~0xfff;
+        break;
+    }
+}
+
+static uint32_t uhci_ioport_readl(void *opaque, uint32_t addr)
+{
+    UHCIState *s = opaque;
+    uint32_t val;
+
+    addr &= 0x1f;
+    switch(addr) {
+    case 0x08:
+        val = s->fl_base_addr;
+        break;
+    default:
+        val = 0xffffffff;
+        break;
+    }
+    return val;
+}
+
+/* signal resume if controller suspended */
+static void uhci_resume (void *opaque)
+{
+    UHCIState *s = (UHCIState *)opaque;
+
+    if (!s)
+        return;
+
+    if (s->cmd & UHCI_CMD_EGSM) {
+        s->cmd |= UHCI_CMD_FGR;
+        s->status |= UHCI_STS_RD;
+        uhci_update_irq(s);
+    }
+}
+
+static void uhci_attach(USBPort *port1)
+{
+    UHCIState *s = port1->opaque;
+    UHCIPort *port = &s->ports[port1->index];
+
+    /* set connect status */
+    port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
+
+    /* update speed */
+    if (port->port.dev->speed == USB_SPEED_LOW) {
+        port->ctrl |= UHCI_PORT_LSDA;
+    } else {
+        port->ctrl &= ~UHCI_PORT_LSDA;
+    }
+
+    uhci_resume(s);
+}
+
+static void uhci_detach(USBPort *port1)
+{
+    UHCIState *s = port1->opaque;
+    UHCIPort *port = &s->ports[port1->index];
+
+    uhci_async_cancel_device(s, port1->dev);
+
+    /* set connect status */
+    if (port->ctrl & UHCI_PORT_CCS) {
+        port->ctrl &= ~UHCI_PORT_CCS;
+        port->ctrl |= UHCI_PORT_CSC;
+    }
+    /* disable port */
+    if (port->ctrl & UHCI_PORT_EN) {
+        port->ctrl &= ~UHCI_PORT_EN;
+        port->ctrl |= UHCI_PORT_ENC;
+    }
+
+    uhci_resume(s);
+}
+
+static void uhci_child_detach(USBPort *port1, USBDevice *child)
+{
+    UHCIState *s = port1->opaque;
+
+    uhci_async_cancel_device(s, child);
+}
+
+static void uhci_wakeup(USBPort *port1)
+{
+    UHCIState *s = port1->opaque;
+    UHCIPort *port = &s->ports[port1->index];
+
+    if (port->ctrl & UHCI_PORT_SUSPEND && !(port->ctrl & UHCI_PORT_RD)) {
+        port->ctrl |= UHCI_PORT_RD;
+        uhci_resume(s);
+    }
+}
+
+static USBDevice *uhci_find_device(UHCIState *s, uint8_t addr)
+{
+    USBDevice *dev;
+    int i;
+
+    for (i = 0; i < NB_PORTS; i++) {
+        UHCIPort *port = &s->ports[i];
+        if (!(port->ctrl & UHCI_PORT_EN)) {
+            continue;
+        }
+        dev = usb_find_device(&port->port, addr);
+        if (dev != NULL) {
+            return dev;
+        }
+    }
+    return NULL;
+}
+
+static void uhci_async_complete(USBPort *port, USBPacket *packet);
+static void uhci_process_frame(UHCIState *s);
+
+/* return -1 if fatal error (frame must be stopped)
+          0 if TD successful
+          1 if TD unsuccessful or inactive
+*/
+static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_t *int_mask)
+{
+    int len = 0, max_len, err, ret;
+    uint8_t pid;
+
+    max_len = ((td->token >> 21) + 1) & 0x7ff;
+    pid = td->token & 0xff;
+
+    ret = async->packet.result;
+
+    if (td->ctrl & TD_CTRL_IOS)
+        td->ctrl &= ~TD_CTRL_ACTIVE;
+
+    if (ret < 0)
+        goto out;
+
+    len = async->packet.result;
+    td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff);
+
+    /* The NAK bit may have been set by a previous frame, so clear it
+       here.  The docs are somewhat unclear, but win2k relies on this
+       behavior.  */
+    td->ctrl &= ~(TD_CTRL_ACTIVE | TD_CTRL_NAK);
+    if (td->ctrl & TD_CTRL_IOC)
+        *int_mask |= 0x01;
+
+    if (pid == USB_TOKEN_IN) {
+        if (len > max_len) {
+            ret = USB_RET_BABBLE;
+            goto out;
+        }
+
+        if ((td->ctrl & TD_CTRL_SPD) && len < max_len) {
+            *int_mask |= 0x02;
+            /* short packet: do not update QH */
+            DPRINTF("uhci: short packet. td 0x%x token 0x%x\n", async->td, async->token);
+            return 1;
+        }
+    }
+
+    /* success */
+    return 0;
+
+out:
+    switch(ret) {
+    case USB_RET_STALL:
+        td->ctrl |= TD_CTRL_STALL;
+        td->ctrl &= ~TD_CTRL_ACTIVE;
+        s->status |= UHCI_STS_USBERR;
+        if (td->ctrl & TD_CTRL_IOC) {
+            *int_mask |= 0x01;
+        }
+        uhci_update_irq(s);
+        return 1;
+
+    case USB_RET_BABBLE:
+        td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL;
+        td->ctrl &= ~TD_CTRL_ACTIVE;
+        s->status |= UHCI_STS_USBERR;
+        if (td->ctrl & TD_CTRL_IOC) {
+            *int_mask |= 0x01;
+        }
+        uhci_update_irq(s);
+        /* frame interrupted */
+        return -1;
+
+    case USB_RET_NAK:
+        td->ctrl |= TD_CTRL_NAK;
+        if (pid == USB_TOKEN_SETUP)
+            break;
+	return 1;
+
+    case USB_RET_IOERROR:
+    case USB_RET_NODEV:
+    default:
+	break;
+    }
+
+    /* Retry the TD if error count is not zero */
+
+    td->ctrl |= TD_CTRL_TIMEOUT;
+    err = (td->ctrl >> TD_CTRL_ERROR_SHIFT) & 3;
+    if (err != 0) {
+        err--;
+        if (err == 0) {
+            td->ctrl &= ~TD_CTRL_ACTIVE;
+            s->status |= UHCI_STS_USBERR;
+            if (td->ctrl & TD_CTRL_IOC)
+                *int_mask |= 0x01;
+            uhci_update_irq(s);
+        }
+    }
+    td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) |
+        (err << TD_CTRL_ERROR_SHIFT);
+    return 1;
+}
+
+static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *int_mask)
+{
+    UHCIAsync *async;
+    int len = 0, max_len;
+    uint8_t pid;
+    USBDevice *dev;
+    USBEndpoint *ep;
+
+    /* Is active ? */
+    if (!(td->ctrl & TD_CTRL_ACTIVE))
+        return 1;
+
+    async = uhci_async_find_td(s, addr, td);
+    if (async) {
+        /* Already submitted */
+        async->queue->valid = 32;
+
+        if (!async->done)
+            return 1;
+
+        uhci_async_unlink(async);
+        goto done;
+    }
+
+    /* Allocate new packet */
+    async = uhci_async_alloc(uhci_queue_get(s, td));
+    if (!async)
+        return 1;
+
+    /* valid needs to be large enough to handle 10 frame delay
+     * for initial isochronous requests
+     */
+    async->queue->valid = 32;
+    async->td    = addr;
+    async->isoc  = td->ctrl & TD_CTRL_IOS;
+
+    max_len = ((td->token >> 21) + 1) & 0x7ff;
+    pid = td->token & 0xff;
+
+    dev = uhci_find_device(s, (td->token >> 8) & 0x7f);
+    ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf);
+    usb_packet_setup(&async->packet, pid, ep);
+    qemu_sglist_add(&async->sgl, td->buffer, max_len);
+    usb_packet_map(&async->packet, &async->sgl);
+
+    switch(pid) {
+    case USB_TOKEN_OUT:
+    case USB_TOKEN_SETUP:
+        len = usb_handle_packet(dev, &async->packet);
+        if (len >= 0)
+            len = max_len;
+        break;
+
+    case USB_TOKEN_IN:
+        len = usb_handle_packet(dev, &async->packet);
+        break;
+
+    default:
+        /* invalid pid : frame interrupted */
+        uhci_async_free(async);
+        s->status |= UHCI_STS_HCPERR;
+        uhci_update_irq(s);
+        return -1;
+    }
+ 
+    if (len == USB_RET_ASYNC) {
+        uhci_async_link(async);
+        return 2;
+    }
+
+    async->packet.result = len;
+
+done:
+    len = uhci_complete_td(s, td, async, int_mask);
+    usb_packet_unmap(&async->packet);
+    uhci_async_free(async);
+    return len;
+}
+
+static void uhci_async_complete(USBPort *port, USBPacket *packet)
+{
+    UHCIAsync *async = container_of(packet, UHCIAsync, packet);
+    UHCIState *s = async->queue->uhci;
+
+    DPRINTF("uhci: async complete. td 0x%x token 0x%x\n", async->td, async->token);
+
+    if (async->isoc) {
+        UHCI_TD td;
+        uint32_t link = async->td;
+        uint32_t int_mask = 0, val;
+
+        pci_dma_read(&s->dev, link & ~0xf, &td, sizeof(td));
+        le32_to_cpus(&td.link);
+        le32_to_cpus(&td.ctrl);
+        le32_to_cpus(&td.token);
+        le32_to_cpus(&td.buffer);
+
+        uhci_async_unlink(async);
+        uhci_complete_td(s, &td, async, &int_mask);
+        s->pending_int_mask |= int_mask;
+
+        /* update the status bits of the TD */
+        val = cpu_to_le32(td.ctrl);
+        pci_dma_write(&s->dev, (link & ~0xf) + 4, &val, sizeof(val));
+        uhci_async_free(async);
+    } else {
+        async->done = 1;
+        uhci_process_frame(s);
+    }
+}
+
+static int is_valid(uint32_t link)
+{
+    return (link & 1) == 0;
+}
+
+static int is_qh(uint32_t link)
+{
+    return (link & 2) != 0;
+}
+
+static int depth_first(uint32_t link)
+{
+    return (link & 4) != 0;
+}
+
+/* QH DB used for detecting QH loops */
+#define UHCI_MAX_QUEUES 128
+typedef struct {
+    uint32_t addr[UHCI_MAX_QUEUES];
+    int      count;
+} QhDb;
+
+static void qhdb_reset(QhDb *db)
+{
+    db->count = 0;
+}
+
+/* Add QH to DB. Returns 1 if already present or DB is full. */
+static int qhdb_insert(QhDb *db, uint32_t addr)
+{
+    int i;
+    for (i = 0; i < db->count; i++)
+        if (db->addr[i] == addr)
+            return 1;
+
+    if (db->count >= UHCI_MAX_QUEUES)
+        return 1;
+
+    db->addr[db->count++] = addr;
+    return 0;
+}
+
+static void uhci_fill_queue(UHCIState *s, UHCI_TD *td)
+{
+    uint32_t int_mask = 0;
+    uint32_t plink = td->link;
+    uint32_t token = uhci_queue_token(td);
+    UHCI_TD ptd;
+    int ret;
+
+    while (is_valid(plink)) {
+        pci_dma_read(&s->dev, plink & ~0xf, &ptd, sizeof(ptd));
+        le32_to_cpus(&ptd.link);
+        le32_to_cpus(&ptd.ctrl);
+        le32_to_cpus(&ptd.token);
+        le32_to_cpus(&ptd.buffer);
+        if (!(ptd.ctrl & TD_CTRL_ACTIVE)) {
+            break;
+        }
+        if (uhci_queue_token(&ptd) != token) {
+            break;
+        }
+        ret = uhci_handle_td(s, plink, &ptd, &int_mask);
+        assert(ret == 2); /* got USB_RET_ASYNC */
+        assert(int_mask == 0);
+        plink = ptd.link;
+    }
+}
+
+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;
+    int cnt, ret;
+    UHCI_TD td;
+    UHCI_QH qh;
+    QhDb qhdb;
+
+    frame_addr = s->fl_base_addr + ((s->frnum & 0x3ff) << 2);
+
+    DPRINTF("uhci: processing frame %d addr 0x%x\n" , s->frnum, frame_addr);
+
+    pci_dma_read(&s->dev, frame_addr, &link, 4);
+    le32_to_cpus(&link);
+
+    int_mask = 0;
+    curr_qh  = 0;
+
+    qhdb_reset(&qhdb);
+
+    for (cnt = FRAME_MAX_LOOPS; is_valid(link) && cnt; cnt--) {
+        if (is_qh(link)) {
+            /* QH */
+
+            if (qhdb_insert(&qhdb, link)) {
+                /*
+                 * 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.
+                 */
+                DPRINTF("uhci: detected loop. qh 0x%x\n", link);
+                if (td_count == 0) {
+                    DPRINTF("uhci: no transaction last round, stop\n");
+                    break;
+                } else if (bytes_count >= 1280) {
+                    DPRINTF("uhci: bandwidth limit reached, stop\n");
+                    break;
+                } else {
+                    td_count = 0;
+                    qhdb_reset(&qhdb);
+                    qhdb_insert(&qhdb, link);
+                }
+            }
+
+            pci_dma_read(&s->dev, link & ~0xf, &qh, sizeof(qh));
+            le32_to_cpus(&qh.link);
+            le32_to_cpus(&qh.el_link);
+
+            DPRINTF("uhci: QH 0x%x load. link 0x%x elink 0x%x\n",
+                    link, qh.link, qh.el_link);
+
+            if (!is_valid(qh.el_link)) {
+                /* QH w/o elements */
+                curr_qh = 0;
+                link = qh.link;
+            } else {
+                /* QH with elements */
+            	curr_qh = link;
+            	link = qh.el_link;
+            }
+            continue;
+        }
+
+        /* TD */
+        pci_dma_read(&s->dev, link & ~0xf, &td, sizeof(td));
+        le32_to_cpus(&td.link);
+        le32_to_cpus(&td.ctrl);
+        le32_to_cpus(&td.token);
+        le32_to_cpus(&td.buffer);
+
+        DPRINTF("uhci: TD 0x%x load. link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n", 
+                link, td.link, td.ctrl, td.token, curr_qh);
+
+        old_td_ctrl = td.ctrl;
+        ret = uhci_handle_td(s, link, &td, &int_mask);
+        if (old_td_ctrl != td.ctrl) {
+            /* update the status bits of the TD */
+            val = cpu_to_le32(td.ctrl);
+            pci_dma_write(&s->dev, (link & ~0xf) + 4, &val, sizeof(val));
+        }
+
+        switch (ret) {
+        case -1: /* interrupted frame */
+            goto out;
+
+        case 1: /* goto next queue */
+            DPRINTF("uhci: TD 0x%x skip. "
+                    "link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n",
+                    link, td.link, td.ctrl, td.token, curr_qh);
+            link = curr_qh ? qh.link : td.link;
+            continue;
+
+        case 2: /* got USB_RET_ASYNC */
+            DPRINTF("uhci: TD 0x%x async. "
+                    "link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n",
+                    link, td.link, td.ctrl, td.token, curr_qh);
+            if (is_valid(td.link)) {
+                uhci_fill_queue(s, &td);
+            }
+            link = curr_qh ? qh.link : td.link;
+            continue;
+
+        case 0: /* completed TD */
+            DPRINTF("uhci: TD 0x%x done. "
+                    "link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n",
+                    link, td.link, td.ctrl, td.token, curr_qh);
+
+            link = td.link;
+            td_count++;
+            bytes_count += (td.ctrl & 0x7ff) + 1;
+
+            if (curr_qh) {
+                /* update QH element link */
+                qh.el_link = link;
+                val = cpu_to_le32(qh.el_link);
+                pci_dma_write(&s->dev, (curr_qh & ~0xf) + 4, &val, sizeof(val));
+
+                if (!depth_first(link)) {
+                    /* done with this QH */
+
+                    DPRINTF("uhci: QH 0x%x done. link 0x%x elink 0x%x\n",
+                            curr_qh, qh.link, qh.el_link);
+
+                    curr_qh = 0;
+                    link    = qh.link;
+                }
+            }
+            break;
+
+        default:
+            assert(!"unknown return code");
+        }
+
+        /* go to the next entry */
+    }
+
+out:
+    s->pending_int_mask |= int_mask;
+}
+
+static void uhci_frame_timer(void *opaque)
+{
+    UHCIState *s = opaque;
+
+    /* prepare the timer for the next frame */
+    s->expire_time += (get_ticks_per_sec() / FRAME_TIMER_FREQ);
+
+    if (!(s->cmd & UHCI_CMD_RS)) {
+        /* Full stop */
+        qemu_del_timer(s->frame_timer);
+        /* set hchalted bit in status - UHCI11D 2.1.2 */
+        s->status |= UHCI_STS_HCHALTED;
+
+        DPRINTF("uhci: halted\n");
+        return;
+    }
+
+    /* Complete the previous frame */
+    if (s->pending_int_mask) {
+        s->status2 |= s->pending_int_mask;
+        s->status  |= UHCI_STS_USBINT;
+        uhci_update_irq(s);
+    }
+    s->pending_int_mask = 0;
+
+    /* Start new frame */
+    s->frnum = (s->frnum + 1) & 0x7ff;
+
+    DPRINTF("uhci: new frame #%u\n" , s->frnum);
+
+    uhci_async_validate_begin(s);
+
+    uhci_process_frame(s);
+
+    uhci_async_validate_end(s);
+
+    qemu_mod_timer(s->frame_timer, s->expire_time);
+}
+
+static const MemoryRegionPortio uhci_portio[] = {
+    { 0, 32, 2, .write = uhci_ioport_writew, },
+    { 0, 32, 2, .read = uhci_ioport_readw, },
+    { 0, 32, 4, .write = uhci_ioport_writel, },
+    { 0, 32, 4, .read = uhci_ioport_readl, },
+    { 0, 32, 1, .write = uhci_ioport_writeb, },
+    { 0, 32, 1, .read = uhci_ioport_readb, },
+    PORTIO_END_OF_LIST()
+};
+
+static const MemoryRegionOps uhci_ioport_ops = {
+    .old_portio = uhci_portio,
+};
+
+static USBPortOps uhci_port_ops = {
+    .attach = uhci_attach,
+    .detach = uhci_detach,
+    .child_detach = uhci_child_detach,
+    .wakeup = uhci_wakeup,
+    .complete = uhci_async_complete,
+};
+
+static USBBusOps uhci_bus_ops = {
+};
+
+static int usb_uhci_common_initfn(PCIDevice *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
+
+    if (s->masterbus) {
+        USBPort *ports[NB_PORTS];
+        for(i = 0; i < NB_PORTS; i++) {
+            ports[i] = &s->ports[i].port;
+        }
+        if (usb_register_companion(s->masterbus, ports, NB_PORTS,
+                s->firstport, s, &uhci_port_ops,
+                USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL) != 0) {
+            return -1;
+        }
+    } else {
+        usb_bus_new(&s->bus, &uhci_bus_ops, &s->dev.qdev);
+        for (i = 0; i < NB_PORTS; i++) {
+            usb_register_port(&s->bus, &s->ports[i].port, s, i, &uhci_port_ops,
+                              USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
+        }
+    }
+    s->frame_timer = qemu_new_timer_ns(vm_clock, uhci_frame_timer, s);
+    s->num_ports_vmstate = NB_PORTS;
+    QTAILQ_INIT(&s->queues);
+
+    qemu_register_reset(uhci_reset, s);
+
+    memory_region_init_io(&s->io_bar, &uhci_ioport_ops, s, "uhci", 0x20);
+    /* Use region 4 for consistency with real hardware.  BSD guests seem
+       to rely on this.  */
+    pci_register_bar(&s->dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar);
+
+    return 0;
+}
+
+static int usb_uhci_vt82c686b_initfn(PCIDevice *dev)
+{
+    UHCIState *s = DO_UPCAST(UHCIState, dev, dev);
+    uint8_t *pci_conf = s->dev.config;
+
+    /* USB misc control 1/2 */
+    pci_set_long(pci_conf + 0x40,0x00001000);
+    /* PM capability */
+    pci_set_long(pci_conf + 0x80,0x00020001);
+    /* USB legacy support  */
+    pci_set_long(pci_conf + 0xc0,0x00002000);
+
+    return usb_uhci_common_initfn(dev);
+}
+
+static int usb_uhci_exit(PCIDevice *dev)
+{
+    UHCIState *s = DO_UPCAST(UHCIState, dev, dev);
+
+    memory_region_destroy(&s->io_bar);
+    return 0;
+}
+
+static Property uhci_properties[] = {
+    DEFINE_PROP_STRING("masterbus", UHCIState, masterbus),
+    DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void piix3_uhci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = usb_uhci_common_initfn;
+    k->exit = usb_uhci_exit;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82371SB_2;
+    k->revision = 0x01;
+    k->class_id = PCI_CLASS_SERIAL_USB;
+    dc->vmsd = &vmstate_uhci;
+    dc->props = uhci_properties;
+}
+
+static TypeInfo piix3_uhci_info = {
+    .name          = "piix3-usb-uhci",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(UHCIState),
+    .class_init    = piix3_uhci_class_init,
+};
+
+static void piix4_uhci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = usb_uhci_common_initfn;
+    k->exit = usb_uhci_exit;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82371AB_2;
+    k->revision = 0x01;
+    k->class_id = PCI_CLASS_SERIAL_USB;
+    dc->vmsd = &vmstate_uhci;
+    dc->props = uhci_properties;
+}
+
+static TypeInfo piix4_uhci_info = {
+    .name          = "piix4-usb-uhci",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(UHCIState),
+    .class_init    = piix4_uhci_class_init,
+};
+
+static void vt82c686b_uhci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = usb_uhci_vt82c686b_initfn;
+    k->exit = usb_uhci_exit;
+    k->vendor_id = PCI_VENDOR_ID_VIA;
+    k->device_id = PCI_DEVICE_ID_VIA_UHCI;
+    k->revision = 0x01;
+    k->class_id = PCI_CLASS_SERIAL_USB;
+    dc->vmsd = &vmstate_uhci;
+    dc->props = uhci_properties;
+}
+
+static TypeInfo vt82c686b_uhci_info = {
+    .name          = "vt82c686b-usb-uhci",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(UHCIState),
+    .class_init    = vt82c686b_uhci_class_init,
+};
+
+static void ich9_uhci1_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = usb_uhci_common_initfn;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI1;
+    k->revision = 0x03;
+    k->class_id = PCI_CLASS_SERIAL_USB;
+    dc->vmsd = &vmstate_uhci;
+    dc->props = uhci_properties;
+}
+
+static TypeInfo ich9_uhci1_info = {
+    .name          = "ich9-usb-uhci1",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(UHCIState),
+    .class_init    = ich9_uhci1_class_init,
+};
+
+static void ich9_uhci2_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = usb_uhci_common_initfn;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI2;
+    k->revision = 0x03;
+    k->class_id = PCI_CLASS_SERIAL_USB;
+    dc->vmsd = &vmstate_uhci;
+    dc->props = uhci_properties;
+}
+
+static TypeInfo ich9_uhci2_info = {
+    .name          = "ich9-usb-uhci2",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(UHCIState),
+    .class_init    = ich9_uhci2_class_init,
+};
+
+static void ich9_uhci3_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = usb_uhci_common_initfn;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI3;
+    k->revision = 0x03;
+    k->class_id = PCI_CLASS_SERIAL_USB;
+    dc->vmsd = &vmstate_uhci;
+    dc->props = uhci_properties;
+}
+
+static TypeInfo ich9_uhci3_info = {
+    .name          = "ich9-usb-uhci3",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(UHCIState),
+    .class_init    = ich9_uhci3_class_init,
+};
+
+static void uhci_register_types(void)
+{
+    type_register_static(&piix3_uhci_info);
+    type_register_static(&piix4_uhci_info);
+    type_register_static(&vt82c686b_uhci_info);
+    type_register_static(&ich9_uhci1_info);
+    type_register_static(&ich9_uhci2_info);
+    type_register_static(&ich9_uhci3_info);
+}
+
+type_init(uhci_register_types)
+
+void usb_uhci_piix3_init(PCIBus *bus, int devfn)
+{
+    pci_create_simple(bus, devfn, "piix3-usb-uhci");
+}
+
+void usb_uhci_piix4_init(PCIBus *bus, int devfn)
+{
+    pci_create_simple(bus, devfn, "piix4-usb-uhci");
+}
+
+void usb_uhci_vt82c686b_init(PCIBus *bus, int devfn)
+{
+    pci_create_simple(bus, devfn, "vt82c686b-usb-uhci");
+}
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
new file mode 100644
index 0000000..73b0c7f
--- /dev/null
+++ b/hw/usb/hcd-xhci.c
@@ -0,0 +1,2925 @@
+/*
+ * USB xHCI controller emulation
+ *
+ * Copyright (c) 2011 Securiforest
+ * Date: 2011-05-11 ;  Author: Hector Martin <hector at marcansoft.com>
+ * Based on usb-ohci.c, emulates Renesas NEC USB 3.0
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "hw/hw.h"
+#include "qemu-timer.h"
+#include "hw/usb.h"
+#include "hw/pci.h"
+#include "hw/qdev-addr.h"
+#include "hw/msi.h"
+
+//#define DEBUG_XHCI
+//#define DEBUG_DATA
+
+#ifdef DEBUG_XHCI
+#define DPRINTF(...) fprintf(stderr, __VA_ARGS__)
+#else
+#define DPRINTF(...) do {} while (0)
+#endif
+#define FIXME() do { fprintf(stderr, "FIXME %s:%d\n", \
+                             __func__, __LINE__); abort(); } while (0)
+
+#define MAXSLOTS 8
+#define MAXINTRS 1
+
+#define USB2_PORTS 4
+#define USB3_PORTS 4
+
+#define MAXPORTS (USB2_PORTS+USB3_PORTS)
+
+#define TD_QUEUE 24
+#define BG_XFERS 8
+#define BG_PKTS 8
+
+/* Very pessimistic, let's hope it's enough for all cases */
+#define EV_QUEUE (((3*TD_QUEUE)+16)*MAXSLOTS)
+/* Do not deliver ER Full events. NEC's driver does some things not bound
+ * to the specs when it gets them */
+#define ER_FULL_HACK
+
+#define LEN_CAP         0x40
+#define OFF_OPER        LEN_CAP
+#define LEN_OPER        (0x400 + 0x10 * MAXPORTS)
+#define OFF_RUNTIME     ((OFF_OPER + LEN_OPER + 0x20) & ~0x1f)
+#define LEN_RUNTIME     (0x20 + MAXINTRS * 0x20)
+#define OFF_DOORBELL    (OFF_RUNTIME + LEN_RUNTIME)
+#define LEN_DOORBELL    ((MAXSLOTS + 1) * 0x20)
+
+/* must be power of 2 */
+#define LEN_REGS        0x2000
+
+#if (OFF_DOORBELL + LEN_DOORBELL) > LEN_REGS
+# error Increase LEN_REGS
+#endif
+
+#if MAXINTRS > 1
+# error TODO: only one interrupter supported
+#endif
+
+/* bit definitions */
+#define USBCMD_RS       (1<<0)
+#define USBCMD_HCRST    (1<<1)
+#define USBCMD_INTE     (1<<2)
+#define USBCMD_HSEE     (1<<3)
+#define USBCMD_LHCRST   (1<<7)
+#define USBCMD_CSS      (1<<8)
+#define USBCMD_CRS      (1<<9)
+#define USBCMD_EWE      (1<<10)
+#define USBCMD_EU3S     (1<<11)
+
+#define USBSTS_HCH      (1<<0)
+#define USBSTS_HSE      (1<<2)
+#define USBSTS_EINT     (1<<3)
+#define USBSTS_PCD      (1<<4)
+#define USBSTS_SSS      (1<<8)
+#define USBSTS_RSS      (1<<9)
+#define USBSTS_SRE      (1<<10)
+#define USBSTS_CNR      (1<<11)
+#define USBSTS_HCE      (1<<12)
+
+
+#define PORTSC_CCS          (1<<0)
+#define PORTSC_PED          (1<<1)
+#define PORTSC_OCA          (1<<3)
+#define PORTSC_PR           (1<<4)
+#define PORTSC_PLS_SHIFT        5
+#define PORTSC_PLS_MASK     0xf
+#define PORTSC_PP           (1<<9)
+#define PORTSC_SPEED_SHIFT      10
+#define PORTSC_SPEED_MASK   0xf
+#define PORTSC_SPEED_FULL   (1<<10)
+#define PORTSC_SPEED_LOW    (2<<10)
+#define PORTSC_SPEED_HIGH   (3<<10)
+#define PORTSC_SPEED_SUPER  (4<<10)
+#define PORTSC_PIC_SHIFT        14
+#define PORTSC_PIC_MASK     0x3
+#define PORTSC_LWS          (1<<16)
+#define PORTSC_CSC          (1<<17)
+#define PORTSC_PEC          (1<<18)
+#define PORTSC_WRC          (1<<19)
+#define PORTSC_OCC          (1<<20)
+#define PORTSC_PRC          (1<<21)
+#define PORTSC_PLC          (1<<22)
+#define PORTSC_CEC          (1<<23)
+#define PORTSC_CAS          (1<<24)
+#define PORTSC_WCE          (1<<25)
+#define PORTSC_WDE          (1<<26)
+#define PORTSC_WOE          (1<<27)
+#define PORTSC_DR           (1<<30)
+#define PORTSC_WPR          (1<<31)
+
+#define CRCR_RCS        (1<<0)
+#define CRCR_CS         (1<<1)
+#define CRCR_CA         (1<<2)
+#define CRCR_CRR        (1<<3)
+
+#define IMAN_IP         (1<<0)
+#define IMAN_IE         (1<<1)
+
+#define ERDP_EHB        (1<<3)
+
+#define TRB_SIZE 16
+typedef struct XHCITRB {
+    uint64_t parameter;
+    uint32_t status;
+    uint32_t control;
+    target_phys_addr_t addr;
+    bool ccs;
+} XHCITRB;
+
+
+typedef enum TRBType {
+    TRB_RESERVED = 0,
+    TR_NORMAL,
+    TR_SETUP,
+    TR_DATA,
+    TR_STATUS,
+    TR_ISOCH,
+    TR_LINK,
+    TR_EVDATA,
+    TR_NOOP,
+    CR_ENABLE_SLOT,
+    CR_DISABLE_SLOT,
+    CR_ADDRESS_DEVICE,
+    CR_CONFIGURE_ENDPOINT,
+    CR_EVALUATE_CONTEXT,
+    CR_RESET_ENDPOINT,
+    CR_STOP_ENDPOINT,
+    CR_SET_TR_DEQUEUE,
+    CR_RESET_DEVICE,
+    CR_FORCE_EVENT,
+    CR_NEGOTIATE_BW,
+    CR_SET_LATENCY_TOLERANCE,
+    CR_GET_PORT_BANDWIDTH,
+    CR_FORCE_HEADER,
+    CR_NOOP,
+    ER_TRANSFER = 32,
+    ER_COMMAND_COMPLETE,
+    ER_PORT_STATUS_CHANGE,
+    ER_BANDWIDTH_REQUEST,
+    ER_DOORBELL,
+    ER_HOST_CONTROLLER,
+    ER_DEVICE_NOTIFICATION,
+    ER_MFINDEX_WRAP,
+    /* vendor specific bits */
+    CR_VENDOR_VIA_CHALLENGE_RESPONSE = 48,
+    CR_VENDOR_NEC_FIRMWARE_REVISION  = 49,
+    CR_VENDOR_NEC_CHALLENGE_RESPONSE = 50,
+} TRBType;
+
+#define CR_LINK TR_LINK
+
+typedef enum TRBCCode {
+    CC_INVALID = 0,
+    CC_SUCCESS,
+    CC_DATA_BUFFER_ERROR,
+    CC_BABBLE_DETECTED,
+    CC_USB_TRANSACTION_ERROR,
+    CC_TRB_ERROR,
+    CC_STALL_ERROR,
+    CC_RESOURCE_ERROR,
+    CC_BANDWIDTH_ERROR,
+    CC_NO_SLOTS_ERROR,
+    CC_INVALID_STREAM_TYPE_ERROR,
+    CC_SLOT_NOT_ENABLED_ERROR,
+    CC_EP_NOT_ENABLED_ERROR,
+    CC_SHORT_PACKET,
+    CC_RING_UNDERRUN,
+    CC_RING_OVERRUN,
+    CC_VF_ER_FULL,
+    CC_PARAMETER_ERROR,
+    CC_BANDWIDTH_OVERRUN,
+    CC_CONTEXT_STATE_ERROR,
+    CC_NO_PING_RESPONSE_ERROR,
+    CC_EVENT_RING_FULL_ERROR,
+    CC_INCOMPATIBLE_DEVICE_ERROR,
+    CC_MISSED_SERVICE_ERROR,
+    CC_COMMAND_RING_STOPPED,
+    CC_COMMAND_ABORTED,
+    CC_STOPPED,
+    CC_STOPPED_LENGTH_INVALID,
+    CC_MAX_EXIT_LATENCY_TOO_LARGE_ERROR = 29,
+    CC_ISOCH_BUFFER_OVERRUN = 31,
+    CC_EVENT_LOST_ERROR,
+    CC_UNDEFINED_ERROR,
+    CC_INVALID_STREAM_ID_ERROR,
+    CC_SECONDARY_BANDWIDTH_ERROR,
+    CC_SPLIT_TRANSACTION_ERROR
+} TRBCCode;
+
+#define TRB_C               (1<<0)
+#define TRB_TYPE_SHIFT          10
+#define TRB_TYPE_MASK       0x3f
+#define TRB_TYPE(t)         (((t).control >> TRB_TYPE_SHIFT) & TRB_TYPE_MASK)
+
+#define TRB_EV_ED           (1<<2)
+
+#define TRB_TR_ENT          (1<<1)
+#define TRB_TR_ISP          (1<<2)
+#define TRB_TR_NS           (1<<3)
+#define TRB_TR_CH           (1<<4)
+#define TRB_TR_IOC          (1<<5)
+#define TRB_TR_IDT          (1<<6)
+#define TRB_TR_TBC_SHIFT        7
+#define TRB_TR_TBC_MASK     0x3
+#define TRB_TR_BEI          (1<<9)
+#define TRB_TR_TLBPC_SHIFT      16
+#define TRB_TR_TLBPC_MASK   0xf
+#define TRB_TR_FRAMEID_SHIFT    20
+#define TRB_TR_FRAMEID_MASK 0x7ff
+#define TRB_TR_SIA          (1<<31)
+
+#define TRB_TR_DIR          (1<<16)
+
+#define TRB_CR_SLOTID_SHIFT     24
+#define TRB_CR_SLOTID_MASK  0xff
+#define TRB_CR_EPID_SHIFT       16
+#define TRB_CR_EPID_MASK    0x1f
+
+#define TRB_CR_BSR          (1<<9)
+#define TRB_CR_DC           (1<<9)
+
+#define TRB_LK_TC           (1<<1)
+
+#define EP_TYPE_MASK        0x7
+#define EP_TYPE_SHIFT           3
+
+#define EP_STATE_MASK       0x7
+#define EP_DISABLED         (0<<0)
+#define EP_RUNNING          (1<<0)
+#define EP_HALTED           (2<<0)
+#define EP_STOPPED          (3<<0)
+#define EP_ERROR            (4<<0)
+
+#define SLOT_STATE_MASK     0x1f
+#define SLOT_STATE_SHIFT        27
+#define SLOT_STATE(s)       (((s)>>SLOT_STATE_SHIFT)&SLOT_STATE_MASK)
+#define SLOT_ENABLED        0
+#define SLOT_DEFAULT        1
+#define SLOT_ADDRESSED      2
+#define SLOT_CONFIGURED     3
+
+#define SLOT_CONTEXT_ENTRIES_MASK 0x1f
+#define SLOT_CONTEXT_ENTRIES_SHIFT 27
+
+typedef enum EPType {
+    ET_INVALID = 0,
+    ET_ISO_OUT,
+    ET_BULK_OUT,
+    ET_INTR_OUT,
+    ET_CONTROL,
+    ET_ISO_IN,
+    ET_BULK_IN,
+    ET_INTR_IN,
+} EPType;
+
+typedef struct XHCIRing {
+    target_phys_addr_t base;
+    target_phys_addr_t dequeue;
+    bool ccs;
+} XHCIRing;
+
+typedef struct XHCIPort {
+    USBPort port;
+    uint32_t portsc;
+} XHCIPort;
+
+struct XHCIState;
+typedef struct XHCIState XHCIState;
+
+typedef struct XHCITransfer {
+    XHCIState *xhci;
+    USBPacket packet;
+    bool running_async;
+    bool running_retry;
+    bool cancelled;
+    bool complete;
+    bool backgrounded;
+    unsigned int iso_pkts;
+    unsigned int slotid;
+    unsigned int epid;
+    bool in_xfer;
+    bool iso_xfer;
+    bool bg_xfer;
+
+    unsigned int trb_count;
+    unsigned int trb_alloced;
+    XHCITRB *trbs;
+
+    unsigned int data_length;
+    unsigned int data_alloced;
+    uint8_t *data;
+
+    TRBCCode status;
+
+    unsigned int pkts;
+    unsigned int pktsize;
+    unsigned int cur_pkt;
+} XHCITransfer;
+
+typedef struct XHCIEPContext {
+    XHCIRing ring;
+    unsigned int next_xfer;
+    unsigned int comp_xfer;
+    XHCITransfer transfers[TD_QUEUE];
+    XHCITransfer *retry;
+    bool bg_running;
+    bool bg_updating;
+    unsigned int next_bg;
+    XHCITransfer bg_transfers[BG_XFERS];
+    EPType type;
+    target_phys_addr_t pctx;
+    unsigned int max_psize;
+    bool has_bg;
+    uint32_t state;
+} XHCIEPContext;
+
+typedef struct XHCISlot {
+    bool enabled;
+    target_phys_addr_t ctx;
+    unsigned int port;
+    unsigned int devaddr;
+    XHCIEPContext * eps[31];
+} XHCISlot;
+
+typedef struct XHCIEvent {
+    TRBType type;
+    TRBCCode ccode;
+    uint64_t ptr;
+    uint32_t length;
+    uint32_t flags;
+    uint8_t slotid;
+    uint8_t epid;
+} XHCIEvent;
+
+struct XHCIState {
+    PCIDevice pci_dev;
+    USBBus bus;
+    qemu_irq irq;
+    MemoryRegion mem;
+    const char *name;
+    uint32_t msi;
+    unsigned int devaddr;
+
+    /* Operational Registers */
+    uint32_t usbcmd;
+    uint32_t usbsts;
+    uint32_t dnctrl;
+    uint32_t crcr_low;
+    uint32_t crcr_high;
+    uint32_t dcbaap_low;
+    uint32_t dcbaap_high;
+    uint32_t config;
+
+    XHCIPort ports[MAXPORTS];
+    XHCISlot slots[MAXSLOTS];
+
+    /* Runtime Registers */
+    uint32_t mfindex;
+    /* note: we only support one interrupter */
+    uint32_t iman;
+    uint32_t imod;
+    uint32_t erstsz;
+    uint32_t erstba_low;
+    uint32_t erstba_high;
+    uint32_t erdp_low;
+    uint32_t erdp_high;
+
+    target_phys_addr_t er_start;
+    uint32_t er_size;
+    bool er_pcs;
+    unsigned int er_ep_idx;
+    bool er_full;
+
+    XHCIEvent ev_buffer[EV_QUEUE];
+    unsigned int ev_buffer_put;
+    unsigned int ev_buffer_get;
+
+    XHCIRing cmd_ring;
+};
+
+typedef struct XHCIEvRingSeg {
+    uint32_t addr_low;
+    uint32_t addr_high;
+    uint32_t size;
+    uint32_t rsvd;
+} XHCIEvRingSeg;
+
+#ifdef DEBUG_XHCI
+static const char *TRBType_names[] = {
+    [TRB_RESERVED]                     = "TRB_RESERVED",
+    [TR_NORMAL]                        = "TR_NORMAL",
+    [TR_SETUP]                         = "TR_SETUP",
+    [TR_DATA]                          = "TR_DATA",
+    [TR_STATUS]                        = "TR_STATUS",
+    [TR_ISOCH]                         = "TR_ISOCH",
+    [TR_LINK]                          = "TR_LINK",
+    [TR_EVDATA]                        = "TR_EVDATA",
+    [TR_NOOP]                          = "TR_NOOP",
+    [CR_ENABLE_SLOT]                   = "CR_ENABLE_SLOT",
+    [CR_DISABLE_SLOT]                  = "CR_DISABLE_SLOT",
+    [CR_ADDRESS_DEVICE]                = "CR_ADDRESS_DEVICE",
+    [CR_CONFIGURE_ENDPOINT]            = "CR_CONFIGURE_ENDPOINT",
+    [CR_EVALUATE_CONTEXT]              = "CR_EVALUATE_CONTEXT",
+    [CR_RESET_ENDPOINT]                = "CR_RESET_ENDPOINT",
+    [CR_STOP_ENDPOINT]                 = "CR_STOP_ENDPOINT",
+    [CR_SET_TR_DEQUEUE]                = "CR_SET_TR_DEQUEUE",
+    [CR_RESET_DEVICE]                  = "CR_RESET_DEVICE",
+    [CR_FORCE_EVENT]                   = "CR_FORCE_EVENT",
+    [CR_NEGOTIATE_BW]                  = "CR_NEGOTIATE_BW",
+    [CR_SET_LATENCY_TOLERANCE]         = "CR_SET_LATENCY_TOLERANCE",
+    [CR_GET_PORT_BANDWIDTH]            = "CR_GET_PORT_BANDWIDTH",
+    [CR_FORCE_HEADER]                  = "CR_FORCE_HEADER",
+    [CR_NOOP]                          = "CR_NOOP",
+    [ER_TRANSFER]                      = "ER_TRANSFER",
+    [ER_COMMAND_COMPLETE]              = "ER_COMMAND_COMPLETE",
+    [ER_PORT_STATUS_CHANGE]            = "ER_PORT_STATUS_CHANGE",
+    [ER_BANDWIDTH_REQUEST]             = "ER_BANDWIDTH_REQUEST",
+    [ER_DOORBELL]                      = "ER_DOORBELL",
+    [ER_HOST_CONTROLLER]               = "ER_HOST_CONTROLLER",
+    [ER_DEVICE_NOTIFICATION]           = "ER_DEVICE_NOTIFICATION",
+    [ER_MFINDEX_WRAP]                  = "ER_MFINDEX_WRAP",
+    [CR_VENDOR_VIA_CHALLENGE_RESPONSE] = "CR_VENDOR_VIA_CHALLENGE_RESPONSE",
+    [CR_VENDOR_NEC_FIRMWARE_REVISION]  = "CR_VENDOR_NEC_FIRMWARE_REVISION",
+    [CR_VENDOR_NEC_CHALLENGE_RESPONSE] = "CR_VENDOR_NEC_CHALLENGE_RESPONSE",
+};
+
+static const char *lookup_name(uint32_t index, const char **list, uint32_t llen)
+{
+    if (index >= llen || list[index] == NULL) {
+        return "???";
+    }
+    return list[index];
+}
+
+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);
+
+static inline target_phys_addr_t xhci_addr64(uint32_t low, uint32_t high)
+{
+#if TARGET_PHYS_ADDR_BITS > 32
+    return low | ((target_phys_addr_t)high << 32);
+#else
+    return low;
+#endif
+}
+
+static inline target_phys_addr_t xhci_mask64(uint64_t addr)
+{
+#if TARGET_PHYS_ADDR_BITS > 32
+    return addr;
+#else
+    return addr & 0xffffffff;
+#endif
+}
+
+static void xhci_irq_update(XHCIState *xhci)
+{
+    int level = 0;
+
+    if (xhci->iman & IMAN_IP && xhci->iman & IMAN_IE &&
+        xhci->usbcmd && USBCMD_INTE) {
+        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");
+            msi_notify(&xhci->pci_dev, 0);
+        }
+    } else {
+        qemu_set_irq(xhci->irq, level);
+    }
+}
+
+static inline int xhci_running(XHCIState *xhci)
+{
+    return !(xhci->usbsts & USBSTS_HCH) && !xhci->er_full;
+}
+
+static void xhci_die(XHCIState *xhci)
+{
+    xhci->usbsts |= USBSTS_HCE;
+    fprintf(stderr, "xhci: asserted controller error\n");
+}
+
+static void xhci_write_event(XHCIState *xhci, XHCIEvent *event)
+{
+    XHCITRB ev_trb;
+    target_phys_addr_t addr;
+
+    ev_trb.parameter = cpu_to_le64(event->ptr);
+    ev_trb.status = cpu_to_le32(event->length | (event->ccode << 24));
+    ev_trb.control = (event->slotid << 24) | (event->epid << 16) |
+                     event->flags | (event->type << TRB_TYPE_SHIFT);
+    if (xhci->er_pcs) {
+        ev_trb.control |= TRB_C;
+    }
+    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));
+
+    addr = xhci->er_start + TRB_SIZE*xhci->er_ep_idx;
+    cpu_physical_memory_write(addr, (uint8_t *) &ev_trb, TRB_SIZE);
+
+    xhci->er_ep_idx++;
+    if (xhci->er_ep_idx >= xhci->er_size) {
+        xhci->er_ep_idx = 0;
+        xhci->er_pcs = !xhci->er_pcs;
+    }
+}
+
+static void xhci_events_update(XHCIState *xhci)
+{
+    target_phys_addr_t erdp;
+    unsigned int dp_idx;
+    bool do_irq = 0;
+
+    if (xhci->usbsts & USBSTS_HCH) {
+        return;
+    }
+
+    erdp = xhci_addr64(xhci->erdp_low, xhci->erdp_high);
+    if (erdp < xhci->er_start ||
+        erdp >= (xhci->er_start + TRB_SIZE*xhci->er_size)) {
+        fprintf(stderr, "xhci: ERDP out of bounds: "TARGET_FMT_plx"\n", erdp);
+        fprintf(stderr, "xhci: ER at "TARGET_FMT_plx" len %d\n",
+                xhci->er_start, xhci->er_size);
+        xhci_die(xhci);
+        return;
+    }
+    dp_idx = (erdp - xhci->er_start) / TRB_SIZE;
+    assert(dp_idx < xhci->er_size);
+
+    /* NEC didn't read section 4.9.4 of the spec (v1.0 p139 top Note) and thus
+     * deadlocks when the ER is full. Hack it by holding off events until
+     * the driver decides to free at least half of the ring */
+    if (xhci->er_full) {
+        int er_free = dp_idx - xhci->er_ep_idx;
+        if (er_free <= 0) {
+            er_free += xhci->er_size;
+        }
+        if (er_free < (xhci->er_size/2)) {
+            DPRINTF("xhci_events_update(): event ring still "
+                    "more than half full (hack)\n");
+            return;
+        }
+    }
+
+    while (xhci->ev_buffer_put != xhci->ev_buffer_get) {
+        assert(xhci->er_full);
+        if (((xhci->er_ep_idx+1) % xhci->er_size) == dp_idx) {
+            DPRINTF("xhci_events_update(): event ring full again\n");
+#ifndef ER_FULL_HACK
+            XHCIEvent full = {ER_HOST_CONTROLLER, CC_EVENT_RING_FULL_ERROR};
+            xhci_write_event(xhci, &full);
+#endif
+            do_irq = 1;
+            break;
+        }
+        XHCIEvent *event = &xhci->ev_buffer[xhci->ev_buffer_get];
+        xhci_write_event(xhci, event);
+        xhci->ev_buffer_get++;
+        do_irq = 1;
+        if (xhci->ev_buffer_get == EV_QUEUE) {
+            xhci->ev_buffer_get = 0;
+        }
+    }
+
+    if (do_irq) {
+        xhci->erdp_low |= ERDP_EHB;
+        xhci->iman |= IMAN_IP;
+        xhci->usbsts |= USBSTS_EINT;
+        xhci_irq_update(xhci);
+    }
+
+    if (xhci->er_full && xhci->ev_buffer_put == xhci->ev_buffer_get) {
+        DPRINTF("xhci_events_update(): event ring no longer full\n");
+        xhci->er_full = 0;
+    }
+    return;
+}
+
+static void xhci_event(XHCIState *xhci, XHCIEvent *event)
+{
+    target_phys_addr_t erdp;
+    unsigned int dp_idx;
+
+    if (xhci->er_full) {
+        DPRINTF("xhci_event(): ER full, queueing\n");
+        if (((xhci->ev_buffer_put+1) % EV_QUEUE) == xhci->ev_buffer_get) {
+            fprintf(stderr, "xhci: event queue full, dropping event!\n");
+            return;
+        }
+        xhci->ev_buffer[xhci->ev_buffer_put++] = *event;
+        if (xhci->ev_buffer_put == EV_QUEUE) {
+            xhci->ev_buffer_put = 0;
+        }
+        return;
+    }
+
+    erdp = xhci_addr64(xhci->erdp_low, xhci->erdp_high);
+    if (erdp < xhci->er_start ||
+        erdp >= (xhci->er_start + TRB_SIZE*xhci->er_size)) {
+        fprintf(stderr, "xhci: ERDP out of bounds: "TARGET_FMT_plx"\n", erdp);
+        fprintf(stderr, "xhci: ER at "TARGET_FMT_plx" len %d\n",
+                xhci->er_start, xhci->er_size);
+        xhci_die(xhci);
+        return;
+    }
+
+    dp_idx = (erdp - xhci->er_start) / TRB_SIZE;
+    assert(dp_idx < xhci->er_size);
+
+    if ((xhci->er_ep_idx+1) % xhci->er_size == dp_idx) {
+        DPRINTF("xhci_event(): ER full, queueing\n");
+#ifndef ER_FULL_HACK
+        XHCIEvent full = {ER_HOST_CONTROLLER, CC_EVENT_RING_FULL_ERROR};
+        xhci_write_event(xhci, &full);
+#endif
+        xhci->er_full = 1;
+        if (((xhci->ev_buffer_put+1) % EV_QUEUE) == xhci->ev_buffer_get) {
+            fprintf(stderr, "xhci: event queue full, dropping event!\n");
+            return;
+        }
+        xhci->ev_buffer[xhci->ev_buffer_put++] = *event;
+        if (xhci->ev_buffer_put == EV_QUEUE) {
+            xhci->ev_buffer_put = 0;
+        }
+    } else {
+        xhci_write_event(xhci, event);
+    }
+
+    xhci->erdp_low |= ERDP_EHB;
+    xhci->iman |= IMAN_IP;
+    xhci->usbsts |= USBSTS_EINT;
+
+    xhci_irq_update(xhci);
+}
+
+static void xhci_ring_init(XHCIState *xhci, XHCIRing *ring,
+                           target_phys_addr_t base)
+{
+    ring->base = base;
+    ring->dequeue = base;
+    ring->ccs = 1;
+}
+
+static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb,
+                               target_phys_addr_t *addr)
+{
+    while (1) {
+        TRBType type;
+        cpu_physical_memory_read(ring->dequeue, (uint8_t *) trb, TRB_SIZE);
+        trb->addr = ring->dequeue;
+        trb->ccs = ring->ccs;
+        le64_to_cpus(&trb->parameter);
+        le32_to_cpus(&trb->status);
+        le32_to_cpus(&trb->control);
+
+        DPRINTF("xhci: TRB fetched [" TARGET_FMT_plx "]: "
+                "%016" PRIx64 " %08x %08x %s\n",
+                ring->dequeue, trb->parameter, trb->status, trb->control,
+                trb_name(trb));
+
+        if ((trb->control & TRB_C) != ring->ccs) {
+            return 0;
+        }
+
+        type = TRB_TYPE(*trb);
+
+        if (type != TR_LINK) {
+            if (addr) {
+                *addr = ring->dequeue;
+            }
+            ring->dequeue += TRB_SIZE;
+            return type;
+        } else {
+            ring->dequeue = xhci_mask64(trb->parameter);
+            if (trb->control & TRB_LK_TC) {
+                ring->ccs = !ring->ccs;
+            }
+        }
+    }
+}
+
+static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring)
+{
+    XHCITRB trb;
+    int length = 0;
+    target_phys_addr_t dequeue = ring->dequeue;
+    bool ccs = ring->ccs;
+    /* hack to bundle together the two/three TDs that make a setup transfer */
+    bool control_td_set = 0;
+
+    while (1) {
+        TRBType type;
+        cpu_physical_memory_read(dequeue, (uint8_t *) &trb, TRB_SIZE);
+        le64_to_cpus(&trb.parameter);
+        le32_to_cpus(&trb.status);
+        le32_to_cpus(&trb.control);
+
+        DPRINTF("xhci: TRB peeked [" TARGET_FMT_plx "]: "
+                "%016" PRIx64 " %08x %08x\n",
+                dequeue, trb.parameter, trb.status, trb.control);
+
+        if ((trb.control & TRB_C) != ccs) {
+            return -length;
+        }
+
+        type = TRB_TYPE(trb);
+
+        if (type == TR_LINK) {
+            dequeue = xhci_mask64(trb.parameter);
+            if (trb.control & TRB_LK_TC) {
+                ccs = !ccs;
+            }
+            continue;
+        }
+
+        length += 1;
+        dequeue += TRB_SIZE;
+
+        if (type == TR_SETUP) {
+            control_td_set = 1;
+        } else if (type == TR_STATUS) {
+            control_td_set = 0;
+        }
+
+        if (!control_td_set && !(trb.control & TRB_TR_CH)) {
+            return length;
+        }
+    }
+}
+
+static void xhci_er_reset(XHCIState *xhci)
+{
+    XHCIEvRingSeg seg;
+
+    /* cache the (sole) event ring segment location */
+    if (xhci->erstsz != 1) {
+        fprintf(stderr, "xhci: invalid value for ERSTSZ: %d\n", xhci->erstsz);
+        xhci_die(xhci);
+        return;
+    }
+    target_phys_addr_t erstba = xhci_addr64(xhci->erstba_low, xhci->erstba_high);
+    cpu_physical_memory_read(erstba, (uint8_t *) &seg, sizeof(seg));
+    le32_to_cpus(&seg.addr_low);
+    le32_to_cpus(&seg.addr_high);
+    le32_to_cpus(&seg.size);
+    if (seg.size < 16 || seg.size > 4096) {
+        fprintf(stderr, "xhci: invalid value for segment size: %d\n", seg.size);
+        xhci_die(xhci);
+        return;
+    }
+    xhci->er_start = xhci_addr64(seg.addr_low, seg.addr_high);
+    xhci->er_size = seg.size;
+
+    xhci->er_ep_idx = 0;
+    xhci->er_pcs = 1;
+    xhci->er_full = 0;
+
+    DPRINTF("xhci: event ring:" TARGET_FMT_plx " [%d]\n",
+            xhci->er_start, xhci->er_size);
+}
+
+static void xhci_run(XHCIState *xhci)
+{
+    DPRINTF("xhci_run()\n");
+
+    xhci->usbsts &= ~USBSTS_HCH;
+}
+
+static void xhci_stop(XHCIState *xhci)
+{
+    DPRINTF("xhci_stop()\n");
+    xhci->usbsts |= USBSTS_HCH;
+    xhci->crcr_low &= ~CRCR_CRR;
+}
+
+static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx,
+                              uint32_t state)
+{
+    uint32_t ctx[5];
+    if (epctx->state == state) {
+        return;
+    }
+
+    cpu_physical_memory_read(epctx->pctx, (uint8_t *) ctx, sizeof(ctx));
+    ctx[0] &= ~EP_STATE_MASK;
+    ctx[0] |= state;
+    ctx[2] = epctx->ring.dequeue | epctx->ring.ccs;
+    ctx[3] = (epctx->ring.dequeue >> 16) >> 16;
+    DPRINTF("xhci: set epctx: " TARGET_FMT_plx " state=%d dequeue=%08x%08x\n",
+            epctx->pctx, state, ctx[3], ctx[2]);
+    cpu_physical_memory_write(epctx->pctx, (uint8_t *) ctx, sizeof(ctx));
+    epctx->state = state;
+}
+
+static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid,
+                               unsigned int epid, target_phys_addr_t pctx,
+                               uint32_t *ctx)
+{
+    XHCISlot *slot;
+    XHCIEPContext *epctx;
+    target_phys_addr_t dequeue;
+    int i;
+
+    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);
+        return CC_TRB_ERROR;
+    }
+
+    epctx = g_malloc(sizeof(XHCIEPContext));
+    memset(epctx, 0, sizeof(XHCIEPContext));
+
+    slot->eps[epid-1] = epctx;
+
+    dequeue = xhci_addr64(ctx[2] & ~0xf, ctx[3]);
+    xhci_ring_init(xhci, &epctx->ring, dequeue);
+    epctx->ring.ccs = ctx[2] & 1;
+
+    epctx->type = (ctx[1] >> EP_TYPE_SHIFT) & EP_TYPE_MASK;
+    DPRINTF("xhci: endpoint %d.%d type is %d\n", epid/2, epid%2, epctx->type);
+    epctx->pctx = pctx;
+    epctx->max_psize = ctx[1]>>16;
+    epctx->max_psize *= 1+((ctx[1]>>8)&0xff);
+    epctx->has_bg = false;
+    if (epctx->type == ET_ISO_IN) {
+        epctx->has_bg = true;
+    }
+    DPRINTF("xhci: endpoint %d.%d max transaction (burst) size is %d\n",
+            epid/2, epid%2, epctx->max_psize);
+    for (i = 0; i < ARRAY_SIZE(epctx->transfers); i++) {
+        usb_packet_init(&epctx->transfers[i].packet);
+    }
+
+    epctx->state = EP_RUNNING;
+    ctx[0] &= ~EP_STATE_MASK;
+    ctx[0] |= EP_RUNNING;
+
+    return CC_SUCCESS;
+}
+
+static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid,
+                               unsigned int epid)
+{
+    XHCISlot *slot;
+    XHCIEPContext *epctx;
+    int i, xferi, killed = 0;
+    assert(slotid >= 1 && slotid <= MAXSLOTS);
+    assert(epid >= 1 && epid <= 31);
+
+    DPRINTF("xhci_ep_nuke_xfers(%d, %d)\n", slotid, epid);
+
+    slot = &xhci->slots[slotid-1];
+
+    if (!slot->eps[epid-1]) {
+        return 0;
+    }
+
+    epctx = slot->eps[epid-1];
+
+    xferi = epctx->next_xfer;
+    for (i = 0; i < TD_QUEUE; i++) {
+        XHCITransfer *t = &epctx->transfers[xferi];
+        if (t->running_async) {
+            usb_cancel_packet(&t->packet);
+            t->running_async = 0;
+            t->cancelled = 1;
+            DPRINTF("xhci: cancelling transfer %d, waiting for it to complete...\n", i);
+            killed++;
+        }
+        if (t->running_retry) {
+            t->running_retry = 0;
+            epctx->retry = NULL;
+        }
+        if (t->backgrounded) {
+            t->backgrounded = 0;
+        }
+        if (t->trbs) {
+            g_free(t->trbs);
+        }
+        if (t->data) {
+            g_free(t->data);
+        }
+
+        t->trbs = NULL;
+        t->data = NULL;
+        t->trb_count = t->trb_alloced = 0;
+        t->data_length = t->data_alloced = 0;
+        xferi = (xferi + 1) % TD_QUEUE;
+    }
+    if (epctx->has_bg) {
+        xferi = epctx->next_bg;
+        for (i = 0; i < BG_XFERS; i++) {
+            XHCITransfer *t = &epctx->bg_transfers[xferi];
+            if (t->running_async) {
+                usb_cancel_packet(&t->packet);
+                t->running_async = 0;
+                t->cancelled = 1;
+                DPRINTF("xhci: cancelling bg transfer %d, waiting for it to complete...\n", i);
+                killed++;
+            }
+            if (t->data) {
+                g_free(t->data);
+            }
+
+            t->data = NULL;
+            xferi = (xferi + 1) % BG_XFERS;
+        }
+    }
+    return killed;
+}
+
+static TRBCCode xhci_disable_ep(XHCIState *xhci, unsigned int slotid,
+                               unsigned int epid)
+{
+    XHCISlot *slot;
+    XHCIEPContext *epctx;
+
+    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]) {
+        DPRINTF("xhci: slot %d ep %d already disabled\n", slotid, epid);
+        return CC_SUCCESS;
+    }
+
+    xhci_ep_nuke_xfers(xhci, slotid, epid);
+
+    epctx = slot->eps[epid-1];
+
+    xhci_set_ep_state(xhci, epctx, EP_DISABLED);
+
+    g_free(epctx);
+    slot->eps[epid-1] = NULL;
+
+    return CC_SUCCESS;
+}
+
+static TRBCCode xhci_stop_ep(XHCIState *xhci, unsigned int slotid,
+                             unsigned int epid)
+{
+    XHCISlot *slot;
+    XHCIEPContext *epctx;
+
+    DPRINTF("xhci_stop_ep(%d, %d)\n", slotid, epid);
+
+    assert(slotid >= 1 && slotid <= MAXSLOTS);
+
+    if (epid < 1 || epid > 31) {
+        fprintf(stderr, "xhci: bad ep %d\n", epid);
+        return CC_TRB_ERROR;
+    }
+
+    slot = &xhci->slots[slotid-1];
+
+    if (!slot->eps[epid-1]) {
+        DPRINTF("xhci: slot %d ep %d not enabled\n", slotid, epid);
+        return CC_EP_NOT_ENABLED_ERROR;
+    }
+
+    if (xhci_ep_nuke_xfers(xhci, slotid, epid) > 0) {
+        fprintf(stderr, "xhci: FIXME: endpoint stopped w/ xfers running, "
+                "data might be lost\n");
+    }
+
+    epctx = slot->eps[epid-1];
+
+    xhci_set_ep_state(xhci, epctx, EP_STOPPED);
+
+    return CC_SUCCESS;
+}
+
+static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigned int slotid,
+                              unsigned int epid)
+{
+    XHCISlot *slot;
+    XHCIEPContext *epctx;
+    USBDevice *dev;
+
+    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;
+    }
+
+    slot = &xhci->slots[slotid-1];
+
+    if (!slot->eps[epid-1]) {
+        DPRINTF("xhci: slot %d ep %d not enabled\n", slotid, epid);
+        return CC_EP_NOT_ENABLED_ERROR;
+    }
+
+    epctx = slot->eps[epid-1];
+
+    if (epctx->state != EP_HALTED) {
+        fprintf(stderr, "xhci: reset EP while EP %d not halted (%d)\n",
+                epid, epctx->state);
+        return CC_CONTEXT_STATE_ERROR;
+    }
+
+    if (xhci_ep_nuke_xfers(xhci, slotid, epid) > 0) {
+        fprintf(stderr, "xhci: FIXME: endpoint reset w/ xfers running, "
+                "data might be lost\n");
+    }
+
+    uint8_t ep = epid>>1;
+
+    if (epid & 1) {
+        ep |= 0x80;
+    }
+
+    dev = xhci->ports[xhci->slots[slotid-1].port-1].port.dev;
+    if (!dev) {
+        return CC_USB_TRANSACTION_ERROR;
+    }
+
+    xhci_set_ep_state(xhci, epctx, EP_STOPPED);
+
+    return CC_SUCCESS;
+}
+
+static TRBCCode xhci_set_ep_dequeue(XHCIState *xhci, unsigned int slotid,
+                                    unsigned int epid, uint64_t pdequeue)
+{
+    XHCISlot *slot;
+    XHCIEPContext *epctx;
+    target_phys_addr_t dequeue;
+
+    assert(slotid >= 1 && slotid <= MAXSLOTS);
+
+    if (epid < 1 || epid > 31) {
+        fprintf(stderr, "xhci: bad ep %d\n", epid);
+        return CC_TRB_ERROR;
+    }
+
+    DPRINTF("xhci_set_ep_dequeue(%d, %d, %016"PRIx64")\n", slotid, epid, pdequeue);
+    dequeue = xhci_mask64(pdequeue);
+
+    slot = &xhci->slots[slotid-1];
+
+    if (!slot->eps[epid-1]) {
+        DPRINTF("xhci: slot %d ep %d not enabled\n", slotid, epid);
+        return CC_EP_NOT_ENABLED_ERROR;
+    }
+
+    epctx = slot->eps[epid-1];
+
+
+    if (epctx->state != EP_STOPPED) {
+        fprintf(stderr, "xhci: set EP dequeue pointer while EP %d not stopped\n", epid);
+        return CC_CONTEXT_STATE_ERROR;
+    }
+
+    xhci_ring_init(xhci, &epctx->ring, dequeue & ~0xF);
+    epctx->ring.ccs = dequeue & 1;
+
+    xhci_set_ep_state(xhci, epctx, EP_STOPPED);
+
+    return CC_SUCCESS;
+}
+
+static int xhci_xfer_data(XHCITransfer *xfer, uint8_t *data,
+                          unsigned int length, bool in_xfer, bool out_xfer,
+                          bool report)
+{
+    int i;
+    uint32_t edtla = 0;
+    unsigned int transferred = 0;
+    unsigned int left = length;
+    bool reported = 0;
+    bool shortpkt = 0;
+    XHCIEvent event = {ER_TRANSFER, CC_SUCCESS};
+    XHCIState *xhci = xfer->xhci;
+
+    DPRINTF("xhci_xfer_data(len=%d, in_xfer=%d, out_xfer=%d, report=%d)\n",
+            length, in_xfer, out_xfer, report);
+
+    assert(!(in_xfer && out_xfer));
+
+    for (i = 0; i < xfer->trb_count; i++) {
+        XHCITRB *trb = &xfer->trbs[i];
+        target_phys_addr_t addr;
+        unsigned int chunk = 0;
+
+        switch (TRB_TYPE(*trb)) {
+        case TR_DATA:
+            if ((!(trb->control & TRB_TR_DIR)) != (!in_xfer)) {
+                fprintf(stderr, "xhci: data direction mismatch for TR_DATA\n");
+                xhci_die(xhci);
+                return transferred;
+            }
+            /* fallthrough */
+        case TR_NORMAL:
+        case TR_ISOCH:
+            addr = xhci_mask64(trb->parameter);
+            chunk = trb->status & 0x1ffff;
+            if (chunk > left) {
+                chunk = left;
+                shortpkt = 1;
+            }
+            if (in_xfer || out_xfer) {
+                if (trb->control & TRB_TR_IDT) {
+                    uint64_t idata;
+                    if (chunk > 8 || in_xfer) {
+                        fprintf(stderr, "xhci: invalid immediate data TRB\n");
+                        xhci_die(xhci);
+                        return transferred;
+                    }
+                    idata = le64_to_cpu(trb->parameter);
+                    memcpy(data, &idata, chunk);
+                } else {
+                    DPRINTF("xhci_xfer_data: r/w(%d) %d bytes at "
+                            TARGET_FMT_plx "\n", in_xfer, chunk, addr);
+                    if (in_xfer) {
+                        cpu_physical_memory_write(addr, data, chunk);
+                    } else {
+                        cpu_physical_memory_read(addr, data, chunk);
+                    }
+#ifdef DEBUG_DATA
+                    unsigned int count = chunk;
+                    int i;
+                    if (count > 16) {
+                        count = 16;
+                    }
+                    DPRINTF(" ::");
+                    for (i = 0; i < count; i++) {
+                        DPRINTF(" %02x", data[i]);
+                    }
+                    DPRINTF("\n");
+#endif
+                }
+            }
+            left -= chunk;
+            data += chunk;
+            edtla += chunk;
+            transferred += chunk;
+            break;
+        case TR_STATUS:
+            reported = 0;
+            shortpkt = 0;
+            break;
+        }
+
+        if (report && !reported && (trb->control & TRB_TR_IOC ||
+            (shortpkt && (trb->control & TRB_TR_ISP)))) {
+            event.slotid = xfer->slotid;
+            event.epid = xfer->epid;
+            event.length = (trb->status & 0x1ffff) - chunk;
+            event.flags = 0;
+            event.ptr = trb->addr;
+            if (xfer->status == CC_SUCCESS) {
+                event.ccode = shortpkt ? CC_SHORT_PACKET : CC_SUCCESS;
+            } else {
+                event.ccode = xfer->status;
+            }
+            if (TRB_TYPE(*trb) == TR_EVDATA) {
+                event.ptr = trb->parameter;
+                event.flags |= TRB_EV_ED;
+                event.length = edtla & 0xffffff;
+                DPRINTF("xhci_xfer_data: EDTLA=%d\n", event.length);
+                edtla = 0;
+            }
+            xhci_event(xhci, &event);
+            reported = 1;
+        }
+    }
+    return transferred;
+}
+
+static void xhci_stall_ep(XHCITransfer *xfer)
+{
+    XHCIState *xhci = xfer->xhci;
+    XHCISlot *slot = &xhci->slots[xfer->slotid-1];
+    XHCIEPContext *epctx = slot->eps[xfer->epid-1];
+
+    epctx->ring.dequeue = xfer->trbs[0].addr;
+    epctx->ring.ccs = xfer->trbs[0].ccs;
+    xhci_set_ep_state(xhci, epctx, EP_HALTED);
+    DPRINTF("xhci: stalled slot %d ep %d\n", xfer->slotid, xfer->epid);
+    DPRINTF("xhci: will continue at "TARGET_FMT_plx"\n", epctx->ring.dequeue);
+}
+
+static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer,
+                       XHCIEPContext *epctx);
+
+static void xhci_bg_update(XHCIState *xhci, XHCIEPContext *epctx)
+{
+    if (epctx->bg_updating) {
+        return;
+    }
+    DPRINTF("xhci_bg_update(%p, %p)\n", xhci, epctx);
+    assert(epctx->has_bg);
+    DPRINTF("xhci: fg=%d bg=%d\n", epctx->comp_xfer, epctx->next_bg);
+    epctx->bg_updating = 1;
+    while (epctx->transfers[epctx->comp_xfer].backgrounded &&
+           epctx->bg_transfers[epctx->next_bg].complete) {
+        XHCITransfer *fg = &epctx->transfers[epctx->comp_xfer];
+        XHCITransfer *bg = &epctx->bg_transfers[epctx->next_bg];
+#if 0
+        DPRINTF("xhci: completing fg %d from bg %d.%d (stat: %d)\n",
+                epctx->comp_xfer, epctx->next_bg, bg->cur_pkt,
+                bg->usbxfer->iso_packet_desc[bg->cur_pkt].status
+               );
+#endif
+        assert(epctx->type == ET_ISO_IN);
+        assert(bg->iso_xfer);
+        assert(bg->in_xfer);
+        uint8_t *p = bg->data + bg->cur_pkt * bg->pktsize;
+#if 0
+        int len = bg->usbxfer->iso_packet_desc[bg->cur_pkt].actual_length;
+        fg->status = libusb_to_ccode(bg->usbxfer->iso_packet_desc[bg->cur_pkt].status);
+#else
+        int len = 0;
+        FIXME();
+#endif
+        fg->complete = 1;
+        fg->backgrounded = 0;
+
+        if (fg->status == CC_STALL_ERROR) {
+            xhci_stall_ep(fg);
+        }
+
+        xhci_xfer_data(fg, p, len, 1, 0, 1);
+
+        epctx->comp_xfer++;
+        if (epctx->comp_xfer == TD_QUEUE) {
+            epctx->comp_xfer = 0;
+        }
+        DPRINTF("next fg xfer: %d\n", epctx->comp_xfer);
+        bg->cur_pkt++;
+        if (bg->cur_pkt == bg->pkts) {
+            bg->complete = 0;
+            if (xhci_submit(xhci, bg, epctx) < 0) {
+                fprintf(stderr, "xhci: bg resubmit failed\n");
+            }
+            epctx->next_bg++;
+            if (epctx->next_bg == BG_XFERS) {
+                epctx->next_bg = 0;
+            }
+            DPRINTF("next bg xfer: %d\n", epctx->next_bg);
+
+        xhci_kick_ep(xhci, fg->slotid, fg->epid);
+        }
+    }
+    epctx->bg_updating = 0;
+}
+
+#if 0
+static void xhci_xfer_cb(struct libusb_transfer *transfer)
+{
+    XHCIState *xhci;
+    XHCITransfer *xfer;
+
+    xfer = (XHCITransfer *)transfer->user_data;
+    xhci = xfer->xhci;
+
+    DPRINTF("xhci_xfer_cb(slot=%d, ep=%d, status=%d)\n", xfer->slotid,
+            xfer->epid, transfer->status);
+
+    assert(xfer->slotid >= 1 && xfer->slotid <= MAXSLOTS);
+    assert(xfer->epid >= 1 && xfer->epid <= 31);
+
+    if (xfer->cancelled) {
+        DPRINTF("xhci: transfer cancelled, not reporting anything\n");
+        xfer->running = 0;
+        return;
+    }
+
+    XHCIEPContext *epctx;
+    XHCISlot *slot;
+    slot = &xhci->slots[xfer->slotid-1];
+    assert(slot->eps[xfer->epid-1]);
+    epctx = slot->eps[xfer->epid-1];
+
+    if (xfer->bg_xfer) {
+        DPRINTF("xhci: background transfer, updating\n");
+        xfer->complete = 1;
+        xfer->running = 0;
+        xhci_bg_update(xhci, epctx);
+        return;
+    }
+
+    if (xfer->iso_xfer) {
+        transfer->status = transfer->iso_packet_desc[0].status;
+        transfer->actual_length = transfer->iso_packet_desc[0].actual_length;
+    }
+
+    xfer->status = libusb_to_ccode(transfer->status);
+
+    xfer->complete = 1;
+    xfer->running = 0;
+
+    if (transfer->status == LIBUSB_TRANSFER_STALL)
+        xhci_stall_ep(xhci, epctx, xfer);
+
+    DPRINTF("xhci: transfer actual length = %d\n", transfer->actual_length);
+
+    if (xfer->in_xfer) {
+        if (xfer->epid == 1) {
+            xhci_xfer_data(xhci, xfer, xfer->data + 8,
+                           transfer->actual_length, 1, 0, 1);
+        } else {
+            xhci_xfer_data(xhci, xfer, xfer->data,
+                           transfer->actual_length, 1, 0, 1);
+        }
+    } else {
+        xhci_xfer_data(xhci, xfer, NULL, transfer->actual_length, 0, 0, 1);
+    }
+
+    xhci_kick_ep(xhci, xfer->slotid, xfer->epid);
+}
+
+static int xhci_hle_control(XHCIState *xhci, XHCITransfer *xfer,
+                            uint8_t bmRequestType, uint8_t bRequest,
+                            uint16_t wValue, uint16_t wIndex, uint16_t wLength)
+{
+    uint16_t type_req = (bmRequestType << 8) | bRequest;
+
+    switch (type_req) {
+        case 0x0000 | USB_REQ_SET_CONFIGURATION:
+            DPRINTF("xhci: HLE switch configuration\n");
+            return xhci_switch_config(xhci, xfer->slotid, wValue) == 0;
+        case 0x0100 | USB_REQ_SET_INTERFACE:
+            DPRINTF("xhci: HLE set interface altsetting\n");
+            return xhci_set_iface_alt(xhci, xfer->slotid, wIndex, wValue) == 0;
+        case 0x0200 | USB_REQ_CLEAR_FEATURE:
+            if (wValue == 0) { // endpoint halt
+                DPRINTF("xhci: HLE clear halt\n");
+                return xhci_clear_halt(xhci, xfer->slotid, wIndex);
+            }
+        case 0x0000 | USB_REQ_SET_ADDRESS:
+            fprintf(stderr, "xhci: warn: illegal SET_ADDRESS request\n");
+            return 0;
+        default:
+            return 0;
+    }
+}
+#endif
+
+static int xhci_setup_packet(XHCITransfer *xfer, USBDevice *dev)
+{
+    USBEndpoint *ep;
+    int dir;
+
+    dir = xfer->in_xfer ? USB_TOKEN_IN : USB_TOKEN_OUT;
+    ep = usb_ep_get(dev, dir, xfer->epid >> 1);
+    usb_packet_setup(&xfer->packet, dir, ep);
+    usb_packet_addbuf(&xfer->packet, xfer->data, xfer->data_length);
+    DPRINTF("xhci: setup packet pid 0x%x addr %d ep %d\n",
+            xfer->packet.pid, dev->addr, ep->nr);
+    return 0;
+}
+
+static int xhci_complete_packet(XHCITransfer *xfer, int ret)
+{
+    if (ret == USB_RET_ASYNC) {
+        xfer->running_async = 1;
+        xfer->running_retry = 0;
+        xfer->complete = 0;
+        xfer->cancelled = 0;
+        return 0;
+    } else if (ret == USB_RET_NAK) {
+        xfer->running_async = 0;
+        xfer->running_retry = 1;
+        xfer->complete = 0;
+        xfer->cancelled = 0;
+        return 0;
+    } else {
+        xfer->running_async = 0;
+        xfer->running_retry = 0;
+        xfer->complete = 1;
+    }
+
+    if (ret >= 0) {
+        xfer->status = CC_SUCCESS;
+        xhci_xfer_data(xfer, xfer->data, ret, xfer->in_xfer, 0, 1);
+        return 0;
+    }
+
+    /* error */
+    switch (ret) {
+    case USB_RET_NODEV:
+        xfer->status = CC_USB_TRANSACTION_ERROR;
+        xhci_xfer_data(xfer, xfer->data, 0, xfer->in_xfer, 0, 1);
+        xhci_stall_ep(xfer);
+        break;
+    case USB_RET_STALL:
+        xfer->status = CC_STALL_ERROR;
+        xhci_xfer_data(xfer, xfer->data, 0, xfer->in_xfer, 0, 1);
+        xhci_stall_ep(xfer);
+        break;
+    default:
+        fprintf(stderr, "%s: FIXME: ret = %d\n", __FUNCTION__, ret);
+        FIXME();
+    }
+    return 0;
+}
+
+static USBDevice *xhci_find_device(XHCIPort *port, uint8_t addr)
+{
+    if (!(port->portsc & PORTSC_PED)) {
+        return NULL;
+    }
+    return usb_find_device(&port->port, addr);
+}
+
+static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
+{
+    XHCITRB *trb_setup, *trb_status;
+    uint8_t bmRequestType;
+    uint16_t wLength;
+    XHCIPort *port;
+    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];
+
+    /* at most one Event Data TRB allowed after STATUS */
+    if (TRB_TYPE(*trb_status) == TR_EVDATA && xfer->trb_count > 2) {
+        trb_status--;
+    }
+
+    /* do some sanity checks */
+    if (TRB_TYPE(*trb_setup) != TR_SETUP) {
+        fprintf(stderr, "xhci: ep0 first TD not SETUP: %d\n",
+                TRB_TYPE(*trb_setup));
+        return -1;
+    }
+    if (TRB_TYPE(*trb_status) != TR_STATUS) {
+        fprintf(stderr, "xhci: ep0 last TD not STATUS: %d\n",
+                TRB_TYPE(*trb_status));
+        return -1;
+    }
+    if (!(trb_setup->control & TRB_TR_IDT)) {
+        fprintf(stderr, "xhci: Setup TRB doesn't have IDT set\n");
+        return -1;
+    }
+    if ((trb_setup->status & 0x1ffff) != 8) {
+        fprintf(stderr, "xhci: Setup TRB has bad length (%d)\n",
+                (trb_setup->status & 0x1ffff));
+        return -1;
+    }
+
+    bmRequestType = trb_setup->parameter;
+    wLength = trb_setup->parameter >> 48;
+
+    if (xfer->data && xfer->data_alloced < wLength) {
+        xfer->data_alloced = 0;
+        g_free(xfer->data);
+        xfer->data = NULL;
+    }
+    if (!xfer->data) {
+        DPRINTF("xhci: alloc %d bytes data\n", wLength);
+        xfer->data = g_malloc(wLength+1);
+        xfer->data_alloced = wLength;
+    }
+    xfer->data_length = wLength;
+
+    port = &xhci->ports[xhci->slots[xfer->slotid-1].port-1];
+    dev = xhci_find_device(port, xhci->slots[xfer->slotid-1].devaddr);
+    if (!dev) {
+        fprintf(stderr, "xhci: slot %d port %d has no device\n", xfer->slotid,
+                xhci->slots[xfer->slotid-1].port);
+        return -1;
+    }
+
+    xfer->in_xfer = bmRequestType & USB_DIR_IN;
+    xfer->iso_xfer = false;
+
+    xhci_setup_packet(xfer, dev);
+    xfer->packet.parameter = trb_setup->parameter;
+    if (!xfer->in_xfer) {
+        xhci_xfer_data(xfer, xfer->data, wLength, 0, 1, 0);
+    }
+
+    ret = usb_handle_packet(dev, &xfer->packet);
+
+    xhci_complete_packet(xfer, ret);
+    if (!xfer->running_async && !xfer->running_retry) {
+        xhci_kick_ep(xhci, xfer->slotid, xfer->epid);
+    }
+    return 0;
+}
+
+static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx)
+{
+    XHCIPort *port;
+    USBDevice *dev;
+    int ret;
+
+    DPRINTF("xhci_submit(slotid=%d,epid=%d)\n", xfer->slotid, xfer->epid);
+
+    xfer->in_xfer = epctx->type>>2;
+
+    if (xfer->data && xfer->data_alloced < xfer->data_length) {
+        xfer->data_alloced = 0;
+        g_free(xfer->data);
+        xfer->data = NULL;
+    }
+    if (!xfer->data && xfer->data_length) {
+        DPRINTF("xhci: alloc %d bytes data\n", xfer->data_length);
+        xfer->data = g_malloc(xfer->data_length);
+        xfer->data_alloced = xfer->data_length;
+    }
+    if (epctx->type == ET_ISO_IN || epctx->type == ET_ISO_OUT) {
+        if (!xfer->bg_xfer) {
+            xfer->pkts = 1;
+        }
+    } else {
+        xfer->pkts = 0;
+    }
+
+    port = &xhci->ports[xhci->slots[xfer->slotid-1].port-1];
+    dev = xhci_find_device(port, xhci->slots[xfer->slotid-1].devaddr);
+    if (!dev) {
+        fprintf(stderr, "xhci: slot %d port %d has no device\n", xfer->slotid,
+                xhci->slots[xfer->slotid-1].port);
+        return -1;
+    }
+
+    xhci_setup_packet(xfer, dev);
+
+    switch(epctx->type) {
+    case ET_INTR_OUT:
+    case ET_INTR_IN:
+    case ET_BULK_OUT:
+    case ET_BULK_IN:
+        break;
+    case ET_ISO_OUT:
+    case ET_ISO_IN:
+        FIXME();
+        break;
+    default:
+        fprintf(stderr, "xhci: unknown or unhandled EP "
+                "(type %d, in %d, ep %02x)\n",
+                epctx->type, xfer->in_xfer, xfer->epid);
+        return -1;
+    }
+
+    if (!xfer->in_xfer) {
+        xhci_xfer_data(xfer, xfer->data, xfer->data_length, 0, 1, 0);
+    }
+    ret = usb_handle_packet(dev, &xfer->packet);
+
+    xhci_complete_packet(xfer, ret);
+    if (!xfer->running_async && !xfer->running_retry) {
+        xhci_kick_ep(xhci, xfer->slotid, xfer->epid);
+    }
+    return 0;
+}
+
+static int xhci_fire_transfer(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx)
+{
+    int i;
+    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);
+
+    if (!epctx->has_bg) {
+        xfer->data_length = length;
+        xfer->backgrounded = 0;
+        return xhci_submit(xhci, xfer, epctx);
+    } else {
+        if (!epctx->bg_running) {
+            for (i = 0; i < BG_XFERS; i++) {
+                XHCITransfer *t = &epctx->bg_transfers[i];
+                t->xhci = xhci;
+                t->epid = xfer->epid;
+                t->slotid = xfer->slotid;
+                t->pkts = BG_PKTS;
+                t->pktsize = epctx->max_psize;
+                t->data_length = t->pkts * t->pktsize;
+                t->bg_xfer = 1;
+                if (xhci_submit(xhci, t, epctx) < 0) {
+                    fprintf(stderr, "xhci: bg submit failed\n");
+                    return -1;
+                }
+            }
+            epctx->bg_running = 1;
+        }
+        xfer->backgrounded = 1;
+        xhci_bg_update(xhci, epctx);
+        return 0;
+    }
+}
+
+static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid)
+{
+    XHCIEPContext *epctx;
+    int length;
+    int i;
+
+    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);
+        return;
+    }
+    epctx = xhci->slots[slotid-1].eps[epid-1];
+    if (!epctx) {
+        fprintf(stderr, "xhci: xhci_kick_ep for disabled endpoint %d,%d\n",
+                epid, slotid);
+        return;
+    }
+
+    if (epctx->retry) {
+        /* retry nak'ed transfer */
+        XHCITransfer *xfer = epctx->retry;
+        int result;
+
+        DPRINTF("xhci: retry nack'ed transfer ...\n");
+        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;
+    }
+
+    if (epctx->state == EP_HALTED) {
+        DPRINTF("xhci: ep halted, not running schedule\n");
+        return;
+    }
+
+    xhci_set_ep_state(xhci, epctx, EP_RUNNING);
+
+    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;
+            g_free(xfer->trbs);
+            xfer->trbs = NULL;
+        }
+        if (!xfer->trbs) {
+            xfer->trbs = g_malloc(sizeof(XHCITRB) * length);
+            xfer->trb_alloced = length;
+        }
+        xfer->trb_count = length;
+
+        for (i = 0; i < length; i++) {
+            assert(xhci_ring_fetch(xhci, &epctx->ring, &xfer->trbs[i], NULL));
+        }
+        xfer->xhci = xhci;
+        xfer->epid = epid;
+        xfer->slotid = slotid;
+
+        if (epid == 1) {
+            if (xhci_fire_ctl_transfer(xhci, xfer) >= 0) {
+                epctx->next_xfer = (epctx->next_xfer + 1) % TD_QUEUE;
+            } else {
+                fprintf(stderr, "xhci: error firing CTL transfer\n");
+            }
+        } else {
+            if (xhci_fire_transfer(xhci, xfer, epctx) >= 0) {
+                epctx->next_xfer = (epctx->next_xfer + 1) % TD_QUEUE;
+            } else {
+                fprintf(stderr, "xhci: error firing data transfer\n");
+            }
+        }
+
+        if (epctx->state == EP_HALTED) {
+            DPRINTF("xhci: ep halted, stopping schedule\n");
+            break;
+        }
+        if (xfer->running_retry) {
+            DPRINTF("xhci: xfer nacked, stopping schedule\n");
+            epctx->retry = xfer;
+            break;
+        }
+    }
+}
+
+static TRBCCode xhci_enable_slot(XHCIState *xhci, unsigned int 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);
+
+    return CC_SUCCESS;
+}
+
+static TRBCCode xhci_disable_slot(XHCIState *xhci, unsigned int slotid)
+{
+    int i;
+
+    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]) {
+            xhci_disable_ep(xhci, slotid, i);
+        }
+    }
+
+    xhci->slots[slotid-1].enabled = 0;
+    return CC_SUCCESS;
+}
+
+static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
+                                  uint64_t pictx, bool bsr)
+{
+    XHCISlot *slot;
+    USBDevice *dev;
+    target_phys_addr_t ictx, octx, dcbaap;
+    uint64_t poctx;
+    uint32_t ictl_ctx[2];
+    uint32_t slot_ctx[4];
+    uint32_t ep0_ctx[5];
+    unsigned int port;
+    int i;
+    TRBCCode res;
+
+    assert(slotid >= 1 && slotid <= MAXSLOTS);
+    DPRINTF("xhci_address_slot(%d)\n", slotid);
+
+    dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high);
+    cpu_physical_memory_read(dcbaap + 8*slotid,
+                             (uint8_t *) &poctx, sizeof(poctx));
+    ictx = xhci_mask64(pictx);
+    octx = xhci_mask64(le64_to_cpu(poctx));
+
+    DPRINTF("xhci: input context at "TARGET_FMT_plx"\n", ictx);
+    DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx);
+
+    cpu_physical_memory_read(ictx, (uint8_t *) ictl_ctx, sizeof(ictl_ctx));
+
+    if (ictl_ctx[0] != 0x0 || ictl_ctx[1] != 0x3) {
+        fprintf(stderr, "xhci: invalid input context control %08x %08x\n",
+                ictl_ctx[0], ictl_ctx[1]);
+        return CC_TRB_ERROR;
+    }
+
+    cpu_physical_memory_read(ictx+32, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+    cpu_physical_memory_read(ictx+64, (uint8_t *) ep0_ctx, sizeof(ep0_ctx));
+
+    DPRINTF("xhci: input slot context: %08x %08x %08x %08x\n",
+            slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
+
+    DPRINTF("xhci: input ep0 context: %08x %08x %08x %08x %08x\n",
+            ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]);
+
+    port = (slot_ctx[1]>>16) & 0xFF;
+    dev = xhci->ports[port-1].port.dev;
+
+    if (port < 1 || port > MAXPORTS) {
+        fprintf(stderr, "xhci: bad port %d\n", port);
+        return CC_TRB_ERROR;
+    } else if (!dev) {
+        fprintf(stderr, "xhci: port %d not connected\n", port);
+        return CC_USB_TRANSACTION_ERROR;
+    }
+
+    for (i = 0; i < MAXSLOTS; i++) {
+        if (xhci->slots[i].port == port) {
+            fprintf(stderr, "xhci: port %d already assigned to slot %d\n",
+                    port, i+1);
+            return CC_TRB_ERROR;
+        }
+    }
+
+    slot = &xhci->slots[slotid-1];
+    slot->port = port;
+    slot->ctx = octx;
+
+    if (bsr) {
+        slot_ctx[3] = SLOT_DEFAULT << SLOT_STATE_SHIFT;
+    } else {
+        slot->devaddr = xhci->devaddr++;
+        slot_ctx[3] = (SLOT_ADDRESSED << SLOT_STATE_SHIFT) | slot->devaddr;
+        DPRINTF("xhci: device address is %d\n", slot->devaddr);
+        usb_device_handle_control(dev, NULL,
+                                  DeviceOutRequest | USB_REQ_SET_ADDRESS,
+                                  slot->devaddr, 0, 0, NULL);
+    }
+
+    res = xhci_enable_ep(xhci, slotid, 1, octx+32, ep0_ctx);
+
+    DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
+            slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
+    DPRINTF("xhci: output ep0 context: %08x %08x %08x %08x %08x\n",
+            ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]);
+
+    cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+    cpu_physical_memory_write(octx+32, (uint8_t *) ep0_ctx, sizeof(ep0_ctx));
+
+    return res;
+}
+
+
+static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid,
+                                  uint64_t pictx, bool dc)
+{
+    target_phys_addr_t ictx, octx;
+    uint32_t ictl_ctx[2];
+    uint32_t slot_ctx[4];
+    uint32_t islot_ctx[4];
+    uint32_t ep_ctx[5];
+    int i;
+    TRBCCode res;
+
+    assert(slotid >= 1 && slotid <= MAXSLOTS);
+    DPRINTF("xhci_configure_slot(%d)\n", slotid);
+
+    ictx = xhci_mask64(pictx);
+    octx = xhci->slots[slotid-1].ctx;
+
+    DPRINTF("xhci: input context at "TARGET_FMT_plx"\n", ictx);
+    DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx);
+
+    if (dc) {
+        for (i = 2; i <= 31; i++) {
+            if (xhci->slots[slotid-1].eps[i-1]) {
+                xhci_disable_ep(xhci, slotid, i);
+            }
+        }
+
+        cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+        slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT);
+        slot_ctx[3] |= SLOT_ADDRESSED << SLOT_STATE_SHIFT;
+        DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
+                slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
+        cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+
+        return CC_SUCCESS;
+    }
+
+    cpu_physical_memory_read(ictx, (uint8_t *) ictl_ctx, sizeof(ictl_ctx));
+
+    if ((ictl_ctx[0] & 0x3) != 0x0 || (ictl_ctx[1] & 0x3) != 0x1) {
+        fprintf(stderr, "xhci: invalid input context control %08x %08x\n",
+                ictl_ctx[0], ictl_ctx[1]);
+        return CC_TRB_ERROR;
+    }
+
+    cpu_physical_memory_read(ictx+32, (uint8_t *) islot_ctx, sizeof(islot_ctx));
+    cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+
+    if (SLOT_STATE(slot_ctx[3]) < SLOT_ADDRESSED) {
+        fprintf(stderr, "xhci: invalid slot state %08x\n", slot_ctx[3]);
+        return CC_CONTEXT_STATE_ERROR;
+    }
+
+    for (i = 2; i <= 31; i++) {
+        if (ictl_ctx[0] & (1<<i)) {
+            xhci_disable_ep(xhci, slotid, i);
+        }
+        if (ictl_ctx[1] & (1<<i)) {
+            cpu_physical_memory_read(ictx+32+(32*i),
+                                     (uint8_t *) ep_ctx, sizeof(ep_ctx));
+            DPRINTF("xhci: input ep%d.%d context: %08x %08x %08x %08x %08x\n",
+                    i/2, i%2, ep_ctx[0], ep_ctx[1], ep_ctx[2],
+                    ep_ctx[3], ep_ctx[4]);
+            xhci_disable_ep(xhci, slotid, i);
+            res = xhci_enable_ep(xhci, slotid, i, octx+(32*i), ep_ctx);
+            if (res != CC_SUCCESS) {
+                return res;
+            }
+            DPRINTF("xhci: output ep%d.%d context: %08x %08x %08x %08x %08x\n",
+                    i/2, i%2, ep_ctx[0], ep_ctx[1], ep_ctx[2],
+                    ep_ctx[3], ep_ctx[4]);
+            cpu_physical_memory_write(octx+(32*i),
+                                      (uint8_t *) ep_ctx, sizeof(ep_ctx));
+        }
+    }
+
+    slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT);
+    slot_ctx[3] |= SLOT_CONFIGURED << SLOT_STATE_SHIFT;
+    slot_ctx[0] &= ~(SLOT_CONTEXT_ENTRIES_MASK << SLOT_CONTEXT_ENTRIES_SHIFT);
+    slot_ctx[0] |= islot_ctx[0] & (SLOT_CONTEXT_ENTRIES_MASK <<
+                                   SLOT_CONTEXT_ENTRIES_SHIFT);
+    DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
+            slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
+
+    cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+
+    return CC_SUCCESS;
+}
+
+
+static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid,
+                                   uint64_t pictx)
+{
+    target_phys_addr_t ictx, octx;
+    uint32_t ictl_ctx[2];
+    uint32_t iep0_ctx[5];
+    uint32_t ep0_ctx[5];
+    uint32_t islot_ctx[4];
+    uint32_t slot_ctx[4];
+
+    assert(slotid >= 1 && slotid <= MAXSLOTS);
+    DPRINTF("xhci_evaluate_slot(%d)\n", slotid);
+
+    ictx = xhci_mask64(pictx);
+    octx = xhci->slots[slotid-1].ctx;
+
+    DPRINTF("xhci: input context at "TARGET_FMT_plx"\n", ictx);
+    DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx);
+
+    cpu_physical_memory_read(ictx, (uint8_t *) ictl_ctx, sizeof(ictl_ctx));
+
+    if (ictl_ctx[0] != 0x0 || ictl_ctx[1] & ~0x3) {
+        fprintf(stderr, "xhci: invalid input context control %08x %08x\n",
+                ictl_ctx[0], ictl_ctx[1]);
+        return CC_TRB_ERROR;
+    }
+
+    if (ictl_ctx[1] & 0x1) {
+        cpu_physical_memory_read(ictx+32,
+                                 (uint8_t *) islot_ctx, sizeof(islot_ctx));
+
+        DPRINTF("xhci: input slot context: %08x %08x %08x %08x\n",
+                islot_ctx[0], islot_ctx[1], islot_ctx[2], islot_ctx[3]);
+
+        cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+
+        slot_ctx[1] &= ~0xFFFF; /* max exit latency */
+        slot_ctx[1] |= islot_ctx[1] & 0xFFFF;
+        slot_ctx[2] &= ~0xFF00000; /* interrupter target */
+        slot_ctx[2] |= islot_ctx[2] & 0xFF000000;
+
+        DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
+                slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
+
+        cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+    }
+
+    if (ictl_ctx[1] & 0x2) {
+        cpu_physical_memory_read(ictx+64,
+                                 (uint8_t *) iep0_ctx, sizeof(iep0_ctx));
+
+        DPRINTF("xhci: input ep0 context: %08x %08x %08x %08x %08x\n",
+                iep0_ctx[0], iep0_ctx[1], iep0_ctx[2],
+                iep0_ctx[3], iep0_ctx[4]);
+
+        cpu_physical_memory_read(octx+32, (uint8_t *) ep0_ctx, sizeof(ep0_ctx));
+
+        ep0_ctx[1] &= ~0xFFFF0000; /* max packet size*/
+        ep0_ctx[1] |= iep0_ctx[1] & 0xFFFF0000;
+
+        DPRINTF("xhci: output ep0 context: %08x %08x %08x %08x %08x\n",
+                ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]);
+
+        cpu_physical_memory_write(octx+32,
+                                  (uint8_t *) ep0_ctx, sizeof(ep0_ctx));
+    }
+
+    return CC_SUCCESS;
+}
+
+static TRBCCode xhci_reset_slot(XHCIState *xhci, unsigned int slotid)
+{
+    uint32_t slot_ctx[4];
+    target_phys_addr_t octx;
+    int i;
+
+    assert(slotid >= 1 && slotid <= MAXSLOTS);
+    DPRINTF("xhci_reset_slot(%d)\n", slotid);
+
+    octx = xhci->slots[slotid-1].ctx;
+
+    DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx);
+
+    for (i = 2; i <= 31; i++) {
+        if (xhci->slots[slotid-1].eps[i-1]) {
+            xhci_disable_ep(xhci, slotid, i);
+        }
+    }
+
+    cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+    slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT);
+    slot_ctx[3] |= SLOT_DEFAULT << SLOT_STATE_SHIFT;
+    DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
+            slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
+    cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+
+    return CC_SUCCESS;
+}
+
+static unsigned int xhci_get_slot(XHCIState *xhci, XHCIEvent *event, XHCITRB *trb)
+{
+    unsigned int slotid;
+    slotid = (trb->control >> TRB_CR_SLOTID_SHIFT) & TRB_CR_SLOTID_MASK;
+    if (slotid < 1 || slotid > MAXSLOTS) {
+        fprintf(stderr, "xhci: bad slot id %d\n", slotid);
+        event->ccode = CC_TRB_ERROR;
+        return 0;
+    } else if (!xhci->slots[slotid-1].enabled) {
+        fprintf(stderr, "xhci: slot id %d not enabled\n", slotid);
+        event->ccode = CC_SLOT_NOT_ENABLED_ERROR;
+        return 0;
+    }
+    return slotid;
+}
+
+static TRBCCode xhci_get_port_bandwidth(XHCIState *xhci, uint64_t pctx)
+{
+    target_phys_addr_t ctx;
+    uint8_t bw_ctx[MAXPORTS+1];
+
+    DPRINTF("xhci_get_port_bandwidth()\n");
+
+    ctx = xhci_mask64(pctx);
+
+    DPRINTF("xhci: bandwidth context at "TARGET_FMT_plx"\n", ctx);
+
+    /* TODO: actually implement real values here */
+    bw_ctx[0] = 0;
+    memset(&bw_ctx[1], 80, MAXPORTS); /* 80% */
+    cpu_physical_memory_write(ctx, bw_ctx, sizeof(bw_ctx));
+
+    return CC_SUCCESS;
+}
+
+static uint32_t rotl(uint32_t v, unsigned count)
+{
+    count &= 31;
+    return (v << count) | (v >> (32 - count));
+}
+
+
+static uint32_t xhci_nec_challenge(uint32_t hi, uint32_t lo)
+{
+    uint32_t val;
+    val = rotl(lo - 0x49434878, 32 - ((hi>>8) & 0x1F));
+    val += rotl(lo + 0x49434878, hi & 0x1F);
+    val -= rotl(hi ^ 0x49434878, (lo >> 16) & 0x1F);
+    return ~val;
+}
+
+static void xhci_via_challenge(uint64_t addr)
+{
+    uint32_t buf[8];
+    uint32_t obuf[8];
+    target_phys_addr_t paddr = xhci_mask64(addr);
+
+    cpu_physical_memory_read(paddr, (uint8_t *) &buf, 32);
+
+    memcpy(obuf, buf, sizeof(obuf));
+
+    if ((buf[0] & 0xff) == 2) {
+        obuf[0] = 0x49932000 + 0x54dc200 * buf[2] + 0x7429b578 * buf[3];
+        obuf[0] |=  (buf[2] * buf[3]) & 0xff;
+        obuf[1] = 0x0132bb37 + 0xe89 * buf[2] + 0xf09 * buf[3];
+        obuf[2] = 0x0066c2e9 + 0x2091 * buf[2] + 0x19bd * buf[3];
+        obuf[3] = 0xd5281342 + 0x2cc9691 * buf[2] + 0x2367662 * buf[3];
+        obuf[4] = 0x0123c75c + 0x1595 * buf[2] + 0x19ec * buf[3];
+        obuf[5] = 0x00f695de + 0x26fd * buf[2] + 0x3e9 * buf[3];
+        obuf[6] = obuf[2] ^ obuf[3] ^ 0x29472956;
+        obuf[7] = obuf[2] ^ obuf[3] ^ 0x65866593;
+    }
+
+    cpu_physical_memory_write(paddr, (uint8_t *) &obuf, 32);
+}
+
+static void xhci_process_commands(XHCIState *xhci)
+{
+    XHCITRB trb;
+    TRBType type;
+    XHCIEvent event = {ER_COMMAND_COMPLETE, CC_SUCCESS};
+    target_phys_addr_t addr;
+    unsigned int i, slotid = 0;
+
+    DPRINTF("xhci_process_commands()\n");
+    if (!xhci_running(xhci)) {
+        DPRINTF("xhci_process_commands() called while xHC stopped or paused\n");
+        return;
+    }
+
+    xhci->crcr_low |= CRCR_CRR;
+
+    while ((type = xhci_ring_fetch(xhci, &xhci->cmd_ring, &trb, &addr))) {
+        event.ptr = addr;
+        switch (type) {
+        case CR_ENABLE_SLOT:
+            for (i = 0; i < MAXSLOTS; i++) {
+                if (!xhci->slots[i].enabled) {
+                    break;
+                }
+            }
+            if (i >= MAXSLOTS) {
+                fprintf(stderr, "xhci: no device slots available\n");
+                event.ccode = CC_NO_SLOTS_ERROR;
+            } else {
+                slotid = i+1;
+                event.ccode = xhci_enable_slot(xhci, slotid);
+            }
+            break;
+        case CR_DISABLE_SLOT:
+            slotid = xhci_get_slot(xhci, &event, &trb);
+            if (slotid) {
+                event.ccode = xhci_disable_slot(xhci, slotid);
+            }
+            break;
+        case CR_ADDRESS_DEVICE:
+            slotid = xhci_get_slot(xhci, &event, &trb);
+            if (slotid) {
+                event.ccode = xhci_address_slot(xhci, slotid, trb.parameter,
+                                                trb.control & TRB_CR_BSR);
+            }
+            break;
+        case CR_CONFIGURE_ENDPOINT:
+            slotid = xhci_get_slot(xhci, &event, &trb);
+            if (slotid) {
+                event.ccode = xhci_configure_slot(xhci, slotid, trb.parameter,
+                                                  trb.control & TRB_CR_DC);
+            }
+            break;
+        case CR_EVALUATE_CONTEXT:
+            slotid = xhci_get_slot(xhci, &event, &trb);
+            if (slotid) {
+                event.ccode = xhci_evaluate_slot(xhci, slotid, trb.parameter);
+            }
+            break;
+        case CR_STOP_ENDPOINT:
+            slotid = xhci_get_slot(xhci, &event, &trb);
+            if (slotid) {
+                unsigned int epid = (trb.control >> TRB_CR_EPID_SHIFT)
+                    & TRB_CR_EPID_MASK;
+                event.ccode = xhci_stop_ep(xhci, slotid, epid);
+            }
+            break;
+        case CR_RESET_ENDPOINT:
+            slotid = xhci_get_slot(xhci, &event, &trb);
+            if (slotid) {
+                unsigned int epid = (trb.control >> TRB_CR_EPID_SHIFT)
+                    & TRB_CR_EPID_MASK;
+                event.ccode = xhci_reset_ep(xhci, slotid, epid);
+            }
+            break;
+        case CR_SET_TR_DEQUEUE:
+            slotid = xhci_get_slot(xhci, &event, &trb);
+            if (slotid) {
+                unsigned int epid = (trb.control >> TRB_CR_EPID_SHIFT)
+                    & TRB_CR_EPID_MASK;
+                event.ccode = xhci_set_ep_dequeue(xhci, slotid, epid,
+                                                  trb.parameter);
+            }
+            break;
+        case CR_RESET_DEVICE:
+            slotid = xhci_get_slot(xhci, &event, &trb);
+            if (slotid) {
+                event.ccode = xhci_reset_slot(xhci, slotid);
+            }
+            break;
+        case CR_GET_PORT_BANDWIDTH:
+            event.ccode = xhci_get_port_bandwidth(xhci, trb.parameter);
+            break;
+        case CR_VENDOR_VIA_CHALLENGE_RESPONSE:
+            xhci_via_challenge(trb.parameter);
+            break;
+        case CR_VENDOR_NEC_FIRMWARE_REVISION:
+            event.type = 48; /* NEC reply */
+            event.length = 0x3025;
+            break;
+        case CR_VENDOR_NEC_CHALLENGE_RESPONSE:
+        {
+            uint32_t chi = trb.parameter >> 32;
+            uint32_t clo = trb.parameter;
+            uint32_t val = xhci_nec_challenge(chi, clo);
+            event.length = val & 0xFFFF;
+            event.epid = val >> 16;
+            slotid = val >> 24;
+            event.type = 48; /* NEC reply */
+        }
+        break;
+        default:
+            fprintf(stderr, "xhci: unimplemented command %d\n", type);
+            event.ccode = CC_TRB_ERROR;
+            break;
+        }
+        event.slotid = slotid;
+        xhci_event(xhci, &event);
+    }
+}
+
+static void xhci_update_port(XHCIState *xhci, XHCIPort *port, int is_detach)
+{
+    int nr = port->port.index + 1;
+
+    port->portsc = PORTSC_PP;
+    if (port->port.dev && port->port.dev->attached && !is_detach) {
+        port->portsc |= PORTSC_CCS;
+        switch (port->port.dev->speed) {
+        case USB_SPEED_LOW:
+            port->portsc |= PORTSC_SPEED_LOW;
+            break;
+        case USB_SPEED_FULL:
+            port->portsc |= PORTSC_SPEED_FULL;
+            break;
+        case USB_SPEED_HIGH:
+            port->portsc |= PORTSC_SPEED_HIGH;
+            break;
+        }
+    }
+
+    if (xhci_running(xhci)) {
+        port->portsc |= PORTSC_CSC;
+        XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, nr << 24};
+        xhci_event(xhci, &ev);
+        DPRINTF("xhci: port change event for port %d\n", nr);
+    }
+}
+
+static void xhci_reset(void *opaque)
+{
+    XHCIState *xhci = opaque;
+    int i;
+
+    DPRINTF("xhci: full reset\n");
+    if (!(xhci->usbsts & USBSTS_HCH)) {
+        fprintf(stderr, "xhci: reset while running!\n");
+    }
+
+    xhci->usbcmd = 0;
+    xhci->usbsts = USBSTS_HCH;
+    xhci->dnctrl = 0;
+    xhci->crcr_low = 0;
+    xhci->crcr_high = 0;
+    xhci->dcbaap_low = 0;
+    xhci->dcbaap_high = 0;
+    xhci->config = 0;
+    xhci->devaddr = 2;
+
+    for (i = 0; i < MAXSLOTS; i++) {
+        xhci_disable_slot(xhci, i+1);
+    }
+
+    for (i = 0; i < MAXPORTS; i++) {
+        xhci_update_port(xhci, xhci->ports + i, 0);
+    }
+
+    xhci->mfindex = 0;
+    xhci->iman = 0;
+    xhci->imod = 0;
+    xhci->erstsz = 0;
+    xhci->erstba_low = 0;
+    xhci->erstba_high = 0;
+    xhci->erdp_low = 0;
+    xhci->erdp_high = 0;
+
+    xhci->er_ep_idx = 0;
+    xhci->er_pcs = 1;
+    xhci->er_full = 0;
+    xhci->ev_buffer_put = 0;
+    xhci->ev_buffer_get = 0;
+}
+
+static uint32_t xhci_cap_read(XHCIState *xhci, uint32_t reg)
+{
+    DPRINTF("xhci_cap_read(0x%x)\n", reg);
+
+    switch (reg) {
+    case 0x00: /* HCIVERSION, CAPLENGTH */
+        return 0x01000000 | LEN_CAP;
+    case 0x04: /* HCSPARAMS 1 */
+        return (MAXPORTS<<24) | (MAXINTRS<<8) | MAXSLOTS;
+    case 0x08: /* HCSPARAMS 2 */
+        return 0x0000000f;
+    case 0x0c: /* HCSPARAMS 3 */
+        return 0x00000000;
+    case 0x10: /* HCCPARAMS */
+#if TARGET_PHYS_ADDR_BITS > 32
+        return 0x00081001;
+#else
+        return 0x00081000;
+#endif
+    case 0x14: /* DBOFF */
+        return OFF_DOORBELL;
+    case 0x18: /* RTSOFF */
+        return OFF_RUNTIME;
+
+    /* extended capabilities */
+    case 0x20: /* Supported Protocol:00 */
+#if USB3_PORTS > 0
+        return 0x02000402; /* USB 2.0 */
+#else
+        return 0x02000002; /* USB 2.0 */
+#endif
+    case 0x24: /* Supported Protocol:04 */
+        return 0x20425455; /* "USB " */
+    case 0x28: /* Supported Protocol:08 */
+        return 0x00000001 | (USB2_PORTS<<8);
+    case 0x2c: /* Supported Protocol:0c */
+        return 0x00000000; /* reserved */
+#if USB3_PORTS > 0
+    case 0x30: /* Supported Protocol:00 */
+        return 0x03000002; /* USB 3.0 */
+    case 0x34: /* Supported Protocol:04 */
+        return 0x20425455; /* "USB " */
+    case 0x38: /* Supported Protocol:08 */
+        return 0x00000000 | (USB2_PORTS+1) | (USB3_PORTS<<8);
+    case 0x3c: /* Supported Protocol:0c */
+        return 0x00000000; /* reserved */
+#endif
+    default:
+        fprintf(stderr, "xhci_cap_read: reg %d unimplemented\n", reg);
+    }
+    return 0;
+}
+
+static uint32_t xhci_port_read(XHCIState *xhci, uint32_t reg)
+{
+    uint32_t port = reg >> 4;
+    if (port >= MAXPORTS) {
+        fprintf(stderr, "xhci_port_read: port %d out of bounds\n", port);
+        return 0;
+    }
+
+    switch (reg & 0xf) {
+    case 0x00: /* PORTSC */
+        return xhci->ports[port].portsc;
+    case 0x04: /* PORTPMSC */
+    case 0x08: /* PORTLI */
+        return 0;
+    case 0x0c: /* reserved */
+    default:
+        fprintf(stderr, "xhci_port_read (port %d): reg 0x%x unimplemented\n",
+                port, reg);
+        return 0;
+    }
+}
+
+static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val)
+{
+    uint32_t port = reg >> 4;
+    uint32_t portsc;
+
+    if (port >= MAXPORTS) {
+        fprintf(stderr, "xhci_port_read: port %d out of bounds\n", port);
+        return;
+    }
+
+    switch (reg & 0xf) {
+    case 0x00: /* PORTSC */
+        portsc = xhci->ports[port].portsc;
+        /* write-1-to-clear bits*/
+        portsc &= ~(val & (PORTSC_CSC|PORTSC_PEC|PORTSC_WRC|PORTSC_OCC|
+                           PORTSC_PRC|PORTSC_PLC|PORTSC_CEC));
+        if (val & PORTSC_LWS) {
+            /* overwrite PLS only when LWS=1 */
+            portsc &= ~(PORTSC_PLS_MASK << PORTSC_PLS_SHIFT);
+            portsc |= val & (PORTSC_PLS_MASK << PORTSC_PLS_SHIFT);
+        }
+        /* read/write bits */
+        portsc &= ~(PORTSC_PP|PORTSC_WCE|PORTSC_WDE|PORTSC_WOE);
+        portsc |= (val & (PORTSC_PP|PORTSC_WCE|PORTSC_WDE|PORTSC_WOE));
+        /* write-1-to-start bits */
+        if (val & PORTSC_PR) {
+            DPRINTF("xhci: port %d reset\n", port);
+            usb_device_reset(xhci->ports[port].port.dev);
+            portsc |= PORTSC_PRC | PORTSC_PED;
+        }
+        xhci->ports[port].portsc = portsc;
+        break;
+    case 0x04: /* PORTPMSC */
+    case 0x08: /* PORTLI */
+    default:
+        fprintf(stderr, "xhci_port_write (port %d): reg 0x%x unimplemented\n",
+                port, reg);
+    }
+}
+
+static uint32_t xhci_oper_read(XHCIState *xhci, uint32_t reg)
+{
+    DPRINTF("xhci_oper_read(0x%x)\n", reg);
+
+    if (reg >= 0x400) {
+        return xhci_port_read(xhci, reg - 0x400);
+    }
+
+    switch (reg) {
+    case 0x00: /* USBCMD */
+        return xhci->usbcmd;
+    case 0x04: /* USBSTS */
+        return xhci->usbsts;
+    case 0x08: /* PAGESIZE */
+        return 1; /* 4KiB */
+    case 0x14: /* DNCTRL */
+        return xhci->dnctrl;
+    case 0x18: /* CRCR low */
+        return xhci->crcr_low & ~0xe;
+    case 0x1c: /* CRCR high */
+        return xhci->crcr_high;
+    case 0x30: /* DCBAAP low */
+        return xhci->dcbaap_low;
+    case 0x34: /* DCBAAP high */
+        return xhci->dcbaap_high;
+    case 0x38: /* CONFIG */
+        return xhci->config;
+    default:
+        fprintf(stderr, "xhci_oper_read: reg 0x%x unimplemented\n", reg);
+    }
+    return 0;
+}
+
+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;
+    }
+
+    switch (reg) {
+    case 0x00: /* USBCMD */
+        if ((val & USBCMD_RS) && !(xhci->usbcmd & USBCMD_RS)) {
+            xhci_run(xhci);
+        } else if (!(val & USBCMD_RS) && (xhci->usbcmd & USBCMD_RS)) {
+            xhci_stop(xhci);
+        }
+        xhci->usbcmd = val & 0xc0f;
+        if (val & USBCMD_HCRST) {
+            xhci_reset(xhci);
+        }
+        xhci_irq_update(xhci);
+        break;
+
+    case 0x04: /* USBSTS */
+        /* these bits are write-1-to-clear */
+        xhci->usbsts &= ~(val & (USBSTS_HSE|USBSTS_EINT|USBSTS_PCD|USBSTS_SRE));
+        xhci_irq_update(xhci);
+        break;
+
+    case 0x14: /* DNCTRL */
+        xhci->dnctrl = val & 0xffff;
+        break;
+    case 0x18: /* CRCR low */
+        xhci->crcr_low = (val & 0xffffffcf) | (xhci->crcr_low & CRCR_CRR);
+        break;
+    case 0x1c: /* CRCR high */
+        xhci->crcr_high = val;
+        if (xhci->crcr_low & (CRCR_CA|CRCR_CS) && (xhci->crcr_low & CRCR_CRR)) {
+            XHCIEvent event = {ER_COMMAND_COMPLETE, CC_COMMAND_RING_STOPPED};
+            xhci->crcr_low &= ~CRCR_CRR;
+            xhci_event(xhci, &event);
+            DPRINTF("xhci: command ring stopped (CRCR=%08x)\n", xhci->crcr_low);
+        } else {
+            target_phys_addr_t base = xhci_addr64(xhci->crcr_low & ~0x3f, val);
+            xhci_ring_init(xhci, &xhci->cmd_ring, base);
+        }
+        xhci->crcr_low &= ~(CRCR_CA | CRCR_CS);
+        break;
+    case 0x30: /* DCBAAP low */
+        xhci->dcbaap_low = val & 0xffffffc0;
+        break;
+    case 0x34: /* DCBAAP high */
+        xhci->dcbaap_high = val;
+        break;
+    case 0x38: /* CONFIG */
+        xhci->config = val & 0xff;
+        break;
+    default:
+        fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", reg);
+    }
+}
+
+static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg)
+{
+    DPRINTF("xhci_runtime_read(0x%x)\n", reg);
+
+    switch (reg) {
+    case 0x00: /* MFINDEX */
+        fprintf(stderr, "xhci_runtime_read: MFINDEX not yet implemented\n");
+        return xhci->mfindex;
+    case 0x20: /* IMAN */
+        return xhci->iman;
+    case 0x24: /* IMOD */
+        return xhci->imod;
+    case 0x28: /* ERSTSZ */
+        return xhci->erstsz;
+    case 0x30: /* ERSTBA low */
+        return xhci->erstba_low;
+    case 0x34: /* ERSTBA high */
+        return xhci->erstba_high;
+    case 0x38: /* ERDP low */
+        return xhci->erdp_low;
+    case 0x3c: /* ERDP high */
+        return xhci->erdp_high;
+    default:
+        fprintf(stderr, "xhci_runtime_read: reg 0x%x unimplemented\n", reg);
+    }
+    return 0;
+}
+
+static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val)
+{
+    DPRINTF("xhci_runtime_write(0x%x, 0x%08x)\n", reg, val);
+
+    switch (reg) {
+    case 0x20: /* IMAN */
+        if (val & IMAN_IP) {
+            xhci->iman &= ~IMAN_IP;
+        }
+        xhci->iman &= ~IMAN_IE;
+        xhci->iman |= val & IMAN_IE;
+        xhci_irq_update(xhci);
+        break;
+    case 0x24: /* IMOD */
+        xhci->imod = val;
+        break;
+    case 0x28: /* ERSTSZ */
+        xhci->erstsz = val & 0xffff;
+        break;
+    case 0x30: /* ERSTBA low */
+        /* XXX NEC driver bug: it doesn't align this to 64 bytes
+        xhci->erstba_low = val & 0xffffffc0; */
+        xhci->erstba_low = val & 0xfffffff0;
+        break;
+    case 0x34: /* ERSTBA high */
+        xhci->erstba_high = val;
+        xhci_er_reset(xhci);
+        break;
+    case 0x38: /* ERDP low */
+        if (val & ERDP_EHB) {
+            xhci->erdp_low &= ~ERDP_EHB;
+        }
+        xhci->erdp_low = (val & ~ERDP_EHB) | (xhci->erdp_low & ERDP_EHB);
+        break;
+    case 0x3c: /* ERDP high */
+        xhci->erdp_high = val;
+        xhci_events_update(xhci);
+        break;
+    default:
+        fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", reg);
+    }
+}
+
+static uint32_t xhci_doorbell_read(XHCIState *xhci, uint32_t reg)
+{
+    DPRINTF("xhci_doorbell_read(0x%x)\n", reg);
+    /* doorbells always read as 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);
+
+    if (!xhci_running(xhci)) {
+        fprintf(stderr, "xhci: wrote doorbell while xHC stopped or paused\n");
+        return;
+    }
+
+    reg >>= 2;
+
+    if (reg == 0) {
+        if (val == 0) {
+            xhci_process_commands(xhci);
+        } else {
+            fprintf(stderr, "xhci: bad doorbell 0 write: 0x%x\n", val);
+        }
+    } else {
+        if (reg > MAXSLOTS) {
+            fprintf(stderr, "xhci: bad doorbell %d\n", reg);
+        } else if (val > 31) {
+            fprintf(stderr, "xhci: bad doorbell %d write: 0x%x\n", reg, val);
+        } else {
+            xhci_kick_ep(xhci, reg, val);
+        }
+    }
+}
+
+static uint64_t xhci_mem_read(void *ptr, target_phys_addr_t addr,
+                              unsigned size)
+{
+    XHCIState *xhci = ptr;
+
+    /* Only aligned reads are allowed on xHCI */
+    if (addr & 3) {
+        fprintf(stderr, "xhci_mem_read: Mis-aligned read\n");
+        return 0;
+    }
+
+    if (addr < LEN_CAP) {
+        return xhci_cap_read(xhci, addr);
+    } else if (addr >= OFF_OPER && addr < (OFF_OPER + LEN_OPER)) {
+        return xhci_oper_read(xhci, addr - OFF_OPER);
+    } else if (addr >= OFF_RUNTIME && addr < (OFF_RUNTIME + LEN_RUNTIME)) {
+        return xhci_runtime_read(xhci, addr - OFF_RUNTIME);
+    } else if (addr >= OFF_DOORBELL && addr < (OFF_DOORBELL + LEN_DOORBELL)) {
+        return xhci_doorbell_read(xhci, addr - OFF_DOORBELL);
+    } else {
+        fprintf(stderr, "xhci_mem_read: Bad offset %x\n", (int)addr);
+        return 0;
+    }
+}
+
+static void xhci_mem_write(void *ptr, target_phys_addr_t addr,
+                           uint64_t val, unsigned size)
+{
+    XHCIState *xhci = ptr;
+
+    /* Only aligned writes are allowed on xHCI */
+    if (addr & 3) {
+        fprintf(stderr, "xhci_mem_write: Mis-aligned write\n");
+        return;
+    }
+
+    if (addr >= OFF_OPER && addr < (OFF_OPER + LEN_OPER)) {
+        xhci_oper_write(xhci, addr - OFF_OPER, val);
+    } else if (addr >= OFF_RUNTIME && addr < (OFF_RUNTIME + LEN_RUNTIME)) {
+        xhci_runtime_write(xhci, addr - OFF_RUNTIME, val);
+    } else if (addr >= OFF_DOORBELL && addr < (OFF_DOORBELL + LEN_DOORBELL)) {
+        xhci_doorbell_write(xhci, addr - OFF_DOORBELL, val);
+    } else {
+        fprintf(stderr, "xhci_mem_write: Bad offset %x\n", (int)addr);
+    }
+}
+
+static const MemoryRegionOps xhci_mem_ops = {
+    .read = xhci_mem_read,
+    .write = xhci_mem_write,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void xhci_attach(USBPort *usbport)
+{
+    XHCIState *xhci = usbport->opaque;
+    XHCIPort *port = &xhci->ports[usbport->index];
+
+    xhci_update_port(xhci, port, 0);
+}
+
+static void xhci_detach(USBPort *usbport)
+{
+    XHCIState *xhci = usbport->opaque;
+    XHCIPort *port = &xhci->ports[usbport->index];
+
+    xhci_update_port(xhci, port, 1);
+}
+
+static void xhci_wakeup(USBPort *usbport)
+{
+    XHCIState *xhci = usbport->opaque;
+    XHCIPort *port = &xhci->ports[usbport->index];
+    int nr = port->port.index + 1;
+    XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, nr << 24};
+    uint32_t pls;
+
+    pls = (port->portsc >> PORTSC_PLS_SHIFT) & PORTSC_PLS_MASK;
+    if (pls != 3) {
+        return;
+    }
+    port->portsc |= 0xf << PORTSC_PLS_SHIFT;
+    if (port->portsc & PORTSC_PLC) {
+        return;
+    }
+    port->portsc |= PORTSC_PLC;
+    xhci_event(xhci, &ev);
+}
+
+static void xhci_complete(USBPort *port, USBPacket *packet)
+{
+    XHCITransfer *xfer = container_of(packet, XHCITransfer, packet);
+
+    xhci_complete_packet(xfer, packet->result);
+    xhci_kick_ep(xfer->xhci, xfer->slotid, xfer->epid);
+}
+
+static void xhci_child_detach(USBPort *port, USBDevice *child)
+{
+    FIXME();
+}
+
+static USBPortOps xhci_port_ops = {
+    .attach   = xhci_attach,
+    .detach   = xhci_detach,
+    .wakeup   = xhci_wakeup,
+    .complete = xhci_complete,
+    .child_detach = xhci_child_detach,
+};
+
+static int xhci_find_slotid(XHCIState *xhci, USBDevice *dev)
+{
+    XHCISlot *slot;
+    int slotid;
+
+    for (slotid = 1; slotid <= MAXSLOTS; slotid++) {
+        slot = &xhci->slots[slotid-1];
+        if (slot->devaddr == dev->addr) {
+            return slotid;
+        }
+    }
+    return 0;
+}
+
+static int xhci_find_epid(USBEndpoint *ep)
+{
+    if (ep->nr == 0) {
+        return 1;
+    }
+    if (ep->pid == USB_TOKEN_IN) {
+        return ep->nr * 2 + 1;
+    } else {
+        return ep->nr * 2;
+    }
+}
+
+static void xhci_wakeup_endpoint(USBBus *bus, USBEndpoint *ep)
+{
+    XHCIState *xhci = container_of(bus, XHCIState, bus);
+    int slotid;
+
+    DPRINTF("%s\n", __func__);
+    slotid = xhci_find_slotid(xhci, ep->dev);
+    if (slotid == 0 || !xhci->slots[slotid-1].enabled) {
+        DPRINTF("%s: oops, no slot for dev %d\n", __func__, ep->dev->addr);
+        return;
+    }
+    xhci_kick_ep(xhci, slotid, xhci_find_epid(ep));
+}
+
+static USBBusOps xhci_bus_ops = {
+    .wakeup_endpoint = xhci_wakeup_endpoint,
+};
+
+static void usb_xhci_init(XHCIState *xhci, DeviceState *dev)
+{
+    int i;
+
+    xhci->usbsts = USBSTS_HCH;
+
+    usb_bus_new(&xhci->bus, &xhci_bus_ops, &xhci->pci_dev.qdev);
+
+    for (i = 0; i < MAXPORTS; i++) {
+        memset(&xhci->ports[i], 0, sizeof(xhci->ports[i]));
+        usb_register_port(&xhci->bus, &xhci->ports[i].port, xhci, i,
+                          &xhci_port_ops,
+                          USB_SPEED_MASK_LOW  |
+                          USB_SPEED_MASK_FULL |
+                          USB_SPEED_MASK_HIGH);
+    }
+    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)
+{
+    int ret;
+
+    XHCIState *xhci = DO_UPCAST(XHCIState, pci_dev, dev);
+
+    xhci->pci_dev.config[PCI_CLASS_PROG] = 0x30;    /* xHCI */
+    xhci->pci_dev.config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin 1 */
+    xhci->pci_dev.config[PCI_CACHE_LINE_SIZE] = 0x10;
+    xhci->pci_dev.config[0x60] = 0x30; /* release number */
+
+    usb_xhci_init(xhci, &dev->qdev);
+
+    xhci->irq = xhci->pci_dev.irq[0];
+
+    memory_region_init_io(&xhci->mem, &xhci_mem_ops, xhci,
+                          "xhci", LEN_REGS);
+    pci_register_bar(&xhci->pci_dev, 0,
+                     PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64,
+                     &xhci->mem);
+
+    ret = pcie_cap_init(&xhci->pci_dev, 0xa0, PCI_EXP_TYPE_ENDPOINT, 0);
+    assert(ret >= 0);
+
+    if (xhci->msi) {
+        ret = msi_init(&xhci->pci_dev, 0x70, 1, true, false);
+        assert(ret >= 0);
+    }
+
+    return 0;
+}
+
+static void xhci_write_config(PCIDevice *dev, uint32_t addr, uint32_t val,
+                              int len)
+{
+    XHCIState *xhci = DO_UPCAST(XHCIState, pci_dev, dev);
+
+    pci_default_write_config(dev, addr, val, len);
+    if (xhci->msi) {
+        msi_write_config(dev, addr, val, len);
+    }
+}
+
+static const VMStateDescription vmstate_xhci = {
+    .name = "xhci",
+    .unmigratable = 1,
+};
+
+static Property xhci_properties[] = {
+    DEFINE_PROP_UINT32("msi", XHCIState, msi, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void xhci_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->vmsd    = &vmstate_xhci;
+    dc->props   = xhci_properties;
+    k->init         = usb_xhci_initfn;
+    k->vendor_id    = PCI_VENDOR_ID_NEC;
+    k->device_id    = PCI_DEVICE_ID_NEC_UPD720200;
+    k->class_id     = PCI_CLASS_SERIAL_USB;
+    k->revision     = 0x03;
+    k->is_express   = 1;
+    k->config_write = xhci_write_config;
+}
+
+static TypeInfo xhci_info = {
+    .name          = "nec-usb-xhci",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(XHCIState),
+    .class_init    = xhci_class_init,
+};
+
+static void xhci_register_types(void)
+{
+    type_register_static(&xhci_info);
+}
+
+type_init(xhci_register_types)
diff --git a/hw/usb/host-bsd.c b/hw/usb/host-bsd.c
new file mode 100644
index 0000000..ec26266
--- /dev/null
+++ b/hw/usb/host-bsd.c
@@ -0,0 +1,647 @@
+/*
+ * BSD host USB redirector
+ *
+ * Copyright (c) 2006 Lonnie Mendez
+ * Portions of code and concepts borrowed from
+ * usb-linux.c and libusb's bsd.c and are copyright their respective owners.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu-common.h"
+#include "monitor.h"
+#include "hw/usb.h"
+
+/* usb.h declares these */
+#undef USB_SPEED_HIGH
+#undef USB_SPEED_FULL
+#undef USB_SPEED_LOW
+
+#include <sys/ioctl.h>
+#ifndef __DragonFly__
+#include <dev/usb/usb.h>
+#else
+#include <bus/usb/usb.h>
+#endif
+
+/* This value has maximum potential at 16.
+ * You should also set hw.usb.debug to gain
+ * more detailed view.
+ */
+//#define DEBUG
+#define UGEN_DEBUG_LEVEL 0
+
+
+typedef int USBScanFunc(void *opaque, int bus_num, int addr, int class_id,
+                        int vendor_id, int product_id,
+                        const char *product_name, int speed);
+static int usb_host_find_device(int *pbus_num, int *paddr,
+                                const char *devname);
+
+typedef struct USBHostDevice {
+    USBDevice dev;
+    int ep_fd[USB_MAX_ENDPOINTS];
+    int devfd;
+    char devpath[32];
+} USBHostDevice;
+
+
+static int ensure_ep_open(USBHostDevice *dev, int ep, int mode)
+{
+    char buf[32];
+    int fd;
+
+    /* Get the address for this endpoint */
+    ep = UE_GET_ADDR(ep);
+
+    if (dev->ep_fd[ep] < 0) {
+#if defined(__FreeBSD__) || defined(__DragonFly__)
+        snprintf(buf, sizeof(buf) - 1, "%s.%d", dev->devpath, ep);
+#else
+        snprintf(buf, sizeof(buf) - 1, "%s.%02d", dev->devpath, ep);
+#endif
+        /* Try to open it O_RDWR first for those devices which have in and out
+         * endpoints with the same address (eg 0x02 and 0x82)
+         */
+        fd = open(buf, O_RDWR);
+        if (fd < 0 && errno == ENXIO)
+            fd = open(buf, mode);
+        if (fd < 0) {
+#ifdef DEBUG
+            printf("ensure_ep_open: failed to open device endpoint %s: %s\n",
+                   buf, strerror(errno));
+#endif
+        }
+        dev->ep_fd[ep] = fd;
+    }
+
+    return dev->ep_fd[ep];
+}
+
+static void ensure_eps_closed(USBHostDevice *dev)
+{
+    int epnum = 1;
+
+    if (!dev)
+        return;
+
+    while (epnum < USB_MAX_ENDPOINTS) {
+        if (dev->ep_fd[epnum] >= 0) {
+            close(dev->ep_fd[epnum]);
+            dev->ep_fd[epnum] = -1;
+        }
+        epnum++;
+    }
+}
+
+static void usb_host_handle_reset(USBDevice *dev)
+{
+#if 0
+    USBHostDevice *s = (USBHostDevice *)dev;
+#endif
+}
+
+/* XXX:
+ * -check device states against transfer requests
+ *  and return appropriate response
+ */
+static int usb_host_handle_control(USBDevice *dev,
+                                   USBPacket *p,
+                                   int request,
+                                   int value,
+                                   int index,
+                                   int length,
+                                   uint8_t *data)
+{
+    USBHostDevice *s = (USBHostDevice *)dev;
+    struct usb_ctl_request req;
+    struct usb_alt_interface aiface;
+    int ret, timeout = 50;
+
+    if ((request >> 8) == UT_WRITE_DEVICE &&
+        (request & 0xff) == UR_SET_ADDRESS) {
+
+        /* specific SET_ADDRESS support */
+        dev->addr = value;
+        return 0;
+    } else if ((request >> 8) == UT_WRITE_DEVICE &&
+               (request & 0xff) == UR_SET_CONFIG) {
+
+        ensure_eps_closed(s); /* can't do this without all eps closed */
+
+        ret = ioctl(s->devfd, USB_SET_CONFIG, &value);
+        if (ret < 0) {
+#ifdef DEBUG
+            printf("handle_control: failed to set configuration - %s\n",
+                   strerror(errno));
+#endif
+            return USB_RET_STALL;
+        }
+
+        return 0;
+    } else if ((request >> 8) == UT_WRITE_INTERFACE &&
+               (request & 0xff) == UR_SET_INTERFACE) {
+
+        aiface.uai_interface_index = index;
+        aiface.uai_alt_no = value;
+
+        ensure_eps_closed(s); /* can't do this without all eps closed */
+        ret = ioctl(s->devfd, USB_SET_ALTINTERFACE, &aiface);
+        if (ret < 0) {
+#ifdef DEBUG
+            printf("handle_control: failed to set alternate interface - %s\n",
+                   strerror(errno));
+#endif
+            return USB_RET_STALL;
+        }
+
+        return 0;
+    } else {
+        req.ucr_request.bmRequestType = request >> 8;
+        req.ucr_request.bRequest = request & 0xff;
+        USETW(req.ucr_request.wValue, value);
+        USETW(req.ucr_request.wIndex, index);
+        USETW(req.ucr_request.wLength, length);
+        req.ucr_data = data;
+        req.ucr_flags = USBD_SHORT_XFER_OK;
+
+        ret = ioctl(s->devfd, USB_SET_TIMEOUT, &timeout);
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+        if (ret < 0 && errno != EINVAL) {
+#else
+        if (ret < 0) {
+#endif
+#ifdef DEBUG
+            printf("handle_control: setting timeout failed - %s\n",
+                   strerror(errno));
+#endif
+        }
+
+        ret = ioctl(s->devfd, USB_DO_REQUEST, &req);
+        /* ugen returns EIO for usbd_do_request_ no matter what
+         * happens with the transfer */
+        if (ret < 0) {
+#ifdef DEBUG
+            printf("handle_control: error after request - %s\n",
+                   strerror(errno));
+#endif
+            return USB_RET_NAK; // STALL
+        } else {
+            return req.ucr_actlen;
+        }
+    }
+}
+
+static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
+{
+    USBHostDevice *s = (USBHostDevice *)dev;
+    int ret, fd, mode;
+    int one = 1, shortpacket = 0, timeout = 50;
+    sigset_t new_mask, old_mask;
+    uint8_t devep = p->ep->nr;
+
+    /* protect data transfers from SIGALRM signal */
+    sigemptyset(&new_mask);
+    sigaddset(&new_mask, SIGALRM);
+    sigprocmask(SIG_BLOCK, &new_mask, &old_mask);
+
+    if (p->pid == USB_TOKEN_IN) {
+        devep |= 0x80;
+        mode = O_RDONLY;
+        shortpacket = 1;
+    } else {
+        mode = O_WRONLY;
+    }
+
+    fd = ensure_ep_open(s, devep, mode);
+    if (fd < 0) {
+        sigprocmask(SIG_SETMASK, &old_mask, NULL);
+        return USB_RET_NODEV;
+    }
+
+    if (ioctl(fd, USB_SET_TIMEOUT, &timeout) < 0) {
+#ifdef DEBUG
+        printf("handle_data: failed to set timeout - %s\n",
+               strerror(errno));
+#endif
+    }
+
+    if (shortpacket) {
+        if (ioctl(fd, USB_SET_SHORT_XFER, &one) < 0) {
+#ifdef DEBUG
+            printf("handle_data: failed to set short xfer mode - %s\n",
+                   strerror(errno));
+#endif
+            sigprocmask(SIG_SETMASK, &old_mask, NULL);
+        }
+    }
+
+    if (p->pid == USB_TOKEN_IN)
+        ret = readv(fd, p->iov.iov, p->iov.niov);
+    else
+        ret = writev(fd, p->iov.iov, p->iov.niov);
+
+    sigprocmask(SIG_SETMASK, &old_mask, NULL);
+
+    if (ret < 0) {
+#ifdef DEBUG
+        printf("handle_data: error after %s data - %s\n",
+               pid == USB_TOKEN_IN ? "reading" : "writing", strerror(errno));
+#endif
+        switch(errno) {
+        case ETIMEDOUT:
+        case EINTR:
+            return USB_RET_NAK;
+        default:
+            return USB_RET_STALL;
+        }
+    } else {
+        return ret;
+    }
+}
+
+static void usb_host_handle_destroy(USBDevice *opaque)
+{
+    USBHostDevice *s = (USBHostDevice *)opaque;
+    int i;
+
+    for (i = 0; i < USB_MAX_ENDPOINTS; i++)
+        if (s->ep_fd[i] >= 0)
+            close(s->ep_fd[i]);
+
+    if (s->devfd < 0)
+        return;
+
+    close(s->devfd);
+
+    g_free(s);
+}
+
+static int usb_host_initfn(USBDevice *dev)
+{
+    return 0;
+}
+
+USBDevice *usb_host_device_open(USBBus *guest_bus, const char *devname)
+{
+    struct usb_device_info bus_info, dev_info;
+    USBDevice *d = NULL, *ret = NULL;
+    USBHostDevice *dev;
+    char ctlpath[PATH_MAX + 1];
+    char buspath[PATH_MAX + 1];
+    int bfd, dfd, bus, address, i;
+    int ugendebug = UGEN_DEBUG_LEVEL;
+
+    if (usb_host_find_device(&bus, &address, devname) < 0) {
+        goto fail;
+    }
+
+    snprintf(buspath, PATH_MAX, "/dev/usb%d", bus);
+
+    bfd = open(buspath, O_RDWR);
+    if (bfd < 0) {
+#ifdef DEBUG
+        printf("usb_host_device_open: failed to open usb bus - %s\n",
+               strerror(errno));
+#endif
+        goto fail;
+    }
+
+    bus_info.udi_addr = address;
+    if (ioctl(bfd, USB_DEVICEINFO, &bus_info) < 0) {
+#ifdef DEBUG
+        printf("usb_host_device_open: failed to grab bus information - %s\n",
+               strerror(errno));
+#endif
+        goto fail_bfd;
+    }
+
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+    snprintf(ctlpath, PATH_MAX, "/dev/%s", bus_info.udi_devnames[0]);
+#else
+    snprintf(ctlpath, PATH_MAX, "/dev/%s.00", bus_info.udi_devnames[0]);
+#endif
+
+    dfd  = open(ctlpath, O_RDWR);
+    if (dfd < 0) {
+        dfd = open(ctlpath, O_RDONLY);
+        if (dfd < 0) {
+#ifdef DEBUG
+            printf("usb_host_device_open: failed to open usb device %s - %s\n",
+                   ctlpath, strerror(errno));
+#endif
+        }
+        goto fail_dfd;
+    }
+
+    if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0) {
+#ifdef DEBUG
+        printf("usb_host_device_open: failed to grab device info - %s\n",
+               strerror(errno));
+#endif
+        goto fail_dfd;
+    }
+
+    d = usb_create(guest_bus, "usb-host");
+    dev = DO_UPCAST(USBHostDevice, dev, d);
+
+    if (dev_info.udi_speed == 1) {
+        dev->dev.speed = USB_SPEED_LOW - 1;
+        dev->dev.speedmask = USB_SPEED_MASK_LOW;
+    } else {
+        dev->dev.speed = USB_SPEED_FULL - 1;
+        dev->dev.speedmask = USB_SPEED_MASK_FULL;
+    }
+
+    if (strncmp(dev_info.udi_product, "product", 7) != 0) {
+        pstrcpy(dev->dev.product_desc, sizeof(dev->dev.product_desc),
+                dev_info.udi_product);
+    } else {
+        snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc),
+                 "host:%s", devname);
+    }
+
+    pstrcpy(dev->devpath, sizeof(dev->devpath), "/dev/");
+    pstrcat(dev->devpath, sizeof(dev->devpath), dev_info.udi_devnames[0]);
+
+    /* Mark the endpoints as not yet open */
+    for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
+        dev->ep_fd[i] = -1;
+    }
+
+    ioctl(dfd, USB_SETDEBUG, &ugendebug);
+
+    ret = (USBDevice *)dev;
+
+fail_dfd:
+    close(dfd);
+fail_bfd:
+    close(bfd);
+fail:
+    return ret;
+}
+
+static void usb_host_class_initfn(ObjectClass *klass, void *data)
+{
+    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+    uc->product_desc   = "USB Host Device";
+    uc->init           = usb_host_initfn;
+    uc->handle_reset   = usb_host_handle_reset;
+    uc->handle_control = usb_host_handle_control;
+    uc->handle_data    = usb_host_handle_data;
+    uc->handle_destroy = usb_host_handle_destroy;
+}
+
+static TypeInfo usb_host_dev_info = {
+    .name          = "usb-host",
+    .parent        = TYPE_USB_DEVICE,
+    .instance_size = sizeof(USBHostDevice),
+    .class_init    = usb_host_class_initfn,
+};
+
+static void usb_host_register_types(void)
+{
+    type_register_static(&usb_host_dev_info);
+}
+
+type_init(usb_host_register_types)
+
+static int usb_host_scan(void *opaque, USBScanFunc *func)
+{
+    struct usb_device_info bus_info;
+    struct usb_device_info dev_info;
+    uint16_t vendor_id, product_id, class_id, speed;
+    int bfd, dfd, bus, address;
+    char busbuf[20], devbuf[20], product_name[256];
+    int ret = 0;
+
+    for (bus = 0; bus < 10; bus++) {
+
+        snprintf(busbuf, sizeof(busbuf) - 1, "/dev/usb%d", bus);
+        bfd = open(busbuf, O_RDWR);
+        if (bfd < 0)
+	    continue;
+
+        for (address = 1; address < 127; address++) {
+
+            bus_info.udi_addr = address;
+            if (ioctl(bfd, USB_DEVICEINFO, &bus_info) < 0)
+                continue;
+
+            /* only list devices that can be used by generic layer */
+            if (strncmp(bus_info.udi_devnames[0], "ugen", 4) != 0)
+                continue;
+
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+            snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s", bus_info.udi_devnames[0]);
+#else
+            snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s.00", bus_info.udi_devnames[0]);
+#endif
+
+            dfd = open(devbuf, O_RDONLY);
+            if (dfd < 0) {
+#ifdef DEBUG
+                printf("usb_host_scan: couldn't open device %s - %s\n", devbuf,
+                       strerror(errno));
+#endif
+                continue;
+            }
+
+            if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0)
+                printf("usb_host_scan: couldn't get device information for %s - %s\n",
+                       devbuf, strerror(errno));
+
+            /* XXX: might need to fixup endianness of word values before copying over */
+
+            vendor_id = dev_info.udi_vendorNo;
+            product_id = dev_info.udi_productNo;
+            class_id = dev_info.udi_class;
+            speed = dev_info.udi_speed;
+
+            if (strncmp(dev_info.udi_product, "product", 7) != 0)
+                pstrcpy(product_name, sizeof(product_name),
+                        dev_info.udi_product);
+            else
+                product_name[0] = '\0';
+
+            ret = func(opaque, bus, address, class_id, vendor_id,
+                       product_id, product_name, speed);
+
+            close(dfd);
+
+            if (ret)
+                goto the_end;
+        }
+
+        close(bfd);
+    }
+
+the_end:
+    return ret;
+}
+
+typedef struct FindDeviceState {
+    int vendor_id;
+    int product_id;
+    int bus_num;
+    int addr;
+} FindDeviceState;
+
+static int usb_host_find_device_scan(void *opaque, int bus_num, int addr,
+                                     int class_id,
+                                     int vendor_id, int product_id,
+                                     const char *product_name, int speed)
+{
+    FindDeviceState *s = opaque;
+    if (vendor_id == s->vendor_id &&
+        product_id == s->product_id) {
+        s->bus_num = bus_num;
+        s->addr = addr;
+        return 1;
+     } else {
+        return 0;
+     }
+}
+
+
+/* the syntax is :
+   'bus.addr' (decimal numbers) or
+   'vendor_id:product_id' (hexa numbers) */
+static int usb_host_find_device(int *pbus_num, int *paddr,
+                                const char *devname)
+{
+    const char *p;
+    int ret;
+    FindDeviceState fs;
+
+    p = strchr(devname, '.');
+    if (p) {
+        *pbus_num = strtoul(devname, NULL, 0);
+        *paddr = strtoul(p + 1, NULL, 0);
+        return 0;
+    }
+    p = strchr(devname, ':');
+    if (p) {
+        fs.vendor_id = strtoul(devname, NULL, 16);
+        fs.product_id = strtoul(p + 1, NULL, 16);
+        ret = usb_host_scan(&fs, usb_host_find_device_scan);
+        if (ret) {
+            *pbus_num = fs.bus_num;
+            *paddr = fs.addr;
+            return 0;
+        }
+     }
+     return -1;
+}
+
+/**********************/
+/* USB host device info */
+
+struct usb_class_info {
+    int class;
+    const char *class_name;
+};
+
+static const struct usb_class_info usb_class_info[] = {
+    { USB_CLASS_AUDIO, "Audio"},
+    { USB_CLASS_COMM, "Communication"},
+    { USB_CLASS_HID, "HID"},
+    { USB_CLASS_HUB, "Hub" },
+    { USB_CLASS_PHYSICAL, "Physical" },
+    { USB_CLASS_PRINTER, "Printer" },
+    { USB_CLASS_MASS_STORAGE, "Storage" },
+    { USB_CLASS_CDC_DATA, "Data" },
+    { USB_CLASS_APP_SPEC, "Application Specific" },
+    { USB_CLASS_VENDOR_SPEC, "Vendor Specific" },
+    { USB_CLASS_STILL_IMAGE, "Still Image" },
+    { USB_CLASS_CSCID, "Smart Card" },
+    { USB_CLASS_CONTENT_SEC, "Content Security" },
+    { -1, NULL }
+};
+
+static const char *usb_class_str(uint8_t class)
+{
+    const struct usb_class_info *p;
+    for (p = usb_class_info; p->class != -1; p++) {
+        if (p->class == class)
+            break;
+    }
+    return p->class_name;
+}
+
+static void usb_info_device(Monitor *mon, int bus_num, int addr, int class_id,
+                            int vendor_id, int product_id,
+                            const char *product_name,
+                            int speed)
+{
+    const char *class_str, *speed_str;
+
+    switch(speed) {
+    case USB_SPEED_LOW:
+        speed_str = "1.5";
+        break;
+    case USB_SPEED_FULL:
+        speed_str = "12";
+        break;
+    case USB_SPEED_HIGH:
+        speed_str = "480";
+        break;
+    default:
+        speed_str = "?";
+        break;
+    }
+
+    monitor_printf(mon, "  Device %d.%d, speed %s Mb/s\n",
+                   bus_num, addr, speed_str);
+    class_str = usb_class_str(class_id);
+    if (class_str)
+        monitor_printf(mon, "    %s:", class_str);
+    else
+        monitor_printf(mon, "    Class %02x:", class_id);
+    monitor_printf(mon, " USB device %04x:%04x", vendor_id, product_id);
+    if (product_name[0] != '\0')
+        monitor_printf(mon, ", %s", product_name);
+    monitor_printf(mon, "\n");
+}
+
+static int usb_host_info_device(void *opaque,
+                                int bus_num, int addr,
+                                int class_id,
+                                int vendor_id, int product_id,
+                                const char *product_name,
+                                int speed)
+{
+    Monitor *mon = opaque;
+
+    usb_info_device(mon, bus_num, addr, class_id, vendor_id, product_id,
+                    product_name, speed);
+    return 0;
+}
+
+void usb_host_info(Monitor *mon)
+{
+    usb_host_scan(mon, usb_host_info_device);
+}
+
+/* XXX add this */
+int usb_host_device_close(const char *devname)
+{
+    return 0;
+}
diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c
new file mode 100644
index 0000000..90919c2
--- /dev/null
+++ b/hw/usb/host-linux.c
@@ -0,0 +1,1913 @@
+/*
+ * Linux host USB redirector
+ *
+ * Copyright (c) 2005 Fabrice Bellard
+ *
+ * Copyright (c) 2008 Max Krasnyansky
+ *      Support for host device auto connect & disconnect
+ *      Major rewrite to support fully async operation
+ *
+ * Copyright 2008 TJ <linux at tjworld.net>
+ *      Added flexible support for /dev/bus/usb /sys/bus/usb/devices in addition
+ *      to the legacy /proc/bus/usb USB device discovery and handling
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu-common.h"
+#include "qemu-timer.h"
+#include "monitor.h"
+#include "sysemu.h"
+#include "trace.h"
+
+#include <dirent.h>
+#include <sys/ioctl.h>
+
+#include <linux/usbdevice_fs.h>
+#include <linux/version.h>
+#include "hw/usb.h"
+
+/* We redefine it to avoid version problems */
+struct usb_ctrltransfer {
+    uint8_t  bRequestType;
+    uint8_t  bRequest;
+    uint16_t wValue;
+    uint16_t wIndex;
+    uint16_t wLength;
+    uint32_t timeout;
+    void *data;
+};
+
+typedef int USBScanFunc(void *opaque, int bus_num, int addr, const char *port,
+                        int class_id, int vendor_id, int product_id,
+                        const char *product_name, int speed);
+
+//#define DEBUG
+
+#ifdef DEBUG
+#define DPRINTF printf
+#else
+#define DPRINTF(...)
+#endif
+
+#define PRODUCT_NAME_SZ 32
+#define MAX_PORTLEN 16
+
+/* endpoint association data */
+#define ISO_FRAME_DESC_PER_URB 32
+
+/* devio.c limits single requests to 16k */
+#define MAX_USBFS_BUFFER_SIZE 16384
+
+typedef struct AsyncURB AsyncURB;
+
+struct endp_data {
+    uint8_t halted;
+    uint8_t iso_started;
+    AsyncURB *iso_urb;
+    int iso_urb_idx;
+    int iso_buffer_used;
+    int inflight;
+};
+
+struct USBAutoFilter {
+    uint32_t bus_num;
+    uint32_t addr;
+    char     *port;
+    uint32_t vendor_id;
+    uint32_t product_id;
+};
+
+typedef struct USBHostDevice {
+    USBDevice dev;
+    int       fd;
+    int       hub_fd;
+    int       hub_port;
+
+    uint8_t   descr[8192];
+    int       descr_len;
+    int       closing;
+    uint32_t  iso_urb_count;
+    Notifier  exit;
+
+    struct endp_data ep_in[USB_MAX_ENDPOINTS];
+    struct endp_data ep_out[USB_MAX_ENDPOINTS];
+    QLIST_HEAD(, AsyncURB) aurbs;
+
+    /* Host side address */
+    int bus_num;
+    int addr;
+    char port[MAX_PORTLEN];
+    struct USBAutoFilter match;
+    int seen, errcount;
+
+    QTAILQ_ENTRY(USBHostDevice) next;
+} USBHostDevice;
+
+static QTAILQ_HEAD(, USBHostDevice) hostdevs = QTAILQ_HEAD_INITIALIZER(hostdevs);
+
+static int usb_host_close(USBHostDevice *dev);
+static int parse_filter(const char *spec, struct USBAutoFilter *f);
+static void usb_host_auto_check(void *unused);
+static int usb_host_read_file(char *line, size_t line_size,
+                            const char *device_file, const char *device_name);
+static int usb_linux_update_endp_table(USBHostDevice *s);
+
+static int usb_host_usbfs_type(USBHostDevice *s, USBPacket *p)
+{
+    static const int usbfs[] = {
+        [USB_ENDPOINT_XFER_CONTROL] = USBDEVFS_URB_TYPE_CONTROL,
+        [USB_ENDPOINT_XFER_ISOC]    = USBDEVFS_URB_TYPE_ISO,
+        [USB_ENDPOINT_XFER_BULK]    = USBDEVFS_URB_TYPE_BULK,
+        [USB_ENDPOINT_XFER_INT]     = USBDEVFS_URB_TYPE_INTERRUPT,
+    };
+    uint8_t type = p->ep->type;
+    assert(type < ARRAY_SIZE(usbfs));
+    return usbfs[type];
+}
+
+static int usb_host_do_reset(USBHostDevice *dev)
+{
+    struct timeval s, e;
+    uint32_t usecs;
+    int ret;
+
+    gettimeofday(&s, NULL);
+    ret = ioctl(dev->fd, USBDEVFS_RESET);
+    gettimeofday(&e, NULL);
+    usecs = (e.tv_sec  - s.tv_sec) * 1000000;
+    usecs += e.tv_usec - s.tv_usec;
+    if (usecs > 1000000) {
+        /* more than a second, something is fishy, broken usb device? */
+        fprintf(stderr, "husb: device %d:%d reset took %d.%06d seconds\n",
+                dev->bus_num, dev->addr, usecs / 1000000, usecs % 1000000);
+    }
+    return ret;
+}
+
+static struct endp_data *get_endp(USBHostDevice *s, int pid, int ep)
+{
+    struct endp_data *eps = pid == USB_TOKEN_IN ? s->ep_in : s->ep_out;
+    assert(pid == USB_TOKEN_IN || pid == USB_TOKEN_OUT);
+    assert(ep > 0 && ep <= USB_MAX_ENDPOINTS);
+    return eps + ep - 1;
+}
+
+static int is_isoc(USBHostDevice *s, int pid, int ep)
+{
+    return usb_ep_get_type(&s->dev, pid, ep) == USB_ENDPOINT_XFER_ISOC;
+}
+
+static int is_valid(USBHostDevice *s, int pid, int ep)
+{
+    return usb_ep_get_type(&s->dev, pid, ep) != USB_ENDPOINT_XFER_INVALID;
+}
+
+static int is_halted(USBHostDevice *s, int pid, int ep)
+{
+    return get_endp(s, pid, ep)->halted;
+}
+
+static void clear_halt(USBHostDevice *s, int pid, int ep)
+{
+    trace_usb_host_ep_clear_halt(s->bus_num, s->addr, ep);
+    get_endp(s, pid, ep)->halted = 0;
+}
+
+static void set_halt(USBHostDevice *s, int pid, int ep)
+{
+    if (ep != 0) {
+        trace_usb_host_ep_set_halt(s->bus_num, s->addr, ep);
+        get_endp(s, pid, ep)->halted = 1;
+    }
+}
+
+static int is_iso_started(USBHostDevice *s, int pid, int ep)
+{
+    return get_endp(s, pid, ep)->iso_started;
+}
+
+static void clear_iso_started(USBHostDevice *s, int pid, int ep)
+{
+    trace_usb_host_ep_stop_iso(s->bus_num, s->addr, ep);
+    get_endp(s, pid, ep)->iso_started = 0;
+}
+
+static void set_iso_started(USBHostDevice *s, int pid, int ep)
+{
+    struct endp_data *e = get_endp(s, pid, ep);
+
+    trace_usb_host_ep_start_iso(s->bus_num, s->addr, ep);
+    if (!e->iso_started) {
+        e->iso_started = 1;
+        e->inflight = 0;
+    }
+}
+
+static int change_iso_inflight(USBHostDevice *s, int pid, int ep, int value)
+{
+    struct endp_data *e = get_endp(s, pid, ep);
+
+    e->inflight += value;
+    return e->inflight;
+}
+
+static void set_iso_urb(USBHostDevice *s, int pid, int ep, AsyncURB *iso_urb)
+{
+    get_endp(s, pid, ep)->iso_urb = iso_urb;
+}
+
+static AsyncURB *get_iso_urb(USBHostDevice *s, int pid, int ep)
+{
+    return get_endp(s, pid, ep)->iso_urb;
+}
+
+static void set_iso_urb_idx(USBHostDevice *s, int pid, int ep, int i)
+{
+    get_endp(s, pid, ep)->iso_urb_idx = i;
+}
+
+static int get_iso_urb_idx(USBHostDevice *s, int pid, int ep)
+{
+    return get_endp(s, pid, ep)->iso_urb_idx;
+}
+
+static void set_iso_buffer_used(USBHostDevice *s, int pid, int ep, int i)
+{
+    get_endp(s, pid, ep)->iso_buffer_used = i;
+}
+
+static int get_iso_buffer_used(USBHostDevice *s, int pid, int ep)
+{
+    return get_endp(s, pid, ep)->iso_buffer_used;
+}
+
+/*
+ * Async URB state.
+ * We always allocate iso packet descriptors even for bulk transfers
+ * to simplify allocation and casts.
+ */
+struct AsyncURB
+{
+    struct usbdevfs_urb urb;
+    struct usbdevfs_iso_packet_desc isocpd[ISO_FRAME_DESC_PER_URB];
+    USBHostDevice *hdev;
+    QLIST_ENTRY(AsyncURB) next;
+
+    /* For regular async urbs */
+    USBPacket     *packet;
+    int more; /* large transfer, more urbs follow */
+
+    /* For buffered iso handling */
+    int iso_frame_idx; /* -1 means in flight */
+};
+
+static AsyncURB *async_alloc(USBHostDevice *s)
+{
+    AsyncURB *aurb = g_malloc0(sizeof(AsyncURB));
+    aurb->hdev = s;
+    QLIST_INSERT_HEAD(&s->aurbs, aurb, next);
+    return aurb;
+}
+
+static void async_free(AsyncURB *aurb)
+{
+    QLIST_REMOVE(aurb, next);
+    g_free(aurb);
+}
+
+static void do_disconnect(USBHostDevice *s)
+{
+    usb_host_close(s);
+    usb_host_auto_check(NULL);
+}
+
+static void async_complete(void *opaque)
+{
+    USBHostDevice *s = opaque;
+    AsyncURB *aurb;
+    int urbs = 0;
+
+    while (1) {
+        USBPacket *p;
+
+        int r = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &aurb);
+        if (r < 0) {
+            if (errno == EAGAIN) {
+                if (urbs > 2) {
+                    fprintf(stderr, "husb: %d iso urbs finished at once\n", urbs);
+                }
+                return;
+            }
+            if (errno == ENODEV) {
+                if (!s->closing) {
+                    trace_usb_host_disconnect(s->bus_num, s->addr);
+                    do_disconnect(s);
+                }
+                return;
+            }
+
+            perror("USBDEVFS_REAPURBNDELAY");
+            return;
+        }
+
+        DPRINTF("husb: async completed. aurb %p status %d alen %d\n",
+                aurb, aurb->urb.status, aurb->urb.actual_length);
+
+        /* If this is a buffered iso urb mark it as complete and don't do
+           anything else (it is handled further in usb_host_handle_iso_data) */
+        if (aurb->iso_frame_idx == -1) {
+            int inflight;
+            int pid = (aurb->urb.endpoint & USB_DIR_IN) ?
+                USB_TOKEN_IN : USB_TOKEN_OUT;
+            int ep = aurb->urb.endpoint & 0xf;
+            if (aurb->urb.status == -EPIPE) {
+                set_halt(s, pid, ep);
+            }
+            aurb->iso_frame_idx = 0;
+            urbs++;
+            inflight = change_iso_inflight(s, pid, ep, -1);
+            if (inflight == 0 && is_iso_started(s, pid, ep)) {
+                fprintf(stderr, "husb: out of buffers for iso stream\n");
+            }
+            continue;
+        }
+
+        p = aurb->packet;
+        trace_usb_host_urb_complete(s->bus_num, s->addr, aurb, aurb->urb.status,
+                                    aurb->urb.actual_length, aurb->more);
+
+        if (p) {
+            switch (aurb->urb.status) {
+            case 0:
+                p->result += aurb->urb.actual_length;
+                break;
+
+            case -EPIPE:
+                set_halt(s, p->pid, p->ep->nr);
+                p->result = USB_RET_STALL;
+                break;
+
+            case -EOVERFLOW:
+                p->result = USB_RET_BABBLE;
+                break;
+
+            default:
+                p->result = USB_RET_IOERROR;
+                break;
+            }
+
+            if (aurb->urb.type == USBDEVFS_URB_TYPE_CONTROL) {
+                trace_usb_host_req_complete(s->bus_num, s->addr, p->result);
+                usb_generic_async_ctrl_complete(&s->dev, p);
+            } else if (!aurb->more) {
+                trace_usb_host_req_complete(s->bus_num, s->addr, p->result);
+                usb_packet_complete(&s->dev, p);
+            }
+        }
+
+        async_free(aurb);
+    }
+}
+
+static void usb_host_async_cancel(USBDevice *dev, USBPacket *p)
+{
+    USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
+    AsyncURB *aurb;
+
+    QLIST_FOREACH(aurb, &s->aurbs, next) {
+        if (p != aurb->packet) {
+            continue;
+        }
+
+        DPRINTF("husb: async cancel: packet %p, aurb %p\n", p, aurb);
+
+        /* Mark it as dead (see async_complete above) */
+        aurb->packet = NULL;
+
+        int r = ioctl(s->fd, USBDEVFS_DISCARDURB, aurb);
+        if (r < 0) {
+            DPRINTF("husb: async. discard urb failed errno %d\n", errno);
+        }
+    }
+}
+
+static int usb_host_open_device(int bus, int addr)
+{
+    const char *usbfs = NULL;
+    char filename[32];
+    struct stat st;
+    int fd, rc;
+
+    rc = stat("/dev/bus/usb", &st);
+    if (rc == 0 && S_ISDIR(st.st_mode)) {
+        /* udev-created device nodes available */
+        usbfs = "/dev/bus/usb";
+    } else {
+        /* fallback: usbfs mounted below /proc */
+        usbfs = "/proc/bus/usb";
+    }
+
+    snprintf(filename, sizeof(filename), "%s/%03d/%03d",
+             usbfs, bus, addr);
+    fd = open(filename, O_RDWR | O_NONBLOCK);
+    if (fd < 0) {
+        fprintf(stderr, "husb: open %s: %s\n", filename, strerror(errno));
+    }
+    return fd;
+}
+
+static int usb_host_claim_port(USBHostDevice *s)
+{
+#ifdef USBDEVFS_CLAIM_PORT
+    char *h, hub_name[64], line[1024];
+    int hub_addr, ret;
+
+    snprintf(hub_name, sizeof(hub_name), "%d-%s",
+             s->match.bus_num, s->match.port);
+
+    /* try strip off last ".$portnr" to get hub */
+    h = strrchr(hub_name, '.');
+    if (h != NULL) {
+        s->hub_port = atoi(h+1);
+        *h = '\0';
+    } else {
+        /* no dot in there -> it is the root hub */
+        snprintf(hub_name, sizeof(hub_name), "usb%d",
+                 s->match.bus_num);
+        s->hub_port = atoi(s->match.port);
+    }
+
+    if (!usb_host_read_file(line, sizeof(line), "devnum",
+                            hub_name)) {
+        return -1;
+    }
+    if (sscanf(line, "%d", &hub_addr) != 1) {
+        return -1;
+    }
+
+    s->hub_fd = usb_host_open_device(s->match.bus_num, hub_addr);
+    if (s->hub_fd < 0) {
+        return -1;
+    }
+
+    ret = ioctl(s->hub_fd, USBDEVFS_CLAIM_PORT, &s->hub_port);
+    if (ret < 0) {
+        close(s->hub_fd);
+        s->hub_fd = -1;
+        return -1;
+    }
+
+    trace_usb_host_claim_port(s->match.bus_num, hub_addr, s->hub_port);
+    return 0;
+#else
+    return -1;
+#endif
+}
+
+static void usb_host_release_port(USBHostDevice *s)
+{
+    if (s->hub_fd == -1) {
+        return;
+    }
+#ifdef USBDEVFS_RELEASE_PORT
+    ioctl(s->hub_fd, USBDEVFS_RELEASE_PORT, &s->hub_port);
+#endif
+    close(s->hub_fd);
+    s->hub_fd = -1;
+}
+
+static int usb_host_disconnect_ifaces(USBHostDevice *dev, int nb_interfaces)
+{
+    /* earlier Linux 2.4 do not support that */
+#ifdef USBDEVFS_DISCONNECT
+    struct usbdevfs_ioctl ctrl;
+    int ret, interface;
+
+    for (interface = 0; interface < nb_interfaces; interface++) {
+        ctrl.ioctl_code = USBDEVFS_DISCONNECT;
+        ctrl.ifno = interface;
+        ctrl.data = 0;
+        ret = ioctl(dev->fd, USBDEVFS_IOCTL, &ctrl);
+        if (ret < 0 && errno != ENODATA) {
+            perror("USBDEVFS_DISCONNECT");
+            return -1;
+        }
+    }
+#endif
+    return 0;
+}
+
+static int usb_linux_get_num_interfaces(USBHostDevice *s)
+{
+    char device_name[64], line[1024];
+    int num_interfaces = 0;
+
+    sprintf(device_name, "%d-%s", s->bus_num, s->port);
+    if (!usb_host_read_file(line, sizeof(line), "bNumInterfaces",
+                            device_name)) {
+        return -1;
+    }
+    if (sscanf(line, "%d", &num_interfaces) != 1) {
+        return -1;
+    }
+    return num_interfaces;
+}
+
+static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
+{
+    const char *op = NULL;
+    int dev_descr_len, config_descr_len;
+    int interface, nb_interfaces;
+    int ret, i;
+
+    for (i = 0; i < USB_MAX_INTERFACES; i++) {
+        dev->dev.altsetting[i] = 0;
+    }
+
+    if (configuration == 0) { /* address state - ignore */
+        dev->dev.ninterfaces   = 0;
+        dev->dev.configuration = 0;
+        return 1;
+    }
+
+    DPRINTF("husb: claiming interfaces. config %d\n", configuration);
+
+    i = 0;
+    dev_descr_len = dev->descr[0];
+    if (dev_descr_len > dev->descr_len) {
+        fprintf(stderr, "husb: update iface failed. descr too short\n");
+        return 0;
+    }
+
+    i += dev_descr_len;
+    while (i < dev->descr_len) {
+        DPRINTF("husb: i is %d, descr_len is %d, dl %d, dt %d\n",
+                i, dev->descr_len,
+               dev->descr[i], dev->descr[i+1]);
+
+        if (dev->descr[i+1] != USB_DT_CONFIG) {
+            i += dev->descr[i];
+            continue;
+        }
+        config_descr_len = dev->descr[i];
+
+        DPRINTF("husb: config #%d need %d\n", dev->descr[i + 5], configuration);
+
+        if (configuration == dev->descr[i + 5]) {
+            configuration = dev->descr[i + 5];
+            break;
+        }
+
+        i += config_descr_len;
+    }
+
+    if (i >= dev->descr_len) {
+        fprintf(stderr,
+                "husb: update iface failed. no matching configuration\n");
+        return 0;
+    }
+    nb_interfaces = dev->descr[i + 4];
+
+    if (usb_host_disconnect_ifaces(dev, nb_interfaces) < 0) {
+        goto fail;
+    }
+
+    /* XXX: only grab if all interfaces are free */
+    for (interface = 0; interface < nb_interfaces; interface++) {
+        op = "USBDEVFS_CLAIMINTERFACE";
+        ret = ioctl(dev->fd, USBDEVFS_CLAIMINTERFACE, &interface);
+        if (ret < 0) {
+            goto fail;
+        }
+    }
+
+    trace_usb_host_claim_interfaces(dev->bus_num, dev->addr,
+                                    nb_interfaces, configuration);
+
+    dev->dev.ninterfaces   = nb_interfaces;
+    dev->dev.configuration = configuration;
+    return 1;
+
+fail:
+    if (errno == ENODEV) {
+        do_disconnect(dev);
+    }
+    perror(op);
+    return 0;
+}
+
+static int usb_host_release_interfaces(USBHostDevice *s)
+{
+    int ret, i;
+
+    trace_usb_host_release_interfaces(s->bus_num, s->addr);
+
+    for (i = 0; i < s->dev.ninterfaces; i++) {
+        ret = ioctl(s->fd, USBDEVFS_RELEASEINTERFACE, &i);
+        if (ret < 0) {
+            perror("USBDEVFS_RELEASEINTERFACE");
+            return 0;
+        }
+    }
+    return 1;
+}
+
+static void usb_host_handle_reset(USBDevice *dev)
+{
+    USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
+
+    trace_usb_host_reset(s->bus_num, s->addr);
+
+    usb_host_do_reset(s);;
+
+    usb_host_claim_interfaces(s, 0);
+    usb_linux_update_endp_table(s);
+}
+
+static void usb_host_handle_destroy(USBDevice *dev)
+{
+    USBHostDevice *s = (USBHostDevice *)dev;
+
+    usb_host_release_port(s);
+    usb_host_close(s);
+    QTAILQ_REMOVE(&hostdevs, s, next);
+    qemu_remove_exit_notifier(&s->exit);
+}
+
+/* iso data is special, we need to keep enough urbs in flight to make sure
+   that the controller never runs out of them, otherwise the device will
+   likely suffer a buffer underrun / overrun. */
+static AsyncURB *usb_host_alloc_iso(USBHostDevice *s, int pid, uint8_t ep)
+{
+    AsyncURB *aurb;
+    int i, j, len = usb_ep_get_max_packet_size(&s->dev, pid, ep);
+
+    aurb = g_malloc0(s->iso_urb_count * sizeof(*aurb));
+    for (i = 0; i < s->iso_urb_count; i++) {
+        aurb[i].urb.endpoint      = ep;
+        aurb[i].urb.buffer_length = ISO_FRAME_DESC_PER_URB * len;
+        aurb[i].urb.buffer        = g_malloc(aurb[i].urb.buffer_length);
+        aurb[i].urb.type          = USBDEVFS_URB_TYPE_ISO;
+        aurb[i].urb.flags         = USBDEVFS_URB_ISO_ASAP;
+        aurb[i].urb.number_of_packets = ISO_FRAME_DESC_PER_URB;
+        for (j = 0 ; j < ISO_FRAME_DESC_PER_URB; j++)
+            aurb[i].urb.iso_frame_desc[j].length = len;
+        if (pid == USB_TOKEN_IN) {
+            aurb[i].urb.endpoint |= 0x80;
+            /* Mark as fully consumed (idle) */
+            aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB;
+        }
+    }
+    set_iso_urb(s, pid, ep, aurb);
+
+    return aurb;
+}
+
+static void usb_host_stop_n_free_iso(USBHostDevice *s, int pid, uint8_t ep)
+{
+    AsyncURB *aurb;
+    int i, ret, killed = 0, free = 1;
+
+    aurb = get_iso_urb(s, pid, ep);
+    if (!aurb) {
+        return;
+    }
+
+    for (i = 0; i < s->iso_urb_count; i++) {
+        /* in flight? */
+        if (aurb[i].iso_frame_idx == -1) {
+            ret = ioctl(s->fd, USBDEVFS_DISCARDURB, &aurb[i]);
+            if (ret < 0) {
+                perror("USBDEVFS_DISCARDURB");
+                free = 0;
+                continue;
+            }
+            killed++;
+        }
+    }
+
+    /* Make sure any urbs we've killed are reaped before we free them */
+    if (killed) {
+        async_complete(s);
+    }
+
+    for (i = 0; i < s->iso_urb_count; i++) {
+        g_free(aurb[i].urb.buffer);
+    }
+
+    if (free)
+        g_free(aurb);
+    else
+        printf("husb: leaking iso urbs because of discard failure\n");
+    set_iso_urb(s, pid, ep, NULL);
+    set_iso_urb_idx(s, pid, ep, 0);
+    clear_iso_started(s, pid, ep);
+}
+
+static int urb_status_to_usb_ret(int status)
+{
+    switch (status) {
+    case -EPIPE:
+        return USB_RET_STALL;
+    case -EOVERFLOW:
+        return USB_RET_BABBLE;
+    default:
+        return USB_RET_IOERROR;
+    }
+}
+
+static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
+{
+    AsyncURB *aurb;
+    int i, j, ret, max_packet_size, offset, len = 0;
+    uint8_t *buf;
+
+    max_packet_size = p->ep->max_packet_size;
+    if (max_packet_size == 0)
+        return USB_RET_NAK;
+
+    aurb = get_iso_urb(s, p->pid, p->ep->nr);
+    if (!aurb) {
+        aurb = usb_host_alloc_iso(s, p->pid, p->ep->nr);
+    }
+
+    i = get_iso_urb_idx(s, p->pid, p->ep->nr);
+    j = aurb[i].iso_frame_idx;
+    if (j >= 0 && j < ISO_FRAME_DESC_PER_URB) {
+        if (in) {
+            /* Check urb status  */
+            if (aurb[i].urb.status) {
+                len = urb_status_to_usb_ret(aurb[i].urb.status);
+                /* Move to the next urb */
+                aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB - 1;
+            /* Check frame status */
+            } else if (aurb[i].urb.iso_frame_desc[j].status) {
+                len = urb_status_to_usb_ret(
+                                        aurb[i].urb.iso_frame_desc[j].status);
+            /* Check the frame fits */
+            } else if (aurb[i].urb.iso_frame_desc[j].actual_length
+                       > p->iov.size) {
+                printf("husb: received iso data is larger then packet\n");
+                len = USB_RET_BABBLE;
+            /* All good copy data over */
+            } else {
+                len = aurb[i].urb.iso_frame_desc[j].actual_length;
+                buf  = aurb[i].urb.buffer +
+                    j * aurb[i].urb.iso_frame_desc[0].length;
+                usb_packet_copy(p, buf, len);
+            }
+        } else {
+            len = p->iov.size;
+            offset = (j == 0) ? 0 : get_iso_buffer_used(s, p->pid, p->ep->nr);
+
+            /* Check the frame fits */
+            if (len > max_packet_size) {
+                printf("husb: send iso data is larger then max packet size\n");
+                return USB_RET_NAK;
+            }
+
+            /* All good copy data over */
+            usb_packet_copy(p, aurb[i].urb.buffer + offset, len);
+            aurb[i].urb.iso_frame_desc[j].length = len;
+            offset += len;
+            set_iso_buffer_used(s, p->pid, p->ep->nr, offset);
+
+            /* Start the stream once we have buffered enough data */
+            if (!is_iso_started(s, p->pid, p->ep->nr) && i == 1 && j == 8) {
+                set_iso_started(s, p->pid, p->ep->nr);
+            }
+        }
+        aurb[i].iso_frame_idx++;
+        if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
+            i = (i + 1) % s->iso_urb_count;
+            set_iso_urb_idx(s, p->pid, p->ep->nr, i);
+        }
+    } else {
+        if (in) {
+            set_iso_started(s, p->pid, p->ep->nr);
+        } else {
+            DPRINTF("hubs: iso out error no free buffer, dropping packet\n");
+        }
+    }
+
+    if (is_iso_started(s, p->pid, p->ep->nr)) {
+        /* (Re)-submit all fully consumed / filled urbs */
+        for (i = 0; i < s->iso_urb_count; i++) {
+            if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
+                ret = ioctl(s->fd, USBDEVFS_SUBMITURB, &aurb[i]);
+                if (ret < 0) {
+                    perror("USBDEVFS_SUBMITURB");
+                    if (!in || len == 0) {
+                        switch(errno) {
+                        case ETIMEDOUT:
+                            len = USB_RET_NAK;
+                            break;
+                        case EPIPE:
+                        default:
+                            len = USB_RET_STALL;
+                        }
+                    }
+                    break;
+                }
+                aurb[i].iso_frame_idx = -1;
+                change_iso_inflight(s, p->pid, p->ep->nr, 1);
+            }
+        }
+    }
+
+    return len;
+}
+
+static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
+{
+    USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
+    struct usbdevfs_urb *urb;
+    AsyncURB *aurb;
+    int ret, rem, prem, v;
+    uint8_t *pbuf;
+    uint8_t ep;
+
+    trace_usb_host_req_data(s->bus_num, s->addr,
+                            p->pid == USB_TOKEN_IN,
+                            p->ep->nr, p->iov.size);
+
+    if (!is_valid(s, p->pid, p->ep->nr)) {
+        trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_NAK);
+        return USB_RET_NAK;
+    }
+
+    if (p->pid == USB_TOKEN_IN) {
+        ep = p->ep->nr | 0x80;
+    } else {
+        ep = p->ep->nr;
+    }
+
+    if (is_halted(s, p->pid, p->ep->nr)) {
+        unsigned int arg = ep;
+        ret = ioctl(s->fd, USBDEVFS_CLEAR_HALT, &arg);
+        if (ret < 0) {
+            perror("USBDEVFS_CLEAR_HALT");
+            trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_NAK);
+            return USB_RET_NAK;
+        }
+        clear_halt(s, p->pid, p->ep->nr);
+    }
+
+    if (is_isoc(s, p->pid, p->ep->nr)) {
+        return usb_host_handle_iso_data(s, p, p->pid == USB_TOKEN_IN);
+    }
+
+    v = 0;
+    prem = p->iov.iov[v].iov_len;
+    pbuf = p->iov.iov[v].iov_base;
+    rem = p->iov.size;
+    while (rem) {
+        if (prem == 0) {
+            v++;
+            assert(v < p->iov.niov);
+            prem = p->iov.iov[v].iov_len;
+            pbuf = p->iov.iov[v].iov_base;
+            assert(prem <= rem);
+        }
+        aurb = async_alloc(s);
+        aurb->packet = p;
+
+        urb = &aurb->urb;
+        urb->endpoint      = ep;
+        urb->type          = usb_host_usbfs_type(s, p);
+        urb->usercontext   = s;
+        urb->buffer        = pbuf;
+        urb->buffer_length = prem;
+
+        if (urb->buffer_length > MAX_USBFS_BUFFER_SIZE) {
+            urb->buffer_length = MAX_USBFS_BUFFER_SIZE;
+        }
+        pbuf += urb->buffer_length;
+        prem -= urb->buffer_length;
+        rem  -= urb->buffer_length;
+        if (rem) {
+            aurb->more         = 1;
+        }
+
+        trace_usb_host_urb_submit(s->bus_num, s->addr, aurb,
+                                  urb->buffer_length, aurb->more);
+        ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
+
+        DPRINTF("husb: data submit: ep 0x%x, len %u, more %d, packet %p, aurb %p\n",
+                urb->endpoint, urb->buffer_length, aurb->more, p, aurb);
+
+        if (ret < 0) {
+            perror("USBDEVFS_SUBMITURB");
+            async_free(aurb);
+
+            switch(errno) {
+            case ETIMEDOUT:
+                trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_NAK);
+                return USB_RET_NAK;
+            case EPIPE:
+            default:
+                trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_STALL);
+                return USB_RET_STALL;
+            }
+        }
+    }
+
+    return USB_RET_ASYNC;
+}
+
+static int ctrl_error(void)
+{
+    if (errno == ETIMEDOUT) {
+        return USB_RET_NAK;
+    } else {
+        return USB_RET_STALL;
+    }
+}
+
+static int usb_host_set_address(USBHostDevice *s, int addr)
+{
+    trace_usb_host_set_address(s->bus_num, s->addr, addr);
+    s->dev.addr = addr;
+    return 0;
+}
+
+static int usb_host_set_config(USBHostDevice *s, int config)
+{
+    int ret, first = 1;
+
+    trace_usb_host_set_config(s->bus_num, s->addr, config);
+
+    usb_host_release_interfaces(s);
+
+again:
+    ret = ioctl(s->fd, USBDEVFS_SETCONFIGURATION, &config);
+
+    DPRINTF("husb: ctrl set config %d ret %d errno %d\n", config, ret, errno);
+
+    if (ret < 0 && errno == EBUSY && first) {
+        /* happens if usb device is in use by host drivers */
+        int count = usb_linux_get_num_interfaces(s);
+        if (count > 0) {
+            DPRINTF("husb: busy -> disconnecting %d interfaces\n", count);
+            usb_host_disconnect_ifaces(s, count);
+            first = 0;
+            goto again;
+        }
+    }
+
+    if (ret < 0) {
+        return ctrl_error();
+    }
+    usb_host_claim_interfaces(s, config);
+    usb_linux_update_endp_table(s);
+    return 0;
+}
+
+static int usb_host_set_interface(USBHostDevice *s, int iface, int alt)
+{
+    struct usbdevfs_setinterface si;
+    int i, ret;
+
+    trace_usb_host_set_interface(s->bus_num, s->addr, iface, alt);
+
+    for (i = 1; i <= USB_MAX_ENDPOINTS; i++) {
+        if (is_isoc(s, USB_TOKEN_IN, i)) {
+            usb_host_stop_n_free_iso(s, USB_TOKEN_IN, i);
+        }
+        if (is_isoc(s, USB_TOKEN_OUT, i)) {
+            usb_host_stop_n_free_iso(s, USB_TOKEN_OUT, i);
+        }
+    }
+
+    if (iface >= USB_MAX_INTERFACES) {
+        return USB_RET_STALL;
+    }
+
+    si.interface  = iface;
+    si.altsetting = alt;
+    ret = ioctl(s->fd, USBDEVFS_SETINTERFACE, &si);
+
+    DPRINTF("husb: ctrl set iface %d altset %d ret %d errno %d\n",
+            iface, alt, ret, errno);
+
+    if (ret < 0) {
+        return ctrl_error();
+    }
+
+    s->dev.altsetting[iface] = alt;
+    usb_linux_update_endp_table(s);
+    return 0;
+}
+
+static int usb_host_handle_control(USBDevice *dev, USBPacket *p,
+               int request, int value, int index, int length, uint8_t *data)
+{
+    USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
+    struct usbdevfs_urb *urb;
+    AsyncURB *aurb;
+    int ret;
+
+    /*
+     * Process certain standard device requests.
+     * These are infrequent and are processed synchronously.
+     */
+
+    /* Note request is (bRequestType << 8) | bRequest */
+    trace_usb_host_req_control(s->bus_num, s->addr, request, value, index);
+
+    switch (request) {
+    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
+        return usb_host_set_address(s, value);
+
+    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
+        return usb_host_set_config(s, value & 0xff);
+
+    case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
+        return usb_host_set_interface(s, index, value);
+    }
+
+    /* The rest are asynchronous */
+
+    if (length > sizeof(dev->data_buf)) {
+        fprintf(stderr, "husb: ctrl buffer too small (%d > %zu)\n",
+                length, sizeof(dev->data_buf));
+        return USB_RET_STALL;
+    }
+
+    aurb = async_alloc(s);
+    aurb->packet = p;
+
+    /*
+     * Setup ctrl transfer.
+     *
+     * s->ctrl is laid out such that data buffer immediately follows
+     * 'req' struct which is exactly what usbdevfs expects.
+     */
+    urb = &aurb->urb;
+
+    urb->type     = USBDEVFS_URB_TYPE_CONTROL;
+    urb->endpoint = p->ep->nr;
+
+    urb->buffer        = &dev->setup_buf;
+    urb->buffer_length = length + 8;
+
+    urb->usercontext = s;
+
+    trace_usb_host_urb_submit(s->bus_num, s->addr, aurb,
+                              urb->buffer_length, aurb->more);
+    ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
+
+    DPRINTF("husb: submit ctrl. len %u aurb %p\n", urb->buffer_length, aurb);
+
+    if (ret < 0) {
+        DPRINTF("husb: submit failed. errno %d\n", errno);
+        async_free(aurb);
+
+        switch(errno) {
+        case ETIMEDOUT:
+            return USB_RET_NAK;
+        case EPIPE:
+        default:
+            return USB_RET_STALL;
+        }
+    }
+
+    return USB_RET_ASYNC;
+}
+
+static uint8_t usb_linux_get_alt_setting(USBHostDevice *s,
+    uint8_t configuration, uint8_t interface)
+{
+    char device_name[64], line[1024];
+    int alt_setting;
+
+    sprintf(device_name, "%d-%s:%d.%d", s->bus_num, s->port,
+            (int)configuration, (int)interface);
+
+    if (!usb_host_read_file(line, sizeof(line), "bAlternateSetting",
+                            device_name)) {
+        /* Assume alt 0 on error */
+        return 0;
+    }
+    if (sscanf(line, "%d", &alt_setting) != 1) {
+        /* Assume alt 0 on error */
+        return 0;
+    }
+    return alt_setting;
+}
+
+/* returns 1 on problem encountered or 0 for success */
+static int usb_linux_update_endp_table(USBHostDevice *s)
+{
+    uint8_t *descriptors;
+    uint8_t devep, type, alt_interface;
+    uint16_t raw;
+    int interface, length, i, ep, pid;
+    struct endp_data *epd;
+
+    usb_ep_init(&s->dev);
+
+    if (s->dev.configuration == 0) {
+        /* not configured yet -- leave all endpoints disabled */
+        return 0;
+    }
+
+    /* get the desired configuration, interface, and endpoint descriptors
+     * from device description */
+    descriptors = &s->descr[18];
+    length = s->descr_len - 18;
+    i = 0;
+
+    while (i < length) {
+        if (descriptors[i + 1] != USB_DT_CONFIG) {
+            fprintf(stderr, "invalid descriptor data\n");
+            return 1;
+        } else if (descriptors[i + 5] != s->dev.configuration) {
+            DPRINTF("not requested configuration %d\n", s->dev.configuration);
+            i += (descriptors[i + 3] << 8) + descriptors[i + 2];
+            continue;
+        }
+        i += descriptors[i];
+
+        if (descriptors[i + 1] != USB_DT_INTERFACE ||
+            (descriptors[i + 1] == USB_DT_INTERFACE &&
+             descriptors[i + 4] == 0)) {
+            i += descriptors[i];
+            continue;
+        }
+
+        interface = descriptors[i + 2];
+        alt_interface = usb_linux_get_alt_setting(s, s->dev.configuration,
+                                                  interface);
+
+        /* the current interface descriptor is the active interface
+         * and has endpoints */
+        if (descriptors[i + 3] != alt_interface) {
+            i += descriptors[i];
+            continue;
+        }
+
+        /* advance to the endpoints */
+        while (i < length && descriptors[i +1] != USB_DT_ENDPOINT) {
+            i += descriptors[i];
+        }
+
+        if (i >= length)
+            break;
+
+        while (i < length) {
+            if (descriptors[i + 1] != USB_DT_ENDPOINT) {
+                break;
+            }
+
+            devep = descriptors[i + 2];
+            pid = (devep & USB_DIR_IN) ? USB_TOKEN_IN : USB_TOKEN_OUT;
+            ep = devep & 0xf;
+            if (ep == 0) {
+                fprintf(stderr, "usb-linux: invalid ep descriptor, ep == 0\n");
+                return 1;
+            }
+
+            type = descriptors[i + 3] & 0x3;
+            raw = descriptors[i + 4] + (descriptors[i + 5] << 8);
+            usb_ep_set_max_packet_size(&s->dev, pid, ep, raw);
+            assert(usb_ep_get_type(&s->dev, pid, ep) ==
+                   USB_ENDPOINT_XFER_INVALID);
+            usb_ep_set_type(&s->dev, pid, ep, type);
+            usb_ep_set_ifnum(&s->dev, pid, ep, interface);
+            if (type == USB_ENDPOINT_XFER_BULK) {
+                usb_ep_set_pipeline(&s->dev, pid, ep, true);
+            }
+
+            epd = get_endp(s, pid, ep);
+            epd->halted = 0;
+
+            i += descriptors[i];
+        }
+    }
+#ifdef DEBUG
+    usb_ep_dump(&s->dev);
+#endif
+    return 0;
+}
+
+/*
+ * Check if we can safely redirect a usb2 device to a usb1 virtual controller,
+ * this function assumes this is safe, if:
+ * 1) There are no isoc endpoints
+ * 2) There are no interrupt endpoints with a max_packet_size > 64
+ * Note bulk endpoints with a max_packet_size > 64 in theory also are not
+ * usb1 compatible, but in practice this seems to work fine.
+ */
+static int usb_linux_full_speed_compat(USBHostDevice *dev)
+{
+    int i, packet_size;
+
+    /*
+     * usb_linux_update_endp_table only registers info about ep in the current
+     * interface altsettings, so we need to parse the descriptors again.
+     */
+    for (i = 0; (i + 5) < dev->descr_len; i += dev->descr[i]) {
+        if (dev->descr[i + 1] == USB_DT_ENDPOINT) {
+            switch (dev->descr[i + 3] & 0x3) {
+            case 0x00: /* CONTROL */
+                break;
+            case 0x01: /* ISO */
+                return 0;
+            case 0x02: /* BULK */
+                break;
+            case 0x03: /* INTERRUPT */
+                packet_size = dev->descr[i + 4] + (dev->descr[i + 5] << 8);
+                if (packet_size > 64)
+                    return 0;
+                break;
+            }
+        }
+    }
+    return 1;
+}
+
+static int usb_host_open(USBHostDevice *dev, int bus_num,
+                         int addr, const char *port,
+                         const char *prod_name, int speed)
+{
+    int fd = -1, ret;
+
+    trace_usb_host_open_started(bus_num, addr);
+
+    if (dev->fd != -1) {
+        goto fail;
+    }
+
+    fd = usb_host_open_device(bus_num, addr);
+    if (fd < 0) {
+        goto fail;
+    }
+    DPRINTF("husb: opened %s\n", buf);
+
+    dev->bus_num = bus_num;
+    dev->addr = addr;
+    strcpy(dev->port, port);
+    dev->fd = fd;
+
+    /* read the device description */
+    dev->descr_len = read(fd, dev->descr, sizeof(dev->descr));
+    if (dev->descr_len <= 0) {
+        perror("husb: reading device data failed");
+        goto fail;
+    }
+
+#ifdef DEBUG
+    {
+        int x;
+        printf("=== begin dumping device descriptor data ===\n");
+        for (x = 0; x < dev->descr_len; x++) {
+            printf("%02x ", dev->descr[x]);
+        }
+        printf("\n=== end dumping device descriptor data ===\n");
+    }
+#endif
+
+
+    /* start unconfigured -- we'll wait for the guest to set a configuration */
+    if (!usb_host_claim_interfaces(dev, 0)) {
+        goto fail;
+    }
+
+    ret = usb_linux_update_endp_table(dev);
+    if (ret) {
+        goto fail;
+    }
+
+    if (speed == -1) {
+        struct usbdevfs_connectinfo ci;
+
+        ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci);
+        if (ret < 0) {
+            perror("usb_host_device_open: USBDEVFS_CONNECTINFO");
+            goto fail;
+        }
+
+        if (ci.slow) {
+            speed = USB_SPEED_LOW;
+        } else {
+            speed = USB_SPEED_HIGH;
+        }
+    }
+    dev->dev.speed = speed;
+    dev->dev.speedmask = (1 << speed);
+    if (dev->dev.speed == USB_SPEED_HIGH && usb_linux_full_speed_compat(dev)) {
+        dev->dev.speedmask |= USB_SPEED_MASK_FULL;
+    }
+
+    trace_usb_host_open_success(bus_num, addr);
+
+    if (!prod_name || prod_name[0] == '\0') {
+        snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc),
+                 "host:%d.%d", bus_num, addr);
+    } else {
+        pstrcpy(dev->dev.product_desc, sizeof(dev->dev.product_desc),
+                prod_name);
+    }
+
+    ret = usb_device_attach(&dev->dev);
+    if (ret) {
+        goto fail;
+    }
+
+    /* USB devio uses 'write' flag to check for async completions */
+    qemu_set_fd_handler(dev->fd, NULL, async_complete, dev);
+
+    return 0;
+
+fail:
+    trace_usb_host_open_failure(bus_num, addr);
+    if (dev->fd != -1) {
+        close(dev->fd);
+        dev->fd = -1;
+    }
+    return -1;
+}
+
+static int usb_host_close(USBHostDevice *dev)
+{
+    int i;
+
+    if (dev->fd == -1) {
+        return -1;
+    }
+
+    trace_usb_host_close(dev->bus_num, dev->addr);
+
+    qemu_set_fd_handler(dev->fd, NULL, NULL, NULL);
+    dev->closing = 1;
+    for (i = 1; i <= USB_MAX_ENDPOINTS; i++) {
+        if (is_isoc(dev, USB_TOKEN_IN, i)) {
+            usb_host_stop_n_free_iso(dev, USB_TOKEN_IN, i);
+        }
+        if (is_isoc(dev, USB_TOKEN_OUT, i)) {
+            usb_host_stop_n_free_iso(dev, USB_TOKEN_OUT, i);
+        }
+    }
+    async_complete(dev);
+    dev->closing = 0;
+    if (dev->dev.attached) {
+        usb_device_detach(&dev->dev);
+    }
+    usb_host_do_reset(dev);
+    close(dev->fd);
+    dev->fd = -1;
+    return 0;
+}
+
+static void usb_host_exit_notifier(struct Notifier *n, void *data)
+{
+    USBHostDevice *s = container_of(n, USBHostDevice, exit);
+
+    usb_host_release_port(s);
+    if (s->fd != -1) {
+        usb_host_do_reset(s);;
+    }
+}
+
+static int usb_host_initfn(USBDevice *dev)
+{
+    USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
+
+    dev->auto_attach = 0;
+    s->fd = -1;
+    s->hub_fd = -1;
+
+    QTAILQ_INSERT_TAIL(&hostdevs, s, next);
+    s->exit.notify = usb_host_exit_notifier;
+    qemu_add_exit_notifier(&s->exit);
+    usb_host_auto_check(NULL);
+
+    if (s->match.bus_num != 0 && s->match.port != NULL) {
+        usb_host_claim_port(s);
+    }
+    return 0;
+}
+
+static const VMStateDescription vmstate_usb_host = {
+    .name = "usb-host",
+    .unmigratable = 1,
+};
+
+static Property usb_host_dev_properties[] = {
+    DEFINE_PROP_UINT32("hostbus",  USBHostDevice, match.bus_num,    0),
+    DEFINE_PROP_UINT32("hostaddr", USBHostDevice, match.addr,       0),
+    DEFINE_PROP_STRING("hostport", USBHostDevice, match.port),
+    DEFINE_PROP_HEX32("vendorid",  USBHostDevice, match.vendor_id,  0),
+    DEFINE_PROP_HEX32("productid", USBHostDevice, match.product_id, 0),
+    DEFINE_PROP_UINT32("isobufs",  USBHostDevice, iso_urb_count,    4),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void usb_host_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+    uc->init           = usb_host_initfn;
+    uc->product_desc   = "USB Host Device";
+    uc->cancel_packet  = usb_host_async_cancel;
+    uc->handle_data    = usb_host_handle_data;
+    uc->handle_control = usb_host_handle_control;
+    uc->handle_reset   = usb_host_handle_reset;
+    uc->handle_destroy = usb_host_handle_destroy;
+    dc->vmsd = &vmstate_usb_host;
+    dc->props = usb_host_dev_properties;
+}
+
+static TypeInfo usb_host_dev_info = {
+    .name          = "usb-host",
+    .parent        = TYPE_USB_DEVICE,
+    .instance_size = sizeof(USBHostDevice),
+    .class_init    = usb_host_class_initfn,
+};
+
+static void usb_host_register_types(void)
+{
+    type_register_static(&usb_host_dev_info);
+    usb_legacy_register("usb-host", "host", usb_host_device_open);
+}
+
+type_init(usb_host_register_types)
+
+USBDevice *usb_host_device_open(USBBus *bus, const char *devname)
+{
+    struct USBAutoFilter filter;
+    USBDevice *dev;
+    char *p;
+
+    dev = usb_create(bus, "usb-host");
+
+    if (strstr(devname, "auto:")) {
+        if (parse_filter(devname, &filter) < 0) {
+            goto fail;
+        }
+    } else {
+        if ((p = strchr(devname, '.'))) {
+            filter.bus_num    = strtoul(devname, NULL, 0);
+            filter.addr       = strtoul(p + 1, NULL, 0);
+            filter.vendor_id  = 0;
+            filter.product_id = 0;
+        } else if ((p = strchr(devname, ':'))) {
+            filter.bus_num    = 0;
+            filter.addr       = 0;
+            filter.vendor_id  = strtoul(devname, NULL, 16);
+            filter.product_id = strtoul(p + 1, NULL, 16);
+        } else {
+            goto fail;
+        }
+    }
+
+    qdev_prop_set_uint32(&dev->qdev, "hostbus",   filter.bus_num);
+    qdev_prop_set_uint32(&dev->qdev, "hostaddr",  filter.addr);
+    qdev_prop_set_uint32(&dev->qdev, "vendorid",  filter.vendor_id);
+    qdev_prop_set_uint32(&dev->qdev, "productid", filter.product_id);
+    qdev_init_nofail(&dev->qdev);
+    return dev;
+
+fail:
+    qdev_free(&dev->qdev);
+    return NULL;
+}
+
+int usb_host_device_close(const char *devname)
+{
+#if 0
+    char product_name[PRODUCT_NAME_SZ];
+    int bus_num, addr;
+    USBHostDevice *s;
+
+    if (strstr(devname, "auto:")) {
+        return usb_host_auto_del(devname);
+    }
+    if (usb_host_find_device(&bus_num, &addr, product_name,
+                                    sizeof(product_name), devname) < 0) {
+        return -1;
+    }
+    s = hostdev_find(bus_num, addr);
+    if (s) {
+        usb_device_delete_addr(s->bus_num, s->dev.addr);
+        return 0;
+    }
+#endif
+
+    return -1;
+}
+
+/*
+ * Read sys file-system device file
+ *
+ * @line address of buffer to put file contents in
+ * @line_size size of line
+ * @device_file path to device file (printf format string)
+ * @device_name device being opened (inserted into device_file)
+ *
+ * @return 0 failed, 1 succeeded ('line' contains data)
+ */
+static int usb_host_read_file(char *line, size_t line_size,
+                              const char *device_file, const char *device_name)
+{
+    FILE *f;
+    int ret = 0;
+    char filename[PATH_MAX];
+
+    snprintf(filename, PATH_MAX, "/sys/bus/usb/devices/%s/%s", device_name,
+             device_file);
+    f = fopen(filename, "r");
+    if (f) {
+        ret = fgets(line, line_size, f) != NULL;
+        fclose(f);
+    }
+
+    return ret;
+}
+
+/*
+ * Use /sys/bus/usb/devices/ directory to determine host's USB
+ * devices.
+ *
+ * This code is based on Robert Schiele's original patches posted to
+ * the Novell bug-tracker https://bugzilla.novell.com/show_bug.cgi?id=241950
+ */
+static int usb_host_scan(void *opaque, USBScanFunc *func)
+{
+    DIR *dir = NULL;
+    char line[1024];
+    int bus_num, addr, speed, class_id, product_id, vendor_id;
+    int ret = 0;
+    char port[MAX_PORTLEN];
+    char product_name[512];
+    struct dirent *de;
+
+    dir = opendir("/sys/bus/usb/devices");
+    if (!dir) {
+        perror("husb: opendir /sys/bus/usb/devices");
+        fprintf(stderr, "husb: please make sure sysfs is mounted at /sys\n");
+        goto the_end;
+    }
+
+    while ((de = readdir(dir))) {
+        if (de->d_name[0] != '.' && !strchr(de->d_name, ':')) {
+            if (sscanf(de->d_name, "%d-%7[0-9.]", &bus_num, port) < 2) {
+                continue;
+            }
+
+            if (!usb_host_read_file(line, sizeof(line), "devnum", de->d_name)) {
+                goto the_end;
+            }
+            if (sscanf(line, "%d", &addr) != 1) {
+                goto the_end;
+            }
+            if (!usb_host_read_file(line, sizeof(line), "bDeviceClass",
+                                    de->d_name)) {
+                goto the_end;
+            }
+            if (sscanf(line, "%x", &class_id) != 1) {
+                goto the_end;
+            }
+
+            if (!usb_host_read_file(line, sizeof(line), "idVendor",
+                                    de->d_name)) {
+                goto the_end;
+            }
+            if (sscanf(line, "%x", &vendor_id) != 1) {
+                goto the_end;
+            }
+            if (!usb_host_read_file(line, sizeof(line), "idProduct",
+                                    de->d_name)) {
+                goto the_end;
+            }
+            if (sscanf(line, "%x", &product_id) != 1) {
+                goto the_end;
+            }
+            if (!usb_host_read_file(line, sizeof(line), "product",
+                                    de->d_name)) {
+                *product_name = 0;
+            } else {
+                if (strlen(line) > 0) {
+                    line[strlen(line) - 1] = '\0';
+                }
+                pstrcpy(product_name, sizeof(product_name), line);
+            }
+
+            if (!usb_host_read_file(line, sizeof(line), "speed", de->d_name)) {
+                goto the_end;
+            }
+            if (!strcmp(line, "5000\n")) {
+                speed = USB_SPEED_SUPER;
+            } else if (!strcmp(line, "480\n")) {
+                speed = USB_SPEED_HIGH;
+            } else if (!strcmp(line, "1.5\n")) {
+                speed = USB_SPEED_LOW;
+            } else {
+                speed = USB_SPEED_FULL;
+            }
+
+            ret = func(opaque, bus_num, addr, port, class_id, vendor_id,
+                       product_id, product_name, speed);
+            if (ret) {
+                goto the_end;
+            }
+        }
+    }
+ the_end:
+    if (dir) {
+        closedir(dir);
+    }
+    return ret;
+}
+
+static QEMUTimer *usb_auto_timer;
+
+static int usb_host_auto_scan(void *opaque, int bus_num,
+                              int addr, const char *port,
+                              int class_id, int vendor_id, int product_id,
+                              const char *product_name, int speed)
+{
+    struct USBAutoFilter *f;
+    struct USBHostDevice *s;
+
+    /* Ignore hubs */
+    if (class_id == 9)
+        return 0;
+
+    QTAILQ_FOREACH(s, &hostdevs, next) {
+        f = &s->match;
+
+        if (f->bus_num > 0 && f->bus_num != bus_num) {
+            continue;
+        }
+        if (f->addr > 0 && f->addr != addr) {
+            continue;
+        }
+        if (f->port != NULL && (port == NULL || strcmp(f->port, port) != 0)) {
+            continue;
+        }
+
+        if (f->vendor_id > 0 && f->vendor_id != vendor_id) {
+            continue;
+        }
+
+        if (f->product_id > 0 && f->product_id != product_id) {
+            continue;
+        }
+        /* We got a match */
+        s->seen++;
+        if (s->errcount >= 3) {
+            return 0;
+        }
+
+        /* Already attached ? */
+        if (s->fd != -1) {
+            return 0;
+        }
+        DPRINTF("husb: auto open: bus_num %d addr %d\n", bus_num, addr);
+
+        if (usb_host_open(s, bus_num, addr, port, product_name, speed) < 0) {
+            s->errcount++;
+        }
+        break;
+    }
+
+    return 0;
+}
+
+static void usb_host_auto_check(void *unused)
+{
+    struct USBHostDevice *s;
+    int unconnected = 0;
+
+    usb_host_scan(NULL, usb_host_auto_scan);
+
+    QTAILQ_FOREACH(s, &hostdevs, next) {
+        if (s->fd == -1) {
+            unconnected++;
+        }
+        if (s->seen == 0) {
+            s->errcount = 0;
+        }
+        s->seen = 0;
+    }
+
+    if (unconnected == 0) {
+        /* nothing to watch */
+        if (usb_auto_timer) {
+            qemu_del_timer(usb_auto_timer);
+            trace_usb_host_auto_scan_disabled();
+        }
+        return;
+    }
+
+    if (!usb_auto_timer) {
+        usb_auto_timer = qemu_new_timer_ms(rt_clock, usb_host_auto_check, NULL);
+        if (!usb_auto_timer) {
+            return;
+        }
+        trace_usb_host_auto_scan_enabled();
+    }
+    qemu_mod_timer(usb_auto_timer, qemu_get_clock_ms(rt_clock) + 2000);
+}
+
+/*
+ * Autoconnect filter
+ * Format:
+ *    auto:bus:dev[:vid:pid]
+ *    auto:bus.dev[:vid:pid]
+ *
+ *    bus  - bus number    (dec, * means any)
+ *    dev  - device number (dec, * means any)
+ *    vid  - vendor id     (hex, * means any)
+ *    pid  - product id    (hex, * means any)
+ *
+ *    See 'lsusb' output.
+ */
+static int parse_filter(const char *spec, struct USBAutoFilter *f)
+{
+    enum { BUS, DEV, VID, PID, DONE };
+    const char *p = spec;
+    int i;
+
+    f->bus_num    = 0;
+    f->addr       = 0;
+    f->vendor_id  = 0;
+    f->product_id = 0;
+
+    for (i = BUS; i < DONE; i++) {
+        p = strpbrk(p, ":.");
+        if (!p) {
+            break;
+        }
+        p++;
+
+        if (*p == '*') {
+            continue;
+        }
+        switch(i) {
+        case BUS: f->bus_num = strtol(p, NULL, 10);    break;
+        case DEV: f->addr    = strtol(p, NULL, 10);    break;
+        case VID: f->vendor_id  = strtol(p, NULL, 16); break;
+        case PID: f->product_id = strtol(p, NULL, 16); break;
+        }
+    }
+
+    if (i < DEV) {
+        fprintf(stderr, "husb: invalid auto filter spec %s\n", spec);
+        return -1;
+    }
+
+    return 0;
+}
+
+/**********************/
+/* USB host device info */
+
+struct usb_class_info {
+    int class;
+    const char *class_name;
+};
+
+static const struct usb_class_info usb_class_info[] = {
+    { USB_CLASS_AUDIO, "Audio"},
+    { USB_CLASS_COMM, "Communication"},
+    { USB_CLASS_HID, "HID"},
+    { USB_CLASS_HUB, "Hub" },
+    { USB_CLASS_PHYSICAL, "Physical" },
+    { USB_CLASS_PRINTER, "Printer" },
+    { USB_CLASS_MASS_STORAGE, "Storage" },
+    { USB_CLASS_CDC_DATA, "Data" },
+    { USB_CLASS_APP_SPEC, "Application Specific" },
+    { USB_CLASS_VENDOR_SPEC, "Vendor Specific" },
+    { USB_CLASS_STILL_IMAGE, "Still Image" },
+    { USB_CLASS_CSCID, "Smart Card" },
+    { USB_CLASS_CONTENT_SEC, "Content Security" },
+    { -1, NULL }
+};
+
+static const char *usb_class_str(uint8_t class)
+{
+    const struct usb_class_info *p;
+    for(p = usb_class_info; p->class != -1; p++) {
+        if (p->class == class) {
+            break;
+        }
+    }
+    return p->class_name;
+}
+
+static void usb_info_device(Monitor *mon, int bus_num,
+                            int addr, const char *port,
+                            int class_id, int vendor_id, int product_id,
+                            const char *product_name,
+                            int speed)
+{
+    const char *class_str, *speed_str;
+
+    switch(speed) {
+    case USB_SPEED_LOW:
+        speed_str = "1.5";
+        break;
+    case USB_SPEED_FULL:
+        speed_str = "12";
+        break;
+    case USB_SPEED_HIGH:
+        speed_str = "480";
+        break;
+    case USB_SPEED_SUPER:
+        speed_str = "5000";
+        break;
+    default:
+        speed_str = "?";
+        break;
+    }
+
+    monitor_printf(mon, "  Bus %d, Addr %d, Port %s, Speed %s Mb/s\n",
+                   bus_num, addr, port, speed_str);
+    class_str = usb_class_str(class_id);
+    if (class_str) {
+        monitor_printf(mon, "    %s:", class_str);
+    } else {
+        monitor_printf(mon, "    Class %02x:", class_id);
+    }
+    monitor_printf(mon, " USB device %04x:%04x", vendor_id, product_id);
+    if (product_name[0] != '\0') {
+        monitor_printf(mon, ", %s", product_name);
+    }
+    monitor_printf(mon, "\n");
+}
+
+static int usb_host_info_device(void *opaque, int bus_num, int addr,
+                                const char *path, int class_id,
+                                int vendor_id, int product_id,
+                                const char *product_name,
+                                int speed)
+{
+    Monitor *mon = opaque;
+
+    usb_info_device(mon, bus_num, addr, path, class_id, vendor_id, product_id,
+                    product_name, speed);
+    return 0;
+}
+
+static void dec2str(int val, char *str, size_t size)
+{
+    if (val == 0) {
+        snprintf(str, size, "*");
+    } else {
+        snprintf(str, size, "%d", val);
+    }
+}
+
+static void hex2str(int val, char *str, size_t size)
+{
+    if (val == 0) {
+        snprintf(str, size, "*");
+    } else {
+        snprintf(str, size, "%04x", val);
+    }
+}
+
+void usb_host_info(Monitor *mon)
+{
+    struct USBAutoFilter *f;
+    struct USBHostDevice *s;
+
+    usb_host_scan(mon, usb_host_info_device);
+
+    if (QTAILQ_EMPTY(&hostdevs)) {
+        return;
+    }
+
+    monitor_printf(mon, "  Auto filters:\n");
+    QTAILQ_FOREACH(s, &hostdevs, next) {
+        char bus[10], addr[10], vid[10], pid[10];
+        f = &s->match;
+        dec2str(f->bus_num, bus, sizeof(bus));
+        dec2str(f->addr, addr, sizeof(addr));
+        hex2str(f->vendor_id, vid, sizeof(vid));
+        hex2str(f->product_id, pid, sizeof(pid));
+        monitor_printf(mon, "    Bus %s, Addr %s, Port %s, ID %s:%s\n",
+                       bus, addr, f->port ? f->port : "*", vid, pid);
+    }
+}
diff --git a/hw/usb/host-stub.c b/hw/usb/host-stub.c
new file mode 100644
index 0000000..b4e10c1
--- /dev/null
+++ b/hw/usb/host-stub.c
@@ -0,0 +1,52 @@
+/*
+ * Stub host USB redirector
+ *
+ * Copyright (c) 2005 Fabrice Bellard
+ *
+ * Copyright (c) 2008 Max Krasnyansky
+ *      Support for host device auto connect & disconnect
+ *      Major rewrite to support fully async operation
+ *
+ * Copyright 2008 TJ <linux at tjworld.net>
+ *      Added flexible support for /dev/bus/usb /sys/bus/usb/devices in addition
+ *      to the legacy /proc/bus/usb USB device discovery and handling
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu-common.h"
+#include "console.h"
+#include "hw/usb.h"
+#include "monitor.h"
+
+void usb_host_info(Monitor *mon)
+{
+    monitor_printf(mon, "USB host devices not supported\n");
+}
+
+/* XXX: modify configure to compile the right host driver */
+USBDevice *usb_host_device_open(USBBus *bus, const char *devname)
+{
+    return NULL;
+}
+
+int usb_host_device_close(const char *devname)
+{
+    return 0;
+}
diff --git a/hw/usb/libhw.c b/hw/usb/libhw.c
new file mode 100644
index 0000000..2462351
--- /dev/null
+++ b/hw/usb/libhw.c
@@ -0,0 +1,63 @@
+/*
+ * QEMU USB emulation, libhw bits.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu-common.h"
+#include "cpu-common.h"
+#include "hw/usb.h"
+#include "dma.h"
+
+int usb_packet_map(USBPacket *p, QEMUSGList *sgl)
+{
+    int is_write = (p->pid == USB_TOKEN_IN);
+    target_phys_addr_t len;
+    void *mem;
+    int i;
+
+    for (i = 0; i < sgl->nsg; i++) {
+        len = sgl->sg[i].len;
+        mem = cpu_physical_memory_map(sgl->sg[i].base, &len,
+                                      is_write);
+        if (!mem) {
+            goto err;
+        }
+        qemu_iovec_add(&p->iov, mem, len);
+        if (len != sgl->sg[i].len) {
+            goto err;
+        }
+    }
+    return 0;
+
+err:
+    usb_packet_unmap(p);
+    return -1;
+}
+
+void usb_packet_unmap(USBPacket *p)
+{
+    int is_write = (p->pid == USB_TOKEN_IN);
+    int i;
+
+    for (i = 0; i < p->iov.niov; i++) {
+        cpu_physical_memory_unmap(p->iov.iov[i].iov_base,
+                                  p->iov.iov[i].iov_len, is_write,
+                                  p->iov.iov[i].iov_len);
+    }
+}
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
new file mode 100644
index 0000000..8e9f175
--- /dev/null
+++ b/hw/usb/redirect.c
@@ -0,0 +1,1485 @@
+/*
+ * USB redirector usb-guest
+ *
+ * Copyright (c) 2011 Red Hat, Inc.
+ *
+ * Red Hat Authors:
+ * Hans de Goede <hdegoede at redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu-common.h"
+#include "qemu-timer.h"
+#include "monitor.h"
+#include "sysemu.h"
+
+#include <dirent.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#include <usbredirparser.h>
+#include <usbredirfilter.h>
+
+#include "hw/usb.h"
+
+#define MAX_ENDPOINTS 32
+#define EP2I(ep_address) (((ep_address & 0x80) >> 3) | (ep_address & 0x0f))
+#define I2EP(i) (((i & 0x10) << 3) | (i & 0x0f))
+
+typedef struct AsyncURB AsyncURB;
+typedef struct USBRedirDevice USBRedirDevice;
+
+/* Struct to hold buffered packets (iso or int input packets) */
+struct buf_packet {
+    uint8_t *data;
+    int len;
+    int status;
+    QTAILQ_ENTRY(buf_packet)next;
+};
+
+struct endp_data {
+    uint8_t type;
+    uint8_t interval;
+    uint8_t interface; /* bInterfaceNumber this ep belongs to */
+    uint8_t iso_started;
+    uint8_t iso_error; /* For reporting iso errors to the HC */
+    uint8_t interrupt_started;
+    uint8_t interrupt_error;
+    uint8_t bufpq_prefilled;
+    uint8_t bufpq_dropping_packets;
+    QTAILQ_HEAD(, buf_packet) bufpq;
+    int bufpq_size;
+    int bufpq_target_size;
+};
+
+struct USBRedirDevice {
+    USBDevice dev;
+    /* Properties */
+    CharDriverState *cs;
+    uint8_t debug;
+    char *filter_str;
+    /* Data passed from chardev the fd_read cb to the usbredirparser read cb */
+    const uint8_t *read_buf;
+    int read_buf_size;
+    /* For async handling of open/close */
+    QEMUBH *open_close_bh;
+    /* To delay the usb attach in case of quick chardev close + open */
+    QEMUTimer *attach_timer;
+    int64_t next_attach_time;
+    struct usbredirparser *parser;
+    struct endp_data endpoint[MAX_ENDPOINTS];
+    uint32_t packet_id;
+    QTAILQ_HEAD(, AsyncURB) asyncq;
+    /* Data for device filtering */
+    struct usb_redir_device_connect_header device_info;
+    struct usb_redir_interface_info_header interface_info;
+    struct usbredirfilter_rule *filter_rules;
+    int filter_rules_count;
+};
+
+struct AsyncURB {
+    USBRedirDevice *dev;
+    USBPacket *packet;
+    uint32_t packet_id;
+    int get;
+    union {
+        struct usb_redir_control_packet_header control_packet;
+        struct usb_redir_bulk_packet_header bulk_packet;
+        struct usb_redir_interrupt_packet_header interrupt_packet;
+    };
+    QTAILQ_ENTRY(AsyncURB)next;
+};
+
+static void usbredir_hello(void *priv, struct usb_redir_hello_header *h);
+static void usbredir_device_connect(void *priv,
+    struct usb_redir_device_connect_header *device_connect);
+static void usbredir_device_disconnect(void *priv);
+static void usbredir_interface_info(void *priv,
+    struct usb_redir_interface_info_header *interface_info);
+static void usbredir_ep_info(void *priv,
+    struct usb_redir_ep_info_header *ep_info);
+static void usbredir_configuration_status(void *priv, uint32_t id,
+    struct usb_redir_configuration_status_header *configuration_status);
+static void usbredir_alt_setting_status(void *priv, uint32_t id,
+    struct usb_redir_alt_setting_status_header *alt_setting_status);
+static void usbredir_iso_stream_status(void *priv, uint32_t id,
+    struct usb_redir_iso_stream_status_header *iso_stream_status);
+static void usbredir_interrupt_receiving_status(void *priv, uint32_t id,
+    struct usb_redir_interrupt_receiving_status_header
+    *interrupt_receiving_status);
+static void usbredir_bulk_streams_status(void *priv, uint32_t id,
+    struct usb_redir_bulk_streams_status_header *bulk_streams_status);
+static void usbredir_control_packet(void *priv, uint32_t id,
+    struct usb_redir_control_packet_header *control_packet,
+    uint8_t *data, int data_len);
+static void usbredir_bulk_packet(void *priv, uint32_t id,
+    struct usb_redir_bulk_packet_header *bulk_packet,
+    uint8_t *data, int data_len);
+static void usbredir_iso_packet(void *priv, uint32_t id,
+    struct usb_redir_iso_packet_header *iso_packet,
+    uint8_t *data, int data_len);
+static void usbredir_interrupt_packet(void *priv, uint32_t id,
+    struct usb_redir_interrupt_packet_header *interrupt_header,
+    uint8_t *data, int data_len);
+
+static int usbredir_handle_status(USBRedirDevice *dev,
+                                       int status, int actual_len);
+
+#define VERSION "qemu usb-redir guest " QEMU_VERSION
+
+/*
+ * Logging stuff
+ */
+
+#define ERROR(...) \
+    do { \
+        if (dev->debug >= usbredirparser_error) { \
+            error_report("usb-redir error: " __VA_ARGS__); \
+        } \
+    } while (0)
+#define WARNING(...) \
+    do { \
+        if (dev->debug >= usbredirparser_warning) { \
+            error_report("usb-redir warning: " __VA_ARGS__); \
+        } \
+    } while (0)
+#define INFO(...) \
+    do { \
+        if (dev->debug >= usbredirparser_info) { \
+            error_report("usb-redir: " __VA_ARGS__); \
+        } \
+    } while (0)
+#define DPRINTF(...) \
+    do { \
+        if (dev->debug >= usbredirparser_debug) { \
+            error_report("usb-redir: " __VA_ARGS__); \
+        } \
+    } while (0)
+#define DPRINTF2(...) \
+    do { \
+        if (dev->debug >= usbredirparser_debug_data) { \
+            error_report("usb-redir: " __VA_ARGS__); \
+        } \
+    } while (0)
+
+static void usbredir_log(void *priv, int level, const char *msg)
+{
+    USBRedirDevice *dev = priv;
+
+    if (dev->debug < level) {
+        return;
+    }
+
+    error_report("%s", msg);
+}
+
+static void usbredir_log_data(USBRedirDevice *dev, const char *desc,
+    const uint8_t *data, int len)
+{
+    int i, j, n;
+
+    if (dev->debug < usbredirparser_debug_data) {
+        return;
+    }
+
+    for (i = 0; i < len; i += j) {
+        char buf[128];
+
+        n = sprintf(buf, "%s", desc);
+        for (j = 0; j < 8 && i + j < len; j++) {
+            n += sprintf(buf + n, " %02X", data[i + j]);
+        }
+        error_report("%s", buf);
+    }
+}
+
+/*
+ * usbredirparser io functions
+ */
+
+static int usbredir_read(void *priv, uint8_t *data, int count)
+{
+    USBRedirDevice *dev = priv;
+
+    if (dev->read_buf_size < count) {
+        count = dev->read_buf_size;
+    }
+
+    memcpy(data, dev->read_buf, count);
+
+    dev->read_buf_size -= count;
+    if (dev->read_buf_size) {
+        dev->read_buf += count;
+    } else {
+        dev->read_buf = NULL;
+    }
+
+    return count;
+}
+
+static int usbredir_write(void *priv, uint8_t *data, int count)
+{
+    USBRedirDevice *dev = priv;
+
+    if (!dev->cs->opened) {
+        return 0;
+    }
+
+    return qemu_chr_fe_write(dev->cs, data, count);
+}
+
+/*
+ * Async and buffered packets helpers
+ */
+
+static AsyncURB *async_alloc(USBRedirDevice *dev, USBPacket *p)
+{
+    AsyncURB *aurb = (AsyncURB *) g_malloc0(sizeof(AsyncURB));
+    aurb->dev = dev;
+    aurb->packet = p;
+    aurb->packet_id = dev->packet_id;
+    QTAILQ_INSERT_TAIL(&dev->asyncq, aurb, next);
+    dev->packet_id++;
+
+    return aurb;
+}
+
+static void async_free(USBRedirDevice *dev, AsyncURB *aurb)
+{
+    QTAILQ_REMOVE(&dev->asyncq, aurb, next);
+    g_free(aurb);
+}
+
+static AsyncURB *async_find(USBRedirDevice *dev, uint32_t packet_id)
+{
+    AsyncURB *aurb;
+
+    QTAILQ_FOREACH(aurb, &dev->asyncq, next) {
+        if (aurb->packet_id == packet_id) {
+            return aurb;
+        }
+    }
+    ERROR("could not find async urb for packet_id %u\n", packet_id);
+    return NULL;
+}
+
+static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p)
+{
+    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+    AsyncURB *aurb;
+
+    QTAILQ_FOREACH(aurb, &dev->asyncq, next) {
+        if (p != aurb->packet) {
+            continue;
+        }
+
+        DPRINTF("async cancel id %u\n", aurb->packet_id);
+        usbredirparser_send_cancel_data_packet(dev->parser, aurb->packet_id);
+        usbredirparser_do_write(dev->parser);
+
+        /* Mark it as dead */
+        aurb->packet = NULL;
+        break;
+    }
+}
+
+static void bufp_alloc(USBRedirDevice *dev,
+    uint8_t *data, int len, int status, uint8_t ep)
+{
+    struct buf_packet *bufp;
+
+    if (!dev->endpoint[EP2I(ep)].bufpq_dropping_packets &&
+        dev->endpoint[EP2I(ep)].bufpq_size >
+            2 * dev->endpoint[EP2I(ep)].bufpq_target_size) {
+        DPRINTF("bufpq overflow, dropping packets ep %02X\n", ep);
+        dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 1;
+    }
+    /* Since we're interupting the stream anyways, drop enough packets to get
+       back to our target buffer size */
+    if (dev->endpoint[EP2I(ep)].bufpq_dropping_packets) {
+        if (dev->endpoint[EP2I(ep)].bufpq_size >
+                dev->endpoint[EP2I(ep)].bufpq_target_size) {
+            free(data);
+            return;
+        }
+        dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0;
+    }
+
+    bufp = g_malloc(sizeof(struct buf_packet));
+    bufp->data   = data;
+    bufp->len    = len;
+    bufp->status = status;
+    QTAILQ_INSERT_TAIL(&dev->endpoint[EP2I(ep)].bufpq, bufp, next);
+    dev->endpoint[EP2I(ep)].bufpq_size++;
+}
+
+static void bufp_free(USBRedirDevice *dev, struct buf_packet *bufp,
+    uint8_t ep)
+{
+    QTAILQ_REMOVE(&dev->endpoint[EP2I(ep)].bufpq, bufp, next);
+    dev->endpoint[EP2I(ep)].bufpq_size--;
+    free(bufp->data);
+    g_free(bufp);
+}
+
+static void usbredir_free_bufpq(USBRedirDevice *dev, uint8_t ep)
+{
+    struct buf_packet *buf, *buf_next;
+
+    QTAILQ_FOREACH_SAFE(buf, &dev->endpoint[EP2I(ep)].bufpq, next, buf_next) {
+        bufp_free(dev, buf, ep);
+    }
+}
+
+/*
+ * USBDevice callbacks
+ */
+
+static void usbredir_handle_reset(USBDevice *udev)
+{
+    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+
+    DPRINTF("reset device\n");
+    usbredirparser_send_reset(dev->parser);
+    usbredirparser_do_write(dev->parser);
+}
+
+static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
+                                     uint8_t ep)
+{
+    int status, len;
+    if (!dev->endpoint[EP2I(ep)].iso_started &&
+            !dev->endpoint[EP2I(ep)].iso_error) {
+        struct usb_redir_start_iso_stream_header start_iso = {
+            .endpoint = ep,
+        };
+        int pkts_per_sec;
+
+        if (dev->dev.speed == USB_SPEED_HIGH) {
+            pkts_per_sec = 8000 / dev->endpoint[EP2I(ep)].interval;
+        } else {
+            pkts_per_sec = 1000 / dev->endpoint[EP2I(ep)].interval;
+        }
+        /* Testing has shown that we need circa 60 ms buffer */
+        dev->endpoint[EP2I(ep)].bufpq_target_size = (pkts_per_sec * 60) / 1000;
+
+        /* Aim for approx 100 interrupts / second on the client to
+           balance latency and interrupt load */
+        start_iso.pkts_per_urb = pkts_per_sec / 100;
+        if (start_iso.pkts_per_urb < 1) {
+            start_iso.pkts_per_urb = 1;
+        } else if (start_iso.pkts_per_urb > 32) {
+            start_iso.pkts_per_urb = 32;
+        }
+
+        start_iso.no_urbs = (dev->endpoint[EP2I(ep)].bufpq_target_size +
+                             start_iso.pkts_per_urb - 1) /
+                            start_iso.pkts_per_urb;
+        /* Output endpoints pre-fill only 1/2 of the packets, keeping the rest
+           as overflow buffer. Also see the usbredir protocol documentation */
+        if (!(ep & USB_DIR_IN)) {
+            start_iso.no_urbs *= 2;
+        }
+        if (start_iso.no_urbs > 16) {
+            start_iso.no_urbs = 16;
+        }
+
+        /* No id, we look at the ep when receiving a status back */
+        usbredirparser_send_start_iso_stream(dev->parser, 0, &start_iso);
+        usbredirparser_do_write(dev->parser);
+        DPRINTF("iso stream started pkts/sec %d pkts/urb %d urbs %d ep %02X\n",
+                pkts_per_sec, start_iso.pkts_per_urb, start_iso.no_urbs, ep);
+        dev->endpoint[EP2I(ep)].iso_started = 1;
+        dev->endpoint[EP2I(ep)].bufpq_prefilled = 0;
+        dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0;
+    }
+
+    if (ep & USB_DIR_IN) {
+        struct buf_packet *isop;
+
+        if (dev->endpoint[EP2I(ep)].iso_started &&
+                !dev->endpoint[EP2I(ep)].bufpq_prefilled) {
+            if (dev->endpoint[EP2I(ep)].bufpq_size <
+                    dev->endpoint[EP2I(ep)].bufpq_target_size) {
+                return usbredir_handle_status(dev, 0, 0);
+            }
+            dev->endpoint[EP2I(ep)].bufpq_prefilled = 1;
+        }
+
+        isop = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq);
+        if (isop == NULL) {
+            DPRINTF("iso-token-in ep %02X, no isop, iso_error: %d\n",
+                    ep, dev->endpoint[EP2I(ep)].iso_error);
+            /* Re-fill the buffer */
+            dev->endpoint[EP2I(ep)].bufpq_prefilled = 0;
+            /* Check iso_error for stream errors, otherwise its an underrun */
+            status = dev->endpoint[EP2I(ep)].iso_error;
+            dev->endpoint[EP2I(ep)].iso_error = 0;
+            return status ? USB_RET_IOERROR : 0;
+        }
+        DPRINTF2("iso-token-in ep %02X status %d len %d queue-size: %d\n", ep,
+                 isop->status, isop->len, dev->endpoint[EP2I(ep)].bufpq_size);
+
+        status = isop->status;
+        if (status != usb_redir_success) {
+            bufp_free(dev, isop, ep);
+            return USB_RET_IOERROR;
+        }
+
+        len = isop->len;
+        if (len > p->iov.size) {
+            ERROR("received iso data is larger then packet ep %02X (%d > %d)\n",
+                  ep, len, (int)p->iov.size);
+            bufp_free(dev, isop, ep);
+            return USB_RET_BABBLE;
+        }
+        usb_packet_copy(p, isop->data, len);
+        bufp_free(dev, isop, ep);
+        return len;
+    } else {
+        /* If the stream was not started because of a pending error don't
+           send the packet to the usb-host */
+        if (dev->endpoint[EP2I(ep)].iso_started) {
+            struct usb_redir_iso_packet_header iso_packet = {
+                .endpoint = ep,
+                .length = p->iov.size
+            };
+            uint8_t buf[p->iov.size];
+            /* No id, we look at the ep when receiving a status back */
+            usb_packet_copy(p, buf, p->iov.size);
+            usbredirparser_send_iso_packet(dev->parser, 0, &iso_packet,
+                                           buf, p->iov.size);
+            usbredirparser_do_write(dev->parser);
+        }
+        status = dev->endpoint[EP2I(ep)].iso_error;
+        dev->endpoint[EP2I(ep)].iso_error = 0;
+        DPRINTF2("iso-token-out ep %02X status %d len %zd\n", ep, status,
+                 p->iov.size);
+        return usbredir_handle_status(dev, status, p->iov.size);
+    }
+}
+
+static void usbredir_stop_iso_stream(USBRedirDevice *dev, uint8_t ep)
+{
+    struct usb_redir_stop_iso_stream_header stop_iso_stream = {
+        .endpoint = ep
+    };
+    if (dev->endpoint[EP2I(ep)].iso_started) {
+        usbredirparser_send_stop_iso_stream(dev->parser, 0, &stop_iso_stream);
+        DPRINTF("iso stream stopped ep %02X\n", ep);
+        dev->endpoint[EP2I(ep)].iso_started = 0;
+    }
+    dev->endpoint[EP2I(ep)].iso_error = 0;
+    usbredir_free_bufpq(dev, ep);
+}
+
+static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,
+                                      uint8_t ep)
+{
+    AsyncURB *aurb = async_alloc(dev, p);
+    struct usb_redir_bulk_packet_header bulk_packet;
+
+    DPRINTF("bulk-out ep %02X len %zd id %u\n", ep,
+            p->iov.size, aurb->packet_id);
+
+    bulk_packet.endpoint  = ep;
+    bulk_packet.length    = p->iov.size;
+    bulk_packet.stream_id = 0;
+    aurb->bulk_packet = bulk_packet;
+
+    if (ep & USB_DIR_IN) {
+        usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id,
+                                        &bulk_packet, NULL, 0);
+    } else {
+        uint8_t buf[p->iov.size];
+        usb_packet_copy(p, buf, p->iov.size);
+        usbredir_log_data(dev, "bulk data out:", buf, p->iov.size);
+        usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id,
+                                        &bulk_packet, buf, p->iov.size);
+    }
+    usbredirparser_do_write(dev->parser);
+    return USB_RET_ASYNC;
+}
+
+static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
+                                           USBPacket *p, uint8_t ep)
+{
+    if (ep & USB_DIR_IN) {
+        /* Input interrupt endpoint, buffered packet input */
+        struct buf_packet *intp;
+        int status, len;
+
+        if (!dev->endpoint[EP2I(ep)].interrupt_started &&
+                !dev->endpoint[EP2I(ep)].interrupt_error) {
+            struct usb_redir_start_interrupt_receiving_header start_int = {
+                .endpoint = ep,
+            };
+            /* No id, we look at the ep when receiving a status back */
+            usbredirparser_send_start_interrupt_receiving(dev->parser, 0,
+                                                          &start_int);
+            usbredirparser_do_write(dev->parser);
+            DPRINTF("interrupt recv started ep %02X\n", ep);
+            dev->endpoint[EP2I(ep)].interrupt_started = 1;
+            /* We don't really want to drop interrupt packets ever, but
+               having some upper limit to how much we buffer is good. */
+            dev->endpoint[EP2I(ep)].bufpq_target_size = 1000;
+            dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0;
+        }
+
+        intp = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq);
+        if (intp == NULL) {
+            DPRINTF2("interrupt-token-in ep %02X, no intp\n", ep);
+            /* Check interrupt_error for stream errors */
+            status = dev->endpoint[EP2I(ep)].interrupt_error;
+            dev->endpoint[EP2I(ep)].interrupt_error = 0;
+            if (status) {
+                return usbredir_handle_status(dev, status, 0);
+            }
+            return USB_RET_NAK;
+        }
+        DPRINTF("interrupt-token-in ep %02X status %d len %d\n", ep,
+                intp->status, intp->len);
+
+        status = intp->status;
+        if (status != usb_redir_success) {
+            bufp_free(dev, intp, ep);
+            return usbredir_handle_status(dev, status, 0);
+        }
+
+        len = intp->len;
+        if (len > p->iov.size) {
+            ERROR("received int data is larger then packet ep %02X\n", ep);
+            bufp_free(dev, intp, ep);
+            return USB_RET_BABBLE;
+        }
+        usb_packet_copy(p, intp->data, len);
+        bufp_free(dev, intp, ep);
+        return len;
+    } else {
+        /* Output interrupt endpoint, normal async operation */
+        AsyncURB *aurb = async_alloc(dev, p);
+        struct usb_redir_interrupt_packet_header interrupt_packet;
+        uint8_t buf[p->iov.size];
+
+        DPRINTF("interrupt-out ep %02X len %zd id %u\n", ep, p->iov.size,
+                aurb->packet_id);
+
+        interrupt_packet.endpoint  = ep;
+        interrupt_packet.length    = p->iov.size;
+        aurb->interrupt_packet     = interrupt_packet;
+
+        usb_packet_copy(p, buf, p->iov.size);
+        usbredir_log_data(dev, "interrupt data out:", buf, p->iov.size);
+        usbredirparser_send_interrupt_packet(dev->parser, aurb->packet_id,
+                                        &interrupt_packet, buf, p->iov.size);
+        usbredirparser_do_write(dev->parser);
+        return USB_RET_ASYNC;
+    }
+}
+
+static void usbredir_stop_interrupt_receiving(USBRedirDevice *dev,
+    uint8_t ep)
+{
+    struct usb_redir_stop_interrupt_receiving_header stop_interrupt_recv = {
+        .endpoint = ep
+    };
+    if (dev->endpoint[EP2I(ep)].interrupt_started) {
+        usbredirparser_send_stop_interrupt_receiving(dev->parser, 0,
+                                                     &stop_interrupt_recv);
+        DPRINTF("interrupt recv stopped ep %02X\n", ep);
+        dev->endpoint[EP2I(ep)].interrupt_started = 0;
+    }
+    dev->endpoint[EP2I(ep)].interrupt_error = 0;
+    usbredir_free_bufpq(dev, ep);
+}
+
+static int usbredir_handle_data(USBDevice *udev, USBPacket *p)
+{
+    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+    uint8_t ep;
+
+    ep = p->ep->nr;
+    if (p->pid == USB_TOKEN_IN) {
+        ep |= USB_DIR_IN;
+    }
+
+    switch (dev->endpoint[EP2I(ep)].type) {
+    case USB_ENDPOINT_XFER_CONTROL:
+        ERROR("handle_data called for control transfer on ep %02X\n", ep);
+        return USB_RET_NAK;
+    case USB_ENDPOINT_XFER_ISOC:
+        return usbredir_handle_iso_data(dev, p, ep);
+    case USB_ENDPOINT_XFER_BULK:
+        return usbredir_handle_bulk_data(dev, p, ep);
+    case USB_ENDPOINT_XFER_INT:
+        return usbredir_handle_interrupt_data(dev, p, ep);
+    default:
+        ERROR("handle_data ep %02X has unknown type %d\n", ep,
+              dev->endpoint[EP2I(ep)].type);
+        return USB_RET_NAK;
+    }
+}
+
+static int usbredir_set_config(USBRedirDevice *dev, USBPacket *p,
+                                int config)
+{
+    struct usb_redir_set_configuration_header set_config;
+    AsyncURB *aurb = async_alloc(dev, p);
+    int i;
+
+    DPRINTF("set config %d id %u\n", config, aurb->packet_id);
+
+    for (i = 0; i < MAX_ENDPOINTS; i++) {
+        switch (dev->endpoint[i].type) {
+        case USB_ENDPOINT_XFER_ISOC:
+            usbredir_stop_iso_stream(dev, I2EP(i));
+            break;
+        case USB_ENDPOINT_XFER_INT:
+            if (i & 0x10) {
+                usbredir_stop_interrupt_receiving(dev, I2EP(i));
+            }
+            break;
+        }
+        usbredir_free_bufpq(dev, I2EP(i));
+    }
+
+    set_config.configuration = config;
+    usbredirparser_send_set_configuration(dev->parser, aurb->packet_id,
+                                          &set_config);
+    usbredirparser_do_write(dev->parser);
+    return USB_RET_ASYNC;
+}
+
+static int usbredir_get_config(USBRedirDevice *dev, USBPacket *p)
+{
+    AsyncURB *aurb = async_alloc(dev, p);
+
+    DPRINTF("get config id %u\n", aurb->packet_id);
+
+    aurb->get = 1;
+    usbredirparser_send_get_configuration(dev->parser, aurb->packet_id);
+    usbredirparser_do_write(dev->parser);
+    return USB_RET_ASYNC;
+}
+
+static int usbredir_set_interface(USBRedirDevice *dev, USBPacket *p,
+                                   int interface, int alt)
+{
+    struct usb_redir_set_alt_setting_header set_alt;
+    AsyncURB *aurb = async_alloc(dev, p);
+    int i;
+
+    DPRINTF("set interface %d alt %d id %u\n", interface, alt,
+            aurb->packet_id);
+
+    for (i = 0; i < MAX_ENDPOINTS; i++) {
+        if (dev->endpoint[i].interface == interface) {
+            switch (dev->endpoint[i].type) {
+            case USB_ENDPOINT_XFER_ISOC:
+                usbredir_stop_iso_stream(dev, I2EP(i));
+                break;
+            case USB_ENDPOINT_XFER_INT:
+                if (i & 0x10) {
+                    usbredir_stop_interrupt_receiving(dev, I2EP(i));
+                }
+                break;
+            }
+            usbredir_free_bufpq(dev, I2EP(i));
+        }
+    }
+
+    set_alt.interface = interface;
+    set_alt.alt = alt;
+    usbredirparser_send_set_alt_setting(dev->parser, aurb->packet_id,
+                                        &set_alt);
+    usbredirparser_do_write(dev->parser);
+    return USB_RET_ASYNC;
+}
+
+static int usbredir_get_interface(USBRedirDevice *dev, USBPacket *p,
+                                   int interface)
+{
+    struct usb_redir_get_alt_setting_header get_alt;
+    AsyncURB *aurb = async_alloc(dev, p);
+
+    DPRINTF("get interface %d id %u\n", interface, aurb->packet_id);
+
+    get_alt.interface = interface;
+    aurb->get = 1;
+    usbredirparser_send_get_alt_setting(dev->parser, aurb->packet_id,
+                                        &get_alt);
+    usbredirparser_do_write(dev->parser);
+    return USB_RET_ASYNC;
+}
+
+static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
+        int request, int value, int index, int length, uint8_t *data)
+{
+    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+    struct usb_redir_control_packet_header control_packet;
+    AsyncURB *aurb;
+
+    /* Special cases for certain standard device requests */
+    switch (request) {
+    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
+        DPRINTF("set address %d\n", value);
+        dev->dev.addr = value;
+        return 0;
+    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
+        return usbredir_set_config(dev, p, value & 0xff);
+    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
+        return usbredir_get_config(dev, p);
+    case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
+        return usbredir_set_interface(dev, p, index, value);
+    case InterfaceRequest | USB_REQ_GET_INTERFACE:
+        return usbredir_get_interface(dev, p, index);
+    }
+
+    /* "Normal" ctrl requests */
+    aurb = async_alloc(dev, p);
+
+    /* Note request is (bRequestType << 8) | bRequest */
+    DPRINTF("ctrl-out type 0x%x req 0x%x val 0x%x index %d len %d id %u\n",
+            request >> 8, request & 0xff, value, index, length,
+            aurb->packet_id);
+
+    control_packet.request     = request & 0xFF;
+    control_packet.requesttype = request >> 8;
+    control_packet.endpoint    = control_packet.requesttype & USB_DIR_IN;
+    control_packet.value       = value;
+    control_packet.index       = index;
+    control_packet.length      = length;
+    aurb->control_packet       = control_packet;
+
+    if (control_packet.requesttype & USB_DIR_IN) {
+        usbredirparser_send_control_packet(dev->parser, aurb->packet_id,
+                                           &control_packet, NULL, 0);
+    } else {
+        usbredir_log_data(dev, "ctrl data out:", data, length);
+        usbredirparser_send_control_packet(dev->parser, aurb->packet_id,
+                                           &control_packet, data, length);
+    }
+    usbredirparser_do_write(dev->parser);
+    return USB_RET_ASYNC;
+}
+
+/*
+ * Close events can be triggered by usbredirparser_do_write which gets called
+ * from within the USBDevice data / control packet callbacks and doing a
+ * usb_detach from within these callbacks is not a good idea.
+ *
+ * So we use a bh handler to take care of close events. We also handle
+ * open events from this callback to make sure that a close directly followed
+ * by an open gets handled in the right order.
+ */
+static void usbredir_open_close_bh(void *opaque)
+{
+    USBRedirDevice *dev = opaque;
+    uint32_t caps[USB_REDIR_CAPS_SIZE] = { 0, };
+
+    usbredir_device_disconnect(dev);
+
+    if (dev->parser) {
+        usbredirparser_destroy(dev->parser);
+        dev->parser = NULL;
+    }
+
+    if (dev->cs->opened) {
+        dev->parser = qemu_oom_check(usbredirparser_create());
+        dev->parser->priv = dev;
+        dev->parser->log_func = usbredir_log;
+        dev->parser->read_func = usbredir_read;
+        dev->parser->write_func = usbredir_write;
+        dev->parser->hello_func = usbredir_hello;
+        dev->parser->device_connect_func = usbredir_device_connect;
+        dev->parser->device_disconnect_func = usbredir_device_disconnect;
+        dev->parser->interface_info_func = usbredir_interface_info;
+        dev->parser->ep_info_func = usbredir_ep_info;
+        dev->parser->configuration_status_func = usbredir_configuration_status;
+        dev->parser->alt_setting_status_func = usbredir_alt_setting_status;
+        dev->parser->iso_stream_status_func = usbredir_iso_stream_status;
+        dev->parser->interrupt_receiving_status_func =
+            usbredir_interrupt_receiving_status;
+        dev->parser->bulk_streams_status_func = usbredir_bulk_streams_status;
+        dev->parser->control_packet_func = usbredir_control_packet;
+        dev->parser->bulk_packet_func = usbredir_bulk_packet;
+        dev->parser->iso_packet_func = usbredir_iso_packet;
+        dev->parser->interrupt_packet_func = usbredir_interrupt_packet;
+        dev->read_buf = NULL;
+        dev->read_buf_size = 0;
+
+        usbredirparser_caps_set_cap(caps, usb_redir_cap_connect_device_version);
+        usbredirparser_caps_set_cap(caps, usb_redir_cap_filter);
+        usbredirparser_init(dev->parser, VERSION, caps, USB_REDIR_CAPS_SIZE, 0);
+        usbredirparser_do_write(dev->parser);
+    }
+}
+
+static void usbredir_do_attach(void *opaque)
+{
+    USBRedirDevice *dev = opaque;
+
+    usb_device_attach(&dev->dev);
+}
+
+/*
+ * chardev callbacks
+ */
+
+static int usbredir_chardev_can_read(void *opaque)
+{
+    USBRedirDevice *dev = opaque;
+
+    if (dev->parser) {
+        /* usbredir_parser_do_read will consume *all* data we give it */
+        return 1024 * 1024;
+    } else {
+        /* usbredir_open_close_bh hasn't handled the open event yet */
+        return 0;
+    }
+}
+
+static void usbredir_chardev_read(void *opaque, const uint8_t *buf, int size)
+{
+    USBRedirDevice *dev = opaque;
+
+    /* No recursion allowed! */
+    assert(dev->read_buf == NULL);
+
+    dev->read_buf = buf;
+    dev->read_buf_size = size;
+
+    usbredirparser_do_read(dev->parser);
+    /* Send any acks, etc. which may be queued now */
+    usbredirparser_do_write(dev->parser);
+}
+
+static void usbredir_chardev_event(void *opaque, int event)
+{
+    USBRedirDevice *dev = opaque;
+
+    switch (event) {
+    case CHR_EVENT_OPENED:
+    case CHR_EVENT_CLOSED:
+        qemu_bh_schedule(dev->open_close_bh);
+        break;
+    }
+}
+
+/*
+ * init + destroy
+ */
+
+static int usbredir_initfn(USBDevice *udev)
+{
+    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+    int i;
+
+    if (dev->cs == NULL) {
+        qerror_report(QERR_MISSING_PARAMETER, "chardev");
+        return -1;
+    }
+
+    if (dev->filter_str) {
+        i = usbredirfilter_string_to_rules(dev->filter_str, ":", "|",
+                                           &dev->filter_rules,
+                                           &dev->filter_rules_count);
+        if (i) {
+            qerror_report(QERR_INVALID_PARAMETER_VALUE, "filter",
+                          "a usb device filter string");
+            return -1;
+        }
+    }
+
+    dev->open_close_bh = qemu_bh_new(usbredir_open_close_bh, dev);
+    dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev);
+
+    QTAILQ_INIT(&dev->asyncq);
+    for (i = 0; i < MAX_ENDPOINTS; i++) {
+        QTAILQ_INIT(&dev->endpoint[i].bufpq);
+    }
+
+    /* We'll do the attach once we receive the speed from the usb-host */
+    udev->auto_attach = 0;
+
+    /* Let the backend know we are ready */
+    qemu_chr_fe_open(dev->cs);
+    qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
+                          usbredir_chardev_read, usbredir_chardev_event, dev);
+
+    return 0;
+}
+
+static void usbredir_cleanup_device_queues(USBRedirDevice *dev)
+{
+    AsyncURB *aurb, *next_aurb;
+    int i;
+
+    QTAILQ_FOREACH_SAFE(aurb, &dev->asyncq, next, next_aurb) {
+        async_free(dev, aurb);
+    }
+    for (i = 0; i < MAX_ENDPOINTS; i++) {
+        usbredir_free_bufpq(dev, I2EP(i));
+    }
+}
+
+static void usbredir_handle_destroy(USBDevice *udev)
+{
+    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+
+    qemu_chr_fe_close(dev->cs);
+    qemu_chr_delete(dev->cs);
+    /* Note must be done after qemu_chr_close, as that causes a close event */
+    qemu_bh_delete(dev->open_close_bh);
+
+    qemu_del_timer(dev->attach_timer);
+    qemu_free_timer(dev->attach_timer);
+
+    usbredir_cleanup_device_queues(dev);
+
+    if (dev->parser) {
+        usbredirparser_destroy(dev->parser);
+    }
+
+    free(dev->filter_rules);
+}
+
+static int usbredir_check_filter(USBRedirDevice *dev)
+{
+    if (dev->interface_info.interface_count == 0) {
+        ERROR("No interface info for device\n");
+        goto error;
+    }
+
+    if (dev->filter_rules) {
+        if (!usbredirparser_peer_has_cap(dev->parser,
+                                    usb_redir_cap_connect_device_version)) {
+            ERROR("Device filter specified and peer does not have the "
+                  "connect_device_version capability\n");
+            goto error;
+        }
+
+        if (usbredirfilter_check(
+                dev->filter_rules,
+                dev->filter_rules_count,
+                dev->device_info.device_class,
+                dev->device_info.device_subclass,
+                dev->device_info.device_protocol,
+                dev->interface_info.interface_class,
+                dev->interface_info.interface_subclass,
+                dev->interface_info.interface_protocol,
+                dev->interface_info.interface_count,
+                dev->device_info.vendor_id,
+                dev->device_info.product_id,
+                dev->device_info.device_version_bcd,
+                0) != 0) {
+            goto error;
+        }
+    }
+
+    return 0;
+
+error:
+    usbredir_device_disconnect(dev);
+    if (usbredirparser_peer_has_cap(dev->parser, usb_redir_cap_filter)) {
+        usbredirparser_send_filter_reject(dev->parser);
+        usbredirparser_do_write(dev->parser);
+    }
+    return -1;
+}
+
+/*
+ * usbredirparser packet complete callbacks
+ */
+
+static int usbredir_handle_status(USBRedirDevice *dev,
+                                       int status, int actual_len)
+{
+    switch (status) {
+    case usb_redir_success:
+        return actual_len;
+    case usb_redir_stall:
+        return USB_RET_STALL;
+    case usb_redir_cancelled:
+        WARNING("returning cancelled packet to HC?\n");
+        return USB_RET_NAK;
+    case usb_redir_inval:
+        WARNING("got invalid param error from usb-host?\n");
+        return USB_RET_NAK;
+    case usb_redir_ioerror:
+    case usb_redir_timeout:
+    default:
+        return USB_RET_IOERROR;
+    }
+}
+
+static void usbredir_hello(void *priv, struct usb_redir_hello_header *h)
+{
+    USBRedirDevice *dev = priv;
+
+    /* Try to send the filter info now that we've the usb-host's caps */
+    if (usbredirparser_peer_has_cap(dev->parser, usb_redir_cap_filter) &&
+            dev->filter_rules) {
+        usbredirparser_send_filter_filter(dev->parser, dev->filter_rules,
+                                          dev->filter_rules_count);
+        usbredirparser_do_write(dev->parser);
+    }
+}
+
+static void usbredir_device_connect(void *priv,
+    struct usb_redir_device_connect_header *device_connect)
+{
+    USBRedirDevice *dev = priv;
+    const char *speed;
+
+    if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) {
+        ERROR("Received device connect while already connected\n");
+        return;
+    }
+
+    switch (device_connect->speed) {
+    case usb_redir_speed_low:
+        speed = "low speed";
+        dev->dev.speed = USB_SPEED_LOW;
+        break;
+    case usb_redir_speed_full:
+        speed = "full speed";
+        dev->dev.speed = USB_SPEED_FULL;
+        break;
+    case usb_redir_speed_high:
+        speed = "high speed";
+        dev->dev.speed = USB_SPEED_HIGH;
+        break;
+    case usb_redir_speed_super:
+        speed = "super speed";
+        dev->dev.speed = USB_SPEED_SUPER;
+        break;
+    default:
+        speed = "unknown speed";
+        dev->dev.speed = USB_SPEED_FULL;
+    }
+
+    if (usbredirparser_peer_has_cap(dev->parser,
+                                    usb_redir_cap_connect_device_version)) {
+        INFO("attaching %s device %04x:%04x version %d.%d class %02x\n",
+             speed, device_connect->vendor_id, device_connect->product_id,
+             ((device_connect->device_version_bcd & 0xf000) >> 12) * 10 +
+             ((device_connect->device_version_bcd & 0x0f00) >>  8),
+             ((device_connect->device_version_bcd & 0x00f0) >>  4) * 10 +
+             ((device_connect->device_version_bcd & 0x000f) >>  0),
+             device_connect->device_class);
+    } else {
+        INFO("attaching %s device %04x:%04x class %02x\n", speed,
+             device_connect->vendor_id, device_connect->product_id,
+             device_connect->device_class);
+    }
+
+    dev->dev.speedmask = (1 << dev->dev.speed);
+    dev->device_info = *device_connect;
+
+    if (usbredir_check_filter(dev)) {
+        WARNING("Device %04x:%04x rejected by device filter, not attaching\n",
+                device_connect->vendor_id, device_connect->product_id);
+        return;
+    }
+
+    qemu_mod_timer(dev->attach_timer, dev->next_attach_time);
+}
+
+static void usbredir_device_disconnect(void *priv)
+{
+    USBRedirDevice *dev = priv;
+    int i;
+
+    /* Stop any pending attaches */
+    qemu_del_timer(dev->attach_timer);
+
+    if (dev->dev.attached) {
+        usb_device_detach(&dev->dev);
+        /*
+         * Delay next usb device attach to give the guest a chance to see
+         * see the detach / attach in case of quick close / open succession
+         */
+        dev->next_attach_time = qemu_get_clock_ms(vm_clock) + 200;
+    }
+
+    /* Reset state so that the next dev connected starts with a clean slate */
+    usbredir_cleanup_device_queues(dev);
+    memset(dev->endpoint, 0, sizeof(dev->endpoint));
+    for (i = 0; i < MAX_ENDPOINTS; i++) {
+        QTAILQ_INIT(&dev->endpoint[i].bufpq);
+    }
+    usb_ep_init(&dev->dev);
+    dev->interface_info.interface_count = 0;
+}
+
+static void usbredir_interface_info(void *priv,
+    struct usb_redir_interface_info_header *interface_info)
+{
+    USBRedirDevice *dev = priv;
+
+    dev->interface_info = *interface_info;
+
+    /*
+     * If we receive interface info after the device has already been
+     * connected (ie on a set_config), re-check the filter.
+     */
+    if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) {
+        if (usbredir_check_filter(dev)) {
+            ERROR("Device no longer matches filter after interface info "
+                  "change, disconnecting!\n");
+        }
+    }
+}
+
+static void usbredir_ep_info(void *priv,
+    struct usb_redir_ep_info_header *ep_info)
+{
+    USBRedirDevice *dev = priv;
+    struct USBEndpoint *usb_ep;
+    int i;
+
+    for (i = 0; i < MAX_ENDPOINTS; i++) {
+        dev->endpoint[i].type = ep_info->type[i];
+        dev->endpoint[i].interval = ep_info->interval[i];
+        dev->endpoint[i].interface = ep_info->interface[i];
+        switch (dev->endpoint[i].type) {
+        case usb_redir_type_invalid:
+            break;
+        case usb_redir_type_iso:
+        case usb_redir_type_interrupt:
+            if (dev->endpoint[i].interval == 0) {
+                ERROR("Received 0 interval for isoc or irq endpoint\n");
+                usbredir_device_disconnect(dev);
+            }
+            /* Fall through */
+        case usb_redir_type_control:
+        case usb_redir_type_bulk:
+            DPRINTF("ep: %02X type: %d interface: %d\n", I2EP(i),
+                    dev->endpoint[i].type, dev->endpoint[i].interface);
+            break;
+        default:
+            ERROR("Received invalid endpoint type\n");
+            usbredir_device_disconnect(dev);
+            return;
+        }
+        usb_ep = usb_ep_get(&dev->dev,
+                            (i & 0x10) ? USB_TOKEN_IN : USB_TOKEN_OUT,
+                            i & 0x0f);
+        usb_ep->type = dev->endpoint[i].type;
+        usb_ep->ifnum = dev->endpoint[i].interface;
+    }
+}
+
+static void usbredir_configuration_status(void *priv, uint32_t id,
+    struct usb_redir_configuration_status_header *config_status)
+{
+    USBRedirDevice *dev = priv;
+    AsyncURB *aurb;
+    int len = 0;
+
+    DPRINTF("set config status %d config %d id %u\n", config_status->status,
+            config_status->configuration, id);
+
+    aurb = async_find(dev, id);
+    if (!aurb) {
+        return;
+    }
+    if (aurb->packet) {
+        if (aurb->get) {
+            dev->dev.data_buf[0] = config_status->configuration;
+            len = 1;
+        }
+        aurb->packet->result =
+            usbredir_handle_status(dev, config_status->status, len);
+        usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
+    }
+    async_free(dev, aurb);
+}
+
+static void usbredir_alt_setting_status(void *priv, uint32_t id,
+    struct usb_redir_alt_setting_status_header *alt_setting_status)
+{
+    USBRedirDevice *dev = priv;
+    AsyncURB *aurb;
+    int len = 0;
+
+    DPRINTF("alt status %d intf %d alt %d id: %u\n",
+            alt_setting_status->status,
+            alt_setting_status->interface,
+            alt_setting_status->alt, id);
+
+    aurb = async_find(dev, id);
+    if (!aurb) {
+        return;
+    }
+    if (aurb->packet) {
+        if (aurb->get) {
+            dev->dev.data_buf[0] = alt_setting_status->alt;
+            len = 1;
+        }
+        aurb->packet->result =
+            usbredir_handle_status(dev, alt_setting_status->status, len);
+        usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
+    }
+    async_free(dev, aurb);
+}
+
+static void usbredir_iso_stream_status(void *priv, uint32_t id,
+    struct usb_redir_iso_stream_status_header *iso_stream_status)
+{
+    USBRedirDevice *dev = priv;
+    uint8_t ep = iso_stream_status->endpoint;
+
+    DPRINTF("iso status %d ep %02X id %u\n", iso_stream_status->status,
+            ep, id);
+
+    if (!dev->dev.attached || !dev->endpoint[EP2I(ep)].iso_started) {
+        return;
+    }
+
+    dev->endpoint[EP2I(ep)].iso_error = iso_stream_status->status;
+    if (iso_stream_status->status == usb_redir_stall) {
+        DPRINTF("iso stream stopped by peer ep %02X\n", ep);
+        dev->endpoint[EP2I(ep)].iso_started = 0;
+    }
+}
+
+static void usbredir_interrupt_receiving_status(void *priv, uint32_t id,
+    struct usb_redir_interrupt_receiving_status_header
+    *interrupt_receiving_status)
+{
+    USBRedirDevice *dev = priv;
+    uint8_t ep = interrupt_receiving_status->endpoint;
+
+    DPRINTF("interrupt recv status %d ep %02X id %u\n",
+            interrupt_receiving_status->status, ep, id);
+
+    if (!dev->dev.attached || !dev->endpoint[EP2I(ep)].interrupt_started) {
+        return;
+    }
+
+    dev->endpoint[EP2I(ep)].interrupt_error =
+        interrupt_receiving_status->status;
+    if (interrupt_receiving_status->status == usb_redir_stall) {
+        DPRINTF("interrupt receiving stopped by peer ep %02X\n", ep);
+        dev->endpoint[EP2I(ep)].interrupt_started = 0;
+    }
+}
+
+static void usbredir_bulk_streams_status(void *priv, uint32_t id,
+    struct usb_redir_bulk_streams_status_header *bulk_streams_status)
+{
+}
+
+static void usbredir_control_packet(void *priv, uint32_t id,
+    struct usb_redir_control_packet_header *control_packet,
+    uint8_t *data, int data_len)
+{
+    USBRedirDevice *dev = priv;
+    int len = control_packet->length;
+    AsyncURB *aurb;
+
+    DPRINTF("ctrl-in status %d len %d id %u\n", control_packet->status,
+            len, id);
+
+    aurb = async_find(dev, id);
+    if (!aurb) {
+        free(data);
+        return;
+    }
+
+    aurb->control_packet.status = control_packet->status;
+    aurb->control_packet.length = control_packet->length;
+    if (memcmp(&aurb->control_packet, control_packet,
+               sizeof(*control_packet))) {
+        ERROR("return control packet mismatch, please report this!\n");
+        len = USB_RET_NAK;
+    }
+
+    if (aurb->packet) {
+        len = usbredir_handle_status(dev, control_packet->status, len);
+        if (len > 0) {
+            usbredir_log_data(dev, "ctrl data in:", data, data_len);
+            if (data_len <= sizeof(dev->dev.data_buf)) {
+                memcpy(dev->dev.data_buf, data, data_len);
+            } else {
+                ERROR("ctrl buffer too small (%d > %zu)\n",
+                      data_len, sizeof(dev->dev.data_buf));
+                len = USB_RET_STALL;
+            }
+        }
+        aurb->packet->result = len;
+        usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
+    }
+    async_free(dev, aurb);
+    free(data);
+}
+
+static void usbredir_bulk_packet(void *priv, uint32_t id,
+    struct usb_redir_bulk_packet_header *bulk_packet,
+    uint8_t *data, int data_len)
+{
+    USBRedirDevice *dev = priv;
+    uint8_t ep = bulk_packet->endpoint;
+    int len = bulk_packet->length;
+    AsyncURB *aurb;
+
+    DPRINTF("bulk-in status %d ep %02X len %d id %u\n", bulk_packet->status,
+            ep, len, id);
+
+    aurb = async_find(dev, id);
+    if (!aurb) {
+        free(data);
+        return;
+    }
+
+    if (aurb->bulk_packet.endpoint != bulk_packet->endpoint ||
+            aurb->bulk_packet.stream_id != bulk_packet->stream_id) {
+        ERROR("return bulk packet mismatch, please report this!\n");
+        len = USB_RET_NAK;
+    }
+
+    if (aurb->packet) {
+        len = usbredir_handle_status(dev, bulk_packet->status, len);
+        if (len > 0) {
+            usbredir_log_data(dev, "bulk data in:", data, data_len);
+            if (data_len <= aurb->packet->iov.size) {
+                usb_packet_copy(aurb->packet, data, data_len);
+            } else {
+                ERROR("bulk buffer too small (%d > %zd)\n", data_len,
+                      aurb->packet->iov.size);
+                len = USB_RET_STALL;
+            }
+        }
+        aurb->packet->result = len;
+        usb_packet_complete(&dev->dev, aurb->packet);
+    }
+    async_free(dev, aurb);
+    free(data);
+}
+
+static void usbredir_iso_packet(void *priv, uint32_t id,
+    struct usb_redir_iso_packet_header *iso_packet,
+    uint8_t *data, int data_len)
+{
+    USBRedirDevice *dev = priv;
+    uint8_t ep = iso_packet->endpoint;
+
+    DPRINTF2("iso-in status %d ep %02X len %d id %u\n", iso_packet->status, ep,
+             data_len, id);
+
+    if (dev->endpoint[EP2I(ep)].type != USB_ENDPOINT_XFER_ISOC) {
+        ERROR("received iso packet for non iso endpoint %02X\n", ep);
+        free(data);
+        return;
+    }
+
+    if (dev->endpoint[EP2I(ep)].iso_started == 0) {
+        DPRINTF("received iso packet for non started stream ep %02X\n", ep);
+        free(data);
+        return;
+    }
+
+    /* bufp_alloc also adds the packet to the ep queue */
+    bufp_alloc(dev, data, data_len, iso_packet->status, ep);
+}
+
+static void usbredir_interrupt_packet(void *priv, uint32_t id,
+    struct usb_redir_interrupt_packet_header *interrupt_packet,
+    uint8_t *data, int data_len)
+{
+    USBRedirDevice *dev = priv;
+    uint8_t ep = interrupt_packet->endpoint;
+
+    DPRINTF("interrupt-in status %d ep %02X len %d id %u\n",
+            interrupt_packet->status, ep, data_len, id);
+
+    if (dev->endpoint[EP2I(ep)].type != USB_ENDPOINT_XFER_INT) {
+        ERROR("received int packet for non interrupt endpoint %02X\n", ep);
+        free(data);
+        return;
+    }
+
+    if (ep & USB_DIR_IN) {
+        if (dev->endpoint[EP2I(ep)].interrupt_started == 0) {
+            DPRINTF("received int packet while not started ep %02X\n", ep);
+            free(data);
+            return;
+        }
+
+        /* bufp_alloc also adds the packet to the ep queue */
+        bufp_alloc(dev, data, data_len, interrupt_packet->status, ep);
+    } else {
+        int len = interrupt_packet->length;
+
+        AsyncURB *aurb = async_find(dev, id);
+        if (!aurb) {
+            return;
+        }
+
+        if (aurb->interrupt_packet.endpoint != interrupt_packet->endpoint) {
+            ERROR("return int packet mismatch, please report this!\n");
+            len = USB_RET_NAK;
+        }
+
+        if (aurb->packet) {
+            aurb->packet->result = usbredir_handle_status(dev,
+                                               interrupt_packet->status, len);
+            usb_packet_complete(&dev->dev, aurb->packet);
+        }
+        async_free(dev, aurb);
+    }
+}
+
+static Property usbredir_properties[] = {
+    DEFINE_PROP_CHR("chardev", USBRedirDevice, cs),
+    DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, 0),
+    DEFINE_PROP_STRING("filter", USBRedirDevice, filter_str),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void usbredir_class_initfn(ObjectClass *klass, void *data)
+{
+    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    uc->init           = usbredir_initfn;
+    uc->product_desc   = "USB Redirection Device";
+    uc->handle_destroy = usbredir_handle_destroy;
+    uc->cancel_packet  = usbredir_cancel_packet;
+    uc->handle_reset   = usbredir_handle_reset;
+    uc->handle_data    = usbredir_handle_data;
+    uc->handle_control = usbredir_handle_control;
+    dc->props          = usbredir_properties;
+}
+
+static TypeInfo usbredir_dev_info = {
+    .name          = "usb-redir",
+    .parent        = TYPE_USB_DEVICE,
+    .instance_size = sizeof(USBRedirDevice),
+    .class_init    = usbredir_class_initfn,
+};
+
+static void usbredir_register_types(void)
+{
+    type_register_static(&usbredir_dev_info);
+}
+
+type_init(usbredir_register_types)
diff --git a/trace-events b/trace-events
index 74bb92a..bcfe13a 100644
--- a/trace-events
+++ b/trace-events
@@ -227,16 +227,16 @@ sun4m_iommu_page_get_flags(uint64_t pa, uint64_t iopte, uint32_t ret) "get flags
 sun4m_iommu_translate_pa(uint64_t addr, uint64_t pa, uint32_t iopte) "xlate dva %"PRIx64" => pa %"PRIx64" iopte = %x"
 sun4m_iommu_bad_addr(uint64_t addr) "bad addr %"PRIx64
 
-# hw/usb.c
+# hw/usb/core.c
 usb_packet_state_change(int bus, const char *port, int ep, void *p, const char *o, const char *n) "bus %d, port %s, ep %d, packet %p, state %s -> %s"
 
-# hw/usb-bus.c
+# hw/usb/bus.c
 usb_port_claim(int bus, const char *port) "bus %d, port %s"
 usb_port_attach(int bus, const char *port) "bus %d, port %s"
 usb_port_detach(int bus, const char *port) "bus %d, port %s"
 usb_port_release(int bus, const char *port) "bus %d, port %s"
 
-# hw/usb-ehci.c
+# hw/usb/hcd-ehci.c
 usb_ehci_reset(void) "=== RESET ==="
 usb_ehci_mmio_readl(uint32_t addr, const char *str, uint32_t val) "rd mmio %04x [%s] = %x"
 usb_ehci_mmio_writel(uint32_t addr, const char *str, uint32_t val) "wr mmio %04x [%s] = %x"
@@ -269,7 +269,7 @@ usb_set_interface(int addr, int iface, int alt, int ret) "dev %d, interface %d,
 usb_clear_device_feature(int addr, int feature, int ret) "dev %d, feature %d, ret %d"
 usb_set_device_feature(int addr, int feature, int ret) "dev %d, feature %d, ret %d"
 
-# usb-linux.c
+# hw/usb/host-linux.c
 usb_host_open_started(int bus, int addr) "dev %d:%d"
 usb_host_open_success(int bus, int addr) "dev %d:%d"
 usb_host_open_failure(int bus, int addr) "dev %d:%d"
diff --git a/usb-bsd.c b/usb-bsd.c
deleted file mode 100644
index ec26266..0000000
--- a/usb-bsd.c
+++ /dev/null
@@ -1,647 +0,0 @@
-/*
- * BSD host USB redirector
- *
- * Copyright (c) 2006 Lonnie Mendez
- * Portions of code and concepts borrowed from
- * usb-linux.c and libusb's bsd.c and are copyright their respective owners.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "qemu-common.h"
-#include "monitor.h"
-#include "hw/usb.h"
-
-/* usb.h declares these */
-#undef USB_SPEED_HIGH
-#undef USB_SPEED_FULL
-#undef USB_SPEED_LOW
-
-#include <sys/ioctl.h>
-#ifndef __DragonFly__
-#include <dev/usb/usb.h>
-#else
-#include <bus/usb/usb.h>
-#endif
-
-/* This value has maximum potential at 16.
- * You should also set hw.usb.debug to gain
- * more detailed view.
- */
-//#define DEBUG
-#define UGEN_DEBUG_LEVEL 0
-
-
-typedef int USBScanFunc(void *opaque, int bus_num, int addr, int class_id,
-                        int vendor_id, int product_id,
-                        const char *product_name, int speed);
-static int usb_host_find_device(int *pbus_num, int *paddr,
-                                const char *devname);
-
-typedef struct USBHostDevice {
-    USBDevice dev;
-    int ep_fd[USB_MAX_ENDPOINTS];
-    int devfd;
-    char devpath[32];
-} USBHostDevice;
-
-
-static int ensure_ep_open(USBHostDevice *dev, int ep, int mode)
-{
-    char buf[32];
-    int fd;
-
-    /* Get the address for this endpoint */
-    ep = UE_GET_ADDR(ep);
-
-    if (dev->ep_fd[ep] < 0) {
-#if defined(__FreeBSD__) || defined(__DragonFly__)
-        snprintf(buf, sizeof(buf) - 1, "%s.%d", dev->devpath, ep);
-#else
-        snprintf(buf, sizeof(buf) - 1, "%s.%02d", dev->devpath, ep);
-#endif
-        /* Try to open it O_RDWR first for those devices which have in and out
-         * endpoints with the same address (eg 0x02 and 0x82)
-         */
-        fd = open(buf, O_RDWR);
-        if (fd < 0 && errno == ENXIO)
-            fd = open(buf, mode);
-        if (fd < 0) {
-#ifdef DEBUG
-            printf("ensure_ep_open: failed to open device endpoint %s: %s\n",
-                   buf, strerror(errno));
-#endif
-        }
-        dev->ep_fd[ep] = fd;
-    }
-
-    return dev->ep_fd[ep];
-}
-
-static void ensure_eps_closed(USBHostDevice *dev)
-{
-    int epnum = 1;
-
-    if (!dev)
-        return;
-
-    while (epnum < USB_MAX_ENDPOINTS) {
-        if (dev->ep_fd[epnum] >= 0) {
-            close(dev->ep_fd[epnum]);
-            dev->ep_fd[epnum] = -1;
-        }
-        epnum++;
-    }
-}
-
-static void usb_host_handle_reset(USBDevice *dev)
-{
-#if 0
-    USBHostDevice *s = (USBHostDevice *)dev;
-#endif
-}
-
-/* XXX:
- * -check device states against transfer requests
- *  and return appropriate response
- */
-static int usb_host_handle_control(USBDevice *dev,
-                                   USBPacket *p,
-                                   int request,
-                                   int value,
-                                   int index,
-                                   int length,
-                                   uint8_t *data)
-{
-    USBHostDevice *s = (USBHostDevice *)dev;
-    struct usb_ctl_request req;
-    struct usb_alt_interface aiface;
-    int ret, timeout = 50;
-
-    if ((request >> 8) == UT_WRITE_DEVICE &&
-        (request & 0xff) == UR_SET_ADDRESS) {
-
-        /* specific SET_ADDRESS support */
-        dev->addr = value;
-        return 0;
-    } else if ((request >> 8) == UT_WRITE_DEVICE &&
-               (request & 0xff) == UR_SET_CONFIG) {
-
-        ensure_eps_closed(s); /* can't do this without all eps closed */
-
-        ret = ioctl(s->devfd, USB_SET_CONFIG, &value);
-        if (ret < 0) {
-#ifdef DEBUG
-            printf("handle_control: failed to set configuration - %s\n",
-                   strerror(errno));
-#endif
-            return USB_RET_STALL;
-        }
-
-        return 0;
-    } else if ((request >> 8) == UT_WRITE_INTERFACE &&
-               (request & 0xff) == UR_SET_INTERFACE) {
-
-        aiface.uai_interface_index = index;
-        aiface.uai_alt_no = value;
-
-        ensure_eps_closed(s); /* can't do this without all eps closed */
-        ret = ioctl(s->devfd, USB_SET_ALTINTERFACE, &aiface);
-        if (ret < 0) {
-#ifdef DEBUG
-            printf("handle_control: failed to set alternate interface - %s\n",
-                   strerror(errno));
-#endif
-            return USB_RET_STALL;
-        }
-
-        return 0;
-    } else {
-        req.ucr_request.bmRequestType = request >> 8;
-        req.ucr_request.bRequest = request & 0xff;
-        USETW(req.ucr_request.wValue, value);
-        USETW(req.ucr_request.wIndex, index);
-        USETW(req.ucr_request.wLength, length);
-        req.ucr_data = data;
-        req.ucr_flags = USBD_SHORT_XFER_OK;
-
-        ret = ioctl(s->devfd, USB_SET_TIMEOUT, &timeout);
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-        if (ret < 0 && errno != EINVAL) {
-#else
-        if (ret < 0) {
-#endif
-#ifdef DEBUG
-            printf("handle_control: setting timeout failed - %s\n",
-                   strerror(errno));
-#endif
-        }
-
-        ret = ioctl(s->devfd, USB_DO_REQUEST, &req);
-        /* ugen returns EIO for usbd_do_request_ no matter what
-         * happens with the transfer */
-        if (ret < 0) {
-#ifdef DEBUG
-            printf("handle_control: error after request - %s\n",
-                   strerror(errno));
-#endif
-            return USB_RET_NAK; // STALL
-        } else {
-            return req.ucr_actlen;
-        }
-    }
-}
-
-static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
-{
-    USBHostDevice *s = (USBHostDevice *)dev;
-    int ret, fd, mode;
-    int one = 1, shortpacket = 0, timeout = 50;
-    sigset_t new_mask, old_mask;
-    uint8_t devep = p->ep->nr;
-
-    /* protect data transfers from SIGALRM signal */
-    sigemptyset(&new_mask);
-    sigaddset(&new_mask, SIGALRM);
-    sigprocmask(SIG_BLOCK, &new_mask, &old_mask);
-
-    if (p->pid == USB_TOKEN_IN) {
-        devep |= 0x80;
-        mode = O_RDONLY;
-        shortpacket = 1;
-    } else {
-        mode = O_WRONLY;
-    }
-
-    fd = ensure_ep_open(s, devep, mode);
-    if (fd < 0) {
-        sigprocmask(SIG_SETMASK, &old_mask, NULL);
-        return USB_RET_NODEV;
-    }
-
-    if (ioctl(fd, USB_SET_TIMEOUT, &timeout) < 0) {
-#ifdef DEBUG
-        printf("handle_data: failed to set timeout - %s\n",
-               strerror(errno));
-#endif
-    }
-
-    if (shortpacket) {
-        if (ioctl(fd, USB_SET_SHORT_XFER, &one) < 0) {
-#ifdef DEBUG
-            printf("handle_data: failed to set short xfer mode - %s\n",
-                   strerror(errno));
-#endif
-            sigprocmask(SIG_SETMASK, &old_mask, NULL);
-        }
-    }
-
-    if (p->pid == USB_TOKEN_IN)
-        ret = readv(fd, p->iov.iov, p->iov.niov);
-    else
-        ret = writev(fd, p->iov.iov, p->iov.niov);
-
-    sigprocmask(SIG_SETMASK, &old_mask, NULL);
-
-    if (ret < 0) {
-#ifdef DEBUG
-        printf("handle_data: error after %s data - %s\n",
-               pid == USB_TOKEN_IN ? "reading" : "writing", strerror(errno));
-#endif
-        switch(errno) {
-        case ETIMEDOUT:
-        case EINTR:
-            return USB_RET_NAK;
-        default:
-            return USB_RET_STALL;
-        }
-    } else {
-        return ret;
-    }
-}
-
-static void usb_host_handle_destroy(USBDevice *opaque)
-{
-    USBHostDevice *s = (USBHostDevice *)opaque;
-    int i;
-
-    for (i = 0; i < USB_MAX_ENDPOINTS; i++)
-        if (s->ep_fd[i] >= 0)
-            close(s->ep_fd[i]);
-
-    if (s->devfd < 0)
-        return;
-
-    close(s->devfd);
-
-    g_free(s);
-}
-
-static int usb_host_initfn(USBDevice *dev)
-{
-    return 0;
-}
-
-USBDevice *usb_host_device_open(USBBus *guest_bus, const char *devname)
-{
-    struct usb_device_info bus_info, dev_info;
-    USBDevice *d = NULL, *ret = NULL;
-    USBHostDevice *dev;
-    char ctlpath[PATH_MAX + 1];
-    char buspath[PATH_MAX + 1];
-    int bfd, dfd, bus, address, i;
-    int ugendebug = UGEN_DEBUG_LEVEL;
-
-    if (usb_host_find_device(&bus, &address, devname) < 0) {
-        goto fail;
-    }
-
-    snprintf(buspath, PATH_MAX, "/dev/usb%d", bus);
-
-    bfd = open(buspath, O_RDWR);
-    if (bfd < 0) {
-#ifdef DEBUG
-        printf("usb_host_device_open: failed to open usb bus - %s\n",
-               strerror(errno));
-#endif
-        goto fail;
-    }
-
-    bus_info.udi_addr = address;
-    if (ioctl(bfd, USB_DEVICEINFO, &bus_info) < 0) {
-#ifdef DEBUG
-        printf("usb_host_device_open: failed to grab bus information - %s\n",
-               strerror(errno));
-#endif
-        goto fail_bfd;
-    }
-
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
-    snprintf(ctlpath, PATH_MAX, "/dev/%s", bus_info.udi_devnames[0]);
-#else
-    snprintf(ctlpath, PATH_MAX, "/dev/%s.00", bus_info.udi_devnames[0]);
-#endif
-
-    dfd  = open(ctlpath, O_RDWR);
-    if (dfd < 0) {
-        dfd = open(ctlpath, O_RDONLY);
-        if (dfd < 0) {
-#ifdef DEBUG
-            printf("usb_host_device_open: failed to open usb device %s - %s\n",
-                   ctlpath, strerror(errno));
-#endif
-        }
-        goto fail_dfd;
-    }
-
-    if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0) {
-#ifdef DEBUG
-        printf("usb_host_device_open: failed to grab device info - %s\n",
-               strerror(errno));
-#endif
-        goto fail_dfd;
-    }
-
-    d = usb_create(guest_bus, "usb-host");
-    dev = DO_UPCAST(USBHostDevice, dev, d);
-
-    if (dev_info.udi_speed == 1) {
-        dev->dev.speed = USB_SPEED_LOW - 1;
-        dev->dev.speedmask = USB_SPEED_MASK_LOW;
-    } else {
-        dev->dev.speed = USB_SPEED_FULL - 1;
-        dev->dev.speedmask = USB_SPEED_MASK_FULL;
-    }
-
-    if (strncmp(dev_info.udi_product, "product", 7) != 0) {
-        pstrcpy(dev->dev.product_desc, sizeof(dev->dev.product_desc),
-                dev_info.udi_product);
-    } else {
-        snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc),
-                 "host:%s", devname);
-    }
-
-    pstrcpy(dev->devpath, sizeof(dev->devpath), "/dev/");
-    pstrcat(dev->devpath, sizeof(dev->devpath), dev_info.udi_devnames[0]);
-
-    /* Mark the endpoints as not yet open */
-    for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
-        dev->ep_fd[i] = -1;
-    }
-
-    ioctl(dfd, USB_SETDEBUG, &ugendebug);
-
-    ret = (USBDevice *)dev;
-
-fail_dfd:
-    close(dfd);
-fail_bfd:
-    close(bfd);
-fail:
-    return ret;
-}
-
-static void usb_host_class_initfn(ObjectClass *klass, void *data)
-{
-    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
-
-    uc->product_desc   = "USB Host Device";
-    uc->init           = usb_host_initfn;
-    uc->handle_reset   = usb_host_handle_reset;
-    uc->handle_control = usb_host_handle_control;
-    uc->handle_data    = usb_host_handle_data;
-    uc->handle_destroy = usb_host_handle_destroy;
-}
-
-static TypeInfo usb_host_dev_info = {
-    .name          = "usb-host",
-    .parent        = TYPE_USB_DEVICE,
-    .instance_size = sizeof(USBHostDevice),
-    .class_init    = usb_host_class_initfn,
-};
-
-static void usb_host_register_types(void)
-{
-    type_register_static(&usb_host_dev_info);
-}
-
-type_init(usb_host_register_types)
-
-static int usb_host_scan(void *opaque, USBScanFunc *func)
-{
-    struct usb_device_info bus_info;
-    struct usb_device_info dev_info;
-    uint16_t vendor_id, product_id, class_id, speed;
-    int bfd, dfd, bus, address;
-    char busbuf[20], devbuf[20], product_name[256];
-    int ret = 0;
-
-    for (bus = 0; bus < 10; bus++) {
-
-        snprintf(busbuf, sizeof(busbuf) - 1, "/dev/usb%d", bus);
-        bfd = open(busbuf, O_RDWR);
-        if (bfd < 0)
-	    continue;
-
-        for (address = 1; address < 127; address++) {
-
-            bus_info.udi_addr = address;
-            if (ioctl(bfd, USB_DEVICEINFO, &bus_info) < 0)
-                continue;
-
-            /* only list devices that can be used by generic layer */
-            if (strncmp(bus_info.udi_devnames[0], "ugen", 4) != 0)
-                continue;
-
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
-            snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s", bus_info.udi_devnames[0]);
-#else
-            snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s.00", bus_info.udi_devnames[0]);
-#endif
-
-            dfd = open(devbuf, O_RDONLY);
-            if (dfd < 0) {
-#ifdef DEBUG
-                printf("usb_host_scan: couldn't open device %s - %s\n", devbuf,
-                       strerror(errno));
-#endif
-                continue;
-            }
-
-            if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0)
-                printf("usb_host_scan: couldn't get device information for %s - %s\n",
-                       devbuf, strerror(errno));
-
-            /* XXX: might need to fixup endianness of word values before copying over */
-
-            vendor_id = dev_info.udi_vendorNo;
-            product_id = dev_info.udi_productNo;
-            class_id = dev_info.udi_class;
-            speed = dev_info.udi_speed;
-
-            if (strncmp(dev_info.udi_product, "product", 7) != 0)
-                pstrcpy(product_name, sizeof(product_name),
-                        dev_info.udi_product);
-            else
-                product_name[0] = '\0';
-
-            ret = func(opaque, bus, address, class_id, vendor_id,
-                       product_id, product_name, speed);
-
-            close(dfd);
-
-            if (ret)
-                goto the_end;
-        }
-
-        close(bfd);
-    }
-
-the_end:
-    return ret;
-}
-
-typedef struct FindDeviceState {
-    int vendor_id;
-    int product_id;
-    int bus_num;
-    int addr;
-} FindDeviceState;
-
-static int usb_host_find_device_scan(void *opaque, int bus_num, int addr,
-                                     int class_id,
-                                     int vendor_id, int product_id,
-                                     const char *product_name, int speed)
-{
-    FindDeviceState *s = opaque;
-    if (vendor_id == s->vendor_id &&
-        product_id == s->product_id) {
-        s->bus_num = bus_num;
-        s->addr = addr;
-        return 1;
-     } else {
-        return 0;
-     }
-}
-
-
-/* the syntax is :
-   'bus.addr' (decimal numbers) or
-   'vendor_id:product_id' (hexa numbers) */
-static int usb_host_find_device(int *pbus_num, int *paddr,
-                                const char *devname)
-{
-    const char *p;
-    int ret;
-    FindDeviceState fs;
-
-    p = strchr(devname, '.');
-    if (p) {
-        *pbus_num = strtoul(devname, NULL, 0);
-        *paddr = strtoul(p + 1, NULL, 0);
-        return 0;
-    }
-    p = strchr(devname, ':');
-    if (p) {
-        fs.vendor_id = strtoul(devname, NULL, 16);
-        fs.product_id = strtoul(p + 1, NULL, 16);
-        ret = usb_host_scan(&fs, usb_host_find_device_scan);
-        if (ret) {
-            *pbus_num = fs.bus_num;
-            *paddr = fs.addr;
-            return 0;
-        }
-     }
-     return -1;
-}
-
-/**********************/
-/* USB host device info */
-
-struct usb_class_info {
-    int class;
-    const char *class_name;
-};
-
-static const struct usb_class_info usb_class_info[] = {
-    { USB_CLASS_AUDIO, "Audio"},
-    { USB_CLASS_COMM, "Communication"},
-    { USB_CLASS_HID, "HID"},
-    { USB_CLASS_HUB, "Hub" },
-    { USB_CLASS_PHYSICAL, "Physical" },
-    { USB_CLASS_PRINTER, "Printer" },
-    { USB_CLASS_MASS_STORAGE, "Storage" },
-    { USB_CLASS_CDC_DATA, "Data" },
-    { USB_CLASS_APP_SPEC, "Application Specific" },
-    { USB_CLASS_VENDOR_SPEC, "Vendor Specific" },
-    { USB_CLASS_STILL_IMAGE, "Still Image" },
-    { USB_CLASS_CSCID, "Smart Card" },
-    { USB_CLASS_CONTENT_SEC, "Content Security" },
-    { -1, NULL }
-};
-
-static const char *usb_class_str(uint8_t class)
-{
-    const struct usb_class_info *p;
-    for (p = usb_class_info; p->class != -1; p++) {
-        if (p->class == class)
-            break;
-    }
-    return p->class_name;
-}
-
-static void usb_info_device(Monitor *mon, int bus_num, int addr, int class_id,
-                            int vendor_id, int product_id,
-                            const char *product_name,
-                            int speed)
-{
-    const char *class_str, *speed_str;
-
-    switch(speed) {
-    case USB_SPEED_LOW:
-        speed_str = "1.5";
-        break;
-    case USB_SPEED_FULL:
-        speed_str = "12";
-        break;
-    case USB_SPEED_HIGH:
-        speed_str = "480";
-        break;
-    default:
-        speed_str = "?";
-        break;
-    }
-
-    monitor_printf(mon, "  Device %d.%d, speed %s Mb/s\n",
-                   bus_num, addr, speed_str);
-    class_str = usb_class_str(class_id);
-    if (class_str)
-        monitor_printf(mon, "    %s:", class_str);
-    else
-        monitor_printf(mon, "    Class %02x:", class_id);
-    monitor_printf(mon, " USB device %04x:%04x", vendor_id, product_id);
-    if (product_name[0] != '\0')
-        monitor_printf(mon, ", %s", product_name);
-    monitor_printf(mon, "\n");
-}
-
-static int usb_host_info_device(void *opaque,
-                                int bus_num, int addr,
-                                int class_id,
-                                int vendor_id, int product_id,
-                                const char *product_name,
-                                int speed)
-{
-    Monitor *mon = opaque;
-
-    usb_info_device(mon, bus_num, addr, class_id, vendor_id, product_id,
-                    product_name, speed);
-    return 0;
-}
-
-void usb_host_info(Monitor *mon)
-{
-    usb_host_scan(mon, usb_host_info_device);
-}
-
-/* XXX add this */
-int usb_host_device_close(const char *devname)
-{
-    return 0;
-}
diff --git a/usb-linux.c b/usb-linux.c
deleted file mode 100644
index 90919c2..0000000
--- a/usb-linux.c
+++ /dev/null
@@ -1,1913 +0,0 @@
-/*
- * Linux host USB redirector
- *
- * Copyright (c) 2005 Fabrice Bellard
- *
- * Copyright (c) 2008 Max Krasnyansky
- *      Support for host device auto connect & disconnect
- *      Major rewrite to support fully async operation
- *
- * Copyright 2008 TJ <linux at tjworld.net>
- *      Added flexible support for /dev/bus/usb /sys/bus/usb/devices in addition
- *      to the legacy /proc/bus/usb USB device discovery and handling
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "qemu-common.h"
-#include "qemu-timer.h"
-#include "monitor.h"
-#include "sysemu.h"
-#include "trace.h"
-
-#include <dirent.h>
-#include <sys/ioctl.h>
-
-#include <linux/usbdevice_fs.h>
-#include <linux/version.h>
-#include "hw/usb.h"
-
-/* We redefine it to avoid version problems */
-struct usb_ctrltransfer {
-    uint8_t  bRequestType;
-    uint8_t  bRequest;
-    uint16_t wValue;
-    uint16_t wIndex;
-    uint16_t wLength;
-    uint32_t timeout;
-    void *data;
-};
-
-typedef int USBScanFunc(void *opaque, int bus_num, int addr, const char *port,
-                        int class_id, int vendor_id, int product_id,
-                        const char *product_name, int speed);
-
-//#define DEBUG
-
-#ifdef DEBUG
-#define DPRINTF printf
-#else
-#define DPRINTF(...)
-#endif
-
-#define PRODUCT_NAME_SZ 32
-#define MAX_PORTLEN 16
-
-/* endpoint association data */
-#define ISO_FRAME_DESC_PER_URB 32
-
-/* devio.c limits single requests to 16k */
-#define MAX_USBFS_BUFFER_SIZE 16384
-
-typedef struct AsyncURB AsyncURB;
-
-struct endp_data {
-    uint8_t halted;
-    uint8_t iso_started;
-    AsyncURB *iso_urb;
-    int iso_urb_idx;
-    int iso_buffer_used;
-    int inflight;
-};
-
-struct USBAutoFilter {
-    uint32_t bus_num;
-    uint32_t addr;
-    char     *port;
-    uint32_t vendor_id;
-    uint32_t product_id;
-};
-
-typedef struct USBHostDevice {
-    USBDevice dev;
-    int       fd;
-    int       hub_fd;
-    int       hub_port;
-
-    uint8_t   descr[8192];
-    int       descr_len;
-    int       closing;
-    uint32_t  iso_urb_count;
-    Notifier  exit;
-
-    struct endp_data ep_in[USB_MAX_ENDPOINTS];
-    struct endp_data ep_out[USB_MAX_ENDPOINTS];
-    QLIST_HEAD(, AsyncURB) aurbs;
-
-    /* Host side address */
-    int bus_num;
-    int addr;
-    char port[MAX_PORTLEN];
-    struct USBAutoFilter match;
-    int seen, errcount;
-
-    QTAILQ_ENTRY(USBHostDevice) next;
-} USBHostDevice;
-
-static QTAILQ_HEAD(, USBHostDevice) hostdevs = QTAILQ_HEAD_INITIALIZER(hostdevs);
-
-static int usb_host_close(USBHostDevice *dev);
-static int parse_filter(const char *spec, struct USBAutoFilter *f);
-static void usb_host_auto_check(void *unused);
-static int usb_host_read_file(char *line, size_t line_size,
-                            const char *device_file, const char *device_name);
-static int usb_linux_update_endp_table(USBHostDevice *s);
-
-static int usb_host_usbfs_type(USBHostDevice *s, USBPacket *p)
-{
-    static const int usbfs[] = {
-        [USB_ENDPOINT_XFER_CONTROL] = USBDEVFS_URB_TYPE_CONTROL,
-        [USB_ENDPOINT_XFER_ISOC]    = USBDEVFS_URB_TYPE_ISO,
-        [USB_ENDPOINT_XFER_BULK]    = USBDEVFS_URB_TYPE_BULK,
-        [USB_ENDPOINT_XFER_INT]     = USBDEVFS_URB_TYPE_INTERRUPT,
-    };
-    uint8_t type = p->ep->type;
-    assert(type < ARRAY_SIZE(usbfs));
-    return usbfs[type];
-}
-
-static int usb_host_do_reset(USBHostDevice *dev)
-{
-    struct timeval s, e;
-    uint32_t usecs;
-    int ret;
-
-    gettimeofday(&s, NULL);
-    ret = ioctl(dev->fd, USBDEVFS_RESET);
-    gettimeofday(&e, NULL);
-    usecs = (e.tv_sec  - s.tv_sec) * 1000000;
-    usecs += e.tv_usec - s.tv_usec;
-    if (usecs > 1000000) {
-        /* more than a second, something is fishy, broken usb device? */
-        fprintf(stderr, "husb: device %d:%d reset took %d.%06d seconds\n",
-                dev->bus_num, dev->addr, usecs / 1000000, usecs % 1000000);
-    }
-    return ret;
-}
-
-static struct endp_data *get_endp(USBHostDevice *s, int pid, int ep)
-{
-    struct endp_data *eps = pid == USB_TOKEN_IN ? s->ep_in : s->ep_out;
-    assert(pid == USB_TOKEN_IN || pid == USB_TOKEN_OUT);
-    assert(ep > 0 && ep <= USB_MAX_ENDPOINTS);
-    return eps + ep - 1;
-}
-
-static int is_isoc(USBHostDevice *s, int pid, int ep)
-{
-    return usb_ep_get_type(&s->dev, pid, ep) == USB_ENDPOINT_XFER_ISOC;
-}
-
-static int is_valid(USBHostDevice *s, int pid, int ep)
-{
-    return usb_ep_get_type(&s->dev, pid, ep) != USB_ENDPOINT_XFER_INVALID;
-}
-
-static int is_halted(USBHostDevice *s, int pid, int ep)
-{
-    return get_endp(s, pid, ep)->halted;
-}
-
-static void clear_halt(USBHostDevice *s, int pid, int ep)
-{
-    trace_usb_host_ep_clear_halt(s->bus_num, s->addr, ep);
-    get_endp(s, pid, ep)->halted = 0;
-}
-
-static void set_halt(USBHostDevice *s, int pid, int ep)
-{
-    if (ep != 0) {
-        trace_usb_host_ep_set_halt(s->bus_num, s->addr, ep);
-        get_endp(s, pid, ep)->halted = 1;
-    }
-}
-
-static int is_iso_started(USBHostDevice *s, int pid, int ep)
-{
-    return get_endp(s, pid, ep)->iso_started;
-}
-
-static void clear_iso_started(USBHostDevice *s, int pid, int ep)
-{
-    trace_usb_host_ep_stop_iso(s->bus_num, s->addr, ep);
-    get_endp(s, pid, ep)->iso_started = 0;
-}
-
-static void set_iso_started(USBHostDevice *s, int pid, int ep)
-{
-    struct endp_data *e = get_endp(s, pid, ep);
-
-    trace_usb_host_ep_start_iso(s->bus_num, s->addr, ep);
-    if (!e->iso_started) {
-        e->iso_started = 1;
-        e->inflight = 0;
-    }
-}
-
-static int change_iso_inflight(USBHostDevice *s, int pid, int ep, int value)
-{
-    struct endp_data *e = get_endp(s, pid, ep);
-
-    e->inflight += value;
-    return e->inflight;
-}
-
-static void set_iso_urb(USBHostDevice *s, int pid, int ep, AsyncURB *iso_urb)
-{
-    get_endp(s, pid, ep)->iso_urb = iso_urb;
-}
-
-static AsyncURB *get_iso_urb(USBHostDevice *s, int pid, int ep)
-{
-    return get_endp(s, pid, ep)->iso_urb;
-}
-
-static void set_iso_urb_idx(USBHostDevice *s, int pid, int ep, int i)
-{
-    get_endp(s, pid, ep)->iso_urb_idx = i;
-}
-
-static int get_iso_urb_idx(USBHostDevice *s, int pid, int ep)
-{
-    return get_endp(s, pid, ep)->iso_urb_idx;
-}
-
-static void set_iso_buffer_used(USBHostDevice *s, int pid, int ep, int i)
-{
-    get_endp(s, pid, ep)->iso_buffer_used = i;
-}
-
-static int get_iso_buffer_used(USBHostDevice *s, int pid, int ep)
-{
-    return get_endp(s, pid, ep)->iso_buffer_used;
-}
-
-/*
- * Async URB state.
- * We always allocate iso packet descriptors even for bulk transfers
- * to simplify allocation and casts.
- */
-struct AsyncURB
-{
-    struct usbdevfs_urb urb;
-    struct usbdevfs_iso_packet_desc isocpd[ISO_FRAME_DESC_PER_URB];
-    USBHostDevice *hdev;
-    QLIST_ENTRY(AsyncURB) next;
-
-    /* For regular async urbs */
-    USBPacket     *packet;
-    int more; /* large transfer, more urbs follow */
-
-    /* For buffered iso handling */
-    int iso_frame_idx; /* -1 means in flight */
-};
-
-static AsyncURB *async_alloc(USBHostDevice *s)
-{
-    AsyncURB *aurb = g_malloc0(sizeof(AsyncURB));
-    aurb->hdev = s;
-    QLIST_INSERT_HEAD(&s->aurbs, aurb, next);
-    return aurb;
-}
-
-static void async_free(AsyncURB *aurb)
-{
-    QLIST_REMOVE(aurb, next);
-    g_free(aurb);
-}
-
-static void do_disconnect(USBHostDevice *s)
-{
-    usb_host_close(s);
-    usb_host_auto_check(NULL);
-}
-
-static void async_complete(void *opaque)
-{
-    USBHostDevice *s = opaque;
-    AsyncURB *aurb;
-    int urbs = 0;
-
-    while (1) {
-        USBPacket *p;
-
-        int r = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &aurb);
-        if (r < 0) {
-            if (errno == EAGAIN) {
-                if (urbs > 2) {
-                    fprintf(stderr, "husb: %d iso urbs finished at once\n", urbs);
-                }
-                return;
-            }
-            if (errno == ENODEV) {
-                if (!s->closing) {
-                    trace_usb_host_disconnect(s->bus_num, s->addr);
-                    do_disconnect(s);
-                }
-                return;
-            }
-
-            perror("USBDEVFS_REAPURBNDELAY");
-            return;
-        }
-
-        DPRINTF("husb: async completed. aurb %p status %d alen %d\n",
-                aurb, aurb->urb.status, aurb->urb.actual_length);
-
-        /* If this is a buffered iso urb mark it as complete and don't do
-           anything else (it is handled further in usb_host_handle_iso_data) */
-        if (aurb->iso_frame_idx == -1) {
-            int inflight;
-            int pid = (aurb->urb.endpoint & USB_DIR_IN) ?
-                USB_TOKEN_IN : USB_TOKEN_OUT;
-            int ep = aurb->urb.endpoint & 0xf;
-            if (aurb->urb.status == -EPIPE) {
-                set_halt(s, pid, ep);
-            }
-            aurb->iso_frame_idx = 0;
-            urbs++;
-            inflight = change_iso_inflight(s, pid, ep, -1);
-            if (inflight == 0 && is_iso_started(s, pid, ep)) {
-                fprintf(stderr, "husb: out of buffers for iso stream\n");
-            }
-            continue;
-        }
-
-        p = aurb->packet;
-        trace_usb_host_urb_complete(s->bus_num, s->addr, aurb, aurb->urb.status,
-                                    aurb->urb.actual_length, aurb->more);
-
-        if (p) {
-            switch (aurb->urb.status) {
-            case 0:
-                p->result += aurb->urb.actual_length;
-                break;
-
-            case -EPIPE:
-                set_halt(s, p->pid, p->ep->nr);
-                p->result = USB_RET_STALL;
-                break;
-
-            case -EOVERFLOW:
-                p->result = USB_RET_BABBLE;
-                break;
-
-            default:
-                p->result = USB_RET_IOERROR;
-                break;
-            }
-
-            if (aurb->urb.type == USBDEVFS_URB_TYPE_CONTROL) {
-                trace_usb_host_req_complete(s->bus_num, s->addr, p->result);
-                usb_generic_async_ctrl_complete(&s->dev, p);
-            } else if (!aurb->more) {
-                trace_usb_host_req_complete(s->bus_num, s->addr, p->result);
-                usb_packet_complete(&s->dev, p);
-            }
-        }
-
-        async_free(aurb);
-    }
-}
-
-static void usb_host_async_cancel(USBDevice *dev, USBPacket *p)
-{
-    USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
-    AsyncURB *aurb;
-
-    QLIST_FOREACH(aurb, &s->aurbs, next) {
-        if (p != aurb->packet) {
-            continue;
-        }
-
-        DPRINTF("husb: async cancel: packet %p, aurb %p\n", p, aurb);
-
-        /* Mark it as dead (see async_complete above) */
-        aurb->packet = NULL;
-
-        int r = ioctl(s->fd, USBDEVFS_DISCARDURB, aurb);
-        if (r < 0) {
-            DPRINTF("husb: async. discard urb failed errno %d\n", errno);
-        }
-    }
-}
-
-static int usb_host_open_device(int bus, int addr)
-{
-    const char *usbfs = NULL;
-    char filename[32];
-    struct stat st;
-    int fd, rc;
-
-    rc = stat("/dev/bus/usb", &st);
-    if (rc == 0 && S_ISDIR(st.st_mode)) {
-        /* udev-created device nodes available */
-        usbfs = "/dev/bus/usb";
-    } else {
-        /* fallback: usbfs mounted below /proc */
-        usbfs = "/proc/bus/usb";
-    }
-
-    snprintf(filename, sizeof(filename), "%s/%03d/%03d",
-             usbfs, bus, addr);
-    fd = open(filename, O_RDWR | O_NONBLOCK);
-    if (fd < 0) {
-        fprintf(stderr, "husb: open %s: %s\n", filename, strerror(errno));
-    }
-    return fd;
-}
-
-static int usb_host_claim_port(USBHostDevice *s)
-{
-#ifdef USBDEVFS_CLAIM_PORT
-    char *h, hub_name[64], line[1024];
-    int hub_addr, ret;
-
-    snprintf(hub_name, sizeof(hub_name), "%d-%s",
-             s->match.bus_num, s->match.port);
-
-    /* try strip off last ".$portnr" to get hub */
-    h = strrchr(hub_name, '.');
-    if (h != NULL) {
-        s->hub_port = atoi(h+1);
-        *h = '\0';
-    } else {
-        /* no dot in there -> it is the root hub */
-        snprintf(hub_name, sizeof(hub_name), "usb%d",
-                 s->match.bus_num);
-        s->hub_port = atoi(s->match.port);
-    }
-
-    if (!usb_host_read_file(line, sizeof(line), "devnum",
-                            hub_name)) {
-        return -1;
-    }
-    if (sscanf(line, "%d", &hub_addr) != 1) {
-        return -1;
-    }
-
-    s->hub_fd = usb_host_open_device(s->match.bus_num, hub_addr);
-    if (s->hub_fd < 0) {
-        return -1;
-    }
-
-    ret = ioctl(s->hub_fd, USBDEVFS_CLAIM_PORT, &s->hub_port);
-    if (ret < 0) {
-        close(s->hub_fd);
-        s->hub_fd = -1;
-        return -1;
-    }
-
-    trace_usb_host_claim_port(s->match.bus_num, hub_addr, s->hub_port);
-    return 0;
-#else
-    return -1;
-#endif
-}
-
-static void usb_host_release_port(USBHostDevice *s)
-{
-    if (s->hub_fd == -1) {
-        return;
-    }
-#ifdef USBDEVFS_RELEASE_PORT
-    ioctl(s->hub_fd, USBDEVFS_RELEASE_PORT, &s->hub_port);
-#endif
-    close(s->hub_fd);
-    s->hub_fd = -1;
-}
-
-static int usb_host_disconnect_ifaces(USBHostDevice *dev, int nb_interfaces)
-{
-    /* earlier Linux 2.4 do not support that */
-#ifdef USBDEVFS_DISCONNECT
-    struct usbdevfs_ioctl ctrl;
-    int ret, interface;
-
-    for (interface = 0; interface < nb_interfaces; interface++) {
-        ctrl.ioctl_code = USBDEVFS_DISCONNECT;
-        ctrl.ifno = interface;
-        ctrl.data = 0;
-        ret = ioctl(dev->fd, USBDEVFS_IOCTL, &ctrl);
-        if (ret < 0 && errno != ENODATA) {
-            perror("USBDEVFS_DISCONNECT");
-            return -1;
-        }
-    }
-#endif
-    return 0;
-}
-
-static int usb_linux_get_num_interfaces(USBHostDevice *s)
-{
-    char device_name[64], line[1024];
-    int num_interfaces = 0;
-
-    sprintf(device_name, "%d-%s", s->bus_num, s->port);
-    if (!usb_host_read_file(line, sizeof(line), "bNumInterfaces",
-                            device_name)) {
-        return -1;
-    }
-    if (sscanf(line, "%d", &num_interfaces) != 1) {
-        return -1;
-    }
-    return num_interfaces;
-}
-
-static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
-{
-    const char *op = NULL;
-    int dev_descr_len, config_descr_len;
-    int interface, nb_interfaces;
-    int ret, i;
-
-    for (i = 0; i < USB_MAX_INTERFACES; i++) {
-        dev->dev.altsetting[i] = 0;
-    }
-
-    if (configuration == 0) { /* address state - ignore */
-        dev->dev.ninterfaces   = 0;
-        dev->dev.configuration = 0;
-        return 1;
-    }
-
-    DPRINTF("husb: claiming interfaces. config %d\n", configuration);
-
-    i = 0;
-    dev_descr_len = dev->descr[0];
-    if (dev_descr_len > dev->descr_len) {
-        fprintf(stderr, "husb: update iface failed. descr too short\n");
-        return 0;
-    }
-
-    i += dev_descr_len;
-    while (i < dev->descr_len) {
-        DPRINTF("husb: i is %d, descr_len is %d, dl %d, dt %d\n",
-                i, dev->descr_len,
-               dev->descr[i], dev->descr[i+1]);
-
-        if (dev->descr[i+1] != USB_DT_CONFIG) {
-            i += dev->descr[i];
-            continue;
-        }
-        config_descr_len = dev->descr[i];
-
-        DPRINTF("husb: config #%d need %d\n", dev->descr[i + 5], configuration);
-
-        if (configuration == dev->descr[i + 5]) {
-            configuration = dev->descr[i + 5];
-            break;
-        }
-
-        i += config_descr_len;
-    }
-
-    if (i >= dev->descr_len) {
-        fprintf(stderr,
-                "husb: update iface failed. no matching configuration\n");
-        return 0;
-    }
-    nb_interfaces = dev->descr[i + 4];
-
-    if (usb_host_disconnect_ifaces(dev, nb_interfaces) < 0) {
-        goto fail;
-    }
-
-    /* XXX: only grab if all interfaces are free */
-    for (interface = 0; interface < nb_interfaces; interface++) {
-        op = "USBDEVFS_CLAIMINTERFACE";
-        ret = ioctl(dev->fd, USBDEVFS_CLAIMINTERFACE, &interface);
-        if (ret < 0) {
-            goto fail;
-        }
-    }
-
-    trace_usb_host_claim_interfaces(dev->bus_num, dev->addr,
-                                    nb_interfaces, configuration);
-
-    dev->dev.ninterfaces   = nb_interfaces;
-    dev->dev.configuration = configuration;
-    return 1;
-
-fail:
-    if (errno == ENODEV) {
-        do_disconnect(dev);
-    }
-    perror(op);
-    return 0;
-}
-
-static int usb_host_release_interfaces(USBHostDevice *s)
-{
-    int ret, i;
-
-    trace_usb_host_release_interfaces(s->bus_num, s->addr);
-
-    for (i = 0; i < s->dev.ninterfaces; i++) {
-        ret = ioctl(s->fd, USBDEVFS_RELEASEINTERFACE, &i);
-        if (ret < 0) {
-            perror("USBDEVFS_RELEASEINTERFACE");
-            return 0;
-        }
-    }
-    return 1;
-}
-
-static void usb_host_handle_reset(USBDevice *dev)
-{
-    USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
-
-    trace_usb_host_reset(s->bus_num, s->addr);
-
-    usb_host_do_reset(s);;
-
-    usb_host_claim_interfaces(s, 0);
-    usb_linux_update_endp_table(s);
-}
-
-static void usb_host_handle_destroy(USBDevice *dev)
-{
-    USBHostDevice *s = (USBHostDevice *)dev;
-
-    usb_host_release_port(s);
-    usb_host_close(s);
-    QTAILQ_REMOVE(&hostdevs, s, next);
-    qemu_remove_exit_notifier(&s->exit);
-}
-
-/* iso data is special, we need to keep enough urbs in flight to make sure
-   that the controller never runs out of them, otherwise the device will
-   likely suffer a buffer underrun / overrun. */
-static AsyncURB *usb_host_alloc_iso(USBHostDevice *s, int pid, uint8_t ep)
-{
-    AsyncURB *aurb;
-    int i, j, len = usb_ep_get_max_packet_size(&s->dev, pid, ep);
-
-    aurb = g_malloc0(s->iso_urb_count * sizeof(*aurb));
-    for (i = 0; i < s->iso_urb_count; i++) {
-        aurb[i].urb.endpoint      = ep;
-        aurb[i].urb.buffer_length = ISO_FRAME_DESC_PER_URB * len;
-        aurb[i].urb.buffer        = g_malloc(aurb[i].urb.buffer_length);
-        aurb[i].urb.type          = USBDEVFS_URB_TYPE_ISO;
-        aurb[i].urb.flags         = USBDEVFS_URB_ISO_ASAP;
-        aurb[i].urb.number_of_packets = ISO_FRAME_DESC_PER_URB;
-        for (j = 0 ; j < ISO_FRAME_DESC_PER_URB; j++)
-            aurb[i].urb.iso_frame_desc[j].length = len;
-        if (pid == USB_TOKEN_IN) {
-            aurb[i].urb.endpoint |= 0x80;
-            /* Mark as fully consumed (idle) */
-            aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB;
-        }
-    }
-    set_iso_urb(s, pid, ep, aurb);
-
-    return aurb;
-}
-
-static void usb_host_stop_n_free_iso(USBHostDevice *s, int pid, uint8_t ep)
-{
-    AsyncURB *aurb;
-    int i, ret, killed = 0, free = 1;
-
-    aurb = get_iso_urb(s, pid, ep);
-    if (!aurb) {
-        return;
-    }
-
-    for (i = 0; i < s->iso_urb_count; i++) {
-        /* in flight? */
-        if (aurb[i].iso_frame_idx == -1) {
-            ret = ioctl(s->fd, USBDEVFS_DISCARDURB, &aurb[i]);
-            if (ret < 0) {
-                perror("USBDEVFS_DISCARDURB");
-                free = 0;
-                continue;
-            }
-            killed++;
-        }
-    }
-
-    /* Make sure any urbs we've killed are reaped before we free them */
-    if (killed) {
-        async_complete(s);
-    }
-
-    for (i = 0; i < s->iso_urb_count; i++) {
-        g_free(aurb[i].urb.buffer);
-    }
-
-    if (free)
-        g_free(aurb);
-    else
-        printf("husb: leaking iso urbs because of discard failure\n");
-    set_iso_urb(s, pid, ep, NULL);
-    set_iso_urb_idx(s, pid, ep, 0);
-    clear_iso_started(s, pid, ep);
-}
-
-static int urb_status_to_usb_ret(int status)
-{
-    switch (status) {
-    case -EPIPE:
-        return USB_RET_STALL;
-    case -EOVERFLOW:
-        return USB_RET_BABBLE;
-    default:
-        return USB_RET_IOERROR;
-    }
-}
-
-static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
-{
-    AsyncURB *aurb;
-    int i, j, ret, max_packet_size, offset, len = 0;
-    uint8_t *buf;
-
-    max_packet_size = p->ep->max_packet_size;
-    if (max_packet_size == 0)
-        return USB_RET_NAK;
-
-    aurb = get_iso_urb(s, p->pid, p->ep->nr);
-    if (!aurb) {
-        aurb = usb_host_alloc_iso(s, p->pid, p->ep->nr);
-    }
-
-    i = get_iso_urb_idx(s, p->pid, p->ep->nr);
-    j = aurb[i].iso_frame_idx;
-    if (j >= 0 && j < ISO_FRAME_DESC_PER_URB) {
-        if (in) {
-            /* Check urb status  */
-            if (aurb[i].urb.status) {
-                len = urb_status_to_usb_ret(aurb[i].urb.status);
-                /* Move to the next urb */
-                aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB - 1;
-            /* Check frame status */
-            } else if (aurb[i].urb.iso_frame_desc[j].status) {
-                len = urb_status_to_usb_ret(
-                                        aurb[i].urb.iso_frame_desc[j].status);
-            /* Check the frame fits */
-            } else if (aurb[i].urb.iso_frame_desc[j].actual_length
-                       > p->iov.size) {
-                printf("husb: received iso data is larger then packet\n");
-                len = USB_RET_BABBLE;
-            /* All good copy data over */
-            } else {
-                len = aurb[i].urb.iso_frame_desc[j].actual_length;
-                buf  = aurb[i].urb.buffer +
-                    j * aurb[i].urb.iso_frame_desc[0].length;
-                usb_packet_copy(p, buf, len);
-            }
-        } else {
-            len = p->iov.size;
-            offset = (j == 0) ? 0 : get_iso_buffer_used(s, p->pid, p->ep->nr);
-
-            /* Check the frame fits */
-            if (len > max_packet_size) {
-                printf("husb: send iso data is larger then max packet size\n");
-                return USB_RET_NAK;
-            }
-
-            /* All good copy data over */
-            usb_packet_copy(p, aurb[i].urb.buffer + offset, len);
-            aurb[i].urb.iso_frame_desc[j].length = len;
-            offset += len;
-            set_iso_buffer_used(s, p->pid, p->ep->nr, offset);
-
-            /* Start the stream once we have buffered enough data */
-            if (!is_iso_started(s, p->pid, p->ep->nr) && i == 1 && j == 8) {
-                set_iso_started(s, p->pid, p->ep->nr);
-            }
-        }
-        aurb[i].iso_frame_idx++;
-        if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
-            i = (i + 1) % s->iso_urb_count;
-            set_iso_urb_idx(s, p->pid, p->ep->nr, i);
-        }
-    } else {
-        if (in) {
-            set_iso_started(s, p->pid, p->ep->nr);
-        } else {
-            DPRINTF("hubs: iso out error no free buffer, dropping packet\n");
-        }
-    }
-
-    if (is_iso_started(s, p->pid, p->ep->nr)) {
-        /* (Re)-submit all fully consumed / filled urbs */
-        for (i = 0; i < s->iso_urb_count; i++) {
-            if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
-                ret = ioctl(s->fd, USBDEVFS_SUBMITURB, &aurb[i]);
-                if (ret < 0) {
-                    perror("USBDEVFS_SUBMITURB");
-                    if (!in || len == 0) {
-                        switch(errno) {
-                        case ETIMEDOUT:
-                            len = USB_RET_NAK;
-                            break;
-                        case EPIPE:
-                        default:
-                            len = USB_RET_STALL;
-                        }
-                    }
-                    break;
-                }
-                aurb[i].iso_frame_idx = -1;
-                change_iso_inflight(s, p->pid, p->ep->nr, 1);
-            }
-        }
-    }
-
-    return len;
-}
-
-static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
-{
-    USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
-    struct usbdevfs_urb *urb;
-    AsyncURB *aurb;
-    int ret, rem, prem, v;
-    uint8_t *pbuf;
-    uint8_t ep;
-
-    trace_usb_host_req_data(s->bus_num, s->addr,
-                            p->pid == USB_TOKEN_IN,
-                            p->ep->nr, p->iov.size);
-
-    if (!is_valid(s, p->pid, p->ep->nr)) {
-        trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_NAK);
-        return USB_RET_NAK;
-    }
-
-    if (p->pid == USB_TOKEN_IN) {
-        ep = p->ep->nr | 0x80;
-    } else {
-        ep = p->ep->nr;
-    }
-
-    if (is_halted(s, p->pid, p->ep->nr)) {
-        unsigned int arg = ep;
-        ret = ioctl(s->fd, USBDEVFS_CLEAR_HALT, &arg);
-        if (ret < 0) {
-            perror("USBDEVFS_CLEAR_HALT");
-            trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_NAK);
-            return USB_RET_NAK;
-        }
-        clear_halt(s, p->pid, p->ep->nr);
-    }
-
-    if (is_isoc(s, p->pid, p->ep->nr)) {
-        return usb_host_handle_iso_data(s, p, p->pid == USB_TOKEN_IN);
-    }
-
-    v = 0;
-    prem = p->iov.iov[v].iov_len;
-    pbuf = p->iov.iov[v].iov_base;
-    rem = p->iov.size;
-    while (rem) {
-        if (prem == 0) {
-            v++;
-            assert(v < p->iov.niov);
-            prem = p->iov.iov[v].iov_len;
-            pbuf = p->iov.iov[v].iov_base;
-            assert(prem <= rem);
-        }
-        aurb = async_alloc(s);
-        aurb->packet = p;
-
-        urb = &aurb->urb;
-        urb->endpoint      = ep;
-        urb->type          = usb_host_usbfs_type(s, p);
-        urb->usercontext   = s;
-        urb->buffer        = pbuf;
-        urb->buffer_length = prem;
-
-        if (urb->buffer_length > MAX_USBFS_BUFFER_SIZE) {
-            urb->buffer_length = MAX_USBFS_BUFFER_SIZE;
-        }
-        pbuf += urb->buffer_length;
-        prem -= urb->buffer_length;
-        rem  -= urb->buffer_length;
-        if (rem) {
-            aurb->more         = 1;
-        }
-
-        trace_usb_host_urb_submit(s->bus_num, s->addr, aurb,
-                                  urb->buffer_length, aurb->more);
-        ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
-
-        DPRINTF("husb: data submit: ep 0x%x, len %u, more %d, packet %p, aurb %p\n",
-                urb->endpoint, urb->buffer_length, aurb->more, p, aurb);
-
-        if (ret < 0) {
-            perror("USBDEVFS_SUBMITURB");
-            async_free(aurb);
-
-            switch(errno) {
-            case ETIMEDOUT:
-                trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_NAK);
-                return USB_RET_NAK;
-            case EPIPE:
-            default:
-                trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_STALL);
-                return USB_RET_STALL;
-            }
-        }
-    }
-
-    return USB_RET_ASYNC;
-}
-
-static int ctrl_error(void)
-{
-    if (errno == ETIMEDOUT) {
-        return USB_RET_NAK;
-    } else {
-        return USB_RET_STALL;
-    }
-}
-
-static int usb_host_set_address(USBHostDevice *s, int addr)
-{
-    trace_usb_host_set_address(s->bus_num, s->addr, addr);
-    s->dev.addr = addr;
-    return 0;
-}
-
-static int usb_host_set_config(USBHostDevice *s, int config)
-{
-    int ret, first = 1;
-
-    trace_usb_host_set_config(s->bus_num, s->addr, config);
-
-    usb_host_release_interfaces(s);
-
-again:
-    ret = ioctl(s->fd, USBDEVFS_SETCONFIGURATION, &config);
-
-    DPRINTF("husb: ctrl set config %d ret %d errno %d\n", config, ret, errno);
-
-    if (ret < 0 && errno == EBUSY && first) {
-        /* happens if usb device is in use by host drivers */
-        int count = usb_linux_get_num_interfaces(s);
-        if (count > 0) {
-            DPRINTF("husb: busy -> disconnecting %d interfaces\n", count);
-            usb_host_disconnect_ifaces(s, count);
-            first = 0;
-            goto again;
-        }
-    }
-
-    if (ret < 0) {
-        return ctrl_error();
-    }
-    usb_host_claim_interfaces(s, config);
-    usb_linux_update_endp_table(s);
-    return 0;
-}
-
-static int usb_host_set_interface(USBHostDevice *s, int iface, int alt)
-{
-    struct usbdevfs_setinterface si;
-    int i, ret;
-
-    trace_usb_host_set_interface(s->bus_num, s->addr, iface, alt);
-
-    for (i = 1; i <= USB_MAX_ENDPOINTS; i++) {
-        if (is_isoc(s, USB_TOKEN_IN, i)) {
-            usb_host_stop_n_free_iso(s, USB_TOKEN_IN, i);
-        }
-        if (is_isoc(s, USB_TOKEN_OUT, i)) {
-            usb_host_stop_n_free_iso(s, USB_TOKEN_OUT, i);
-        }
-    }
-
-    if (iface >= USB_MAX_INTERFACES) {
-        return USB_RET_STALL;
-    }
-
-    si.interface  = iface;
-    si.altsetting = alt;
-    ret = ioctl(s->fd, USBDEVFS_SETINTERFACE, &si);
-
-    DPRINTF("husb: ctrl set iface %d altset %d ret %d errno %d\n",
-            iface, alt, ret, errno);
-
-    if (ret < 0) {
-        return ctrl_error();
-    }
-
-    s->dev.altsetting[iface] = alt;
-    usb_linux_update_endp_table(s);
-    return 0;
-}
-
-static int usb_host_handle_control(USBDevice *dev, USBPacket *p,
-               int request, int value, int index, int length, uint8_t *data)
-{
-    USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
-    struct usbdevfs_urb *urb;
-    AsyncURB *aurb;
-    int ret;
-
-    /*
-     * Process certain standard device requests.
-     * These are infrequent and are processed synchronously.
-     */
-
-    /* Note request is (bRequestType << 8) | bRequest */
-    trace_usb_host_req_control(s->bus_num, s->addr, request, value, index);
-
-    switch (request) {
-    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
-        return usb_host_set_address(s, value);
-
-    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
-        return usb_host_set_config(s, value & 0xff);
-
-    case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
-        return usb_host_set_interface(s, index, value);
-    }
-
-    /* The rest are asynchronous */
-
-    if (length > sizeof(dev->data_buf)) {
-        fprintf(stderr, "husb: ctrl buffer too small (%d > %zu)\n",
-                length, sizeof(dev->data_buf));
-        return USB_RET_STALL;
-    }
-
-    aurb = async_alloc(s);
-    aurb->packet = p;
-
-    /*
-     * Setup ctrl transfer.
-     *
-     * s->ctrl is laid out such that data buffer immediately follows
-     * 'req' struct which is exactly what usbdevfs expects.
-     */
-    urb = &aurb->urb;
-
-    urb->type     = USBDEVFS_URB_TYPE_CONTROL;
-    urb->endpoint = p->ep->nr;
-
-    urb->buffer        = &dev->setup_buf;
-    urb->buffer_length = length + 8;
-
-    urb->usercontext = s;
-
-    trace_usb_host_urb_submit(s->bus_num, s->addr, aurb,
-                              urb->buffer_length, aurb->more);
-    ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
-
-    DPRINTF("husb: submit ctrl. len %u aurb %p\n", urb->buffer_length, aurb);
-
-    if (ret < 0) {
-        DPRINTF("husb: submit failed. errno %d\n", errno);
-        async_free(aurb);
-
-        switch(errno) {
-        case ETIMEDOUT:
-            return USB_RET_NAK;
-        case EPIPE:
-        default:
-            return USB_RET_STALL;
-        }
-    }
-
-    return USB_RET_ASYNC;
-}
-
-static uint8_t usb_linux_get_alt_setting(USBHostDevice *s,
-    uint8_t configuration, uint8_t interface)
-{
-    char device_name[64], line[1024];
-    int alt_setting;
-
-    sprintf(device_name, "%d-%s:%d.%d", s->bus_num, s->port,
-            (int)configuration, (int)interface);
-
-    if (!usb_host_read_file(line, sizeof(line), "bAlternateSetting",
-                            device_name)) {
-        /* Assume alt 0 on error */
-        return 0;
-    }
-    if (sscanf(line, "%d", &alt_setting) != 1) {
-        /* Assume alt 0 on error */
-        return 0;
-    }
-    return alt_setting;
-}
-
-/* returns 1 on problem encountered or 0 for success */
-static int usb_linux_update_endp_table(USBHostDevice *s)
-{
-    uint8_t *descriptors;
-    uint8_t devep, type, alt_interface;
-    uint16_t raw;
-    int interface, length, i, ep, pid;
-    struct endp_data *epd;
-
-    usb_ep_init(&s->dev);
-
-    if (s->dev.configuration == 0) {
-        /* not configured yet -- leave all endpoints disabled */
-        return 0;
-    }
-
-    /* get the desired configuration, interface, and endpoint descriptors
-     * from device description */
-    descriptors = &s->descr[18];
-    length = s->descr_len - 18;
-    i = 0;
-
-    while (i < length) {
-        if (descriptors[i + 1] != USB_DT_CONFIG) {
-            fprintf(stderr, "invalid descriptor data\n");
-            return 1;
-        } else if (descriptors[i + 5] != s->dev.configuration) {
-            DPRINTF("not requested configuration %d\n", s->dev.configuration);
-            i += (descriptors[i + 3] << 8) + descriptors[i + 2];
-            continue;
-        }
-        i += descriptors[i];
-
-        if (descriptors[i + 1] != USB_DT_INTERFACE ||
-            (descriptors[i + 1] == USB_DT_INTERFACE &&
-             descriptors[i + 4] == 0)) {
-            i += descriptors[i];
-            continue;
-        }
-
-        interface = descriptors[i + 2];
-        alt_interface = usb_linux_get_alt_setting(s, s->dev.configuration,
-                                                  interface);
-
-        /* the current interface descriptor is the active interface
-         * and has endpoints */
-        if (descriptors[i + 3] != alt_interface) {
-            i += descriptors[i];
-            continue;
-        }
-
-        /* advance to the endpoints */
-        while (i < length && descriptors[i +1] != USB_DT_ENDPOINT) {
-            i += descriptors[i];
-        }
-
-        if (i >= length)
-            break;
-
-        while (i < length) {
-            if (descriptors[i + 1] != USB_DT_ENDPOINT) {
-                break;
-            }
-
-            devep = descriptors[i + 2];
-            pid = (devep & USB_DIR_IN) ? USB_TOKEN_IN : USB_TOKEN_OUT;
-            ep = devep & 0xf;
-            if (ep == 0) {
-                fprintf(stderr, "usb-linux: invalid ep descriptor, ep == 0\n");
-                return 1;
-            }
-
-            type = descriptors[i + 3] & 0x3;
-            raw = descriptors[i + 4] + (descriptors[i + 5] << 8);
-            usb_ep_set_max_packet_size(&s->dev, pid, ep, raw);
-            assert(usb_ep_get_type(&s->dev, pid, ep) ==
-                   USB_ENDPOINT_XFER_INVALID);
-            usb_ep_set_type(&s->dev, pid, ep, type);
-            usb_ep_set_ifnum(&s->dev, pid, ep, interface);
-            if (type == USB_ENDPOINT_XFER_BULK) {
-                usb_ep_set_pipeline(&s->dev, pid, ep, true);
-            }
-
-            epd = get_endp(s, pid, ep);
-            epd->halted = 0;
-
-            i += descriptors[i];
-        }
-    }
-#ifdef DEBUG
-    usb_ep_dump(&s->dev);
-#endif
-    return 0;
-}
-
-/*
- * Check if we can safely redirect a usb2 device to a usb1 virtual controller,
- * this function assumes this is safe, if:
- * 1) There are no isoc endpoints
- * 2) There are no interrupt endpoints with a max_packet_size > 64
- * Note bulk endpoints with a max_packet_size > 64 in theory also are not
- * usb1 compatible, but in practice this seems to work fine.
- */
-static int usb_linux_full_speed_compat(USBHostDevice *dev)
-{
-    int i, packet_size;
-
-    /*
-     * usb_linux_update_endp_table only registers info about ep in the current
-     * interface altsettings, so we need to parse the descriptors again.
-     */
-    for (i = 0; (i + 5) < dev->descr_len; i += dev->descr[i]) {
-        if (dev->descr[i + 1] == USB_DT_ENDPOINT) {
-            switch (dev->descr[i + 3] & 0x3) {
-            case 0x00: /* CONTROL */
-                break;
-            case 0x01: /* ISO */
-                return 0;
-            case 0x02: /* BULK */
-                break;
-            case 0x03: /* INTERRUPT */
-                packet_size = dev->descr[i + 4] + (dev->descr[i + 5] << 8);
-                if (packet_size > 64)
-                    return 0;
-                break;
-            }
-        }
-    }
-    return 1;
-}
-
-static int usb_host_open(USBHostDevice *dev, int bus_num,
-                         int addr, const char *port,
-                         const char *prod_name, int speed)
-{
-    int fd = -1, ret;
-
-    trace_usb_host_open_started(bus_num, addr);
-
-    if (dev->fd != -1) {
-        goto fail;
-    }
-
-    fd = usb_host_open_device(bus_num, addr);
-    if (fd < 0) {
-        goto fail;
-    }
-    DPRINTF("husb: opened %s\n", buf);
-
-    dev->bus_num = bus_num;
-    dev->addr = addr;
-    strcpy(dev->port, port);
-    dev->fd = fd;
-
-    /* read the device description */
-    dev->descr_len = read(fd, dev->descr, sizeof(dev->descr));
-    if (dev->descr_len <= 0) {
-        perror("husb: reading device data failed");
-        goto fail;
-    }
-
-#ifdef DEBUG
-    {
-        int x;
-        printf("=== begin dumping device descriptor data ===\n");
-        for (x = 0; x < dev->descr_len; x++) {
-            printf("%02x ", dev->descr[x]);
-        }
-        printf("\n=== end dumping device descriptor data ===\n");
-    }
-#endif
-
-
-    /* start unconfigured -- we'll wait for the guest to set a configuration */
-    if (!usb_host_claim_interfaces(dev, 0)) {
-        goto fail;
-    }
-
-    ret = usb_linux_update_endp_table(dev);
-    if (ret) {
-        goto fail;
-    }
-
-    if (speed == -1) {
-        struct usbdevfs_connectinfo ci;
-
-        ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci);
-        if (ret < 0) {
-            perror("usb_host_device_open: USBDEVFS_CONNECTINFO");
-            goto fail;
-        }
-
-        if (ci.slow) {
-            speed = USB_SPEED_LOW;
-        } else {
-            speed = USB_SPEED_HIGH;
-        }
-    }
-    dev->dev.speed = speed;
-    dev->dev.speedmask = (1 << speed);
-    if (dev->dev.speed == USB_SPEED_HIGH && usb_linux_full_speed_compat(dev)) {
-        dev->dev.speedmask |= USB_SPEED_MASK_FULL;
-    }
-
-    trace_usb_host_open_success(bus_num, addr);
-
-    if (!prod_name || prod_name[0] == '\0') {
-        snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc),
-                 "host:%d.%d", bus_num, addr);
-    } else {
-        pstrcpy(dev->dev.product_desc, sizeof(dev->dev.product_desc),
-                prod_name);
-    }
-
-    ret = usb_device_attach(&dev->dev);
-    if (ret) {
-        goto fail;
-    }
-
-    /* USB devio uses 'write' flag to check for async completions */
-    qemu_set_fd_handler(dev->fd, NULL, async_complete, dev);
-
-    return 0;
-
-fail:
-    trace_usb_host_open_failure(bus_num, addr);
-    if (dev->fd != -1) {
-        close(dev->fd);
-        dev->fd = -1;
-    }
-    return -1;
-}
-
-static int usb_host_close(USBHostDevice *dev)
-{
-    int i;
-
-    if (dev->fd == -1) {
-        return -1;
-    }
-
-    trace_usb_host_close(dev->bus_num, dev->addr);
-
-    qemu_set_fd_handler(dev->fd, NULL, NULL, NULL);
-    dev->closing = 1;
-    for (i = 1; i <= USB_MAX_ENDPOINTS; i++) {
-        if (is_isoc(dev, USB_TOKEN_IN, i)) {
-            usb_host_stop_n_free_iso(dev, USB_TOKEN_IN, i);
-        }
-        if (is_isoc(dev, USB_TOKEN_OUT, i)) {
-            usb_host_stop_n_free_iso(dev, USB_TOKEN_OUT, i);
-        }
-    }
-    async_complete(dev);
-    dev->closing = 0;
-    if (dev->dev.attached) {
-        usb_device_detach(&dev->dev);
-    }
-    usb_host_do_reset(dev);
-    close(dev->fd);
-    dev->fd = -1;
-    return 0;
-}
-
-static void usb_host_exit_notifier(struct Notifier *n, void *data)
-{
-    USBHostDevice *s = container_of(n, USBHostDevice, exit);
-
-    usb_host_release_port(s);
-    if (s->fd != -1) {
-        usb_host_do_reset(s);;
-    }
-}
-
-static int usb_host_initfn(USBDevice *dev)
-{
-    USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
-
-    dev->auto_attach = 0;
-    s->fd = -1;
-    s->hub_fd = -1;
-
-    QTAILQ_INSERT_TAIL(&hostdevs, s, next);
-    s->exit.notify = usb_host_exit_notifier;
-    qemu_add_exit_notifier(&s->exit);
-    usb_host_auto_check(NULL);
-
-    if (s->match.bus_num != 0 && s->match.port != NULL) {
-        usb_host_claim_port(s);
-    }
-    return 0;
-}
-
-static const VMStateDescription vmstate_usb_host = {
-    .name = "usb-host",
-    .unmigratable = 1,
-};
-
-static Property usb_host_dev_properties[] = {
-    DEFINE_PROP_UINT32("hostbus",  USBHostDevice, match.bus_num,    0),
-    DEFINE_PROP_UINT32("hostaddr", USBHostDevice, match.addr,       0),
-    DEFINE_PROP_STRING("hostport", USBHostDevice, match.port),
-    DEFINE_PROP_HEX32("vendorid",  USBHostDevice, match.vendor_id,  0),
-    DEFINE_PROP_HEX32("productid", USBHostDevice, match.product_id, 0),
-    DEFINE_PROP_UINT32("isobufs",  USBHostDevice, iso_urb_count,    4),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void usb_host_class_initfn(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
-
-    uc->init           = usb_host_initfn;
-    uc->product_desc   = "USB Host Device";
-    uc->cancel_packet  = usb_host_async_cancel;
-    uc->handle_data    = usb_host_handle_data;
-    uc->handle_control = usb_host_handle_control;
-    uc->handle_reset   = usb_host_handle_reset;
-    uc->handle_destroy = usb_host_handle_destroy;
-    dc->vmsd = &vmstate_usb_host;
-    dc->props = usb_host_dev_properties;
-}
-
-static TypeInfo usb_host_dev_info = {
-    .name          = "usb-host",
-    .parent        = TYPE_USB_DEVICE,
-    .instance_size = sizeof(USBHostDevice),
-    .class_init    = usb_host_class_initfn,
-};
-
-static void usb_host_register_types(void)
-{
-    type_register_static(&usb_host_dev_info);
-    usb_legacy_register("usb-host", "host", usb_host_device_open);
-}
-
-type_init(usb_host_register_types)
-
-USBDevice *usb_host_device_open(USBBus *bus, const char *devname)
-{
-    struct USBAutoFilter filter;
-    USBDevice *dev;
-    char *p;
-
-    dev = usb_create(bus, "usb-host");
-
-    if (strstr(devname, "auto:")) {
-        if (parse_filter(devname, &filter) < 0) {
-            goto fail;
-        }
-    } else {
-        if ((p = strchr(devname, '.'))) {
-            filter.bus_num    = strtoul(devname, NULL, 0);
-            filter.addr       = strtoul(p + 1, NULL, 0);
-            filter.vendor_id  = 0;
-            filter.product_id = 0;
-        } else if ((p = strchr(devname, ':'))) {
-            filter.bus_num    = 0;
-            filter.addr       = 0;
-            filter.vendor_id  = strtoul(devname, NULL, 16);
-            filter.product_id = strtoul(p + 1, NULL, 16);
-        } else {
-            goto fail;
-        }
-    }
-
-    qdev_prop_set_uint32(&dev->qdev, "hostbus",   filter.bus_num);
-    qdev_prop_set_uint32(&dev->qdev, "hostaddr",  filter.addr);
-    qdev_prop_set_uint32(&dev->qdev, "vendorid",  filter.vendor_id);
-    qdev_prop_set_uint32(&dev->qdev, "productid", filter.product_id);
-    qdev_init_nofail(&dev->qdev);
-    return dev;
-
-fail:
-    qdev_free(&dev->qdev);
-    return NULL;
-}
-
-int usb_host_device_close(const char *devname)
-{
-#if 0
-    char product_name[PRODUCT_NAME_SZ];
-    int bus_num, addr;
-    USBHostDevice *s;
-
-    if (strstr(devname, "auto:")) {
-        return usb_host_auto_del(devname);
-    }
-    if (usb_host_find_device(&bus_num, &addr, product_name,
-                                    sizeof(product_name), devname) < 0) {
-        return -1;
-    }
-    s = hostdev_find(bus_num, addr);
-    if (s) {
-        usb_device_delete_addr(s->bus_num, s->dev.addr);
-        return 0;
-    }
-#endif
-
-    return -1;
-}
-
-/*
- * Read sys file-system device file
- *
- * @line address of buffer to put file contents in
- * @line_size size of line
- * @device_file path to device file (printf format string)
- * @device_name device being opened (inserted into device_file)
- *
- * @return 0 failed, 1 succeeded ('line' contains data)
- */
-static int usb_host_read_file(char *line, size_t line_size,
-                              const char *device_file, const char *device_name)
-{
-    FILE *f;
-    int ret = 0;
-    char filename[PATH_MAX];
-
-    snprintf(filename, PATH_MAX, "/sys/bus/usb/devices/%s/%s", device_name,
-             device_file);
-    f = fopen(filename, "r");
-    if (f) {
-        ret = fgets(line, line_size, f) != NULL;
-        fclose(f);
-    }
-
-    return ret;
-}
-
-/*
- * Use /sys/bus/usb/devices/ directory to determine host's USB
- * devices.
- *
- * This code is based on Robert Schiele's original patches posted to
- * the Novell bug-tracker https://bugzilla.novell.com/show_bug.cgi?id=241950
- */
-static int usb_host_scan(void *opaque, USBScanFunc *func)
-{
-    DIR *dir = NULL;
-    char line[1024];
-    int bus_num, addr, speed, class_id, product_id, vendor_id;
-    int ret = 0;
-    char port[MAX_PORTLEN];
-    char product_name[512];
-    struct dirent *de;
-
-    dir = opendir("/sys/bus/usb/devices");
-    if (!dir) {
-        perror("husb: opendir /sys/bus/usb/devices");
-        fprintf(stderr, "husb: please make sure sysfs is mounted at /sys\n");
-        goto the_end;
-    }
-
-    while ((de = readdir(dir))) {
-        if (de->d_name[0] != '.' && !strchr(de->d_name, ':')) {
-            if (sscanf(de->d_name, "%d-%7[0-9.]", &bus_num, port) < 2) {
-                continue;
-            }
-
-            if (!usb_host_read_file(line, sizeof(line), "devnum", de->d_name)) {
-                goto the_end;
-            }
-            if (sscanf(line, "%d", &addr) != 1) {
-                goto the_end;
-            }
-            if (!usb_host_read_file(line, sizeof(line), "bDeviceClass",
-                                    de->d_name)) {
-                goto the_end;
-            }
-            if (sscanf(line, "%x", &class_id) != 1) {
-                goto the_end;
-            }
-
-            if (!usb_host_read_file(line, sizeof(line), "idVendor",
-                                    de->d_name)) {
-                goto the_end;
-            }
-            if (sscanf(line, "%x", &vendor_id) != 1) {
-                goto the_end;
-            }
-            if (!usb_host_read_file(line, sizeof(line), "idProduct",
-                                    de->d_name)) {
-                goto the_end;
-            }
-            if (sscanf(line, "%x", &product_id) != 1) {
-                goto the_end;
-            }
-            if (!usb_host_read_file(line, sizeof(line), "product",
-                                    de->d_name)) {
-                *product_name = 0;
-            } else {
-                if (strlen(line) > 0) {
-                    line[strlen(line) - 1] = '\0';
-                }
-                pstrcpy(product_name, sizeof(product_name), line);
-            }
-
-            if (!usb_host_read_file(line, sizeof(line), "speed", de->d_name)) {
-                goto the_end;
-            }
-            if (!strcmp(line, "5000\n")) {
-                speed = USB_SPEED_SUPER;
-            } else if (!strcmp(line, "480\n")) {
-                speed = USB_SPEED_HIGH;
-            } else if (!strcmp(line, "1.5\n")) {
-                speed = USB_SPEED_LOW;
-            } else {
-                speed = USB_SPEED_FULL;
-            }
-
-            ret = func(opaque, bus_num, addr, port, class_id, vendor_id,
-                       product_id, product_name, speed);
-            if (ret) {
-                goto the_end;
-            }
-        }
-    }
- the_end:
-    if (dir) {
-        closedir(dir);
-    }
-    return ret;
-}
-
-static QEMUTimer *usb_auto_timer;
-
-static int usb_host_auto_scan(void *opaque, int bus_num,
-                              int addr, const char *port,
-                              int class_id, int vendor_id, int product_id,
-                              const char *product_name, int speed)
-{
-    struct USBAutoFilter *f;
-    struct USBHostDevice *s;
-
-    /* Ignore hubs */
-    if (class_id == 9)
-        return 0;
-
-    QTAILQ_FOREACH(s, &hostdevs, next) {
-        f = &s->match;
-
-        if (f->bus_num > 0 && f->bus_num != bus_num) {
-            continue;
-        }
-        if (f->addr > 0 && f->addr != addr) {
-            continue;
-        }
-        if (f->port != NULL && (port == NULL || strcmp(f->port, port) != 0)) {
-            continue;
-        }
-
-        if (f->vendor_id > 0 && f->vendor_id != vendor_id) {
-            continue;
-        }
-
-        if (f->product_id > 0 && f->product_id != product_id) {
-            continue;
-        }
-        /* We got a match */
-        s->seen++;
-        if (s->errcount >= 3) {
-            return 0;
-        }
-
-        /* Already attached ? */
-        if (s->fd != -1) {
-            return 0;
-        }
-        DPRINTF("husb: auto open: bus_num %d addr %d\n", bus_num, addr);
-
-        if (usb_host_open(s, bus_num, addr, port, product_name, speed) < 0) {
-            s->errcount++;
-        }
-        break;
-    }
-
-    return 0;
-}
-
-static void usb_host_auto_check(void *unused)
-{
-    struct USBHostDevice *s;
-    int unconnected = 0;
-
-    usb_host_scan(NULL, usb_host_auto_scan);
-
-    QTAILQ_FOREACH(s, &hostdevs, next) {
-        if (s->fd == -1) {
-            unconnected++;
-        }
-        if (s->seen == 0) {
-            s->errcount = 0;
-        }
-        s->seen = 0;
-    }
-
-    if (unconnected == 0) {
-        /* nothing to watch */
-        if (usb_auto_timer) {
-            qemu_del_timer(usb_auto_timer);
-            trace_usb_host_auto_scan_disabled();
-        }
-        return;
-    }
-
-    if (!usb_auto_timer) {
-        usb_auto_timer = qemu_new_timer_ms(rt_clock, usb_host_auto_check, NULL);
-        if (!usb_auto_timer) {
-            return;
-        }
-        trace_usb_host_auto_scan_enabled();
-    }
-    qemu_mod_timer(usb_auto_timer, qemu_get_clock_ms(rt_clock) + 2000);
-}
-
-/*
- * Autoconnect filter
- * Format:
- *    auto:bus:dev[:vid:pid]
- *    auto:bus.dev[:vid:pid]
- *
- *    bus  - bus number    (dec, * means any)
- *    dev  - device number (dec, * means any)
- *    vid  - vendor id     (hex, * means any)
- *    pid  - product id    (hex, * means any)
- *
- *    See 'lsusb' output.
- */
-static int parse_filter(const char *spec, struct USBAutoFilter *f)
-{
-    enum { BUS, DEV, VID, PID, DONE };
-    const char *p = spec;
-    int i;
-
-    f->bus_num    = 0;
-    f->addr       = 0;
-    f->vendor_id  = 0;
-    f->product_id = 0;
-
-    for (i = BUS; i < DONE; i++) {
-        p = strpbrk(p, ":.");
-        if (!p) {
-            break;
-        }
-        p++;
-
-        if (*p == '*') {
-            continue;
-        }
-        switch(i) {
-        case BUS: f->bus_num = strtol(p, NULL, 10);    break;
-        case DEV: f->addr    = strtol(p, NULL, 10);    break;
-        case VID: f->vendor_id  = strtol(p, NULL, 16); break;
-        case PID: f->product_id = strtol(p, NULL, 16); break;
-        }
-    }
-
-    if (i < DEV) {
-        fprintf(stderr, "husb: invalid auto filter spec %s\n", spec);
-        return -1;
-    }
-
-    return 0;
-}
-
-/**********************/
-/* USB host device info */
-
-struct usb_class_info {
-    int class;
-    const char *class_name;
-};
-
-static const struct usb_class_info usb_class_info[] = {
-    { USB_CLASS_AUDIO, "Audio"},
-    { USB_CLASS_COMM, "Communication"},
-    { USB_CLASS_HID, "HID"},
-    { USB_CLASS_HUB, "Hub" },
-    { USB_CLASS_PHYSICAL, "Physical" },
-    { USB_CLASS_PRINTER, "Printer" },
-    { USB_CLASS_MASS_STORAGE, "Storage" },
-    { USB_CLASS_CDC_DATA, "Data" },
-    { USB_CLASS_APP_SPEC, "Application Specific" },
-    { USB_CLASS_VENDOR_SPEC, "Vendor Specific" },
-    { USB_CLASS_STILL_IMAGE, "Still Image" },
-    { USB_CLASS_CSCID, "Smart Card" },
-    { USB_CLASS_CONTENT_SEC, "Content Security" },
-    { -1, NULL }
-};
-
-static const char *usb_class_str(uint8_t class)
-{
-    const struct usb_class_info *p;
-    for(p = usb_class_info; p->class != -1; p++) {
-        if (p->class == class) {
-            break;
-        }
-    }
-    return p->class_name;
-}
-
-static void usb_info_device(Monitor *mon, int bus_num,
-                            int addr, const char *port,
-                            int class_id, int vendor_id, int product_id,
-                            const char *product_name,
-                            int speed)
-{
-    const char *class_str, *speed_str;
-
-    switch(speed) {
-    case USB_SPEED_LOW:
-        speed_str = "1.5";
-        break;
-    case USB_SPEED_FULL:
-        speed_str = "12";
-        break;
-    case USB_SPEED_HIGH:
-        speed_str = "480";
-        break;
-    case USB_SPEED_SUPER:
-        speed_str = "5000";
-        break;
-    default:
-        speed_str = "?";
-        break;
-    }
-
-    monitor_printf(mon, "  Bus %d, Addr %d, Port %s, Speed %s Mb/s\n",
-                   bus_num, addr, port, speed_str);
-    class_str = usb_class_str(class_id);
-    if (class_str) {
-        monitor_printf(mon, "    %s:", class_str);
-    } else {
-        monitor_printf(mon, "    Class %02x:", class_id);
-    }
-    monitor_printf(mon, " USB device %04x:%04x", vendor_id, product_id);
-    if (product_name[0] != '\0') {
-        monitor_printf(mon, ", %s", product_name);
-    }
-    monitor_printf(mon, "\n");
-}
-
-static int usb_host_info_device(void *opaque, int bus_num, int addr,
-                                const char *path, int class_id,
-                                int vendor_id, int product_id,
-                                const char *product_name,
-                                int speed)
-{
-    Monitor *mon = opaque;
-
-    usb_info_device(mon, bus_num, addr, path, class_id, vendor_id, product_id,
-                    product_name, speed);
-    return 0;
-}
-
-static void dec2str(int val, char *str, size_t size)
-{
-    if (val == 0) {
-        snprintf(str, size, "*");
-    } else {
-        snprintf(str, size, "%d", val);
-    }
-}
-
-static void hex2str(int val, char *str, size_t size)
-{
-    if (val == 0) {
-        snprintf(str, size, "*");
-    } else {
-        snprintf(str, size, "%04x", val);
-    }
-}
-
-void usb_host_info(Monitor *mon)
-{
-    struct USBAutoFilter *f;
-    struct USBHostDevice *s;
-
-    usb_host_scan(mon, usb_host_info_device);
-
-    if (QTAILQ_EMPTY(&hostdevs)) {
-        return;
-    }
-
-    monitor_printf(mon, "  Auto filters:\n");
-    QTAILQ_FOREACH(s, &hostdevs, next) {
-        char bus[10], addr[10], vid[10], pid[10];
-        f = &s->match;
-        dec2str(f->bus_num, bus, sizeof(bus));
-        dec2str(f->addr, addr, sizeof(addr));
-        hex2str(f->vendor_id, vid, sizeof(vid));
-        hex2str(f->product_id, pid, sizeof(pid));
-        monitor_printf(mon, "    Bus %s, Addr %s, Port %s, ID %s:%s\n",
-                       bus, addr, f->port ? f->port : "*", vid, pid);
-    }
-}
diff --git a/usb-redir.c b/usb-redir.c
deleted file mode 100644
index 8e9f175..0000000
--- a/usb-redir.c
+++ /dev/null
@@ -1,1485 +0,0 @@
-/*
- * USB redirector usb-guest
- *
- * Copyright (c) 2011 Red Hat, Inc.
- *
- * Red Hat Authors:
- * Hans de Goede <hdegoede at redhat.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "qemu-common.h"
-#include "qemu-timer.h"
-#include "monitor.h"
-#include "sysemu.h"
-
-#include <dirent.h>
-#include <sys/ioctl.h>
-#include <signal.h>
-#include <usbredirparser.h>
-#include <usbredirfilter.h>
-
-#include "hw/usb.h"
-
-#define MAX_ENDPOINTS 32
-#define EP2I(ep_address) (((ep_address & 0x80) >> 3) | (ep_address & 0x0f))
-#define I2EP(i) (((i & 0x10) << 3) | (i & 0x0f))
-
-typedef struct AsyncURB AsyncURB;
-typedef struct USBRedirDevice USBRedirDevice;
-
-/* Struct to hold buffered packets (iso or int input packets) */
-struct buf_packet {
-    uint8_t *data;
-    int len;
-    int status;
-    QTAILQ_ENTRY(buf_packet)next;
-};
-
-struct endp_data {
-    uint8_t type;
-    uint8_t interval;
-    uint8_t interface; /* bInterfaceNumber this ep belongs to */
-    uint8_t iso_started;
-    uint8_t iso_error; /* For reporting iso errors to the HC */
-    uint8_t interrupt_started;
-    uint8_t interrupt_error;
-    uint8_t bufpq_prefilled;
-    uint8_t bufpq_dropping_packets;
-    QTAILQ_HEAD(, buf_packet) bufpq;
-    int bufpq_size;
-    int bufpq_target_size;
-};
-
-struct USBRedirDevice {
-    USBDevice dev;
-    /* Properties */
-    CharDriverState *cs;
-    uint8_t debug;
-    char *filter_str;
-    /* Data passed from chardev the fd_read cb to the usbredirparser read cb */
-    const uint8_t *read_buf;
-    int read_buf_size;
-    /* For async handling of open/close */
-    QEMUBH *open_close_bh;
-    /* To delay the usb attach in case of quick chardev close + open */
-    QEMUTimer *attach_timer;
-    int64_t next_attach_time;
-    struct usbredirparser *parser;
-    struct endp_data endpoint[MAX_ENDPOINTS];
-    uint32_t packet_id;
-    QTAILQ_HEAD(, AsyncURB) asyncq;
-    /* Data for device filtering */
-    struct usb_redir_device_connect_header device_info;
-    struct usb_redir_interface_info_header interface_info;
-    struct usbredirfilter_rule *filter_rules;
-    int filter_rules_count;
-};
-
-struct AsyncURB {
-    USBRedirDevice *dev;
-    USBPacket *packet;
-    uint32_t packet_id;
-    int get;
-    union {
-        struct usb_redir_control_packet_header control_packet;
-        struct usb_redir_bulk_packet_header bulk_packet;
-        struct usb_redir_interrupt_packet_header interrupt_packet;
-    };
-    QTAILQ_ENTRY(AsyncURB)next;
-};
-
-static void usbredir_hello(void *priv, struct usb_redir_hello_header *h);
-static void usbredir_device_connect(void *priv,
-    struct usb_redir_device_connect_header *device_connect);
-static void usbredir_device_disconnect(void *priv);
-static void usbredir_interface_info(void *priv,
-    struct usb_redir_interface_info_header *interface_info);
-static void usbredir_ep_info(void *priv,
-    struct usb_redir_ep_info_header *ep_info);
-static void usbredir_configuration_status(void *priv, uint32_t id,
-    struct usb_redir_configuration_status_header *configuration_status);
-static void usbredir_alt_setting_status(void *priv, uint32_t id,
-    struct usb_redir_alt_setting_status_header *alt_setting_status);
-static void usbredir_iso_stream_status(void *priv, uint32_t id,
-    struct usb_redir_iso_stream_status_header *iso_stream_status);
-static void usbredir_interrupt_receiving_status(void *priv, uint32_t id,
-    struct usb_redir_interrupt_receiving_status_header
-    *interrupt_receiving_status);
-static void usbredir_bulk_streams_status(void *priv, uint32_t id,
-    struct usb_redir_bulk_streams_status_header *bulk_streams_status);
-static void usbredir_control_packet(void *priv, uint32_t id,
-    struct usb_redir_control_packet_header *control_packet,
-    uint8_t *data, int data_len);
-static void usbredir_bulk_packet(void *priv, uint32_t id,
-    struct usb_redir_bulk_packet_header *bulk_packet,
-    uint8_t *data, int data_len);
-static void usbredir_iso_packet(void *priv, uint32_t id,
-    struct usb_redir_iso_packet_header *iso_packet,
-    uint8_t *data, int data_len);
-static void usbredir_interrupt_packet(void *priv, uint32_t id,
-    struct usb_redir_interrupt_packet_header *interrupt_header,
-    uint8_t *data, int data_len);
-
-static int usbredir_handle_status(USBRedirDevice *dev,
-                                       int status, int actual_len);
-
-#define VERSION "qemu usb-redir guest " QEMU_VERSION
-
-/*
- * Logging stuff
- */
-
-#define ERROR(...) \
-    do { \
-        if (dev->debug >= usbredirparser_error) { \
-            error_report("usb-redir error: " __VA_ARGS__); \
-        } \
-    } while (0)
-#define WARNING(...) \
-    do { \
-        if (dev->debug >= usbredirparser_warning) { \
-            error_report("usb-redir warning: " __VA_ARGS__); \
-        } \
-    } while (0)
-#define INFO(...) \
-    do { \
-        if (dev->debug >= usbredirparser_info) { \
-            error_report("usb-redir: " __VA_ARGS__); \
-        } \
-    } while (0)
-#define DPRINTF(...) \
-    do { \
-        if (dev->debug >= usbredirparser_debug) { \
-            error_report("usb-redir: " __VA_ARGS__); \
-        } \
-    } while (0)
-#define DPRINTF2(...) \
-    do { \
-        if (dev->debug >= usbredirparser_debug_data) { \
-            error_report("usb-redir: " __VA_ARGS__); \
-        } \
-    } while (0)
-
-static void usbredir_log(void *priv, int level, const char *msg)
-{
-    USBRedirDevice *dev = priv;
-
-    if (dev->debug < level) {
-        return;
-    }
-
-    error_report("%s", msg);
-}
-
-static void usbredir_log_data(USBRedirDevice *dev, const char *desc,
-    const uint8_t *data, int len)
-{
-    int i, j, n;
-
-    if (dev->debug < usbredirparser_debug_data) {
-        return;
-    }
-
-    for (i = 0; i < len; i += j) {
-        char buf[128];
-
-        n = sprintf(buf, "%s", desc);
-        for (j = 0; j < 8 && i + j < len; j++) {
-            n += sprintf(buf + n, " %02X", data[i + j]);
-        }
-        error_report("%s", buf);
-    }
-}
-
-/*
- * usbredirparser io functions
- */
-
-static int usbredir_read(void *priv, uint8_t *data, int count)
-{
-    USBRedirDevice *dev = priv;
-
-    if (dev->read_buf_size < count) {
-        count = dev->read_buf_size;
-    }
-
-    memcpy(data, dev->read_buf, count);
-
-    dev->read_buf_size -= count;
-    if (dev->read_buf_size) {
-        dev->read_buf += count;
-    } else {
-        dev->read_buf = NULL;
-    }
-
-    return count;
-}
-
-static int usbredir_write(void *priv, uint8_t *data, int count)
-{
-    USBRedirDevice *dev = priv;
-
-    if (!dev->cs->opened) {
-        return 0;
-    }
-
-    return qemu_chr_fe_write(dev->cs, data, count);
-}
-
-/*
- * Async and buffered packets helpers
- */
-
-static AsyncURB *async_alloc(USBRedirDevice *dev, USBPacket *p)
-{
-    AsyncURB *aurb = (AsyncURB *) g_malloc0(sizeof(AsyncURB));
-    aurb->dev = dev;
-    aurb->packet = p;
-    aurb->packet_id = dev->packet_id;
-    QTAILQ_INSERT_TAIL(&dev->asyncq, aurb, next);
-    dev->packet_id++;
-
-    return aurb;
-}
-
-static void async_free(USBRedirDevice *dev, AsyncURB *aurb)
-{
-    QTAILQ_REMOVE(&dev->asyncq, aurb, next);
-    g_free(aurb);
-}
-
-static AsyncURB *async_find(USBRedirDevice *dev, uint32_t packet_id)
-{
-    AsyncURB *aurb;
-
-    QTAILQ_FOREACH(aurb, &dev->asyncq, next) {
-        if (aurb->packet_id == packet_id) {
-            return aurb;
-        }
-    }
-    ERROR("could not find async urb for packet_id %u\n", packet_id);
-    return NULL;
-}
-
-static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p)
-{
-    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
-    AsyncURB *aurb;
-
-    QTAILQ_FOREACH(aurb, &dev->asyncq, next) {
-        if (p != aurb->packet) {
-            continue;
-        }
-
-        DPRINTF("async cancel id %u\n", aurb->packet_id);
-        usbredirparser_send_cancel_data_packet(dev->parser, aurb->packet_id);
-        usbredirparser_do_write(dev->parser);
-
-        /* Mark it as dead */
-        aurb->packet = NULL;
-        break;
-    }
-}
-
-static void bufp_alloc(USBRedirDevice *dev,
-    uint8_t *data, int len, int status, uint8_t ep)
-{
-    struct buf_packet *bufp;
-
-    if (!dev->endpoint[EP2I(ep)].bufpq_dropping_packets &&
-        dev->endpoint[EP2I(ep)].bufpq_size >
-            2 * dev->endpoint[EP2I(ep)].bufpq_target_size) {
-        DPRINTF("bufpq overflow, dropping packets ep %02X\n", ep);
-        dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 1;
-    }
-    /* Since we're interupting the stream anyways, drop enough packets to get
-       back to our target buffer size */
-    if (dev->endpoint[EP2I(ep)].bufpq_dropping_packets) {
-        if (dev->endpoint[EP2I(ep)].bufpq_size >
-                dev->endpoint[EP2I(ep)].bufpq_target_size) {
-            free(data);
-            return;
-        }
-        dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0;
-    }
-
-    bufp = g_malloc(sizeof(struct buf_packet));
-    bufp->data   = data;
-    bufp->len    = len;
-    bufp->status = status;
-    QTAILQ_INSERT_TAIL(&dev->endpoint[EP2I(ep)].bufpq, bufp, next);
-    dev->endpoint[EP2I(ep)].bufpq_size++;
-}
-
-static void bufp_free(USBRedirDevice *dev, struct buf_packet *bufp,
-    uint8_t ep)
-{
-    QTAILQ_REMOVE(&dev->endpoint[EP2I(ep)].bufpq, bufp, next);
-    dev->endpoint[EP2I(ep)].bufpq_size--;
-    free(bufp->data);
-    g_free(bufp);
-}
-
-static void usbredir_free_bufpq(USBRedirDevice *dev, uint8_t ep)
-{
-    struct buf_packet *buf, *buf_next;
-
-    QTAILQ_FOREACH_SAFE(buf, &dev->endpoint[EP2I(ep)].bufpq, next, buf_next) {
-        bufp_free(dev, buf, ep);
-    }
-}
-
-/*
- * USBDevice callbacks
- */
-
-static void usbredir_handle_reset(USBDevice *udev)
-{
-    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
-
-    DPRINTF("reset device\n");
-    usbredirparser_send_reset(dev->parser);
-    usbredirparser_do_write(dev->parser);
-}
-
-static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
-                                     uint8_t ep)
-{
-    int status, len;
-    if (!dev->endpoint[EP2I(ep)].iso_started &&
-            !dev->endpoint[EP2I(ep)].iso_error) {
-        struct usb_redir_start_iso_stream_header start_iso = {
-            .endpoint = ep,
-        };
-        int pkts_per_sec;
-
-        if (dev->dev.speed == USB_SPEED_HIGH) {
-            pkts_per_sec = 8000 / dev->endpoint[EP2I(ep)].interval;
-        } else {
-            pkts_per_sec = 1000 / dev->endpoint[EP2I(ep)].interval;
-        }
-        /* Testing has shown that we need circa 60 ms buffer */
-        dev->endpoint[EP2I(ep)].bufpq_target_size = (pkts_per_sec * 60) / 1000;
-
-        /* Aim for approx 100 interrupts / second on the client to
-           balance latency and interrupt load */
-        start_iso.pkts_per_urb = pkts_per_sec / 100;
-        if (start_iso.pkts_per_urb < 1) {
-            start_iso.pkts_per_urb = 1;
-        } else if (start_iso.pkts_per_urb > 32) {
-            start_iso.pkts_per_urb = 32;
-        }
-
-        start_iso.no_urbs = (dev->endpoint[EP2I(ep)].bufpq_target_size +
-                             start_iso.pkts_per_urb - 1) /
-                            start_iso.pkts_per_urb;
-        /* Output endpoints pre-fill only 1/2 of the packets, keeping the rest
-           as overflow buffer. Also see the usbredir protocol documentation */
-        if (!(ep & USB_DIR_IN)) {
-            start_iso.no_urbs *= 2;
-        }
-        if (start_iso.no_urbs > 16) {
-            start_iso.no_urbs = 16;
-        }
-
-        /* No id, we look at the ep when receiving a status back */
-        usbredirparser_send_start_iso_stream(dev->parser, 0, &start_iso);
-        usbredirparser_do_write(dev->parser);
-        DPRINTF("iso stream started pkts/sec %d pkts/urb %d urbs %d ep %02X\n",
-                pkts_per_sec, start_iso.pkts_per_urb, start_iso.no_urbs, ep);
-        dev->endpoint[EP2I(ep)].iso_started = 1;
-        dev->endpoint[EP2I(ep)].bufpq_prefilled = 0;
-        dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0;
-    }
-
-    if (ep & USB_DIR_IN) {
-        struct buf_packet *isop;
-
-        if (dev->endpoint[EP2I(ep)].iso_started &&
-                !dev->endpoint[EP2I(ep)].bufpq_prefilled) {
-            if (dev->endpoint[EP2I(ep)].bufpq_size <
-                    dev->endpoint[EP2I(ep)].bufpq_target_size) {
-                return usbredir_handle_status(dev, 0, 0);
-            }
-            dev->endpoint[EP2I(ep)].bufpq_prefilled = 1;
-        }
-
-        isop = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq);
-        if (isop == NULL) {
-            DPRINTF("iso-token-in ep %02X, no isop, iso_error: %d\n",
-                    ep, dev->endpoint[EP2I(ep)].iso_error);
-            /* Re-fill the buffer */
-            dev->endpoint[EP2I(ep)].bufpq_prefilled = 0;
-            /* Check iso_error for stream errors, otherwise its an underrun */
-            status = dev->endpoint[EP2I(ep)].iso_error;
-            dev->endpoint[EP2I(ep)].iso_error = 0;
-            return status ? USB_RET_IOERROR : 0;
-        }
-        DPRINTF2("iso-token-in ep %02X status %d len %d queue-size: %d\n", ep,
-                 isop->status, isop->len, dev->endpoint[EP2I(ep)].bufpq_size);
-
-        status = isop->status;
-        if (status != usb_redir_success) {
-            bufp_free(dev, isop, ep);
-            return USB_RET_IOERROR;
-        }
-
-        len = isop->len;
-        if (len > p->iov.size) {
-            ERROR("received iso data is larger then packet ep %02X (%d > %d)\n",
-                  ep, len, (int)p->iov.size);
-            bufp_free(dev, isop, ep);
-            return USB_RET_BABBLE;
-        }
-        usb_packet_copy(p, isop->data, len);
-        bufp_free(dev, isop, ep);
-        return len;
-    } else {
-        /* If the stream was not started because of a pending error don't
-           send the packet to the usb-host */
-        if (dev->endpoint[EP2I(ep)].iso_started) {
-            struct usb_redir_iso_packet_header iso_packet = {
-                .endpoint = ep,
-                .length = p->iov.size
-            };
-            uint8_t buf[p->iov.size];
-            /* No id, we look at the ep when receiving a status back */
-            usb_packet_copy(p, buf, p->iov.size);
-            usbredirparser_send_iso_packet(dev->parser, 0, &iso_packet,
-                                           buf, p->iov.size);
-            usbredirparser_do_write(dev->parser);
-        }
-        status = dev->endpoint[EP2I(ep)].iso_error;
-        dev->endpoint[EP2I(ep)].iso_error = 0;
-        DPRINTF2("iso-token-out ep %02X status %d len %zd\n", ep, status,
-                 p->iov.size);
-        return usbredir_handle_status(dev, status, p->iov.size);
-    }
-}
-
-static void usbredir_stop_iso_stream(USBRedirDevice *dev, uint8_t ep)
-{
-    struct usb_redir_stop_iso_stream_header stop_iso_stream = {
-        .endpoint = ep
-    };
-    if (dev->endpoint[EP2I(ep)].iso_started) {
-        usbredirparser_send_stop_iso_stream(dev->parser, 0, &stop_iso_stream);
-        DPRINTF("iso stream stopped ep %02X\n", ep);
-        dev->endpoint[EP2I(ep)].iso_started = 0;
-    }
-    dev->endpoint[EP2I(ep)].iso_error = 0;
-    usbredir_free_bufpq(dev, ep);
-}
-
-static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,
-                                      uint8_t ep)
-{
-    AsyncURB *aurb = async_alloc(dev, p);
-    struct usb_redir_bulk_packet_header bulk_packet;
-
-    DPRINTF("bulk-out ep %02X len %zd id %u\n", ep,
-            p->iov.size, aurb->packet_id);
-
-    bulk_packet.endpoint  = ep;
-    bulk_packet.length    = p->iov.size;
-    bulk_packet.stream_id = 0;
-    aurb->bulk_packet = bulk_packet;
-
-    if (ep & USB_DIR_IN) {
-        usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id,
-                                        &bulk_packet, NULL, 0);
-    } else {
-        uint8_t buf[p->iov.size];
-        usb_packet_copy(p, buf, p->iov.size);
-        usbredir_log_data(dev, "bulk data out:", buf, p->iov.size);
-        usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id,
-                                        &bulk_packet, buf, p->iov.size);
-    }
-    usbredirparser_do_write(dev->parser);
-    return USB_RET_ASYNC;
-}
-
-static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
-                                           USBPacket *p, uint8_t ep)
-{
-    if (ep & USB_DIR_IN) {
-        /* Input interrupt endpoint, buffered packet input */
-        struct buf_packet *intp;
-        int status, len;
-
-        if (!dev->endpoint[EP2I(ep)].interrupt_started &&
-                !dev->endpoint[EP2I(ep)].interrupt_error) {
-            struct usb_redir_start_interrupt_receiving_header start_int = {
-                .endpoint = ep,
-            };
-            /* No id, we look at the ep when receiving a status back */
-            usbredirparser_send_start_interrupt_receiving(dev->parser, 0,
-                                                          &start_int);
-            usbredirparser_do_write(dev->parser);
-            DPRINTF("interrupt recv started ep %02X\n", ep);
-            dev->endpoint[EP2I(ep)].interrupt_started = 1;
-            /* We don't really want to drop interrupt packets ever, but
-               having some upper limit to how much we buffer is good. */
-            dev->endpoint[EP2I(ep)].bufpq_target_size = 1000;
-            dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0;
-        }
-
-        intp = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq);
-        if (intp == NULL) {
-            DPRINTF2("interrupt-token-in ep %02X, no intp\n", ep);
-            /* Check interrupt_error for stream errors */
-            status = dev->endpoint[EP2I(ep)].interrupt_error;
-            dev->endpoint[EP2I(ep)].interrupt_error = 0;
-            if (status) {
-                return usbredir_handle_status(dev, status, 0);
-            }
-            return USB_RET_NAK;
-        }
-        DPRINTF("interrupt-token-in ep %02X status %d len %d\n", ep,
-                intp->status, intp->len);
-
-        status = intp->status;
-        if (status != usb_redir_success) {
-            bufp_free(dev, intp, ep);
-            return usbredir_handle_status(dev, status, 0);
-        }
-
-        len = intp->len;
-        if (len > p->iov.size) {
-            ERROR("received int data is larger then packet ep %02X\n", ep);
-            bufp_free(dev, intp, ep);
-            return USB_RET_BABBLE;
-        }
-        usb_packet_copy(p, intp->data, len);
-        bufp_free(dev, intp, ep);
-        return len;
-    } else {
-        /* Output interrupt endpoint, normal async operation */
-        AsyncURB *aurb = async_alloc(dev, p);
-        struct usb_redir_interrupt_packet_header interrupt_packet;
-        uint8_t buf[p->iov.size];
-
-        DPRINTF("interrupt-out ep %02X len %zd id %u\n", ep, p->iov.size,
-                aurb->packet_id);
-
-        interrupt_packet.endpoint  = ep;
-        interrupt_packet.length    = p->iov.size;
-        aurb->interrupt_packet     = interrupt_packet;
-
-        usb_packet_copy(p, buf, p->iov.size);
-        usbredir_log_data(dev, "interrupt data out:", buf, p->iov.size);
-        usbredirparser_send_interrupt_packet(dev->parser, aurb->packet_id,
-                                        &interrupt_packet, buf, p->iov.size);
-        usbredirparser_do_write(dev->parser);
-        return USB_RET_ASYNC;
-    }
-}
-
-static void usbredir_stop_interrupt_receiving(USBRedirDevice *dev,
-    uint8_t ep)
-{
-    struct usb_redir_stop_interrupt_receiving_header stop_interrupt_recv = {
-        .endpoint = ep
-    };
-    if (dev->endpoint[EP2I(ep)].interrupt_started) {
-        usbredirparser_send_stop_interrupt_receiving(dev->parser, 0,
-                                                     &stop_interrupt_recv);
-        DPRINTF("interrupt recv stopped ep %02X\n", ep);
-        dev->endpoint[EP2I(ep)].interrupt_started = 0;
-    }
-    dev->endpoint[EP2I(ep)].interrupt_error = 0;
-    usbredir_free_bufpq(dev, ep);
-}
-
-static int usbredir_handle_data(USBDevice *udev, USBPacket *p)
-{
-    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
-    uint8_t ep;
-
-    ep = p->ep->nr;
-    if (p->pid == USB_TOKEN_IN) {
-        ep |= USB_DIR_IN;
-    }
-
-    switch (dev->endpoint[EP2I(ep)].type) {
-    case USB_ENDPOINT_XFER_CONTROL:
-        ERROR("handle_data called for control transfer on ep %02X\n", ep);
-        return USB_RET_NAK;
-    case USB_ENDPOINT_XFER_ISOC:
-        return usbredir_handle_iso_data(dev, p, ep);
-    case USB_ENDPOINT_XFER_BULK:
-        return usbredir_handle_bulk_data(dev, p, ep);
-    case USB_ENDPOINT_XFER_INT:
-        return usbredir_handle_interrupt_data(dev, p, ep);
-    default:
-        ERROR("handle_data ep %02X has unknown type %d\n", ep,
-              dev->endpoint[EP2I(ep)].type);
-        return USB_RET_NAK;
-    }
-}
-
-static int usbredir_set_config(USBRedirDevice *dev, USBPacket *p,
-                                int config)
-{
-    struct usb_redir_set_configuration_header set_config;
-    AsyncURB *aurb = async_alloc(dev, p);
-    int i;
-
-    DPRINTF("set config %d id %u\n", config, aurb->packet_id);
-
-    for (i = 0; i < MAX_ENDPOINTS; i++) {
-        switch (dev->endpoint[i].type) {
-        case USB_ENDPOINT_XFER_ISOC:
-            usbredir_stop_iso_stream(dev, I2EP(i));
-            break;
-        case USB_ENDPOINT_XFER_INT:
-            if (i & 0x10) {
-                usbredir_stop_interrupt_receiving(dev, I2EP(i));
-            }
-            break;
-        }
-        usbredir_free_bufpq(dev, I2EP(i));
-    }
-
-    set_config.configuration = config;
-    usbredirparser_send_set_configuration(dev->parser, aurb->packet_id,
-                                          &set_config);
-    usbredirparser_do_write(dev->parser);
-    return USB_RET_ASYNC;
-}
-
-static int usbredir_get_config(USBRedirDevice *dev, USBPacket *p)
-{
-    AsyncURB *aurb = async_alloc(dev, p);
-
-    DPRINTF("get config id %u\n", aurb->packet_id);
-
-    aurb->get = 1;
-    usbredirparser_send_get_configuration(dev->parser, aurb->packet_id);
-    usbredirparser_do_write(dev->parser);
-    return USB_RET_ASYNC;
-}
-
-static int usbredir_set_interface(USBRedirDevice *dev, USBPacket *p,
-                                   int interface, int alt)
-{
-    struct usb_redir_set_alt_setting_header set_alt;
-    AsyncURB *aurb = async_alloc(dev, p);
-    int i;
-
-    DPRINTF("set interface %d alt %d id %u\n", interface, alt,
-            aurb->packet_id);
-
-    for (i = 0; i < MAX_ENDPOINTS; i++) {
-        if (dev->endpoint[i].interface == interface) {
-            switch (dev->endpoint[i].type) {
-            case USB_ENDPOINT_XFER_ISOC:
-                usbredir_stop_iso_stream(dev, I2EP(i));
-                break;
-            case USB_ENDPOINT_XFER_INT:
-                if (i & 0x10) {
-                    usbredir_stop_interrupt_receiving(dev, I2EP(i));
-                }
-                break;
-            }
-            usbredir_free_bufpq(dev, I2EP(i));
-        }
-    }
-
-    set_alt.interface = interface;
-    set_alt.alt = alt;
-    usbredirparser_send_set_alt_setting(dev->parser, aurb->packet_id,
-                                        &set_alt);
-    usbredirparser_do_write(dev->parser);
-    return USB_RET_ASYNC;
-}
-
-static int usbredir_get_interface(USBRedirDevice *dev, USBPacket *p,
-                                   int interface)
-{
-    struct usb_redir_get_alt_setting_header get_alt;
-    AsyncURB *aurb = async_alloc(dev, p);
-
-    DPRINTF("get interface %d id %u\n", interface, aurb->packet_id);
-
-    get_alt.interface = interface;
-    aurb->get = 1;
-    usbredirparser_send_get_alt_setting(dev->parser, aurb->packet_id,
-                                        &get_alt);
-    usbredirparser_do_write(dev->parser);
-    return USB_RET_ASYNC;
-}
-
-static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
-        int request, int value, int index, int length, uint8_t *data)
-{
-    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
-    struct usb_redir_control_packet_header control_packet;
-    AsyncURB *aurb;
-
-    /* Special cases for certain standard device requests */
-    switch (request) {
-    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
-        DPRINTF("set address %d\n", value);
-        dev->dev.addr = value;
-        return 0;
-    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
-        return usbredir_set_config(dev, p, value & 0xff);
-    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
-        return usbredir_get_config(dev, p);
-    case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
-        return usbredir_set_interface(dev, p, index, value);
-    case InterfaceRequest | USB_REQ_GET_INTERFACE:
-        return usbredir_get_interface(dev, p, index);
-    }
-
-    /* "Normal" ctrl requests */
-    aurb = async_alloc(dev, p);
-
-    /* Note request is (bRequestType << 8) | bRequest */
-    DPRINTF("ctrl-out type 0x%x req 0x%x val 0x%x index %d len %d id %u\n",
-            request >> 8, request & 0xff, value, index, length,
-            aurb->packet_id);
-
-    control_packet.request     = request & 0xFF;
-    control_packet.requesttype = request >> 8;
-    control_packet.endpoint    = control_packet.requesttype & USB_DIR_IN;
-    control_packet.value       = value;
-    control_packet.index       = index;
-    control_packet.length      = length;
-    aurb->control_packet       = control_packet;
-
-    if (control_packet.requesttype & USB_DIR_IN) {
-        usbredirparser_send_control_packet(dev->parser, aurb->packet_id,
-                                           &control_packet, NULL, 0);
-    } else {
-        usbredir_log_data(dev, "ctrl data out:", data, length);
-        usbredirparser_send_control_packet(dev->parser, aurb->packet_id,
-                                           &control_packet, data, length);
-    }
-    usbredirparser_do_write(dev->parser);
-    return USB_RET_ASYNC;
-}
-
-/*
- * Close events can be triggered by usbredirparser_do_write which gets called
- * from within the USBDevice data / control packet callbacks and doing a
- * usb_detach from within these callbacks is not a good idea.
- *
- * So we use a bh handler to take care of close events. We also handle
- * open events from this callback to make sure that a close directly followed
- * by an open gets handled in the right order.
- */
-static void usbredir_open_close_bh(void *opaque)
-{
-    USBRedirDevice *dev = opaque;
-    uint32_t caps[USB_REDIR_CAPS_SIZE] = { 0, };
-
-    usbredir_device_disconnect(dev);
-
-    if (dev->parser) {
-        usbredirparser_destroy(dev->parser);
-        dev->parser = NULL;
-    }
-
-    if (dev->cs->opened) {
-        dev->parser = qemu_oom_check(usbredirparser_create());
-        dev->parser->priv = dev;
-        dev->parser->log_func = usbredir_log;
-        dev->parser->read_func = usbredir_read;
-        dev->parser->write_func = usbredir_write;
-        dev->parser->hello_func = usbredir_hello;
-        dev->parser->device_connect_func = usbredir_device_connect;
-        dev->parser->device_disconnect_func = usbredir_device_disconnect;
-        dev->parser->interface_info_func = usbredir_interface_info;
-        dev->parser->ep_info_func = usbredir_ep_info;
-        dev->parser->configuration_status_func = usbredir_configuration_status;
-        dev->parser->alt_setting_status_func = usbredir_alt_setting_status;
-        dev->parser->iso_stream_status_func = usbredir_iso_stream_status;
-        dev->parser->interrupt_receiving_status_func =
-            usbredir_interrupt_receiving_status;
-        dev->parser->bulk_streams_status_func = usbredir_bulk_streams_status;
-        dev->parser->control_packet_func = usbredir_control_packet;
-        dev->parser->bulk_packet_func = usbredir_bulk_packet;
-        dev->parser->iso_packet_func = usbredir_iso_packet;
-        dev->parser->interrupt_packet_func = usbredir_interrupt_packet;
-        dev->read_buf = NULL;
-        dev->read_buf_size = 0;
-
-        usbredirparser_caps_set_cap(caps, usb_redir_cap_connect_device_version);
-        usbredirparser_caps_set_cap(caps, usb_redir_cap_filter);
-        usbredirparser_init(dev->parser, VERSION, caps, USB_REDIR_CAPS_SIZE, 0);
-        usbredirparser_do_write(dev->parser);
-    }
-}
-
-static void usbredir_do_attach(void *opaque)
-{
-    USBRedirDevice *dev = opaque;
-
-    usb_device_attach(&dev->dev);
-}
-
-/*
- * chardev callbacks
- */
-
-static int usbredir_chardev_can_read(void *opaque)
-{
-    USBRedirDevice *dev = opaque;
-
-    if (dev->parser) {
-        /* usbredir_parser_do_read will consume *all* data we give it */
-        return 1024 * 1024;
-    } else {
-        /* usbredir_open_close_bh hasn't handled the open event yet */
-        return 0;
-    }
-}
-
-static void usbredir_chardev_read(void *opaque, const uint8_t *buf, int size)
-{
-    USBRedirDevice *dev = opaque;
-
-    /* No recursion allowed! */
-    assert(dev->read_buf == NULL);
-
-    dev->read_buf = buf;
-    dev->read_buf_size = size;
-
-    usbredirparser_do_read(dev->parser);
-    /* Send any acks, etc. which may be queued now */
-    usbredirparser_do_write(dev->parser);
-}
-
-static void usbredir_chardev_event(void *opaque, int event)
-{
-    USBRedirDevice *dev = opaque;
-
-    switch (event) {
-    case CHR_EVENT_OPENED:
-    case CHR_EVENT_CLOSED:
-        qemu_bh_schedule(dev->open_close_bh);
-        break;
-    }
-}
-
-/*
- * init + destroy
- */
-
-static int usbredir_initfn(USBDevice *udev)
-{
-    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
-    int i;
-
-    if (dev->cs == NULL) {
-        qerror_report(QERR_MISSING_PARAMETER, "chardev");
-        return -1;
-    }
-
-    if (dev->filter_str) {
-        i = usbredirfilter_string_to_rules(dev->filter_str, ":", "|",
-                                           &dev->filter_rules,
-                                           &dev->filter_rules_count);
-        if (i) {
-            qerror_report(QERR_INVALID_PARAMETER_VALUE, "filter",
-                          "a usb device filter string");
-            return -1;
-        }
-    }
-
-    dev->open_close_bh = qemu_bh_new(usbredir_open_close_bh, dev);
-    dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev);
-
-    QTAILQ_INIT(&dev->asyncq);
-    for (i = 0; i < MAX_ENDPOINTS; i++) {
-        QTAILQ_INIT(&dev->endpoint[i].bufpq);
-    }
-
-    /* We'll do the attach once we receive the speed from the usb-host */
-    udev->auto_attach = 0;
-
-    /* Let the backend know we are ready */
-    qemu_chr_fe_open(dev->cs);
-    qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
-                          usbredir_chardev_read, usbredir_chardev_event, dev);
-
-    return 0;
-}
-
-static void usbredir_cleanup_device_queues(USBRedirDevice *dev)
-{
-    AsyncURB *aurb, *next_aurb;
-    int i;
-
-    QTAILQ_FOREACH_SAFE(aurb, &dev->asyncq, next, next_aurb) {
-        async_free(dev, aurb);
-    }
-    for (i = 0; i < MAX_ENDPOINTS; i++) {
-        usbredir_free_bufpq(dev, I2EP(i));
-    }
-}
-
-static void usbredir_handle_destroy(USBDevice *udev)
-{
-    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
-
-    qemu_chr_fe_close(dev->cs);
-    qemu_chr_delete(dev->cs);
-    /* Note must be done after qemu_chr_close, as that causes a close event */
-    qemu_bh_delete(dev->open_close_bh);
-
-    qemu_del_timer(dev->attach_timer);
-    qemu_free_timer(dev->attach_timer);
-
-    usbredir_cleanup_device_queues(dev);
-
-    if (dev->parser) {
-        usbredirparser_destroy(dev->parser);
-    }
-
-    free(dev->filter_rules);
-}
-
-static int usbredir_check_filter(USBRedirDevice *dev)
-{
-    if (dev->interface_info.interface_count == 0) {
-        ERROR("No interface info for device\n");
-        goto error;
-    }
-
-    if (dev->filter_rules) {
-        if (!usbredirparser_peer_has_cap(dev->parser,
-                                    usb_redir_cap_connect_device_version)) {
-            ERROR("Device filter specified and peer does not have the "
-                  "connect_device_version capability\n");
-            goto error;
-        }
-
-        if (usbredirfilter_check(
-                dev->filter_rules,
-                dev->filter_rules_count,
-                dev->device_info.device_class,
-                dev->device_info.device_subclass,
-                dev->device_info.device_protocol,
-                dev->interface_info.interface_class,
-                dev->interface_info.interface_subclass,
-                dev->interface_info.interface_protocol,
-                dev->interface_info.interface_count,
-                dev->device_info.vendor_id,
-                dev->device_info.product_id,
-                dev->device_info.device_version_bcd,
-                0) != 0) {
-            goto error;
-        }
-    }
-
-    return 0;
-
-error:
-    usbredir_device_disconnect(dev);
-    if (usbredirparser_peer_has_cap(dev->parser, usb_redir_cap_filter)) {
-        usbredirparser_send_filter_reject(dev->parser);
-        usbredirparser_do_write(dev->parser);
-    }
-    return -1;
-}
-
-/*
- * usbredirparser packet complete callbacks
- */
-
-static int usbredir_handle_status(USBRedirDevice *dev,
-                                       int status, int actual_len)
-{
-    switch (status) {
-    case usb_redir_success:
-        return actual_len;
-    case usb_redir_stall:
-        return USB_RET_STALL;
-    case usb_redir_cancelled:
-        WARNING("returning cancelled packet to HC?\n");
-        return USB_RET_NAK;
-    case usb_redir_inval:
-        WARNING("got invalid param error from usb-host?\n");
-        return USB_RET_NAK;
-    case usb_redir_ioerror:
-    case usb_redir_timeout:
-    default:
-        return USB_RET_IOERROR;
-    }
-}
-
-static void usbredir_hello(void *priv, struct usb_redir_hello_header *h)
-{
-    USBRedirDevice *dev = priv;
-
-    /* Try to send the filter info now that we've the usb-host's caps */
-    if (usbredirparser_peer_has_cap(dev->parser, usb_redir_cap_filter) &&
-            dev->filter_rules) {
-        usbredirparser_send_filter_filter(dev->parser, dev->filter_rules,
-                                          dev->filter_rules_count);
-        usbredirparser_do_write(dev->parser);
-    }
-}
-
-static void usbredir_device_connect(void *priv,
-    struct usb_redir_device_connect_header *device_connect)
-{
-    USBRedirDevice *dev = priv;
-    const char *speed;
-
-    if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) {
-        ERROR("Received device connect while already connected\n");
-        return;
-    }
-
-    switch (device_connect->speed) {
-    case usb_redir_speed_low:
-        speed = "low speed";
-        dev->dev.speed = USB_SPEED_LOW;
-        break;
-    case usb_redir_speed_full:
-        speed = "full speed";
-        dev->dev.speed = USB_SPEED_FULL;
-        break;
-    case usb_redir_speed_high:
-        speed = "high speed";
-        dev->dev.speed = USB_SPEED_HIGH;
-        break;
-    case usb_redir_speed_super:
-        speed = "super speed";
-        dev->dev.speed = USB_SPEED_SUPER;
-        break;
-    default:
-        speed = "unknown speed";
-        dev->dev.speed = USB_SPEED_FULL;
-    }
-
-    if (usbredirparser_peer_has_cap(dev->parser,
-                                    usb_redir_cap_connect_device_version)) {
-        INFO("attaching %s device %04x:%04x version %d.%d class %02x\n",
-             speed, device_connect->vendor_id, device_connect->product_id,
-             ((device_connect->device_version_bcd & 0xf000) >> 12) * 10 +
-             ((device_connect->device_version_bcd & 0x0f00) >>  8),
-             ((device_connect->device_version_bcd & 0x00f0) >>  4) * 10 +
-             ((device_connect->device_version_bcd & 0x000f) >>  0),
-             device_connect->device_class);
-    } else {
-        INFO("attaching %s device %04x:%04x class %02x\n", speed,
-             device_connect->vendor_id, device_connect->product_id,
-             device_connect->device_class);
-    }
-
-    dev->dev.speedmask = (1 << dev->dev.speed);
-    dev->device_info = *device_connect;
-
-    if (usbredir_check_filter(dev)) {
-        WARNING("Device %04x:%04x rejected by device filter, not attaching\n",
-                device_connect->vendor_id, device_connect->product_id);
-        return;
-    }
-
-    qemu_mod_timer(dev->attach_timer, dev->next_attach_time);
-}
-
-static void usbredir_device_disconnect(void *priv)
-{
-    USBRedirDevice *dev = priv;
-    int i;
-
-    /* Stop any pending attaches */
-    qemu_del_timer(dev->attach_timer);
-
-    if (dev->dev.attached) {
-        usb_device_detach(&dev->dev);
-        /*
-         * Delay next usb device attach to give the guest a chance to see
-         * see the detach / attach in case of quick close / open succession
-         */
-        dev->next_attach_time = qemu_get_clock_ms(vm_clock) + 200;
-    }
-
-    /* Reset state so that the next dev connected starts with a clean slate */
-    usbredir_cleanup_device_queues(dev);
-    memset(dev->endpoint, 0, sizeof(dev->endpoint));
-    for (i = 0; i < MAX_ENDPOINTS; i++) {
-        QTAILQ_INIT(&dev->endpoint[i].bufpq);
-    }
-    usb_ep_init(&dev->dev);
-    dev->interface_info.interface_count = 0;
-}
-
-static void usbredir_interface_info(void *priv,
-    struct usb_redir_interface_info_header *interface_info)
-{
-    USBRedirDevice *dev = priv;
-
-    dev->interface_info = *interface_info;
-
-    /*
-     * If we receive interface info after the device has already been
-     * connected (ie on a set_config), re-check the filter.
-     */
-    if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) {
-        if (usbredir_check_filter(dev)) {
-            ERROR("Device no longer matches filter after interface info "
-                  "change, disconnecting!\n");
-        }
-    }
-}
-
-static void usbredir_ep_info(void *priv,
-    struct usb_redir_ep_info_header *ep_info)
-{
-    USBRedirDevice *dev = priv;
-    struct USBEndpoint *usb_ep;
-    int i;
-
-    for (i = 0; i < MAX_ENDPOINTS; i++) {
-        dev->endpoint[i].type = ep_info->type[i];
-        dev->endpoint[i].interval = ep_info->interval[i];
-        dev->endpoint[i].interface = ep_info->interface[i];
-        switch (dev->endpoint[i].type) {
-        case usb_redir_type_invalid:
-            break;
-        case usb_redir_type_iso:
-        case usb_redir_type_interrupt:
-            if (dev->endpoint[i].interval == 0) {
-                ERROR("Received 0 interval for isoc or irq endpoint\n");
-                usbredir_device_disconnect(dev);
-            }
-            /* Fall through */
-        case usb_redir_type_control:
-        case usb_redir_type_bulk:
-            DPRINTF("ep: %02X type: %d interface: %d\n", I2EP(i),
-                    dev->endpoint[i].type, dev->endpoint[i].interface);
-            break;
-        default:
-            ERROR("Received invalid endpoint type\n");
-            usbredir_device_disconnect(dev);
-            return;
-        }
-        usb_ep = usb_ep_get(&dev->dev,
-                            (i & 0x10) ? USB_TOKEN_IN : USB_TOKEN_OUT,
-                            i & 0x0f);
-        usb_ep->type = dev->endpoint[i].type;
-        usb_ep->ifnum = dev->endpoint[i].interface;
-    }
-}
-
-static void usbredir_configuration_status(void *priv, uint32_t id,
-    struct usb_redir_configuration_status_header *config_status)
-{
-    USBRedirDevice *dev = priv;
-    AsyncURB *aurb;
-    int len = 0;
-
-    DPRINTF("set config status %d config %d id %u\n", config_status->status,
-            config_status->configuration, id);
-
-    aurb = async_find(dev, id);
-    if (!aurb) {
-        return;
-    }
-    if (aurb->packet) {
-        if (aurb->get) {
-            dev->dev.data_buf[0] = config_status->configuration;
-            len = 1;
-        }
-        aurb->packet->result =
-            usbredir_handle_status(dev, config_status->status, len);
-        usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
-    }
-    async_free(dev, aurb);
-}
-
-static void usbredir_alt_setting_status(void *priv, uint32_t id,
-    struct usb_redir_alt_setting_status_header *alt_setting_status)
-{
-    USBRedirDevice *dev = priv;
-    AsyncURB *aurb;
-    int len = 0;
-
-    DPRINTF("alt status %d intf %d alt %d id: %u\n",
-            alt_setting_status->status,
-            alt_setting_status->interface,
-            alt_setting_status->alt, id);
-
-    aurb = async_find(dev, id);
-    if (!aurb) {
-        return;
-    }
-    if (aurb->packet) {
-        if (aurb->get) {
-            dev->dev.data_buf[0] = alt_setting_status->alt;
-            len = 1;
-        }
-        aurb->packet->result =
-            usbredir_handle_status(dev, alt_setting_status->status, len);
-        usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
-    }
-    async_free(dev, aurb);
-}
-
-static void usbredir_iso_stream_status(void *priv, uint32_t id,
-    struct usb_redir_iso_stream_status_header *iso_stream_status)
-{
-    USBRedirDevice *dev = priv;
-    uint8_t ep = iso_stream_status->endpoint;
-
-    DPRINTF("iso status %d ep %02X id %u\n", iso_stream_status->status,
-            ep, id);
-
-    if (!dev->dev.attached || !dev->endpoint[EP2I(ep)].iso_started) {
-        return;
-    }
-
-    dev->endpoint[EP2I(ep)].iso_error = iso_stream_status->status;
-    if (iso_stream_status->status == usb_redir_stall) {
-        DPRINTF("iso stream stopped by peer ep %02X\n", ep);
-        dev->endpoint[EP2I(ep)].iso_started = 0;
-    }
-}
-
-static void usbredir_interrupt_receiving_status(void *priv, uint32_t id,
-    struct usb_redir_interrupt_receiving_status_header
-    *interrupt_receiving_status)
-{
-    USBRedirDevice *dev = priv;
-    uint8_t ep = interrupt_receiving_status->endpoint;
-
-    DPRINTF("interrupt recv status %d ep %02X id %u\n",
-            interrupt_receiving_status->status, ep, id);
-
-    if (!dev->dev.attached || !dev->endpoint[EP2I(ep)].interrupt_started) {
-        return;
-    }
-
-    dev->endpoint[EP2I(ep)].interrupt_error =
-        interrupt_receiving_status->status;
-    if (interrupt_receiving_status->status == usb_redir_stall) {
-        DPRINTF("interrupt receiving stopped by peer ep %02X\n", ep);
-        dev->endpoint[EP2I(ep)].interrupt_started = 0;
-    }
-}
-
-static void usbredir_bulk_streams_status(void *priv, uint32_t id,
-    struct usb_redir_bulk_streams_status_header *bulk_streams_status)
-{
-}
-
-static void usbredir_control_packet(void *priv, uint32_t id,
-    struct usb_redir_control_packet_header *control_packet,
-    uint8_t *data, int data_len)
-{
-    USBRedirDevice *dev = priv;
-    int len = control_packet->length;
-    AsyncURB *aurb;
-
-    DPRINTF("ctrl-in status %d len %d id %u\n", control_packet->status,
-            len, id);
-
-    aurb = async_find(dev, id);
-    if (!aurb) {
-        free(data);
-        return;
-    }
-
-    aurb->control_packet.status = control_packet->status;
-    aurb->control_packet.length = control_packet->length;
-    if (memcmp(&aurb->control_packet, control_packet,
-               sizeof(*control_packet))) {
-        ERROR("return control packet mismatch, please report this!\n");
-        len = USB_RET_NAK;
-    }
-
-    if (aurb->packet) {
-        len = usbredir_handle_status(dev, control_packet->status, len);
-        if (len > 0) {
-            usbredir_log_data(dev, "ctrl data in:", data, data_len);
-            if (data_len <= sizeof(dev->dev.data_buf)) {
-                memcpy(dev->dev.data_buf, data, data_len);
-            } else {
-                ERROR("ctrl buffer too small (%d > %zu)\n",
-                      data_len, sizeof(dev->dev.data_buf));
-                len = USB_RET_STALL;
-            }
-        }
-        aurb->packet->result = len;
-        usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
-    }
-    async_free(dev, aurb);
-    free(data);
-}
-
-static void usbredir_bulk_packet(void *priv, uint32_t id,
-    struct usb_redir_bulk_packet_header *bulk_packet,
-    uint8_t *data, int data_len)
-{
-    USBRedirDevice *dev = priv;
-    uint8_t ep = bulk_packet->endpoint;
-    int len = bulk_packet->length;
-    AsyncURB *aurb;
-
-    DPRINTF("bulk-in status %d ep %02X len %d id %u\n", bulk_packet->status,
-            ep, len, id);
-
-    aurb = async_find(dev, id);
-    if (!aurb) {
-        free(data);
-        return;
-    }
-
-    if (aurb->bulk_packet.endpoint != bulk_packet->endpoint ||
-            aurb->bulk_packet.stream_id != bulk_packet->stream_id) {
-        ERROR("return bulk packet mismatch, please report this!\n");
-        len = USB_RET_NAK;
-    }
-
-    if (aurb->packet) {
-        len = usbredir_handle_status(dev, bulk_packet->status, len);
-        if (len > 0) {
-            usbredir_log_data(dev, "bulk data in:", data, data_len);
-            if (data_len <= aurb->packet->iov.size) {
-                usb_packet_copy(aurb->packet, data, data_len);
-            } else {
-                ERROR("bulk buffer too small (%d > %zd)\n", data_len,
-                      aurb->packet->iov.size);
-                len = USB_RET_STALL;
-            }
-        }
-        aurb->packet->result = len;
-        usb_packet_complete(&dev->dev, aurb->packet);
-    }
-    async_free(dev, aurb);
-    free(data);
-}
-
-static void usbredir_iso_packet(void *priv, uint32_t id,
-    struct usb_redir_iso_packet_header *iso_packet,
-    uint8_t *data, int data_len)
-{
-    USBRedirDevice *dev = priv;
-    uint8_t ep = iso_packet->endpoint;
-
-    DPRINTF2("iso-in status %d ep %02X len %d id %u\n", iso_packet->status, ep,
-             data_len, id);
-
-    if (dev->endpoint[EP2I(ep)].type != USB_ENDPOINT_XFER_ISOC) {
-        ERROR("received iso packet for non iso endpoint %02X\n", ep);
-        free(data);
-        return;
-    }
-
-    if (dev->endpoint[EP2I(ep)].iso_started == 0) {
-        DPRINTF("received iso packet for non started stream ep %02X\n", ep);
-        free(data);
-        return;
-    }
-
-    /* bufp_alloc also adds the packet to the ep queue */
-    bufp_alloc(dev, data, data_len, iso_packet->status, ep);
-}
-
-static void usbredir_interrupt_packet(void *priv, uint32_t id,
-    struct usb_redir_interrupt_packet_header *interrupt_packet,
-    uint8_t *data, int data_len)
-{
-    USBRedirDevice *dev = priv;
-    uint8_t ep = interrupt_packet->endpoint;
-
-    DPRINTF("interrupt-in status %d ep %02X len %d id %u\n",
-            interrupt_packet->status, ep, data_len, id);
-
-    if (dev->endpoint[EP2I(ep)].type != USB_ENDPOINT_XFER_INT) {
-        ERROR("received int packet for non interrupt endpoint %02X\n", ep);
-        free(data);
-        return;
-    }
-
-    if (ep & USB_DIR_IN) {
-        if (dev->endpoint[EP2I(ep)].interrupt_started == 0) {
-            DPRINTF("received int packet while not started ep %02X\n", ep);
-            free(data);
-            return;
-        }
-
-        /* bufp_alloc also adds the packet to the ep queue */
-        bufp_alloc(dev, data, data_len, interrupt_packet->status, ep);
-    } else {
-        int len = interrupt_packet->length;
-
-        AsyncURB *aurb = async_find(dev, id);
-        if (!aurb) {
-            return;
-        }
-
-        if (aurb->interrupt_packet.endpoint != interrupt_packet->endpoint) {
-            ERROR("return int packet mismatch, please report this!\n");
-            len = USB_RET_NAK;
-        }
-
-        if (aurb->packet) {
-            aurb->packet->result = usbredir_handle_status(dev,
-                                               interrupt_packet->status, len);
-            usb_packet_complete(&dev->dev, aurb->packet);
-        }
-        async_free(dev, aurb);
-    }
-}
-
-static Property usbredir_properties[] = {
-    DEFINE_PROP_CHR("chardev", USBRedirDevice, cs),
-    DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, 0),
-    DEFINE_PROP_STRING("filter", USBRedirDevice, filter_str),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void usbredir_class_initfn(ObjectClass *klass, void *data)
-{
-    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    uc->init           = usbredir_initfn;
-    uc->product_desc   = "USB Redirection Device";
-    uc->handle_destroy = usbredir_handle_destroy;
-    uc->cancel_packet  = usbredir_cancel_packet;
-    uc->handle_reset   = usbredir_handle_reset;
-    uc->handle_data    = usbredir_handle_data;
-    uc->handle_control = usbredir_handle_control;
-    dc->props          = usbredir_properties;
-}
-
-static TypeInfo usbredir_dev_info = {
-    .name          = "usb-redir",
-    .parent        = TYPE_USB_DEVICE,
-    .instance_size = sizeof(USBRedirDevice),
-    .class_init    = usbredir_class_initfn,
-};
-
-static void usbredir_register_types(void)
-{
-    type_register_static(&usbredir_dev_info);
-}
-
-type_init(usbredir_register_types)
diff --git a/usb-stub.c b/usb-stub.c
deleted file mode 100644
index b4e10c1..0000000
--- a/usb-stub.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Stub host USB redirector
- *
- * Copyright (c) 2005 Fabrice Bellard
- *
- * Copyright (c) 2008 Max Krasnyansky
- *      Support for host device auto connect & disconnect
- *      Major rewrite to support fully async operation
- *
- * Copyright 2008 TJ <linux at tjworld.net>
- *      Added flexible support for /dev/bus/usb /sys/bus/usb/devices in addition
- *      to the legacy /proc/bus/usb USB device discovery and handling
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "qemu-common.h"
-#include "console.h"
-#include "hw/usb.h"
-#include "monitor.h"
-
-void usb_host_info(Monitor *mon)
-{
-    monitor_printf(mon, "USB host devices not supported\n");
-}
-
-/* XXX: modify configure to compile the right host driver */
-USBDevice *usb_host_device_open(USBBus *bus, const char *devname)
-{
-    return NULL;
-}
-
-int usb_host_device_close(const char *devname)
-{
-    return 0;
-}
commit cb72b75824c0362e5cb32eb8796930f29fa36d17
Merge: fb23ae6... 3cf0bed...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 12 20:52:34 2012 -0500

    Merge remote-tracking branch 'mdroth/qga-pull-3-12-2012' into staging
    
    * mdroth/qga-pull-3-12-2012:
      qemu-ga: add guest-sync-delimited
      qemu-ga: add guest-network-get-interfaces command
      qemu-ga: add win32 guest-suspend-ram command
      qemu-ga: add win32 guest-suspend-disk command.
      qemu-ga: add guest-suspend-hybrid
      qemu-ga: add guest-suspend-ram
      qemu-ga: add guest-suspend-disk

commit fb23ae6e41aad0404154be7af576e76f16466f8e
Merge: 79122e9... 7e849a9...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 12 20:51:42 2012 -0500

    Merge remote-tracking branch 'kwolf/for-anthony' into staging
    
    * kwolf/for-anthony:
      test-coroutine: add performance test for nesting
      coroutine: adding configure option for sigaltstack coroutine backend
      coroutine: adding configure choose mechanism for coroutine backend
      coroutine: adding sigaltstack method (.c source)
      qcow2: Reduce number of I/O requests
      qcow2: Add qcow2_alloc_clusters_at()
      qcow2: Factor out count_cow_clusters
      qmp: convert blockdev-snapshot-sync to a wrapper around transactions
      add mode field to blockdev-snapshot-sync transaction item
      rename blockdev-group-snapshot-sync
      qapi: complete implementation of unions
      use QSIMPLEQ_FOREACH_SAFE when freeing list elements
      Add 'make check-block'
      make check: Add qemu-iotests subset
      qemu-iotests: Mark some tests as quick
      qcow2: Add error messages in qcow2_truncate
      block: handle -EBUSY in bdrv_commit_all()
      qcow2: Add some tracing
      qed: do not evict in-use L2 table cache entries
      Group snapshot: Fix format name for backing file

commit 79122e933cd8bda0917c56c1bdac3f2b8d49fb23
Merge: cbedde0... 97161e1...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 12 20:50:09 2012 -0500

    Merge remote-tracking branch 'qemu-kvm/memory/core' into staging
    
    * qemu-kvm/memory/core:
      memory: get rid of cpu_register_io_memory()
      memory: dispatch directly via MemoryRegion
      exec: fix code tlb entry misused as iotlb in get_page_addr_code()
      memory: store section indices in iotlb instead of io indices
      memory: make phys_page_find() return an unadjusted section

commit cbedde09698d3506da429ae305dcea7f7deee554
Merge: 1d2cb1a... 7275001...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 12 20:49:13 2012 -0500

    Merge remote-tracking branch 'stefanha/tracing' into staging
    
    * stefanha/tracing:
      vga: add trace event for ppm_save
      console: add some trace events
      maintainers: Add docs/tracing.txt to Tracing
      docs: correct ./configure line in tracing.txt
      trace: make trace_thread_create() use its function arg
      tracetool: Omit useless QEMU_*_ENABLED() check
      trace: Provide a per-event status define for conditional compilation

commit 1d2cb1a2d81af4a760aac18521e11e268ad3711b
Merge: 8d9dde9... d03ee40...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 12 20:48:00 2012 -0500

    Merge remote-tracking branch 'qmp/queue/qmp' into staging
    
    * qmp/queue/qmp:
      qapi-schema.json: fix comment for type ObjectPropretyInfo
      qapi-schema: fix typos and explain 'spice' auth
      qjson.h: include compiler.h for GCC_FMT_ATTR

commit 3cf0bed8369267184e5dc5b58882811519d67437
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Tue Feb 7 13:56:48 2012 -0600

    qemu-ga: add guest-sync-delimited
    
    guest-sync leaves it as an exercise to the user as to how to reliably
    obtain the response to guest-sync if the client had previously read in a
    partial response (due qemu-ga previously being restarted mid-"sentence"
    due to reboot, forced restart, etc).
    
    qemu-ga handles this situation on its end by having a client precede
    their guest-sync request with a 0xFF byte (invalid UTF-8), which
    qemu-ga/QEMU JSON parsers will treat as a flush event. Thus we can
    reliably flush the qemu-ga parser state in preparation for receiving
    the guest-sync request.
    
    guest-sync-delimited provides the same functionality for a client: when
    a guest-sync-delimited is issued, qemu-ga will precede it's response
    with a 0xFF byte that the client can use as an indicator to flush its
    buffer/parser state in preparation for reliably receiving the
    guest-sync-delimited response.
    
    It is also useful as an optimization for clients, since, after issuing a
    guest-sync-delimited, clients can safely discard all stale data read
    from the channel until the 0xFF is found.
    
    More information available on the wiki:
    
    http://wiki.qemu.org/Features/QAPI/GuestAgent#QEMU_Guest_Agent_Protocol
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>

diff --git a/qapi-schema-guest.json b/qapi-schema-guest.json
index 12b5d4f..cf18876 100644
--- a/qapi-schema-guest.json
+++ b/qapi-schema-guest.json
@@ -1,6 +1,41 @@
 # *-*- Mode: Python -*-*
 
 ##
+#
+# Echo back a unique integer value, and prepend to response a
+# leading sentinel byte (0xFF) the client can check scan for.
+#
+# This is used by clients talking to the guest agent over the
+# wire to ensure the stream is in sync and doesn't contain stale
+# data from previous client. It must be issued upon initial
+# connection, and after any client-side timeouts (including
+# timeouts on receiving a response to this command).
+#
+# After issuing this request, all guest agent responses should be
+# ignored until the response containing the unique integer value
+# the client passed in is returned. Receival of the 0xFF sentinel
+# byte must be handled as an indication that the client's
+# lexer/tokenizer/parser state should be flushed/reset in
+# preparation for reliably receiving the subsequent response. As
+# an optimization, clients may opt to ignore all data until a
+# sentinel value is receiving to avoid unecessary processing of
+# stale data.
+#
+# Similarly, clients should also precede this *request*
+# with a 0xFF byte to make sure the guest agent flushes any
+# partially read JSON data from a previous client connection.
+#
+# @id: randomly generated 64-bit integer
+#
+# Returns: The unique integer id passed in by the client
+#
+# Since: 1.1
+# ##
+{ 'command': 'guest-sync-delimited'
+  'data':    { 'id': 'int' },
+  'returns': 'int' }
+
+##
 # @guest-sync:
 #
 # Echo back a unique integer value
@@ -13,8 +48,19 @@
 # partially-delivered JSON text in such a way that this response
 # can be obtained.
 #
+# In cases where a partial stale response was previously
+# received by the client, this cannot always be done reliably.
+# One particular scenario being if qemu-ga responses are fed
+# character-by-character into a JSON parser. In these situations,
+# using guest-sync-delimited may be optimal.
+#
+# For clients that fetch responses line by line and convert them
+# to JSON objects, guest-sync should be sufficient, but note that
+# in cases where the channel is dirty some attempts at parsing the
+# response may result in a parser error.
+#
 # Such clients should also precede this command
-# with a 0xFF byte to make such the guest agent flushes any
+# with a 0xFF byte to make sure the guest agent flushes any
 # partially read JSON data from a previous session.
 #
 # @id: randomly generated 64-bit integer
diff --git a/qemu-ga.c b/qemu-ga.c
index 1c90e6e..d6f786e 100644
--- a/qemu-ga.c
+++ b/qemu-ga.c
@@ -41,6 +41,7 @@
 #define QGA_VIRTIO_PATH_DEFAULT "\\\\.\\Global\\org.qemu.guest_agent.0"
 #endif
 #define QGA_PIDFILE_DEFAULT "/var/run/qemu-ga.pid"
+#define QGA_SENTINEL_BYTE 0xFF
 
 struct GAState {
     JSONMessageParser parser;
@@ -54,9 +55,10 @@ struct GAState {
 #ifdef _WIN32
     GAService service;
 #endif
+    bool delimit_response;
 };
 
-static struct GAState *ga_state;
+struct GAState *ga_state;
 
 #ifdef _WIN32
 DWORD WINAPI service_ctrl_handler(DWORD ctrl, DWORD type, LPVOID data,
@@ -198,6 +200,11 @@ static void ga_log(const gchar *domain, GLogLevelFlags level,
     }
 }
 
+void ga_set_response_delimited(GAState *s)
+{
+    s->delimit_response = true;
+}
+
 #ifndef _WIN32
 static void become_daemon(const char *pidfile)
 {
@@ -254,7 +261,7 @@ fail:
 static int send_response(GAState *s, QObject *payload)
 {
     const char *buf;
-    QString *payload_qstr;
+    QString *payload_qstr, *response_qstr;
     GIOStatus status;
 
     g_assert(payload && s->channel);
@@ -264,10 +271,20 @@ static int send_response(GAState *s, QObject *payload)
         return -EINVAL;
     }
 
-    qstring_append_chr(payload_qstr, '\n');
-    buf = qstring_get_str(payload_qstr);
+    if (s->delimit_response) {
+        s->delimit_response = false;
+        response_qstr = qstring_new();
+        qstring_append_chr(response_qstr, QGA_SENTINEL_BYTE);
+        qstring_append(response_qstr, qstring_get_str(payload_qstr));
+        QDECREF(payload_qstr);
+    } else {
+        response_qstr = payload_qstr;
+    }
+
+    qstring_append_chr(response_qstr, '\n');
+    buf = qstring_get_str(response_qstr);
     status = ga_channel_write_all(s->channel, buf, strlen(buf));
-    QDECREF(payload_qstr);
+    QDECREF(response_qstr);
     if (status != G_IO_STATUS_NORMAL) {
         return -EIO;
     }
diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 5b77fa9..7b2be2f 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -35,8 +35,6 @@
 #include "qemu-queue.h"
 #include "host-utils.h"
 
-static GAState *ga_state;
-
 static void reopen_fd_to_null(int fd)
 {
     int nullfd;
@@ -909,7 +907,6 @@ error:
 /* register init/cleanup routines for stateful command groups */
 void ga_command_state_init(GAState *s, GACommandState *cs)
 {
-    ga_state = s;
 #if defined(CONFIG_FSFREEZE)
     ga_command_state_add(cs, guest_fsfreeze_init, guest_fsfreeze_cleanup);
 #endif
diff --git a/qga/commands.c b/qga/commands.c
index b27407d..5bcceaa 100644
--- a/qga/commands.c
+++ b/qga/commands.c
@@ -29,6 +29,12 @@ void slog(const gchar *fmt, ...)
     va_end(ap);
 }
 
+int64_t qmp_guest_sync_delimited(int64_t id, Error **errp)
+{
+    ga_set_response_delimited(ga_state);
+    return id;
+}
+
 int64_t qmp_guest_sync(int64_t id, Error **errp)
 {
     return id;
diff --git a/qga/guest-agent-core.h b/qga/guest-agent-core.h
index b5dfa5b..304525d 100644
--- a/qga/guest-agent-core.h
+++ b/qga/guest-agent-core.h
@@ -18,6 +18,7 @@
 
 typedef struct GAState GAState;
 typedef struct GACommandState GACommandState;
+extern GAState *ga_state;
 
 void ga_command_state_init(GAState *s, GACommandState *cs);
 void ga_command_state_add(GACommandState *cs,
@@ -30,3 +31,4 @@ bool ga_logging_enabled(GAState *s);
 void ga_disable_logging(GAState *s);
 void ga_enable_logging(GAState *s);
 void slog(const gchar *fmt, ...);
+void ga_set_response_delimited(GAState *s);
commit 3424fc9f16a1e7d1c48eb6d605eb0ca63e199ec2
Author: Michal Privoznik <mprivozn at redhat.com>
Date:   Wed Feb 29 17:02:23 2012 +0100

    qemu-ga: add guest-network-get-interfaces command
    
    This command returns an array of:
    
     [ifname, hwaddr, [ipaddr, ipaddr_family, prefix] ]
    
    for each interface in the system.
    Currently, only IPv4 and IPv6 are supported.
    
    Signed-off-by: Michal Privoznik <mprivozn at redhat.com>

diff --git a/qapi-schema-guest.json b/qapi-schema-guest.json
index 6a75552..12b5d4f 100644
--- a/qapi-schema-guest.json
+++ b/qapi-schema-guest.json
@@ -370,3 +370,62 @@
 # Since: 1.1
 ##
 { 'command': 'guest-suspend-hybrid' }
+
+##
+# @GuestIpAddressType:
+#
+# An enumeration of supported IP address types
+#
+# @ipv4: IP version 4
+#
+# @ipv6: IP version 6
+#
+# Since: 1.1
+##
+{ 'enum': 'GuestIpAddressType',
+  'data': [ 'ipv4', 'ipv6' ] }
+
+##
+# @GuestIpAddress:
+#
+# @ip-address: IP address
+#
+# @ip-address-type: Type of @ip-address (e.g. ipv4, ipv6)
+#
+# @prefix: Network prefix length of @ip-address
+#
+# Since: 1.1
+##
+{ 'type': 'GuestIpAddress',
+  'data': {'ip-address': 'str',
+           'ip-address-type': 'GuestIpAddressType',
+           'prefix': 'int'} }
+
+##
+# @GuestNetworkInterface:
+#
+# @name: The name of interface for which info are being delivered
+#
+# @hardware-address: Hardware address of @name
+#
+# @ip-addresses: List of addresses assigned to @name
+#
+# Since: 1.1
+##
+{ 'type': 'GuestNetworkInterface',
+  'data': {'name': 'str',
+           '*hardware-address': 'str',
+           '*ip-addresses': ['GuestIpAddress'] } }
+
+##
+# @guest-network-get-interfaces:
+#
+# Get list of guest IP addresses, MAC addresses
+# and netmasks.
+#
+# Returns: List of GuestNetworkInfo on success.
+#
+# Since: 1.1
+##
+{ 'command': 'guest-network-get-interfaces',
+  'returns': ['GuestNetworkInterface'] }
diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 79571bf..5b77fa9 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -5,6 +5,7 @@
  *
  * Authors:
  *  Michael Roth      <mdroth at linux.vnet.ibm.com>
+ *  Michal Privoznik  <mprivozn at redhat.com>
  *
  * This work is licensed under the terms of the GNU GPL, version 2 or later.
  * See the COPYING file in the top-level directory.
@@ -23,11 +24,16 @@
 
 #include <sys/types.h>
 #include <sys/ioctl.h>
+#include <ifaddrs.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <net/if.h>
 #include <sys/wait.h>
 #include "qga/guest-agent-core.h"
 #include "qga-qmp-commands.h"
 #include "qerror.h"
 #include "qemu-queue.h"
+#include "host-utils.h"
 
 static GAState *ga_state;
 
@@ -725,6 +731,181 @@ void qmp_guest_suspend_hybrid(Error **err)
     guest_suspend("pm-suspend-hybrid", NULL, err);
 }
 
+static GuestNetworkInterfaceList *
+guest_find_interface(GuestNetworkInterfaceList *head,
+                     const char *name)
+{
+    for (; head; head = head->next) {
+        if (strcmp(head->value->name, name) == 0) {
+            break;
+        }
+    }
+
+    return head;
+}
+
+/*
+ * Build information about guest interfaces
+ */
+GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
+{
+    GuestNetworkInterfaceList *head = NULL, *cur_item = NULL;
+    struct ifaddrs *ifap, *ifa;
+    char err_msg[512];
+
+    if (getifaddrs(&ifap) < 0) {
+        snprintf(err_msg, sizeof(err_msg),
+                 "getifaddrs failed: %s", strerror(errno));
+        error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg);
+        goto error;
+    }
+
+    for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+        GuestNetworkInterfaceList *info;
+        GuestIpAddressList **address_list = NULL, *address_item = NULL;
+        char addr4[INET_ADDRSTRLEN];
+        char addr6[INET6_ADDRSTRLEN];
+        int sock;
+        struct ifreq ifr;
+        unsigned char *mac_addr;
+        void *p;
+
+        g_debug("Processing %s interface", ifa->ifa_name);
+
+        info = guest_find_interface(head, ifa->ifa_name);
+
+        if (!info) {
+            info = g_malloc0(sizeof(*info));
+            info->value = g_malloc0(sizeof(*info->value));
+            info->value->name = g_strdup(ifa->ifa_name);
+
+            if (!cur_item) {
+                head = cur_item = info;
+            } else {
+                cur_item->next = info;
+                cur_item = info;
+            }
+        }
+
+        if (!info->value->has_hardware_address &&
+            ifa->ifa_flags & SIOCGIFHWADDR) {
+            /* we haven't obtained HW address yet */
+            sock = socket(PF_INET, SOCK_STREAM, 0);
+            if (sock == -1) {
+                snprintf(err_msg, sizeof(err_msg),
+                         "failed to create socket: %s", strerror(errno));
+                error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg);
+                goto error;
+            }
+
+            memset(&ifr, 0, sizeof(ifr));
+            strncpy(ifr.ifr_name,  info->value->name, IF_NAMESIZE);
+            if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) {
+                snprintf(err_msg, sizeof(err_msg),
+                         "failed to get MAC addres of %s: %s",
+                         ifa->ifa_name,
+                         strerror(errno));
+                error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg);
+                goto error;
+            }
+
+            mac_addr = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
+
+            if (asprintf(&info->value->hardware_address,
+                         "%02x:%02x:%02x:%02x:%02x:%02x",
+                         (int) mac_addr[0], (int) mac_addr[1],
+                         (int) mac_addr[2], (int) mac_addr[3],
+                         (int) mac_addr[4], (int) mac_addr[5]) == -1) {
+                snprintf(err_msg, sizeof(err_msg),
+                         "failed to format MAC: %s", strerror(errno));
+                error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg);
+                goto error;
+            }
+
+            info->value->has_hardware_address = true;
+            close(sock);
+        }
+
+        if (ifa->ifa_addr &&
+            ifa->ifa_addr->sa_family == AF_INET) {
+            /* interface with IPv4 address */
+            address_item = g_malloc0(sizeof(*address_item));
+            address_item->value = g_malloc0(sizeof(*address_item->value));
+            p = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
+            if (!inet_ntop(AF_INET, p, addr4, sizeof(addr4))) {
+                snprintf(err_msg, sizeof(err_msg),
+                         "inet_ntop failed : %s", strerror(errno));
+                error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg);
+                goto error;
+            }
+
+            address_item->value->ip_address = g_strdup(addr4);
+            address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV4;
+
+            if (ifa->ifa_netmask) {
+                /* Count the number of set bits in netmask.
+                 * This is safe as '1' and '0' cannot be shuffled in netmask. */
+                p = &((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr;
+                address_item->value->prefix = ctpop32(((uint32_t *) p)[0]);
+            }
+        } else if (ifa->ifa_addr &&
+                   ifa->ifa_addr->sa_family == AF_INET6) {
+            /* interface with IPv6 address */
+            address_item = g_malloc0(sizeof(*address_item));
+            address_item->value = g_malloc0(sizeof(*address_item->value));
+            p = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
+            if (!inet_ntop(AF_INET6, p, addr6, sizeof(addr6))) {
+                snprintf(err_msg, sizeof(err_msg),
+                         "inet_ntop failed : %s", strerror(errno));
+                error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg);
+                goto error;
+            }
+
+            address_item->value->ip_address = g_strdup(addr6);
+            address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV6;
+
+            if (ifa->ifa_netmask) {
+                /* Count the number of set bits in netmask.
+                 * This is safe as '1' and '0' cannot be shuffled in netmask. */
+                p = &((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr;
+                address_item->value->prefix =
+                    ctpop32(((uint32_t *) p)[0]) +
+                    ctpop32(((uint32_t *) p)[1]) +
+                    ctpop32(((uint32_t *) p)[2]) +
+                    ctpop32(((uint32_t *) p)[3]);
+            }
+        }
+
+        if (!address_item) {
+            continue;
+        }
+
+        address_list = &info->value->ip_addresses;
+
+        while (*address_list && (*address_list)->next) {
+            address_list = &(*address_list)->next;
+        }
+
+        if (!*address_list) {
+            *address_list = address_item;
+        } else {
+            (*address_list)->next = address_item;
+        }
+
+        info->value->has_ip_addresses = true;
+
+
+    }
+
+    freeifaddrs(ifap);
+    return head;
+
+error:
+    freeifaddrs(ifap);
+    qapi_free_GuestNetworkInterfaceList(head);
+    return NULL;
+}
+
 /* register init/cleanup routines for stateful command groups */
 void ga_command_state_init(GAState *s, GACommandState *cs)
 {
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index b7600ed..eb8d140 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -263,6 +263,12 @@ void qmp_guest_suspend_hybrid(Error **err)
     error_set(err, QERR_UNSUPPORTED);
 }
 
+GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **err)
+{
+    error_set(err, QERR_UNSUPPORTED);
+    return NULL;
+}
+
 /* register init/cleanup routines for stateful command groups */
 void ga_command_state_init(GAState *s, GACommandState *cs)
 {
commit f54603b6aa765514b2519e74114a2f417759d727
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Mon Mar 12 12:50:02 2012 -0500

    qemu-ga: add win32 guest-suspend-ram command
    
    S3 sleep implementation for windows.

diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 062e519..b7600ed 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -174,7 +174,8 @@ int64_t qmp_guest_fsfreeze_thaw(Error **err)
 }
 
 typedef enum {
-    GUEST_SUSPEND_MODE_DISK
+    GUEST_SUSPEND_MODE_DISK,
+    GUEST_SUSPEND_MODE_RAM
 } GuestSuspendMode;
 
 static void check_suspend_mode(GuestSuspendMode mode, Error **err)
@@ -192,18 +193,24 @@ static void check_suspend_mode(GuestSuspendMode mode, Error **err)
         goto out;
     }
 
-    if (mode == GUEST_SUSPEND_MODE_DISK) {
-        if (sys_pwr_caps.SystemS4) {
-            return;
+    switch (mode) {
+    case GUEST_SUSPEND_MODE_DISK:
+        if (!sys_pwr_caps.SystemS4) {
+            error_set(&local_err, QERR_QGA_COMMAND_FAILED,
+                      "suspend-to-disk not supported by OS");
         }
-    } else {
+        break;
+    case GUEST_SUSPEND_MODE_RAM:
+        if (!sys_pwr_caps.SystemS3) {
+            error_set(&local_err, QERR_QGA_COMMAND_FAILED,
+                      "suspend-to-ram not supported by OS");
+        }
+        break;
+    default:
         error_set(&local_err, QERR_INVALID_PARAMETER_VALUE, "mode",
                   "GuestSuspendMode");
-        goto out;
     }
 
-    error_set(&local_err, QERR_QGA_COMMAND_FAILED,
-              "suspend mode not supported by OS");
 out:
     if (local_err) {
         error_propagate(err, local_err);
@@ -239,7 +246,16 @@ void qmp_guest_suspend_disk(Error **err)
 
 void qmp_guest_suspend_ram(Error **err)
 {
-    error_set(err, QERR_UNSUPPORTED);
+    GuestSuspendMode *mode = g_malloc(sizeof(GuestSuspendMode));
+
+    *mode = GUEST_SUSPEND_MODE_RAM;
+    check_suspend_mode(*mode, err);
+    acquire_privilege(SE_SHUTDOWN_NAME, err);
+    execute_async(do_suspend, mode, err);
+
+    if (error_is_set(err)) {
+        g_free(mode);
+    }
 }
 
 void qmp_guest_suspend_hybrid(Error **err)
commit aa59637ea1c6a4c83430933f9c44c43e6c3f1b69
Author: Gal Hammer <ghammer at redhat.com>
Date:   Sun Jan 29 11:53:31 2012 +0200

    qemu-ga: add win32 guest-suspend-disk command.
    
    Implement guest-suspend-disk RPC for Windows. Functionally this should be
    equivalent to the posix implementation.
    
    Signed-off-by: Gal Hammer <ghammer at redhat.com>

diff --git a/configure b/configure
index 39d2b54..709e4b9 100755
--- a/configure
+++ b/configure
@@ -525,7 +525,7 @@ EOF
   bindir="\${prefix}"
   sysconfdir="\${prefix}"
   confsuffix=""
-  libs_qga="-lws2_32 -lwinmm $lib_qga"
+  libs_qga="-lws2_32 -lwinmm -lpowrprof $lib_qga"
 fi
 
 werror=""
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 7ef185f..062e519 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -5,12 +5,15 @@
  *
  * Authors:
  *  Michael Roth      <mdroth at linux.vnet.ibm.com>
+ *  Gal Hammer        <ghammer at redhat.com>
  *
  * This work is licensed under the terms of the GNU GPL, version 2 or later.
  * See the COPYING file in the top-level directory.
  */
 
 #include <glib.h>
+#include <wtypes.h>
+#include <powrprof.h>
 #include "qga/guest-agent-core.h"
 #include "qga-qmp-commands.h"
 #include "qerror.h"
@@ -19,10 +22,63 @@
 #define SHTDN_REASON_FLAG_PLANNED 0x80000000
 #endif
 
-void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
+static void acquire_privilege(const char *name, Error **err)
 {
     HANDLE token;
     TOKEN_PRIVILEGES priv;
+    Error *local_err = NULL;
+
+    if (error_is_set(err)) {
+        return;
+    }
+
+    if (OpenProcessToken(GetCurrentProcess(),
+        TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &token))
+    {
+        if (!LookupPrivilegeValue(NULL, name, &priv.Privileges[0].Luid)) {
+            error_set(&local_err, QERR_QGA_COMMAND_FAILED,
+                      "no luid for requested privilege");
+            goto out;
+        }
+
+        priv.PrivilegeCount = 1;
+        priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+        if (!AdjustTokenPrivileges(token, FALSE, &priv, 0, NULL, 0)) {
+            error_set(&local_err, QERR_QGA_COMMAND_FAILED,
+                      "unable to acquire requested privilege");
+            goto out;
+        }
+
+        CloseHandle(token);
+    } else {
+        error_set(&local_err, QERR_QGA_COMMAND_FAILED,
+                  "failed to open privilege token");
+    }
+
+out:
+    if (local_err) {
+        error_propagate(err, local_err);
+    }
+}
+
+static void execute_async(DWORD WINAPI (*func)(LPVOID), LPVOID opaque, Error **err)
+{
+    Error *local_err = NULL;
+
+    if (error_is_set(err)) {
+        return;
+    }
+    HANDLE thread = CreateThread(NULL, 0, func, opaque, 0, NULL);
+    if (!thread) {
+        error_set(&local_err, QERR_QGA_COMMAND_FAILED,
+                  "failed to dispatch asynchronous command");
+        error_propagate(err, local_err);
+    }
+}
+
+void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
+{
     UINT shutdown_flag = EWX_FORCE;
 
     slog("guest-shutdown called, mode: %s", mode);
@@ -41,16 +97,9 @@ void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
 
     /* Request a shutdown privilege, but try to shut down the system
        anyway. */
-    if (OpenProcessToken(GetCurrentProcess(),
-        TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &token))
-    {
-        LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
-            &priv.Privileges[0].Luid);
-
-        priv.PrivilegeCount = 1;
-        priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
-
-        AdjustTokenPrivileges(token, FALSE, &priv, 0, NULL, 0);
+    acquire_privilege(SE_SHUTDOWN_NAME, err);
+    if (error_is_set(err)) {
+        return;
     }
 
     if (!ExitWindowsEx(shutdown_flag, SHTDN_REASON_FLAG_PLANNED)) {
@@ -124,9 +173,68 @@ int64_t qmp_guest_fsfreeze_thaw(Error **err)
     return 0;
 }
 
+typedef enum {
+    GUEST_SUSPEND_MODE_DISK
+} GuestSuspendMode;
+
+static void check_suspend_mode(GuestSuspendMode mode, Error **err)
+{
+    SYSTEM_POWER_CAPABILITIES sys_pwr_caps;
+    Error *local_err = NULL;
+
+    if (error_is_set(err)) {
+        return;
+    }
+    ZeroMemory(&sys_pwr_caps, sizeof(sys_pwr_caps));
+    if (!GetPwrCapabilities(&sys_pwr_caps)) {
+        error_set(&local_err, QERR_QGA_COMMAND_FAILED,
+                  "failed to determine guest suspend capabilities");
+        goto out;
+    }
+
+    if (mode == GUEST_SUSPEND_MODE_DISK) {
+        if (sys_pwr_caps.SystemS4) {
+            return;
+        }
+    } else {
+        error_set(&local_err, QERR_INVALID_PARAMETER_VALUE, "mode",
+                  "GuestSuspendMode");
+        goto out;
+    }
+
+    error_set(&local_err, QERR_QGA_COMMAND_FAILED,
+              "suspend mode not supported by OS");
+out:
+    if (local_err) {
+        error_propagate(err, local_err);
+    }
+}
+
+static DWORD WINAPI do_suspend(LPVOID opaque)
+{
+    GuestSuspendMode *mode = opaque;
+    DWORD ret = 0;
+
+    if (!SetSuspendState(*mode == GUEST_SUSPEND_MODE_DISK, TRUE, TRUE)) {
+        slog("failed to suspend guest, %s", GetLastError());
+        ret = -1;
+    }
+    g_free(mode);
+    return ret;
+}
+
 void qmp_guest_suspend_disk(Error **err)
 {
-    error_set(err, QERR_UNSUPPORTED);
+    GuestSuspendMode *mode = g_malloc(sizeof(GuestSuspendMode));
+
+    *mode = GUEST_SUSPEND_MODE_DISK;
+    check_suspend_mode(*mode, err);
+    acquire_privilege(SE_SHUTDOWN_NAME, err);
+    execute_async(do_suspend, mode, err);
+
+    if (error_is_set(err)) {
+        g_free(mode);
+    }
 }
 
 void qmp_guest_suspend_ram(Error **err)
commit 95f4f404e108f8c6b937ddf2ba973f3799b51fb5
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Tue Feb 28 11:03:05 2012 -0300

    qemu-ga: add guest-suspend-hybrid
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qapi-schema-guest.json b/qapi-schema-guest.json
index b102311..6a75552 100644
--- a/qapi-schema-guest.json
+++ b/qapi-schema-guest.json
@@ -347,3 +347,26 @@
 # Since: 1.1
 ##
 { 'command': 'guest-suspend-ram' }
+
+##
+# @guest-suspend-hybrid
+#
+# Save guest state to disk and suspend to ram.
+#
+# This command requires the pm-utils package to be installed in the guest.
+#
+# IMPORTANT: guest-suspend-hybrid requires QEMU to support the 'system_wakeup'
+# command.  Thus, it's *required* to query QEMU for the presence of the
+# 'system_wakeup' command before issuing guest-suspend-hybrid.
+#
+# Returns: nothing on success
+#          If hybrid suspend is not supported, Unsupported
+#
+# Notes: o This is an asynchronous request. There's no guarantee a response
+#          will be sent
+#        o It's strongly recommended to issue the guest-sync command before
+#          sending commands when the guest resumes
+#
+# Since: 1.1
+##
+{ 'command': 'guest-suspend-hybrid' }
diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 134c130..79571bf 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -715,6 +715,16 @@ void qmp_guest_suspend_ram(Error **err)
     guest_suspend("pm-suspend", "mem", err);
 }
 
+void qmp_guest_suspend_hybrid(Error **err)
+{
+    bios_supports_mode("pm-is-supported", "--suspend-hybrid", NULL, err);
+    if (error_is_set(err)) {
+        return;
+    }
+
+    guest_suspend("pm-suspend-hybrid", NULL, err);
+}
+
 /* register init/cleanup routines for stateful command groups */
 void ga_command_state_init(GAState *s, GACommandState *cs)
 {
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index b19a63c..7ef185f 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -134,6 +134,11 @@ void qmp_guest_suspend_ram(Error **err)
     error_set(err, QERR_UNSUPPORTED);
 }
 
+void qmp_guest_suspend_hybrid(Error **err)
+{
+    error_set(err, QERR_UNSUPPORTED);
+}
+
 /* register init/cleanup routines for stateful command groups */
 void ga_command_state_init(GAState *s, GACommandState *cs)
 {
commit fbf42210c19ec4315e409b7f9f0bfa46c7dfb921
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Tue Feb 28 11:03:04 2012 -0300

    qemu-ga: add guest-suspend-ram
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qapi-schema-guest.json b/qapi-schema-guest.json
index f4e0e1d..b102311 100644
--- a/qapi-schema-guest.json
+++ b/qapi-schema-guest.json
@@ -319,3 +319,31 @@
 # Since: 1.1
 ##
 { 'command': 'guest-suspend-disk' }
+
+##
+# @guest-suspend-ram
+#
+# Suspend guest to ram.
+#
+# This command tries to execute the scripts provided by the pm-utils package.
+# If it's not available, the suspend operation will be performed by manually
+# writing to a sysfs file.
+#
+# For the best results it's strongly recommended to have the pm-utils
+# package installed in the guest.
+#
+# IMPORTANT: guest-suspend-ram requires QEMU to support the 'system_wakeup'
+# command.  Thus, it's *required* to query QEMU for the presence of the
+# 'system_wakeup' command before issuing guest-suspend-ram.
+#
+# Returns: nothing on success
+#          If suspend to ram is not supported, Unsupported
+#
+# Notes: o This is an asynchronous request. There's no guarantee a response
+#          will be sent
+#        o It's strongly recommended to issue the guest-sync command before
+#          sending commands when the guest resumes
+#
+# Since: 1.1
+##
+{ 'command': 'guest-suspend-ram' }
diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index af785f5..134c130 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -705,6 +705,16 @@ void qmp_guest_suspend_disk(Error **err)
     guest_suspend("pm-hibernate", "disk", err);
 }
 
+void qmp_guest_suspend_ram(Error **err)
+{
+    bios_supports_mode("pm-is-supported", "--suspend", "mem", err);
+    if (error_is_set(err)) {
+        return;
+    }
+
+    guest_suspend("pm-suspend", "mem", err);
+}
+
 /* register init/cleanup routines for stateful command groups */
 void ga_command_state_init(GAState *s, GACommandState *cs)
 {
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index c688476..b19a63c 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -129,6 +129,11 @@ void qmp_guest_suspend_disk(Error **err)
     error_set(err, QERR_UNSUPPORTED);
 }
 
+void qmp_guest_suspend_ram(Error **err)
+{
+    error_set(err, QERR_UNSUPPORTED);
+}
+
 /* register init/cleanup routines for stateful command groups */
 void ga_command_state_init(GAState *s, GACommandState *cs)
 {
commit 11d0f1255bd5651f628280dc96c4ce9d63ae9236
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Tue Feb 28 11:03:03 2012 -0300

    qemu-ga: add guest-suspend-disk
    
    As the command name implies, this command suspends the guest to disk.
    
    The suspend operation is implemented by two functions: bios_supports_mode()
    and guest_suspend(). Both functions are generic enough to be used by
    other suspend modes (introduced by next commits).
    
    Both functions will try to use the scripts provided by the pm-utils
    package if it's available. If it's not available, a manual method,
    which consists of directly writing to '/sys/power/state', will be used.
    
    To reap terminated children, a new signal handler is installed in the
    parent to catch SIGCHLD signals and a non-blocking call to waitpid()
    is done to collect their exit statuses. The statuses, however, are
    discarded.
    
    The approach used to query the guest for suspend support deserves some
    explanation. It's implemented by bios_supports_mode() and shown below:
    
      qemu-ga
         |
     create pipe
         |
       fork()
         -----------------
         |               |
         |               |
         |             fork()
         |               --------------------------
         |               |                        |
         |               |                        |
         |               |               exec('pm-is-supported')
         |               |
         |              wait()
         |       write exit status to pipe
         |              exit
         |
      read pipe
    
    This might look complex, but the resulting code is quite simple.
    The purpose of that approach is to allow qemu-ga to reap its children
    (semi-)automatically from its SIGCHLD handler.
    
    Implementing this the obvious way, that's, doing the exec() call from
    the first child process, would force us to introduce a more complex way
    to reap qemu-ga's children. Like registering PIDs to be reaped and
    having a way to wait for them when returning their exit status to
    qemu-ga is necessary. The approach explained above avoids that complexity.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qapi-schema-guest.json b/qapi-schema-guest.json
index 706925d..f4e0e1d 100644
--- a/qapi-schema-guest.json
+++ b/qapi-schema-guest.json
@@ -295,3 +295,27 @@
 ##
 { 'command': 'guest-fsfreeze-thaw',
   'returns': 'int' }
+
+##
+# @guest-suspend-disk
+#
+# Suspend guest to disk.
+#
+# This command tries to execute the scripts provided by the pm-utils package.
+# If it's not available, the suspend operation will be performed by manually
+# writing to a sysfs file.
+#
+# For the best results it's strongly recommended to have the pm-utils
+# package installed in the guest.
+#
+# Returns: nothing on success
+#          If suspend to disk is not supported, Unsupported
+#
+# Notes: o This is an asynchronous request. There's no guarantee a response
+#          will be sent
+#        o It's strongly recommended to issue the guest-sync command before
+#          sending commands when the guest resumes
+#
+# Since: 1.1
+##
+{ 'command': 'guest-suspend-disk' }
diff --git a/qemu-ga.c b/qemu-ga.c
index ba355d8..1c90e6e 100644
--- a/qemu-ga.c
+++ b/qemu-ga.c
@@ -17,6 +17,7 @@
 #include <getopt.h>
 #ifndef _WIN32
 #include <syslog.h>
+#include <sys/wait.h>
 #endif
 #include "json-streamer.h"
 #include "json-parser.h"
@@ -73,9 +74,16 @@ static void quit_handler(int sig)
 }
 
 #ifndef _WIN32
+/* reap _all_ terminated children */
+static void child_handler(int sig)
+{
+    int status;
+    while (waitpid(-1, &status, WNOHANG) > 0) /* NOTHING */;
+}
+
 static gboolean register_signal_handlers(void)
 {
-    struct sigaction sigact;
+    struct sigaction sigact, sigact_chld;
     int ret;
 
     memset(&sigact, 0, sizeof(struct sigaction));
@@ -91,6 +99,15 @@ static gboolean register_signal_handlers(void)
         g_error("error configuring signal handler: %s", strerror(errno));
         return false;
     }
+
+    memset(&sigact_chld, 0, sizeof(struct sigaction));
+    sigact_chld.sa_handler = child_handler;
+    sigact_chld.sa_flags = SA_NOCLDSTOP;
+    ret = sigaction(SIGCHLD, &sigact_chld, NULL);
+    if (ret == -1) {
+        g_error("error configuring signal handler: %s", strerror(errno));
+    }
+
     return true;
 }
 #endif
diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 126127a..af785f5 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -23,6 +23,7 @@
 
 #include <sys/types.h>
 #include <sys/ioctl.h>
+#include <sys/wait.h>
 #include "qga/guest-agent-core.h"
 #include "qga-qmp-commands.h"
 #include "qerror.h"
@@ -30,6 +31,22 @@
 
 static GAState *ga_state;
 
+static void reopen_fd_to_null(int fd)
+{
+    int nullfd;
+
+    nullfd = open("/dev/null", O_RDWR);
+    if (nullfd < 0) {
+        return;
+    }
+
+    dup2(nullfd, fd);
+
+    if (nullfd != fd) {
+        close(nullfd);
+    }
+}
+
 void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
 {
     int ret;
@@ -517,6 +534,177 @@ int64_t qmp_guest_fsfreeze_thaw(Error **err)
 }
 #endif
 
+#define LINUX_SYS_STATE_FILE "/sys/power/state"
+#define SUSPEND_SUPPORTED 0
+#define SUSPEND_NOT_SUPPORTED 1
+
+/**
+ * This function forks twice and the information about the mode support
+ * status is passed to the qemu-ga process via a pipe.
+ *
+ * This approach allows us to keep the way we reap terminated children
+ * in qemu-ga quite simple.
+ */
+static void bios_supports_mode(const char *pmutils_bin, const char *pmutils_arg,
+                               const char *sysfile_str, Error **err)
+{
+    pid_t pid;
+    ssize_t ret;
+    char *pmutils_path;
+    int status, pipefds[2];
+
+    if (pipe(pipefds) < 0) {
+        error_set(err, QERR_UNDEFINED_ERROR);
+        return;
+    }
+
+    pmutils_path = g_find_program_in_path(pmutils_bin);
+
+    pid = fork();
+    if (!pid) {
+        struct sigaction act;
+
+        memset(&act, 0, sizeof(act));
+        act.sa_handler = SIG_DFL;
+        sigaction(SIGCHLD, &act, NULL);
+
+        setsid();
+        close(pipefds[0]);
+        reopen_fd_to_null(0);
+        reopen_fd_to_null(1);
+        reopen_fd_to_null(2);
+
+        pid = fork();
+        if (!pid) {
+            int fd;
+            char buf[32]; /* hopefully big enough */
+
+            if (pmutils_path) {
+                execle(pmutils_path, pmutils_bin, pmutils_arg, NULL, environ);
+            }
+
+            /*
+             * If we get here either pm-utils is not installed or execle() has
+             * failed. Let's try the manual method if the caller wants it.
+             */
+
+            if (!sysfile_str) {
+                _exit(SUSPEND_NOT_SUPPORTED);
+            }
+
+            fd = open(LINUX_SYS_STATE_FILE, O_RDONLY);
+            if (fd < 0) {
+                _exit(SUSPEND_NOT_SUPPORTED);
+            }
+
+            ret = read(fd, buf, sizeof(buf)-1);
+            if (ret <= 0) {
+                _exit(SUSPEND_NOT_SUPPORTED);
+            }
+            buf[ret] = '\0';
+
+            if (strstr(buf, sysfile_str)) {
+                _exit(SUSPEND_SUPPORTED);
+            }
+
+            _exit(SUSPEND_NOT_SUPPORTED);
+        }
+
+        if (pid > 0) {
+            wait(&status);
+        } else {
+            status = SUSPEND_NOT_SUPPORTED;
+        }
+
+        ret = write(pipefds[1], &status, sizeof(status));
+        if (ret != sizeof(status)) {
+            _exit(EXIT_FAILURE);
+        }
+
+        _exit(EXIT_SUCCESS);
+    }
+
+    close(pipefds[1]);
+    g_free(pmutils_path);
+
+    if (pid < 0) {
+        error_set(err, QERR_UNDEFINED_ERROR);
+        goto out;
+    }
+
+    ret = read(pipefds[0], &status, sizeof(status));
+    if (ret == sizeof(status) && WIFEXITED(status) &&
+        WEXITSTATUS(status) == SUSPEND_SUPPORTED) {
+            goto out;
+    }
+
+    error_set(err, QERR_UNSUPPORTED);
+
+out:
+    close(pipefds[0]);
+}
+
+static void guest_suspend(const char *pmutils_bin, const char *sysfile_str,
+                          Error **err)
+{
+    pid_t pid;
+    char *pmutils_path;
+
+    pmutils_path = g_find_program_in_path(pmutils_bin);
+
+    pid = fork();
+    if (pid == 0) {
+        /* child */
+        int fd;
+
+        setsid();
+        reopen_fd_to_null(0);
+        reopen_fd_to_null(1);
+        reopen_fd_to_null(2);
+
+        if (pmutils_path) {
+            execle(pmutils_path, pmutils_bin, NULL, environ);
+        }
+
+        /*
+         * If we get here either pm-utils is not installed or execle() has
+         * failed. Let's try the manual method if the caller wants it.
+         */
+
+        if (!sysfile_str) {
+            _exit(EXIT_FAILURE);
+        }
+
+        fd = open(LINUX_SYS_STATE_FILE, O_WRONLY);
+        if (fd < 0) {
+            _exit(EXIT_FAILURE);
+        }
+
+        if (write(fd, sysfile_str, strlen(sysfile_str)) < 0) {
+            _exit(EXIT_FAILURE);
+        }
+
+        _exit(EXIT_SUCCESS);
+    }
+
+    g_free(pmutils_path);
+
+    if (pid < 0) {
+        error_set(err, QERR_UNDEFINED_ERROR);
+        return;
+    }
+}
+
+void qmp_guest_suspend_disk(Error **err)
+{
+    bios_supports_mode("pm-is-supported", "--hibernate", "disk", err);
+    if (error_is_set(err)) {
+        return;
+    }
+
+    guest_suspend("pm-hibernate", "disk", err);
+}
+
 /* register init/cleanup routines for stateful command groups */
 void ga_command_state_init(GAState *s, GACommandState *cs)
 {
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 4aa0f0d..c688476 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -124,6 +124,11 @@ int64_t qmp_guest_fsfreeze_thaw(Error **err)
     return 0;
 }
 
+void qmp_guest_suspend_disk(Error **err)
+{
+    error_set(err, QERR_UNSUPPORTED);
+}
+
 /* register init/cleanup routines for stateful command groups */
 void ga_command_state_init(GAState *s, GACommandState *cs)
 {
commit 8d9dde9429d2b5b513bf92d94a257a00ea2da1bf
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 9 14:33:20 2012 +0000

    cpu-all.h: Don't accidentally sign extend in g2h()
    
    Cast the argument of the g2h() macro to a target_ulong so that
    it isn't accidentally sign-extended if it is a signed 32 bit
    type and long is a 64 bit type. In particular, this fixes a
    bug where it would return the wrong value for 32 bit guests
    on 64 bit hosts when passed in one of the arg* values from
    do_syscall() [which are all abi_long and thus signed types].
    This could result in spurious failure of mlock(), among others.
    
    Reviewed-by: Andreas F=E4rber <afaerber at suse.de>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/cpu-all.h b/cpu-all.h
index 80e6d42..a174532 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -197,7 +197,7 @@ extern unsigned long reserved_va;
 #endif
 
 /* All direct uses of g2h and h2g need to go away for usermode softmmu.  */
-#define g2h(x) ((void *)((unsigned long)(x) + GUEST_BASE))
+#define g2h(x) ((void *)((unsigned long)(target_ulong)(x) + GUEST_BASE))
 
 #if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
 #define h2g_valid(x) 1
commit 1d3323de5fe5656844ea57a16eb432f09a366140
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Mar 8 11:19:19 2012 +0100

    implement vnc_dpy_setdata
    
    The comment is wrong, we have to do something in the setdata callback.
    Changing the framebuffer backing storage (happens when the guest pans
    the display) renders the whole screen content invalid.
    
    Trigger #1: cirrus vga + 32bit linux guest + vesafb with ypan enabled.
    Trigger #2: std vga + http://patchwork.ozlabs.org/patch/145479/
    
    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 8ee39bc..bdec33a 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1936,7 +1936,10 @@ static void pixel_format_message (VncState *vs) {
 
 static void vnc_dpy_setdata(DisplayState *ds)
 {
-    /* We don't have to do anything */
+    VncDisplay *vd = ds->opaque;
+
+    *(vd->guest.ds) = *(ds->surface);
+    vnc_dpy_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
 }
 
 static void vnc_colordepth(VncState *vs)
commit ecf40beae7dcbb057d4f115207f9d8276832a774
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Fri Mar 9 16:19:07 2012 -0300

    initialize CPU model list after handling -readconfig options
    
    To properly load cpudefs using -readconfig, we have to call
    cpudef_init() after finishing the command-line option handling.
    
    Consequently, the handling of "-cpu ?" has to be done after the
    command-line option handling loop, too.
    
    Without this patch, "-readconfig configfile -cpu ?" fails to list the
    CPU definitions read from 'configfile'.
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vl.c b/vl.c
index 97ab2b9..65f11f2 100644
--- a/vl.c
+++ b/vl.c
@@ -2359,7 +2359,6 @@ int main(int argc, char **argv, char **envp)
             exit(1);
         }
     }
-    cpudef_init();
 
     /* second pass of option parsing */
     optind = 1;
@@ -2382,12 +2381,7 @@ int main(int argc, char **argv, char **envp)
                 break;
             case QEMU_OPTION_cpu:
                 /* hw initialization will check this */
-                if (*optarg == '?') {
-                    list_cpus(stdout, &fprintf, optarg);
-                    exit(0);
-                } else {
-                    cpu_model = optarg;
-                }
+                cpu_model = optarg;
                 break;
             case QEMU_OPTION_hda:
                 {
@@ -3191,6 +3185,18 @@ int main(int argc, char **argv, char **envp)
     }
     loc_set_none();
 
+    /* Init CPU def lists, based on config
+     * - Must be called after all the qemu_read_config_file() calls
+     * - Must be called before list_cpus()
+     * - Must be called before machine->init()
+     */
+    cpudef_init();
+
+    if (cpu_model && *cpu_model == '?') {
+        list_cpus(stdout, &fprintf, optarg);
+        exit(0);
+    }
+
     /* Open the logfile at this point, if necessary. We can't open the logfile
      * when encountering either of the logging options (-d or -D) because the
      * other one may be encountered later on the command line, changing the
commit 885bb0369a4f0abe2c0185178f3cb347cb02cdf1
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Tue Mar 6 15:11:32 2012 -0300

    add Opteron_G4 CPU model (v2)
    
    This patch addes a Bulldozer-based Opteron_G4 CPU model.
    
    This version has the ffxsr bit actually disabled, to match what was
    documented below. Thanks to Andre Przywara for spotting the bug.
    
    I am trying to be conservative with the new model, so I am enabling only
    features known to be useful to guests, and not enabling anything that
    was not tested or found to be useful to a guest.
    
    List of missing flags in comparison to real hardware:
    
    - vme: host-specific feature.
    - osxsave: it is not set here because it is set by the guest OS, not by KVM
    - monitor: this is filtered out by the KVM module, so no point in
      enabling it.
    - mmxext: untested, so not enabled.
    - Perf*, Topology*, lwp, ibs: not emulated by KVM.
    - wdt, skinit, osvw, altmovcr8, extapicspace, cmplegacy: untested,
      so not enabled.
    
    List of new flags, in comparison to the Opteron_G3 model:
    
    - xsave: xsave feature, already implemented by Qemu
    - avx, aes, sse4.x, ssse3, pclmulqdq: all new state the new instructions
      could use is handled by the xsave state loading/saving code on Qemu.
    - pdpe1gb: 1GB pages, supported by the KVM kernel module.
    - ffxsr: untested, so not enabled
    - fma4, xop: all new state the new instructions could use is handled by
      the xsave loading/saving code on Qemu.
    - 3dnowprefetch: safe to pass through, though the flag is not used by
      Linux guests, at least.
    
    Below is the comparison between the current Opteron_G3 model
    and the new model being added.
    
    - The "full" line contains the flags found on actual hardware.
    - The "missing" line shows the flags that are present on actual
      hardware, but not on the added Opteron_G4 model.
    - The "new" line shows the flags that were not on the Opteron_G3 model
      but are on Opteron_G4.
    
    feature_edx:
      Opteron_G3: sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de     fpu
      full:       sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de vme fpu
      Opteron_G4: sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de     fpu
      missing:                                                                                              vme
    
    feature_ecx:
      Opteron_G3:                       popcnt               cx16       monitor           sse3
      full:       avx osxsave xsave aes popcnt sse4.2 sse4.1 cx16 ssse3 monitor pclmulqdq sse3
      Opteron_G4: avx         xsave aes popcnt sse4.2 sse4.1 cx16 ssse3         pclmulqdq sse3
      missing:        osxsave                                           monitor
      new:        avx         xsave aes        sse4.2 sse4.1      ssse3         pclmulqdq
    
    extfeature_edx:
      Opteron_G3: lm rdtscp               fxsr mmx        nx pse36 pat cmov mca pge mtrr syscall apic cx8 mce pae msr tsc pse de     fpu
      full:       lm rdtscp pdpe1gb ffxsr fxsr mmx mmxext nx pse36 pat cmov mca pge mtrr syscall apic cx8 mce pae msr tsc pse de vme fpu
      Opteron_G4: lm rdtscp pdpe1gb       fxsr mmx        nx pse36 pat cmov mca pge mtrr syscall apic cx8 mce pae msr tsc pse de     fpu
      missing:                                     mmxext                                                                        vme
      new:                  pdpe1gb
    
    extfeature_ecx:
      Opteron_G3:                                                                misalignsse sse4a abm                        svm           lahf_lm
      full:       Perf* Topology* fma4 lwp wdt skinit xop ibs osvw 3dnowprefetch misalignsse sse4a abm altmovcr8 extapicspace svm cmplegacy lahf_lm
      Opteron_G4:                 fma4                xop          3dnowprefetch misalignsse sse4a abm                        svm           lahf_lm
      new:                        fma4                xop          3dnowprefetch
      missing:    Perf* Topology*      lwp wdt skinit     ibs osvw                                     altmovcr8 extapicspace     cmplegacy
    
    Changes v1 -> v2:
     - Actually disable ffxsr bit
    
    Cc: Andre Przywara <andre.przywara at amd.com>
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/sysconfigs/target/target-x86_64.conf b/sysconfigs/target/target-x86_64.conf
index 9fecb94..cee0ea9 100644
--- a/sysconfigs/target/target-x86_64.conf
+++ b/sysconfigs/target/target-x86_64.conf
@@ -112,3 +112,17 @@
    xlevel = "0x80000008"
    model_id = "AMD Opteron 23xx (Gen 3 Class Opteron)"
 
+[cpudef]
+   name = "Opteron_G4"
+   level = "0xd"
+   vendor = "AuthenticAMD"
+   family = "21"
+   model = "1"
+   stepping = "2"
+   feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu"
+   feature_ecx = "avx xsave aes popcnt sse4.2 sse4.1 cx16 ssse3 pclmulqdq sse3"
+   extfeature_edx = "lm rdtscp pdpe1gb fxsr mmx nx pse36 pat cmov mca pge mtrr syscall apic cx8 mce pae msr tsc pse de fpu"
+   extfeature_ecx = " fma4 xop 3dnowprefetch misalignsse sse4a abm svm lahf_lm"
+   xlevel = "0x8000001A"
+   model_id = "AMD Opteron 62xx class CPU"
+
commit c34ea31416a9631b0a552afa08b99ec29cf44272
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Tue Mar 6 15:11:31 2012 -0300

    add SandyBridge CPU model
    
    This patches add the definition of a SandyBridge CPU model.
    
    Summary of differences:
    
    Flags present on actual hardware, but not on the added model definition:
    
    - pbe, tm, ht, ss, acpi, vme, xTPR, tm2, eist, smx: host-specific
      features, not exposed to guest.
    - ds, ds-cpl, dtes64, pdcm: emulation not supported by KVM (although it
      may be added in the future if implementing PMU virtualization)
    - pcid, vmx, monitor: not emulated by Qemu/KVM right now.
    - osxsave: set by the guest OS, not by Qemu.
    
    Flags added, that were not present on Westmere model:
    
    - xsave: already supported by Qemu
    - avx, pclmulqdq: all new state the new instructions could use is
      handled by xsave state loading/saving code.
    - tsc-deadline, x2apic, rdtscp: already supported by Qemu/KVM.
    
    Below there's a comparison of the features on the current Westmere CPU
    model, and the SandyBridge CPU model.
    
    - The "full" line contains the flags found on actual hardware.
    - The "missing" line shows the flags that are present on actual
      hardware, but not on the added SandyBridge model.
    - The "new" line shows the flags that were not on the Westmere model,
      but are on SandyBridge.
    
    feature_edx:
      Westmere:                 sse2 sse fxsr mmx         clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de     fpu
      full:        pbe tm ht ss sse2 sse fxsr mmx ds acpi clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pge msr tsc pse de vme fpu
      SandyBridge:              sse2 sse fxsr mmx         clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de     fpu
      missing:     pbe tm ht ss                   ds acpi                                                                         vme
    
    feature_ecx:
      Westmere:                      aes              popcnt        sse4.2 sse4.1                cx16 ssse3                                                  sse3
      full:        avx osxsave xsave aes tsc-deadline popcnt x2apic sse4.2 sse4.1 pcid pdcm xTPR cx16 ssse3 tm2 eist smx vmx ds-cpl monitor dtes64 pclmulqdq sse3
      SandyBridge: avx         xsave aes tsc-deadline popcnt x2apic sse4.2 sse4.1                cx16 ssse3                                        pclmulqdq sse3
      missing:         osxsave                                                    pcid pdcm xTPR            tm2 eist smx vmx ds-cpl monitor dtes64
      new:         avx         xsave     tsc-deadline        x2apic                                                                                pclmulqdq
    
    extfeature_edx:
      Westmere:    i64        nx syscall
      full:        i64 rdtscp nx syscall
      SandyBridge: i64 rdtscp nx syscall
      new:             rdtscp
    
    extfeature_ecx:
      Westmere:    lahf_lm
      full:        lahf_lm
      SandyBridge: lahf_lm
    
    Cc: "Dugger, Donald D" <donald.d.dugger at intel.com>
    Cc: "Zhang, Xiantao" <xiantao.zhang at intel.com>
    Acked-by: Xiantao Zhang <xiantao.zhang at intel.com>
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/sysconfigs/target/target-x86_64.conf b/sysconfigs/target/target-x86_64.conf
index d050380..9fecb94 100644
--- a/sysconfigs/target/target-x86_64.conf
+++ b/sysconfigs/target/target-x86_64.conf
@@ -57,6 +57,20 @@
    model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)"
 
 [cpudef]
+   name = "SandyBridge"
+   level = "0xd"
+   vendor = "GenuineIntel"
+   family = "6"
+   model = "42"
+   stepping = "1"
+   feature_edx = " sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu"
+   feature_ecx = "avx xsave aes tsc-deadline popcnt x2apic sse4.2 sse4.1 cx16 ssse3 pclmulqdq sse3"
+   extfeature_edx = "i64 rdtscp nx syscall "
+   extfeature_ecx = "lahf_lm"
+   xlevel = "0x8000000A"
+   model_id = "Intel Xeon E312xx (Sandy Bridge)"
+
+[cpudef]
    name = "Opteron_G1"
    level = "5"
    vendor = "AuthenticAMD"
commit eaf3f0974ba48e3ebf76b331101ad333957432af
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Tue Mar 6 15:11:30 2012 -0300

    add "tsc-deadline" flag name to feature_ecx table
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index c2edb64..465ea15 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -50,7 +50,7 @@ static const char *ext_feature_name[] = {
     "fma", "cx16", "xtpr", "pdcm",
     NULL, NULL, "dca", "sse4.1|sse4_1",
     "sse4.2|sse4_2", "x2apic", "movbe", "popcnt",
-    NULL, "aes", "xsave", "osxsave",
+    "tsc-deadline", "aes", "xsave", "osxsave",
     "avx", NULL, NULL, "hypervisor",
 };
 static const char *ext2_feature_name[] = {
commit 6c1fdcf902bb61920e0cf8476b213a85c0697c09
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Feb 28 09:54:15 2012 +0100

    qom: fix device hot-unplug
    
    Property removal modifies the list, so it is not safe to continue
    iteration.  We know anyway that each object can have only one
    parent (see object_property_add_child), so exit after finding
    the requested object.
    
    Reported-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qom/object.c b/qom/object.c
index aa037d2..39cbcb9 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -304,12 +304,9 @@ static void object_property_del_child(Object *obj, Object *child, Error **errp)
     ObjectProperty *prop;
 
     QTAILQ_FOREACH(prop, &obj->properties, node) {
-        if (!strstart(prop->type, "child<", NULL)) {
-            continue;
-        }
-
-        if (prop->opaque == child) {
+        if (strstart(prop->type, "child<", NULL) && prop->opaque == child) {
             object_property_del(obj, prop->name, errp);
+            break;
         }
     }
 }
commit 66d341e54f7b81ff076ffd681ed574d557bd7495
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Feb 28 09:54:14 2012 +0100

    qdev: accept empty string properties
    
    These were stored as NULL due to wrong cut-and-paste from set_pointer.
    
    Reported-by: Gerhard Wiesinger <lists at wiesinger.com>
    Tested-by: Gerhard Wiesinger <lists at wiesinger.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 0423af1..bff9152 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -421,10 +421,6 @@ static void set_string(Object *obj, Visitor *v, void *opaque,
         error_propagate(errp, local_err);
         return;
     }
-    if (!*str) {
-        g_free(str);
-        str = NULL;
-    }
     if (*ptr) {
         g_free(*ptr);
     }
commit 7e849a9919aac147a768a775014f2eff98e44323
Author: Alex Barcelo <abarcelo at ac.upc.edu>
Date:   Thu Feb 16 13:14:06 2012 +0100

    test-coroutine: add performance test for nesting
    
    The performance test will also check for nesting. It will do
    a certain quantity of cycles, and each of one will do a depth
    nesting process.
    
    This is useful for benchmarking the creation of coroutines,
    given that nesting is creation-intensive (and the other perf
    test does not benchmark that).
    
    Signed-off-by: Alex Barcelo <abarcelo at ac.upc.edu>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/test-coroutine.c b/test-coroutine.c
index bf9f3e9..e5d14eb 100644
--- a/test-coroutine.c
+++ b/test-coroutine.c
@@ -177,6 +177,32 @@ static void perf_lifecycle(void)
     g_test_message("Lifecycle %u iterations: %f s\n", max, duration);
 }
 
+static void perf_nesting(void)
+{
+    unsigned int i, maxcycles, maxnesting;
+    double duration;
+
+    maxcycles = 100000000;
+    maxnesting = 20000;
+    Coroutine *root;
+    NestData nd = {
+        .n_enter  = 0,
+        .n_return = 0,
+        .max      = maxnesting,
+    };
+
+    g_test_timer_start();
+    for (i = 0; i < maxcycles; i++) {
+        root = qemu_coroutine_create(nest);
+        qemu_coroutine_enter(root, &nd);
+    }
+    duration = g_test_timer_elapsed();
+
+    g_test_message("Nesting %u iterations of %u depth each: %f s\n",
+        maxcycles, maxnesting, duration);
+}
+
+
 int main(int argc, char **argv)
 {
     g_test_init(&argc, &argv, NULL);
@@ -187,6 +213,7 @@ int main(int argc, char **argv)
     g_test_add_func("/basic/in_coroutine", test_in_coroutine);
     if (g_test_perf()) {
         g_test_add_func("/perf/lifecycle", perf_lifecycle);
+        g_test_add_func("/perf/nesting", perf_nesting);
     }
     return g_test_run();
 }
commit fe91bfa8a26832cc07a6b74b8decfb687499caee
Author: Alex Barcelo <abarcelo at ac.upc.edu>
Date:   Tue Feb 28 12:25:51 2012 +0100

    coroutine: adding configure option for sigaltstack coroutine backend
    
    It's possible to use sigaltstack backend with --with-coroutine=sigaltstack
    
    v2: changed from enable/disable configure flags
    
    Signed-off-by: Alex Barcelo <abarcelo at ac.upc.edu>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index b39d76c..5f0b3f7 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -17,8 +17,12 @@ coroutine-obj-y += qemu-coroutine-sleep.o
 ifeq ($(CONFIG_UCONTEXT_COROUTINE),y)
 coroutine-obj-$(CONFIG_POSIX) += coroutine-ucontext.o
 else
+ifeq ($(CONFIG_SIGALTSTACK_COROUTINE),y)
+coroutine-obj-$(CONFIG_POSIX) += coroutine-sigaltstack.o
+else
 coroutine-obj-$(CONFIG_POSIX) += coroutine-gthread.o
 endif
+endif
 coroutine-obj-$(CONFIG_WIN32) += coroutine-win32.o
 
 #######################################################################
diff --git a/configure b/configure
index bb80822..ddb3e39 100755
--- a/configure
+++ b/configure
@@ -1114,7 +1114,7 @@ echo "  --enable-usb-redir       enable usb network redirection support"
 echo "  --disable-guest-agent    disable building of the QEMU Guest Agent"
 echo "  --enable-guest-agent     enable building of the QEMU Guest Agent"
 echo "  --with-coroutine=BACKEND coroutine backend. Supported options:"
-echo "                           gthread, ucontext, windows"
+echo "                           gthread, ucontext, sigaltstack, windows"
 echo ""
 echo "NOTE: The object files are built at the place where configure is launched"
 exit 1
@@ -2745,6 +2745,8 @@ elif test "$coroutine" = "gthread" ; then
   coroutine_backend=gthread
 elif test "$coroutine" = "windows" ; then
   coroutine_backend=windows
+elif test "$coroutine" = "sigaltstack" ; then
+  coroutine_backend=sigaltstack
 else
   echo
   echo "Error: unknown coroutine backend $coroutine"
@@ -3269,6 +3271,8 @@ fi
 
 if test "$coroutine_backend" = "ucontext" ; then
   echo "CONFIG_UCONTEXT_COROUTINE=y" >> $config_host_mak
+elif test "$coroutine_backend" = "sigaltstack" ; then
+  echo "CONFIG_SIGALTSTACK_COROUTINE=y" >> $config_host_mak
 fi
 
 if test "$open_by_handle_at" = "yes" ; then
commit 519175a2fdfd3766f99bc29f0b199e23d57a3dd2
Author: Alex Barcelo <abarcelo at ac.upc.edu>
Date:   Tue Feb 28 12:25:50 2012 +0100

    coroutine: adding configure choose mechanism for coroutine backend
    
    Configure tries, as a default, ucontext functions for the
    coroutines. But now the user can force another backend by
    --with-coroutine=BACKEND option
    
    v2: Using --with-coroutine=BACKEND instead of enable
    disable individual configure options
    
    Signed-off-by: Alex Barcelo <abarcelo at ac.upc.edu>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/configure b/configure
index 39d2b54..bb80822 100755
--- a/configure
+++ b/configure
@@ -194,6 +194,7 @@ opengl=""
 zlib="yes"
 guest_agent="yes"
 libiscsi=""
+coroutine=""
 
 # parse CC options first
 for opt do
@@ -784,6 +785,8 @@ for opt do
   ;;
   --with-pkgversion=*) pkgversion=" ($optarg)"
   ;;
+  --with-coroutine=*) coroutine="$optarg"
+  ;;
   --disable-docs) docs="no"
   ;;
   --enable-docs) docs="yes"
@@ -1110,6 +1113,8 @@ echo "  --disable-usb-redir      disable usb network redirection support"
 echo "  --enable-usb-redir       enable usb network redirection support"
 echo "  --disable-guest-agent    disable building of the QEMU Guest Agent"
 echo "  --enable-guest-agent     enable building of the QEMU Guest Agent"
+echo "  --with-coroutine=BACKEND coroutine backend. Supported options:"
+echo "                           gthread, ucontext, windows"
 echo ""
 echo "NOTE: The object files are built at the place where configure is launched"
 exit 1
@@ -2715,21 +2720,36 @@ EOF
 fi
 
 ##########################################
-# check if we have makecontext
-# (and that it's not a glibc stub which always returns -1)
+# check and set a backend for coroutine
 
-ucontext_coroutine=no
-if test "$darwin" != "yes"; then
-  cat > $TMPC << EOF
+# default is ucontext, but always fallback to gthread
+# windows autodetected by make
+if test "$coroutine" = "" -o "$coroutine" = "ucontext"; then
+  if test "$darwin" != "yes"; then
+    cat > $TMPC << EOF
 #include <ucontext.h>
 #ifdef __stub_makecontext
 #error Ignoring glibc stub makecontext which will always fail
 #endif
 int main(void) { makecontext(0, 0, 0); return 0; }
 EOF
-  if compile_prog "" "" ; then
-      ucontext_coroutine=yes
+    if compile_prog "" "" ; then
+        coroutine_backend=ucontext
+    else
+	coroutine_backend=gthread
+    fi
+  else
+    echo "Silently falling back into gthread backend under darwin"
   fi
+elif test "$coroutine" = "gthread" ; then
+  coroutine_backend=gthread
+elif test "$coroutine" = "windows" ; then
+  coroutine_backend=windows
+else
+  echo
+  echo "Error: unknown coroutine backend $coroutine"
+  echo
+  exit 1
 fi
 
 ##########################################
@@ -2931,6 +2951,7 @@ echo "usb net redir     $usb_redir"
 echo "OpenGL support    $opengl"
 echo "libiscsi support  $libiscsi"
 echo "build guest agent $guest_agent"
+echo "coroutine backend $coroutine_backend"
 
 if test "$sdl_too_old" = "yes"; then
 echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -3246,7 +3267,7 @@ if test "$rbd" = "yes" ; then
   echo "CONFIG_RBD=y" >> $config_host_mak
 fi
 
-if test "$ucontext_coroutine" = "yes" ; then
+if test "$coroutine_backend" = "ucontext" ; then
   echo "CONFIG_UCONTEXT_COROUTINE=y" >> $config_host_mak
 fi
 
commit 3194c8ceeba06c3b54621ea7afd6879bc50c2d1d
Author: Alex Barcelo <abarcelo at ac.upc.edu>
Date:   Tue Feb 28 12:25:49 2012 +0100

    coroutine: adding sigaltstack method (.c source)
    
    This file is based in both coroutine-ucontext.c and
    pth_mctx.c (from the GNU Portable Threads library).
    
    The mechanism used to change stacks is the sigaltstack
    function (variant 2 of the pth library).
    
    v2: Some corrections. Moving global variables into
    thread storage (CoroutineThreadState).
    
    Signed-off-by: Alex Barcelo <abarcelo at ac.upc.edu>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/coroutine-sigaltstack.c b/coroutine-sigaltstack.c
new file mode 100644
index 0000000..7ff2d33
--- /dev/null
+++ b/coroutine-sigaltstack.c
@@ -0,0 +1,334 @@
+/*
+ * sigaltstack coroutine initialization code
+ *
+ * Copyright (C) 2006  Anthony Liguori <anthony at codemonkey.ws>
+ * Copyright (C) 2011  Kevin Wolf <kwolf at redhat.com>
+ * Copyright (C) 2012  Alex Barcelo <abarcelo at ac.upc.edu>
+** This file is partly based on pth_mctx.c, from the GNU Portable Threads
+**  Copyright (c) 1999-2006 Ralf S. Engelschall <rse at engelschall.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* XXX Is there a nicer way to disable glibc's stack check for longjmp? */
+#ifdef _FORTIFY_SOURCE
+#undef _FORTIFY_SOURCE
+#endif
+#include <stdlib.h>
+#include <setjmp.h>
+#include <stdint.h>
+#include <pthread.h>
+#include <signal.h>
+#include "qemu-common.h"
+#include "qemu-coroutine-int.h"
+
+enum {
+    /* Maximum free pool size prevents holding too many freed coroutines */
+    POOL_MAX_SIZE = 64,
+};
+
+/** Free list to speed up creation */
+static QSLIST_HEAD(, Coroutine) pool = QSLIST_HEAD_INITIALIZER(pool);
+static unsigned int pool_size;
+
+typedef struct {
+    Coroutine base;
+    void *stack;
+    jmp_buf env;
+} CoroutineUContext;
+
+/**
+ * Per-thread coroutine bookkeeping
+ */
+typedef struct {
+    /** Currently executing coroutine */
+    Coroutine *current;
+
+    /** The default coroutine */
+    CoroutineUContext leader;
+
+    /** Information for the signal handler (trampoline) */
+    jmp_buf tr_reenter;
+    volatile sig_atomic_t tr_called;
+    void *tr_handler;
+} CoroutineThreadState;
+
+static pthread_key_t thread_state_key;
+
+static CoroutineThreadState *coroutine_get_thread_state(void)
+{
+    CoroutineThreadState *s = pthread_getspecific(thread_state_key);
+
+    if (!s) {
+        s = g_malloc0(sizeof(*s));
+        s->current = &s->leader.base;
+        pthread_setspecific(thread_state_key, s);
+    }
+    return s;
+}
+
+static void qemu_coroutine_thread_cleanup(void *opaque)
+{
+    CoroutineThreadState *s = opaque;
+
+    g_free(s);
+}
+
+static void __attribute__((destructor)) coroutine_cleanup(void)
+{
+    Coroutine *co;
+    Coroutine *tmp;
+
+    QSLIST_FOREACH_SAFE(co, &pool, pool_next, tmp) {
+        g_free(DO_UPCAST(CoroutineUContext, base, co)->stack);
+        g_free(co);
+    }
+}
+
+static void __attribute__((constructor)) coroutine_init(void)
+{
+    int ret;
+
+    ret = pthread_key_create(&thread_state_key, qemu_coroutine_thread_cleanup);
+    if (ret != 0) {
+        fprintf(stderr, "unable to create leader key: %s\n", strerror(errno));
+        abort();
+    }
+}
+
+/* "boot" function
+ * This is what starts the coroutine, is called from the trampoline
+ * (from the signal handler when it is not signal handling, read ahead
+ * for more information).
+ */
+static void coroutine_bootstrap(CoroutineUContext *self, Coroutine *co)
+{
+    /* Initialize longjmp environment and switch back the caller */
+    if (!setjmp(self->env)) {
+        longjmp(*(jmp_buf *)co->entry_arg, 1);
+    }
+
+    while (true) {
+        co->entry(co->entry_arg);
+        qemu_coroutine_switch(co, co->caller, COROUTINE_TERMINATE);
+    }
+}
+
+/*
+ * This is used as the signal handler. This is called with the brand new stack
+ * (thanks to sigaltstack). We have to return, given that this is a signal
+ * handler and the sigmask and some other things are changed.
+ */
+static void coroutine_trampoline(int signal)
+{
+    CoroutineUContext *self;
+    Coroutine *co;
+    CoroutineThreadState *coTS;
+
+    /* Get the thread specific information */
+    coTS = coroutine_get_thread_state();
+    self = coTS->tr_handler;
+    coTS->tr_called = 1;
+    co = &self->base;
+
+    /*
+     * Here we have to do a bit of a ping pong between the caller, given that
+     * this is a signal handler and we have to do a return "soon". Then the
+     * caller can reestablish everything and do a longjmp here again.
+     */
+    if (!setjmp(coTS->tr_reenter)) {
+        return;
+    }
+
+    /*
+     * Ok, the caller has longjmp'ed back to us, so now prepare
+     * us for the real machine state switching. We have to jump
+     * into another function here to get a new stack context for
+     * the auto variables (which have to be auto-variables
+     * because the start of the thread happens later). Else with
+     * PIC (i.e. Position Independent Code which is used when PTH
+     * is built as a shared library) most platforms would
+     * horrible core dump as experience showed.
+     */
+    coroutine_bootstrap(self, co);
+}
+
+static Coroutine *coroutine_new(void)
+{
+    const size_t stack_size = 1 << 20;
+    CoroutineUContext *co;
+    CoroutineThreadState *coTS;
+    struct sigaction sa;
+    struct sigaction osa;
+    struct sigaltstack ss;
+    struct sigaltstack oss;
+    sigset_t sigs;
+    sigset_t osigs;
+    jmp_buf old_env;
+
+    /* The way to manipulate stack is with the sigaltstack function. We
+     * prepare a stack, with it delivering a signal to ourselves and then
+     * put setjmp/longjmp where needed.
+     * This has been done keeping coroutine-ucontext as a model and with the
+     * pth ideas (GNU Portable Threads). See coroutine-ucontext for the basics
+     * of the coroutines and see pth_mctx.c (from the pth project) for the
+     * sigaltstack way of manipulating stacks.
+     */
+
+    co = g_malloc0(sizeof(*co));
+    co->stack = g_malloc(stack_size);
+    co->base.entry_arg = &old_env; /* stash away our jmp_buf */
+
+    coTS = coroutine_get_thread_state();
+    coTS->tr_handler = co;
+
+    /*
+     * Preserve the SIGUSR2 signal state, block SIGUSR2,
+     * and establish our signal handler. The signal will
+     * later transfer control onto the signal stack.
+     */
+    sigemptyset(&sigs);
+    sigaddset(&sigs, SIGUSR2);
+    pthread_sigmask(SIG_BLOCK, &sigs, &osigs);
+    sa.sa_handler = coroutine_trampoline;
+    sigfillset(&sa.sa_mask);
+    sa.sa_flags = SA_ONSTACK;
+    if (sigaction(SIGUSR2, &sa, &osa) != 0) {
+        abort();
+    }
+
+    /*
+     * Set the new stack.
+     */
+    ss.ss_sp = co->stack;
+    ss.ss_size = stack_size;
+    ss.ss_flags = 0;
+    if (sigaltstack(&ss, &oss) < 0) {
+        abort();
+    }
+
+    /*
+     * Now transfer control onto the signal stack and set it up.
+     * It will return immediately via "return" after the setjmp()
+     * was performed. Be careful here with race conditions.  The
+     * signal can be delivered the first time sigsuspend() is
+     * called.
+     */
+    coTS->tr_called = 0;
+    kill(getpid(), SIGUSR2);
+    sigfillset(&sigs);
+    sigdelset(&sigs, SIGUSR2);
+    while (!coTS->tr_called) {
+        sigsuspend(&sigs);
+    }
+
+    /*
+     * Inform the system that we are back off the signal stack by
+     * removing the alternative signal stack. Be careful here: It
+     * first has to be disabled, before it can be removed.
+     */
+    sigaltstack(NULL, &ss);
+    ss.ss_flags = SS_DISABLE;
+    if (sigaltstack(&ss, NULL) < 0) {
+        abort();
+    }
+    sigaltstack(NULL, &ss);
+    if (!(oss.ss_flags & SS_DISABLE)) {
+        sigaltstack(&oss, NULL);
+    }
+
+    /*
+     * Restore the old SIGUSR2 signal handler and mask
+     */
+    sigaction(SIGUSR2, &osa, NULL);
+    pthread_sigmask(SIG_SETMASK, &osigs, NULL);
+
+    /*
+     * Now enter the trampoline again, but this time not as a signal
+     * handler. Instead we jump into it directly. The functionally
+     * redundant ping-pong pointer arithmentic is neccessary to avoid
+     * type-conversion warnings related to the `volatile' qualifier and
+     * the fact that `jmp_buf' usually is an array type.
+     */
+    if (!setjmp(old_env)) {
+        longjmp(coTS->tr_reenter, 1);
+    }
+
+    /*
+     * Ok, we returned again, so now we're finished
+     */
+
+    return &co->base;
+}
+
+Coroutine *qemu_coroutine_new(void)
+{
+    Coroutine *co;
+
+    co = QSLIST_FIRST(&pool);
+    if (co) {
+        QSLIST_REMOVE_HEAD(&pool, pool_next);
+        pool_size--;
+    } else {
+        co = coroutine_new();
+    }
+    return co;
+}
+
+void qemu_coroutine_delete(Coroutine *co_)
+{
+    CoroutineUContext *co = DO_UPCAST(CoroutineUContext, base, co_);
+
+    if (pool_size < POOL_MAX_SIZE) {
+        QSLIST_INSERT_HEAD(&pool, &co->base, pool_next);
+        co->base.caller = NULL;
+        pool_size++;
+        return;
+    }
+
+    g_free(co->stack);
+    g_free(co);
+}
+
+CoroutineAction qemu_coroutine_switch(Coroutine *from_, Coroutine *to_,
+                                      CoroutineAction action)
+{
+    CoroutineUContext *from = DO_UPCAST(CoroutineUContext, base, from_);
+    CoroutineUContext *to = DO_UPCAST(CoroutineUContext, base, to_);
+    CoroutineThreadState *s = coroutine_get_thread_state();
+    int ret;
+
+    s->current = to_;
+
+    ret = setjmp(from->env);
+    if (ret == 0) {
+        longjmp(to->env, action);
+    }
+    return ret;
+}
+
+Coroutine *qemu_coroutine_self(void)
+{
+    CoroutineThreadState *s = coroutine_get_thread_state();
+
+    return s->current;
+}
+
+bool qemu_in_coroutine(void)
+{
+    CoroutineThreadState *s = pthread_getspecific(thread_state_key);
+
+    return s && s->current->caller;
+}
+
commit 250196f19c6e7df12965d74a5073e10aba06c802
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Mar 2 14:10:54 2012 +0100

    qcow2: Reduce number of I/O requests
    
    If the first part of a write request is allocated, but the second isn't
    and it can be allocated so that the resulting area is contiguous, handle
    it at once. This is a common case for sequential writes.
    
    After this patch, alloc_cluster_offset() only checks if the clusters are
    already allocated or how many new clusters can be allocated contigouosly.
    The actual cluster allocation is split off into a new function
    do_alloc_cluster_offset().
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 903454d..e0fb907 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -589,7 +589,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
     BDRVQcowState *s = bs->opaque;
     int i, j = 0, l2_index, ret;
     uint64_t *old_cluster, start_sect, l2_offset, *l2_table;
-    uint64_t cluster_offset = m->cluster_offset;
+    uint64_t cluster_offset = m->alloc_offset;
     bool cow = false;
 
     trace_qcow2_cluster_link_l2(qemu_coroutine_self(), m->nb_clusters);
@@ -712,12 +712,94 @@ static int count_cow_clusters(BDRVQcowState *s, int nb_clusters,
 }
 
 /*
+ * Allocates new clusters for the given guest_offset.
+ *
+ * At most *nb_clusters are allocated, and on return *nb_clusters is updated to
+ * contain the number of clusters that have been allocated and are contiguous
+ * in the image file.
+ *
+ * If *host_offset is non-zero, it specifies the offset in the image file at
+ * which the new clusters must start. *nb_clusters can be 0 on return in this
+ * case if the cluster at host_offset is already in use. If *host_offset is
+ * zero, the clusters can be allocated anywhere in the image file.
+ *
+ * *host_offset is updated to contain the offset into the image file at which
+ * the first allocated cluster starts.
+ *
+ * Return 0 on success and -errno in error cases. -EAGAIN means that the
+ * function has been waiting for another request and the allocation must be
+ * restarted, but the whole request should not be failed.
+ */
+static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
+    uint64_t *host_offset, unsigned int *nb_clusters, uint64_t *l2_table)
+{
+    BDRVQcowState *s = bs->opaque;
+    int64_t cluster_offset;
+    QCowL2Meta *old_alloc;
+
+    trace_qcow2_do_alloc_clusters_offset(qemu_coroutine_self(), guest_offset,
+                                         *host_offset, *nb_clusters);
+
+    /*
+     * Check if there already is an AIO write request in flight which allocates
+     * the same cluster. In this case we need to wait until the previous
+     * request has completed and updated the L2 table accordingly.
+     */
+    QLIST_FOREACH(old_alloc, &s->cluster_allocs, next_in_flight) {
+
+        uint64_t start = guest_offset >> s->cluster_bits;
+        uint64_t end = start + *nb_clusters;
+        uint64_t old_start = old_alloc->offset >> s->cluster_bits;
+        uint64_t old_end = old_start + old_alloc->nb_clusters;
+
+        if (end < old_start || start > old_end) {
+            /* No intersection */
+        } else {
+            if (start < old_start) {
+                /* Stop at the start of a running allocation */
+                *nb_clusters = old_start - start;
+            } else {
+                *nb_clusters = 0;
+            }
+
+            if (*nb_clusters == 0) {
+                /* Wait for the dependency to complete. We need to recheck
+                 * the free/allocated clusters when we continue. */
+                qemu_co_mutex_unlock(&s->lock);
+                qemu_co_queue_wait(&old_alloc->dependent_requests);
+                qemu_co_mutex_lock(&s->lock);
+                return -EAGAIN;
+            }
+        }
+    }
+
+    if (!*nb_clusters) {
+        abort();
+    }
+
+    /* Allocate new clusters */
+    trace_qcow2_cluster_alloc_phys(qemu_coroutine_self());
+    if (*host_offset == 0) {
+        cluster_offset = qcow2_alloc_clusters(bs, *nb_clusters * s->cluster_size);
+    } else {
+        cluster_offset = *host_offset;
+        *nb_clusters = qcow2_alloc_clusters_at(bs, cluster_offset, *nb_clusters);
+    }
+
+    if (cluster_offset < 0) {
+        return cluster_offset;
+    }
+    *host_offset = cluster_offset;
+    return 0;
+}
+
+/*
  * alloc_cluster_offset
  *
- * For a given offset of the disk image, return cluster offset in qcow2 file.
- * If the offset is not found, allocate a new cluster.
+ * For a given offset on the virtual disk, find the cluster offset in qcow2
+ * file. If the offset is not found, allocate a new cluster.
  *
- * If the cluster was already allocated, m->nb_clusters is set to 0,
+ * If the cluster was already allocated, m->nb_clusters is set to 0 and
  * other fields in m are meaningless.
  *
  * If the cluster is newly allocated, m->nb_clusters is set to the number of
@@ -734,119 +816,126 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
     int n_start, int n_end, int *num, QCowL2Meta *m)
 {
     BDRVQcowState *s = bs->opaque;
-    int l2_index, ret;
+    int l2_index, ret, sectors;
     uint64_t l2_offset, *l2_table;
-    int64_t cluster_offset;
-    unsigned int nb_clusters, i = 0;
-    QCowL2Meta *old_alloc;
+    unsigned int nb_clusters, keep_clusters;
+    uint64_t cluster_offset;
 
     trace_qcow2_alloc_clusters_offset(qemu_coroutine_self(), offset,
                                       n_start, n_end);
 
+    /* Find L2 entry for the first involved cluster */
     ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index);
     if (ret < 0) {
         return ret;
     }
 
+    /*
+     * Calculate the number of clusters to look for. We stop at L2 table
+     * boundaries to keep things simple.
+     */
 again:
-    nb_clusters = size_to_clusters(s, n_end << 9);
-
-    nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
+    nb_clusters = MIN(size_to_clusters(s, n_end << BDRV_SECTOR_BITS),
+                      s->l2_size - l2_index);
 
     cluster_offset = be64_to_cpu(l2_table[l2_index]);
 
-    /* We keep all QCOW_OFLAG_COPIED clusters */
-
+    /*
+     * Check how many clusters are already allocated and don't need COW, and how
+     * many need a new allocation.
+     */
     if (cluster_offset & QCOW_OFLAG_COPIED) {
-        nb_clusters = count_contiguous_clusters(nb_clusters, s->cluster_size,
-                &l2_table[l2_index], 0, 0);
-
-        cluster_offset &= ~QCOW_OFLAG_COPIED;
-        m->nb_clusters = 0;
+        /* We keep all QCOW_OFLAG_COPIED clusters */
+        keep_clusters = count_contiguous_clusters(nb_clusters, s->cluster_size,
+                                                  &l2_table[l2_index], 0, 0);
+        assert(keep_clusters <= nb_clusters);
+        nb_clusters -= keep_clusters;
+    } else {
+        /* For the moment, overwrite compressed clusters one by one */
+        if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
+            nb_clusters = 1;
+        } else {
+            nb_clusters = count_cow_clusters(s, nb_clusters, l2_table, l2_index);
+        }
 
-        goto out;
+        keep_clusters = 0;
+        cluster_offset = 0;
     }
 
-    /* for the moment, multiple compressed clusters are not managed */
+    cluster_offset &= ~QCOW_OFLAG_COPIED;
 
-    if (cluster_offset & QCOW_OFLAG_COMPRESSED)
-        nb_clusters = 1;
+    /* If there is something left to allocate, do that now */
+    *m = (QCowL2Meta) {
+        .cluster_offset     = cluster_offset,
+        .nb_clusters        = 0,
+    };
+    qemu_co_queue_init(&m->dependent_requests);
 
-    /* how many available clusters ? */
+    if (nb_clusters > 0) {
+        uint64_t alloc_offset;
+        uint64_t alloc_cluster_offset;
+        uint64_t keep_bytes = keep_clusters * s->cluster_size;
 
-    i = count_cow_clusters(s, nb_clusters, l2_table, l2_index);
-    assert(i <= nb_clusters);
-    nb_clusters = i;
+        /* Calculate start and size of allocation */
+        alloc_offset = offset + keep_bytes;
 
-    /*
-     * Check if there already is an AIO write request in flight which allocates
-     * the same cluster. In this case we need to wait until the previous
-     * request has completed and updated the L2 table accordingly.
-     */
-    QLIST_FOREACH(old_alloc, &s->cluster_allocs, next_in_flight) {
-
-        uint64_t start = offset >> s->cluster_bits;
-        uint64_t end = start + nb_clusters;
-        uint64_t old_start = old_alloc->offset >> s->cluster_bits;
-        uint64_t old_end = old_start + old_alloc->nb_clusters;
-
-        if (end < old_start || start > old_end) {
-            /* No intersection */
+        if (keep_clusters == 0) {
+            alloc_cluster_offset = 0;
         } else {
-            if (start < old_start) {
-                /* Stop at the start of a running allocation */
-                nb_clusters = old_start - start;
-            } else {
-                nb_clusters = 0;
-            }
-
-            if (nb_clusters == 0) {
-                /* Wait for the dependency to complete. We need to recheck
-                 * the free/allocated clusters when we continue. */
-                qemu_co_mutex_unlock(&s->lock);
-                qemu_co_queue_wait(&old_alloc->dependent_requests);
-                qemu_co_mutex_lock(&s->lock);
-                goto again;
-            }
+            alloc_cluster_offset = cluster_offset + keep_bytes;
         }
-    }
 
-    if (!nb_clusters) {
-        abort();
-    }
-
-    /* save info needed for meta data update */
-    m->offset = offset;
-    m->n_start = n_start;
-    m->nb_clusters = nb_clusters;
-
-    QLIST_INSERT_HEAD(&s->cluster_allocs, m, next_in_flight);
+        /* Allocate, if necessary at a given offset in the image file */
+        ret = do_alloc_cluster_offset(bs, alloc_offset, &alloc_cluster_offset,
+                                      &nb_clusters, l2_table);
+        if (ret == -EAGAIN) {
+            goto again;
+        } else if (ret < 0) {
+            goto fail;
+        }
 
-    /* allocate a new cluster */
-    trace_qcow2_cluster_alloc_phys(qemu_coroutine_self());
-    cluster_offset = qcow2_alloc_clusters(bs, nb_clusters * s->cluster_size);
-    if (cluster_offset < 0) {
-        ret = cluster_offset;
-        goto fail;
+        /* save info needed for meta data update */
+        if (nb_clusters > 0) {
+            int requested_sectors = n_end - keep_clusters * s->cluster_sectors;
+            int avail_sectors = (keep_clusters + nb_clusters)
+                                << (s->cluster_bits - BDRV_SECTOR_BITS);
+
+            *m = (QCowL2Meta) {
+                .cluster_offset = keep_clusters == 0 ?
+                                  alloc_cluster_offset : cluster_offset,
+                .alloc_offset   = alloc_cluster_offset,
+                .offset         = alloc_offset,
+                .n_start        = keep_clusters == 0 ? n_start : 0,
+                .nb_clusters    = nb_clusters,
+                .nb_available   = MIN(requested_sectors, avail_sectors),
+            };
+            qemu_co_queue_init(&m->dependent_requests);
+            QLIST_INSERT_HEAD(&s->cluster_allocs, m, next_in_flight);
+        }
     }
 
-out:
+    /* Some cleanup work */
     ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
     if (ret < 0) {
         goto fail_put;
     }
 
-    m->nb_available = MIN(nb_clusters << (s->cluster_bits - 9), n_end);
-    m->cluster_offset = cluster_offset;
+    sectors = (keep_clusters + nb_clusters) << (s->cluster_bits - 9);
+    if (sectors > n_end) {
+        sectors = n_end;
+    }
 
-    *num = m->nb_available - n_start;
+    assert(sectors > n_start);
+    *num = sectors - n_start;
 
     return 0;
 
 fail:
     qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
 fail_put:
-    QLIST_REMOVE(m, next_in_flight);
+    if (nb_clusters > 0) {
+        QLIST_REMOVE(m, next_in_flight);
+    }
     return ret;
 }
 
diff --git a/block/qcow2.h b/block/qcow2.h
index 5129e3e..e4ac366 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -155,6 +155,7 @@ typedef struct QCowL2Meta
 {
     uint64_t offset;
     uint64_t cluster_offset;
+    uint64_t alloc_offset;
     int n_start;
     int nb_available;
     int nb_clusters;
diff --git a/trace-events b/trace-events
index d818ff1..606d903 100644
--- a/trace-events
+++ b/trace-events
@@ -320,6 +320,7 @@ qcow2_writev_done_part(void *co, int cur_nr_sectors) "co %p cur_nr_sectors %d"
 qcow2_writev_data(void *co, uint64_t offset) "co %p offset %" PRIx64
 
 qcow2_alloc_clusters_offset(void *co, uint64_t offset, int n_start, int n_end) "co %p offet %" PRIx64 " n_start %d n_end %d"
+qcow2_do_alloc_clusters_offset(void *co, uint64_t guest_offset, uint64_t host_offset, int nb_clusters) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " nb_clusters %d"
 qcow2_cluster_alloc_phys(void *co) "co %p"
 qcow2_cluster_link_l2(void *co, int nb_clusters) "co %p nb_clusters %d"
 
commit 256900b16b0264af9e165bceabbf74dcece4ea38
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Mar 2 19:35:58 2012 +0100

    qcow2: Add qcow2_alloc_clusters_at()
    
    This function allows to allocate clusters at a given offset in the image
    file. This is useful if you want to allocate the second part of an area
    that must be contiguous.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 2db2ede..f39928a 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -582,6 +582,34 @@ int64_t qcow2_alloc_clusters(BlockDriverState *bs, int64_t size)
     return offset;
 }
 
+int qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
+    int nb_clusters)
+{
+    BDRVQcowState *s = bs->opaque;
+    uint64_t cluster_index;
+    int i, refcount, ret;
+
+    /* Check how many clusters there are free */
+    cluster_index = offset >> s->cluster_bits;
+    for(i = 0; i < nb_clusters; i++) {
+        refcount = get_refcount(bs, cluster_index++);
+
+        if (refcount < 0) {
+            return refcount;
+        } else if (refcount != 0) {
+            break;
+        }
+    }
+
+    /* And then allocate them */
+    ret = update_refcount(bs, offset, i << s->cluster_bits, 1);
+    if (ret < 0) {
+        return ret;
+    }
+
+    return i;
+}
+
 /* only used to allocate compressed sectors. We try to allocate
    contiguous sectors. size must be <= cluster_size */
 int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)
diff --git a/block/qcow2.h b/block/qcow2.h
index fc35838..5129e3e 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -193,6 +193,8 @@ int qcow2_refcount_init(BlockDriverState *bs);
 void qcow2_refcount_close(BlockDriverState *bs);
 
 int64_t qcow2_alloc_clusters(BlockDriverState *bs, int64_t size);
+int qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
+    int nb_clusters);
 int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size);
 void qcow2_free_clusters(BlockDriverState *bs,
     int64_t offset, int64_t size);
commit bf319ece56bc07608bfdf46b8ef5c61b52be83f6
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Mar 2 19:27:53 2012 +0100

    qcow2: Factor out count_cow_clusters
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index a791bbe..903454d 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -677,6 +677,41 @@ err:
  }
 
 /*
+ * Returns the number of contiguous clusters that can be used for an allocating
+ * write, but require COW to be performed (this includes yet unallocated space,
+ * which must copy from the backing file)
+ */
+static int count_cow_clusters(BDRVQcowState *s, int nb_clusters,
+    uint64_t *l2_table, int l2_index)
+{
+    int i = 0;
+    uint64_t cluster_offset;
+
+    while (i < nb_clusters) {
+        i += count_contiguous_clusters(nb_clusters - i, s->cluster_size,
+                &l2_table[l2_index], i, 0);
+        if ((i >= nb_clusters) || be64_to_cpu(l2_table[l2_index + i])) {
+            break;
+        }
+
+        i += count_contiguous_free_clusters(nb_clusters - i,
+                &l2_table[l2_index + i]);
+        if (i >= nb_clusters) {
+            break;
+        }
+
+        cluster_offset = be64_to_cpu(l2_table[l2_index + i]);
+
+        if ((cluster_offset & QCOW_OFLAG_COPIED) ||
+                (cluster_offset & QCOW_OFLAG_COMPRESSED))
+            break;
+    }
+
+    assert(i <= nb_clusters);
+    return i;
+}
+
+/*
  * alloc_cluster_offset
  *
  * For a given offset of the disk image, return cluster offset in qcow2 file.
@@ -739,25 +774,7 @@ again:
 
     /* how many available clusters ? */
 
-    while (i < nb_clusters) {
-        i += count_contiguous_clusters(nb_clusters - i, s->cluster_size,
-                &l2_table[l2_index], i, 0);
-        if ((i >= nb_clusters) || be64_to_cpu(l2_table[l2_index + i])) {
-            break;
-        }
-
-        i += count_contiguous_free_clusters(nb_clusters - i,
-                &l2_table[l2_index + i]);
-        if (i >= nb_clusters) {
-            break;
-        }
-
-        cluster_offset = be64_to_cpu(l2_table[l2_index + i]);
-
-        if ((cluster_offset & QCOW_OFLAG_COPIED) ||
-                (cluster_offset & QCOW_OFLAG_COMPRESSED))
-            break;
-    }
+    i = count_cow_clusters(s, nb_clusters, l2_table, l2_index);
     assert(i <= nb_clusters);
     nb_clusters = i;
 
commit 6cc2a4157b31c47303da96c5ed7836db3c10def6
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Mar 6 18:55:59 2012 +0100

    qmp: convert blockdev-snapshot-sync to a wrapper around transactions
    
    Simplify the blockdev-snapshot-sync code and gain failsafe operation
    by turning it into a wrapper around the new transaction command.  A new
    option is also added matching "mode".
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 0a6edc3..1a500b8 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -649,72 +649,33 @@ void do_commit(Monitor *mon, const QDict *qdict)
     }
 }
 
+static void blockdev_do_action(int kind, void *data, Error **errp)
+{
+    BlockdevAction action;
+    BlockdevActionList list;
+
+    action.kind = kind;
+    action.data = data;
+    list.value = &action;
+    list.next = NULL;
+    qmp_transaction(&list, errp);
+}
+
 void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file,
                                 bool has_format, const char *format,
+                                bool has_mode, enum NewImageMode mode,
                                 Error **errp)
 {
-    BlockDriverState *bs;
-    BlockDriver *drv, *old_drv, *proto_drv;
-    int ret = 0;
-    int flags;
-    char old_filename[1024];
-
-    bs = bdrv_find(device);
-    if (!bs) {
-        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
-        return;
-    }
-    if (bdrv_in_use(bs)) {
-        error_set(errp, QERR_DEVICE_IN_USE, device);
-        return;
-    }
-
-    pstrcpy(old_filename, sizeof(old_filename), bs->filename);
-
-    old_drv = bs->drv;
-    flags = bs->open_flags;
-
-    if (!has_format) {
-        format = "qcow2";
-    }
-
-    drv = bdrv_find_format(format);
-    if (!drv) {
-        error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
-        return;
-    }
-
-    proto_drv = bdrv_find_protocol(snapshot_file);
-    if (!proto_drv) {
-        error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
-        return;
-    }
-
-    ret = bdrv_img_create(snapshot_file, format, bs->filename,
-                          bs->drv->format_name, NULL, -1, flags);
-    if (ret) {
-        error_set(errp, QERR_UNDEFINED_ERROR);
-        return;
-    }
-
-    bdrv_drain_all();
-    bdrv_flush(bs);
-
-    bdrv_close(bs);
-    ret = bdrv_open(bs, snapshot_file, flags, drv);
-    /*
-     * If reopening the image file we just created fails, fall back
-     * and try to re-open the original image. If that fails too, we
-     * are in serious trouble.
-     */
-    if (ret != 0) {
-        ret = bdrv_open(bs, old_filename, flags, old_drv);
-        if (ret != 0) {
-            error_set(errp, QERR_OPEN_FILE_FAILED, old_filename);
-        } else {
-            error_set(errp, QERR_OPEN_FILE_FAILED, snapshot_file);
-        }
-    }
+    BlockdevSnapshot snapshot = {
+        .device = (char *) device,
+        .snapshot_file = (char *) snapshot_file,
+        .has_format = has_format,
+        .format = (char *) format,
+        .has_mode = has_mode,
+        .mode = mode,
+    };
+    blockdev_do_action(BLOCKDEV_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC, &snapshot,
+                       errp);
 }
 
 
diff --git a/hmp-commands.hx b/hmp-commands.hx
index ed88877..6980214 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -882,14 +882,17 @@ ETEXI
 
     {
         .name       = "snapshot_blkdev",
-        .args_type  = "device:B,snapshot-file:s?,format:s?",
-        .params     = "device [new-image-file] [format]",
+        .args_type  = "reuse:-n,device:B,snapshot-file:s?,format:s?",
+        .params     = "[-n] device [new-image-file] [format]",
         .help       = "initiates a live snapshot\n\t\t\t"
                       "of device. If a new image file is specified, the\n\t\t\t"
                       "new image file will become the new root image.\n\t\t\t"
                       "If format is specified, the snapshot file will\n\t\t\t"
                       "be created in that format. Otherwise the\n\t\t\t"
-                      "snapshot will be internal! (currently unsupported)",
+                      "snapshot will be internal! (currently unsupported).\n\t\t\t"
+                      "The default format is qcow2.  The -n flag requests QEMU\n\t\t\t"
+                      "to reuse the image found in new-image-file, instead of\n\t\t\t"
+                      "recreating it from scratch.",
         .mhandler.cmd = hmp_snapshot_blkdev,
     },
 
diff --git a/hmp.c b/hmp.c
index 3a54455..290c43d 100644
--- a/hmp.c
+++ b/hmp.c
@@ -692,6 +692,8 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict)
     const char *device = qdict_get_str(qdict, "device");
     const char *filename = qdict_get_try_str(qdict, "snapshot-file");
     const char *format = qdict_get_try_str(qdict, "format");
+    int reuse = qdict_get_try_bool(qdict, "reuse", 0);
+    enum NewImageMode mode;
     Error *errp = NULL;
 
     if (!filename) {
@@ -702,7 +704,9 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict)
         return;
     }
 
-    qmp_blockdev_snapshot_sync(device, filename, !!format, format, &errp);
+    mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS;
+    qmp_blockdev_snapshot_sync(device, filename, !!format, format,
+                               true, mode, &errp);
     hmp_handle_error(mon, &errp);
 }
 
diff --git a/qapi-schema.json b/qapi-schema.json
index 0882f43..4df6b8f 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1141,6 +1141,9 @@
 # @snapshot-file: the target of the new image. A new file will be created.
 #
 # @format: #optional the format of the snapshot image, default is 'qcow2'.
+#
+# @mode: #optional whether and how QEMU should create a new image, default is
+# 'absolute-paths'.
 ##
 { 'type': 'BlockdevSnapshot',
   'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str',
@@ -1197,21 +1200,19 @@
 #
 # @format: #optional the format of the snapshot image, default is 'qcow2'.
 #
+# @mode: #optional whether and how QEMU should create a new image, default is
+# 'absolute-paths'.
+#
 # Returns: nothing on success
 #          If @device is not a valid block device, DeviceNotFound
 #          If @snapshot-file can't be opened, OpenFileFailed
 #          If @format is invalid, InvalidBlockFormat
 #
-# Notes: One of the last steps taken by this command is to close the current
-#        image being used by @device and open the @snapshot-file one. If that
-#        fails, the command will try to reopen the original image file. If
-#        that also fails OpenFileFailed will be returned and the guest may get
-#        unexpected errors.
-#
 # Since 0.14.0
 ##
 { 'command': 'blockdev-snapshot-sync',
-  'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str' } }
+  'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str',
+            '*mode': 'NewImageMode'} }
 
 ##
 # @human-monitor-command:
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 7c03b62..dfe8a5b 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -760,6 +760,8 @@ Arguments:
 
 - "device": device name to snapshot (json-string)
 - "snapshot-file": name of new image file (json-string)
+- "mode": whether and how QEMU should create the snapshot file
+  (NewImageMode, optional, default "absolute-paths")
 - "format": format of new image (json-string, optional)
 
 Example:
commit bc8b094feb61c5f3ad55113f1c9b3288dd843b10
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Mar 6 18:55:58 2012 +0100

    add mode field to blockdev-snapshot-sync transaction item
    
    The mode field lets a management application create the snapshot
    destination outside QEMU.
    
    Right now, the only modes are "existing" and "absolute-paths".  Mirroring
    introduces "no-backing-file".  In the future "relative-paths" could be
    implemented too.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 88730c1..0a6edc3 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -748,9 +748,10 @@ void qmp_transaction(BlockdevActionList *dev_list, Error **errp)
         BlockDriver *proto_drv;
         BlockDriver *drv;
         int flags;
+        enum NewImageMode mode;
+        const char *new_image_file;
         const char *device;
         const char *format = "qcow2";
-        const char *new_image_file = NULL;
 
         dev_info = dev_entry->value;
         dev_entry = dev_entry->next;
@@ -761,10 +762,14 @@ void qmp_transaction(BlockdevActionList *dev_list, Error **errp)
         switch (dev_info->kind) {
         case BLOCKDEV_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC:
             device = dev_info->blockdev_snapshot_sync->device;
+            if (!dev_info->blockdev_snapshot_sync->has_mode) {
+                dev_info->blockdev_snapshot_sync->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
+            }
+            new_image_file = dev_info->blockdev_snapshot_sync->snapshot_file;
             if (dev_info->blockdev_snapshot_sync->has_format) {
                 format = dev_info->blockdev_snapshot_sync->format;
             }
-            new_image_file = dev_info->blockdev_snapshot_sync->snapshot_file;
+            mode = dev_info->blockdev_snapshot_sync->mode;
             break;
         default:
             abort();
@@ -805,13 +810,15 @@ void qmp_transaction(BlockdevActionList *dev_list, Error **errp)
         }
 
         /* create new image w/backing file */
-        ret = bdrv_img_create(new_image_file, format,
-                              states->old_bs->filename,
-                              states->old_bs->drv->format_name,
-                              NULL, -1, flags);
-        if (ret) {
-            error_set(errp, QERR_OPEN_FILE_FAILED, new_image_file);
-            goto delete_and_fail;
+        if (mode != NEW_IMAGE_MODE_EXISTING) {
+            ret = bdrv_img_create(new_image_file, format,
+                                  states->old_bs->filename,
+                                  states->old_bs->drv->format_name,
+                                  NULL, -1, flags);
+            if (ret) {
+                error_set(errp, QERR_OPEN_FILE_FAILED, new_image_file);
+                goto delete_and_fail;
+            }
         }
 
         /* We will manually add the backing_hd field to the bs later */
diff --git a/qapi-schema.json b/qapi-schema.json
index 85de38e..0882f43 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1118,6 +1118,22 @@
 { 'command': 'block_resize', 'data': { 'device': 'str', 'size': 'int' }}
 
 ##
+# @NewImageMode
+#
+# An enumeration that tells QEMU how to set the backing file path in
+# a new image file.
+#
+# @existing: QEMU should look for an existing image file.
+#
+# @absolute-paths: QEMU should create a new image with absolute paths
+# for the backing file.
+#
+# Since: 1.1
+##
+{ 'enum': 'NewImageMode'
+  'data': [ 'existing', 'absolute-paths' ] }
+
+##
 # @BlockdevSnapshot
 #
 # @device:  the name of the device to generate the snapshot from.
@@ -1127,7 +1143,8 @@
 # @format: #optional the format of the snapshot image, default is 'qcow2'.
 ##
 { 'type': 'BlockdevSnapshot',
-  'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str' } }
+  'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str',
+            '*mode': 'NewImageMode' } }
 
 ##
 # @BlockdevAction
diff --git a/qmp-commands.hx b/qmp-commands.hx
index fb4f1df..7c03b62 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -705,6 +705,13 @@ A list of dictionaries is accepted, that contains the actions to be performed.
 For snapshots this is the device, the file to use for the new snapshot,
 and the format.  The default format, if not specified, is qcow2.
 
+Each new snapshot defaults to being created by QEMU (wiping any
+contents if the file already exists), but it is also possible to reuse
+an externally-created file.  In the latter case, you should ensure that
+the new image file has the same contents as the current one; QEMU cannot
+perform any meaningful check.  Typically this is achieved by using the
+current image file as the backing file for the new image.
+
 Arguments:
 
 actions array:
@@ -715,6 +722,8 @@ actions array:
       - "device": device name to snapshot (json-string)
       - "snapshot-file": name of new image file (json-string)
       - "format": format of new image (json-string, optional)
+      - "mode": whether and how QEMU should create the snapshot file
+        (NewImageMode, optional, default "absolute-paths")
 
 Example:
 
@@ -725,6 +734,7 @@ Example:
                                          "format": "qcow2" } },
          { 'type': 'blockdev-snapshot-sync', 'data' : { "device": "ide-hd1",
                                          "snapshot-file": "/some/place/my-image2",
+                                         "mode": "existing",
                                          "format": "qcow2" } } ] } }
 <- { "return": {} }
 
commit 52e7c241ac766406f05fa331eec9dbb33ebd2640
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Mar 6 18:55:57 2012 +0100

    rename blockdev-group-snapshot-sync
    
    We will add other kinds of operation.  Prepare for this by adjusting
    the schema.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 3abc1da..88730c1 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -719,31 +719,24 @@ void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file,
 
 
 /* New and old BlockDriverState structs for group snapshots */
-typedef struct BlkGroupSnapshotStates {
+typedef struct BlkTransactionStates {
     BlockDriverState *old_bs;
     BlockDriverState *new_bs;
-    QSIMPLEQ_ENTRY(BlkGroupSnapshotStates) entry;
-} BlkGroupSnapshotStates;
+    QSIMPLEQ_ENTRY(BlkTransactionStates) entry;
+} BlkTransactionStates;
 
 /*
  * 'Atomic' group snapshots.  The snapshots are taken as a set, and if any fail
  *  then we do not pivot any of the devices in the group, and abandon the
  *  snapshots
  */
-void qmp_blockdev_group_snapshot_sync(SnapshotDevList *dev_list,
-                                      Error **errp)
+void qmp_transaction(BlockdevActionList *dev_list, Error **errp)
 {
     int ret = 0;
-    SnapshotDevList *dev_entry = dev_list;
-    SnapshotDev *dev_info = NULL;
-    BlkGroupSnapshotStates *states, *next;
-    BlockDriver *proto_drv;
-    BlockDriver *drv;
-    int flags;
-    const char *format;
-    const char *snapshot_file;
+    BlockdevActionList *dev_entry = dev_list;
+    BlkTransactionStates *states, *next;
 
-    QSIMPLEQ_HEAD(snap_bdrv_states, BlkGroupSnapshotStates) snap_bdrv_states;
+    QSIMPLEQ_HEAD(snap_bdrv_states, BlkTransactionStates) snap_bdrv_states;
     QSIMPLEQ_INIT(&snap_bdrv_states);
 
     /* drain all i/o before any snapshots */
@@ -751,21 +744,46 @@ void qmp_blockdev_group_snapshot_sync(SnapshotDevList *dev_list,
 
     /* We don't do anything in this loop that commits us to the snapshot */
     while (NULL != dev_entry) {
+        BlockdevAction *dev_info = NULL;
+        BlockDriver *proto_drv;
+        BlockDriver *drv;
+        int flags;
+        const char *device;
+        const char *format = "qcow2";
+        const char *new_image_file = NULL;
+
         dev_info = dev_entry->value;
         dev_entry = dev_entry->next;
 
-        states = g_malloc0(sizeof(BlkGroupSnapshotStates));
+        states = g_malloc0(sizeof(BlkTransactionStates));
         QSIMPLEQ_INSERT_TAIL(&snap_bdrv_states, states, entry);
 
-        states->old_bs = bdrv_find(dev_info->device);
+        switch (dev_info->kind) {
+        case BLOCKDEV_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC:
+            device = dev_info->blockdev_snapshot_sync->device;
+            if (dev_info->blockdev_snapshot_sync->has_format) {
+                format = dev_info->blockdev_snapshot_sync->format;
+            }
+            new_image_file = dev_info->blockdev_snapshot_sync->snapshot_file;
+            break;
+        default:
+            abort();
+        }
+
+        drv = bdrv_find_format(format);
+        if (!drv) {
+            error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
+            goto delete_and_fail;
+        }
 
+        states->old_bs = bdrv_find(device);
         if (!states->old_bs) {
-            error_set(errp, QERR_DEVICE_NOT_FOUND, dev_info->device);
+            error_set(errp, QERR_DEVICE_NOT_FOUND, device);
             goto delete_and_fail;
         }
 
         if (bdrv_in_use(states->old_bs)) {
-            error_set(errp, QERR_DEVICE_IN_USE, dev_info->device);
+            error_set(errp, QERR_DEVICE_IN_USE, device);
             goto delete_and_fail;
         }
 
@@ -778,44 +796,30 @@ void qmp_blockdev_group_snapshot_sync(SnapshotDevList *dev_list,
             }
         }
 
-        snapshot_file = dev_info->snapshot_file;
-
         flags = states->old_bs->open_flags;
 
-        if (!dev_info->has_format) {
-            format = "qcow2";
-        } else {
-            format = dev_info->format;
-        }
-
-        drv = bdrv_find_format(format);
-        if (!drv) {
-            error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
-            goto delete_and_fail;
-        }
-
-        proto_drv = bdrv_find_protocol(snapshot_file);
+        proto_drv = bdrv_find_protocol(new_image_file);
         if (!proto_drv) {
             error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
             goto delete_and_fail;
         }
 
         /* create new image w/backing file */
-        ret = bdrv_img_create(snapshot_file, format,
+        ret = bdrv_img_create(new_image_file, format,
                               states->old_bs->filename,
                               states->old_bs->drv->format_name,
                               NULL, -1, flags);
         if (ret) {
-            error_set(errp, QERR_OPEN_FILE_FAILED, snapshot_file);
+            error_set(errp, QERR_OPEN_FILE_FAILED, new_image_file);
             goto delete_and_fail;
         }
 
         /* We will manually add the backing_hd field to the bs later */
         states->new_bs = bdrv_new("");
-        ret = bdrv_open(states->new_bs, snapshot_file,
+        ret = bdrv_open(states->new_bs, new_image_file,
                         flags | BDRV_O_NO_BACKING, drv);
         if (ret != 0) {
-            error_set(errp, QERR_OPEN_FILE_FAILED, snapshot_file);
+            error_set(errp, QERR_OPEN_FILE_FAILED, new_image_file);
             goto delete_and_fail;
         }
     }
diff --git a/qapi-schema.json b/qapi-schema.json
index 5f293c4..85de38e 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1118,7 +1118,7 @@
 { 'command': 'block_resize', 'data': { 'device': 'str', 'size': 'int' }}
 
 ##
-# @SnapshotDev
+# @BlockdevSnapshot
 #
 # @device:  the name of the device to generate the snapshot from.
 #
@@ -1126,19 +1126,30 @@
 #
 # @format: #optional the format of the snapshot image, default is 'qcow2'.
 ##
-{ 'type': 'SnapshotDev',
-  'data': {'device': 'str', 'snapshot-file': 'str', '*format': 'str' } }
+{ 'type': 'BlockdevSnapshot',
+  'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str' } }
+
+##
+# @BlockdevAction
+#
+# A discriminated record of operations that can be performed with
+# @transaction.
+##
+{ 'union': 'BlockdevAction',
+  'data': {
+       'blockdev-snapshot-sync': 'BlockdevSnapshot',
+   } }
 
 ##
-# @blockdev-group-snapshot-sync
+# @transaction
 #
-# Generates a synchronous snapshot of a group of one or more block devices,
-# as atomically as possible.  If the snapshot of any device in the group
-# fails, then the entire group snapshot will be abandoned and the
-# appropriate error returned.
+# Atomically operate on a group of one or more block devices.  If
+# any operation fails, then the entire set of actions will be
+# abandoned and the appropriate error returned.  The only operation
+# supported is currently blockdev-snapshot-sync.
 #
 #  List of:
-#  @SnapshotDev: information needed for the device snapshot
+#  @BlockdevAction: information needed for the device snapshot
 #
 # Returns: nothing on success
 #          If @device is not a valid block device, DeviceNotFound
@@ -1147,13 +1158,14 @@
 #          If @snapshot-file can't be opened, OpenFileFailed
 #          If @format is invalid, InvalidBlockFormat
 #
-# Note: The group snapshot attempt returns failure on the first snapshot
-# device failure.  Therefore, there will be only one device or snapshot file
-# returned in an error condition, and subsequent devices will not have been
-# attempted.
+# Note: The transaction aborts on the first failure.  Therefore, there will
+# be only one device or snapshot file returned in an error condition, and
+# subsequent actions will not have been attempted.
+#
+# Since 1.1
 ##
-{ 'command': 'blockdev-group-snapshot-sync',
-  'data': { 'devlist': [ 'SnapshotDev' ] } }
+{ 'command': 'transaction',
+  'data': { 'actions': [ 'BlockdevAction' ] } }
 
 ##
 # @blockdev-snapshot-sync
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 0c9bfac..fb4f1df 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -687,41 +687,45 @@ EQMP
         .mhandler.cmd_new = qmp_marshal_input_block_job_cancel,
     },
     {
-        .name       = "blockdev-group-snapshot-sync",
-        .args_type  = "devlist:O",
-        .params  = "device:B,snapshot-file:s,format:s?",
-        .mhandler.cmd_new = qmp_marshal_input_blockdev_group_snapshot_sync,
+        .name       = "transaction",
+        .args_type  = "actions:O",
+        .mhandler.cmd_new = qmp_marshal_input_transaction,
     },
 
 SQMP
-blockdev-group-snapshot-sync
-----------------------
-
-Synchronous snapshot of one or more block devices.  A list array input
-is accepted, that contains the device and snapshot file information for
-each device in group. The default format, if not specified, is qcow2.
+transaction
+-----------
 
-If there is any failure creating or opening a new snapshot, all snapshots
-for the group are abandoned, and the original disks pre-snapshot attempt
-are used.
+Atomically operate on one or more block devices.  The only supported
+operation for now is snapshotting.  If there is any failure performing
+any of the operations, all snapshots for the group are abandoned, and
+the original disks pre-snapshot attempt are used.
 
+A list of dictionaries is accepted, that contains the actions to be performed.
+For snapshots this is the device, the file to use for the new snapshot,
+and the format.  The default format, if not specified, is qcow2.
 
 Arguments:
 
-devlist array:
-    - "device": device name to snapshot (json-string)
-    - "snapshot-file": name of new image file (json-string)
-    - "format": format of new image (json-string, optional)
+actions array:
+    - "type": the operation to perform.  The only supported
+      value is "blockdev-snapshot-sync". (json-string)
+    - "data": a dictionary.  The contents depend on the value
+      of "type".  When "type" is "blockdev-snapshot-sync":
+      - "device": device name to snapshot (json-string)
+      - "snapshot-file": name of new image file (json-string)
+      - "format": format of new image (json-string, optional)
 
 Example:
 
--> { "execute": "blockdev-group-snapshot-sync", "arguments":
-                      { "devlist": [{ "device": "ide-hd0",
-                                      "snapshot-file": "/some/place/my-image",
-                                      "format": "qcow2" },
-                                    { "device": "ide-hd1",
-                                      "snapshot-file": "/some/place/my-image2",
-                                      "format": "qcow2" }] } }
+-> { "execute": "transaction",
+     "arguments": { "actions": [
+         { 'type': 'blockdev-snapshot-sync', 'data' : { "device": "ide-hd0",
+                                         "snapshot-file": "/some/place/my-image",
+                                         "format": "qcow2" } },
+         { 'type': 'blockdev-snapshot-sync', 'data' : { "device": "ide-hd1",
+                                         "snapshot-file": "/some/place/my-image2",
+                                         "format": "qcow2" } } ] } }
 <- { "return": {} }
 
 EQMP
commit dc8fb6df5a13f7231f88c78966f8a6c5306840b5
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Mar 6 18:55:56 2012 +0100

    qapi: complete implementation of unions
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Acked-by: Luiz Capitulino <lcapitulino at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qapi-schema-test.json b/qapi-schema-test.json
index 2b38919..8c7f9f7 100644
--- a/qapi-schema-test.json
+++ b/qapi-schema-test.json
@@ -22,6 +22,16 @@
                        'dict2': { 'userdef1': 'UserDefOne', 'string2': 'str' },
                        '*dict3': { 'userdef2': 'UserDefOne', 'string3': 'str' } } } }
 
+# for testing unions
+{ 'type': 'UserDefA',
+  'data': { 'boolean': 'bool' } }
+
+{ 'type': 'UserDefB',
+  'data': { 'integer': 'int' } }
+
+{ 'union': 'UserDefUnion',
+  'data': { 'a' : 'UserDefA', 'b' : 'UserDefB' } }
+
 # testing commands
 { 'command': 'user_def_cmd', 'data': {} }
 { 'command': 'user_def_cmd1', 'data': {'ud1a': 'UserDefOne'} }
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index b56225b..727fb77 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -117,6 +117,7 @@ struct %(name)s
 {
     %(name)sKind kind;
     union {
+        void *data;
 ''',
                 name=name)
 
@@ -269,6 +270,7 @@ for expr in exprs:
     elif expr.has_key('union'):
         ret += generate_fwd_struct(expr['union'], expr['data']) + "\n"
         ret += generate_enum('%sKind' % expr['union'], expr['data'].keys())
+        fdef.write(generate_enum_lookup('%sKind' % expr['union'], expr['data'].keys()))
     else:
         continue
     fdecl.write(ret)
@@ -283,6 +285,10 @@ for expr in exprs:
         fdef.write(generate_type_cleanup(expr['type']) + "\n")
     elif expr.has_key('union'):
         ret += generate_union(expr['union'], expr['data'])
+        ret += generate_type_cleanup_decl(expr['union'] + "List")
+        fdef.write(generate_type_cleanup(expr['union'] + "List") + "\n")
+        ret += generate_type_cleanup_decl(expr['union'])
+        fdef.write(generate_type_cleanup(expr['union']) + "\n")
     else:
         continue
     fdecl.write(ret)
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 5160d83..54117d4 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -110,10 +110,38 @@ def generate_visit_union(name, members):
 
 void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp)
 {
-}
+    Error *err = NULL;
+
+    visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err);
+    visit_type_%(name)sKind(m, &(*obj)->kind, "type", &err);
+    if (err) {
+        error_propagate(errp, err);
+        goto end;
+    }
+    switch ((*obj)->kind) {
 ''',
                  name=name)
 
+    for key in members:
+        ret += mcgen('''
+    case %(abbrev)s_KIND_%(enum)s:
+        visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "data", errp);
+        break;
+''',
+                abbrev = de_camel_case(name).upper(),
+                enum = de_camel_case(key).upper(),
+                c_type=members[key],
+                c_name=c_var(key))
+
+    ret += mcgen('''
+    default:
+        abort();
+    }
+end:
+    visit_end_struct(m, errp);
+}
+''')
+
     return ret
 
 def generate_declaration(name, members, genlist=True):
@@ -242,6 +270,7 @@ for expr in exprs:
         fdecl.write(ret)
     elif expr.has_key('union'):
         ret = generate_visit_union(expr['union'], expr['data'])
+        ret += generate_visit_list(expr['union'], expr['data'])
         fdef.write(ret)
 
         ret = generate_decl_enum('%sKind' % expr['union'], expr['data'].keys())
diff --git a/test-qmp-input-visitor.c b/test-qmp-input-visitor.c
index 926db5c..1996e49 100644
--- a/test-qmp-input-visitor.c
+++ b/test-qmp-input-visitor.c
@@ -234,6 +234,22 @@ static void test_visitor_in_list(TestInputVisitorData *data,
     qapi_free_UserDefOneList(head);
 }
 
+static void test_visitor_in_union(TestInputVisitorData *data,
+                                  const void *unused)
+{
+    Visitor *v;
+    Error *err = NULL;
+    UserDefUnion *tmp;
+
+    v = visitor_input_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 } }");
+
+    visit_type_UserDefUnion(v, &tmp, NULL, &err);
+    g_assert(err == NULL);
+    g_assert_cmpint(tmp->kind, ==, USER_DEF_UNION_KIND_B);
+    g_assert_cmpint(tmp->b->integer, ==, 42);
+    qapi_free_UserDefUnion(tmp);
+}
+
 static void input_visitor_test_add(const char *testpath,
                                    TestInputVisitorData *data,
                                    void (*test_func)(TestInputVisitorData *data, const void *user_data))
@@ -264,6 +280,8 @@ int main(int argc, char **argv)
                             &in_visitor_data, test_visitor_in_struct_nested);
     input_visitor_test_add("/visitor/input/list",
                             &in_visitor_data, test_visitor_in_list);
+    input_visitor_test_add("/visitor/input/union",
+                            &in_visitor_data, test_visitor_in_union);
 
     g_test_run();
 
diff --git a/test-qmp-output-visitor.c b/test-qmp-output-visitor.c
index 5452cd4..4d6c4d4 100644
--- a/test-qmp-output-visitor.c
+++ b/test-qmp-output-visitor.c
@@ -380,6 +380,38 @@ static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
     qapi_free_UserDefNestedList(head);
 }
 
+static void test_visitor_out_union(TestOutputVisitorData *data,
+                                   const void *unused)
+{
+    QObject *arg, *qvalue;
+    QDict *qdict, *value;
+
+    Error *err = NULL;
+
+    UserDefUnion *tmp = g_malloc0(sizeof(UserDefUnion));
+    tmp->kind = USER_DEF_UNION_KIND_A;
+    tmp->a = g_malloc0(sizeof(UserDefA));
+    tmp->a->boolean = true;
+
+    visit_type_UserDefUnion(data->ov, &tmp, NULL, &err);
+    g_assert(err == NULL);
+    arg = qmp_output_get_qobject(data->qov);
+
+    g_assert(qobject_type(arg) == QTYPE_QDICT);
+    qdict = qobject_to_qdict(arg);
+
+    g_assert_cmpstr(qdict_get_str(qdict, "type"), ==, "a");
+
+    qvalue = qdict_get(qdict, "data");
+    g_assert(data != NULL);
+    g_assert(qobject_type(qvalue) == QTYPE_QDICT);
+    value = qobject_to_qdict(qvalue);
+    g_assert_cmpint(qdict_get_bool(value, "boolean"), ==, true);
+
+    qapi_free_UserDefUnion(tmp);
+    QDECREF(qdict);
+}
+
 static void output_visitor_test_add(const char *testpath,
                                     TestOutputVisitorData *data,
                                     void (*test_func)(TestOutputVisitorData *data, const void *user_data))
@@ -416,6 +448,8 @@ int main(int argc, char **argv)
                             &out_visitor_data, test_visitor_out_list);
     output_visitor_test_add("/visitor/output/list-qapi-free",
                             &out_visitor_data, test_visitor_out_list_qapi_free);
+    output_visitor_test_add("/visitor/output/union",
+                            &out_visitor_data, test_visitor_out_union);
 
     g_test_run();
 
commit 622d241998b6a981483594712b039190ee94eff8
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Mar 6 18:55:54 2012 +0100

    use QSIMPLEQ_FOREACH_SAFE when freeing list elements
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 0e8666a..3abc1da 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -736,7 +736,7 @@ void qmp_blockdev_group_snapshot_sync(SnapshotDevList *dev_list,
     int ret = 0;
     SnapshotDevList *dev_entry = dev_list;
     SnapshotDev *dev_info = NULL;
-    BlkGroupSnapshotStates *states;
+    BlkGroupSnapshotStates *states, *next;
     BlockDriver *proto_drv;
     BlockDriver *drv;
     int flags;
@@ -842,7 +842,7 @@ delete_and_fail:
         }
     }
 exit:
-    QSIMPLEQ_FOREACH(states, &snap_bdrv_states, entry) {
+    QSIMPLEQ_FOREACH_SAFE(states, &snap_bdrv_states, entry, next) {
         g_free(states);
     }
     return;
commit b8c6f29eb84cd3ccbbf23a5951224ae33f11116b
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Mar 9 13:37:40 2012 +0100

    Add 'make check-block'
    
    Runs the full qemu-iotests suite for various image formats.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/tests/Makefile b/tests/Makefile
index 571ad42..c78ade1 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -47,6 +47,11 @@ test-qmp-commands: test-qmp-commands.o $(qobject-obj-y) $(qapi-obj-y) $(tools-ob
 
 $(SRC_PATH)/tests/qemu-iotests-quick.sh: qemu-img qemu-io
 
-.PHONY: check
+
+.PHONY: check check-block
+
 check: $(CHECKS)
 	$(call quiet-command, gtester $(CHECKS), "  CHECK")
+
+check-block:
+	$(call quiet-command, $(SHELL) $(SRC_PATH)/tests/check-block.sh , "  CHECK")
diff --git a/tests/check-block.sh b/tests/check-block.sh
new file mode 100755
index 0000000..b9d9c6a
--- /dev/null
+++ b/tests/check-block.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+export QEMU_PROG="$(pwd)/x86_64-softmmu/qemu-system-x86_64"
+export QEMU_IMG_PROG="$(pwd)/qemu-img"
+export QEMU_IO_PROG="$(pwd)/qemu-io"
+
+if [ ! -x $QEMU_PROG ]; then
+    echo "'make check-block' requires qemu-system-x86_64"
+    exit 1
+fi
+
+cd $SRC_PATH/tests/qemu-iotests
+
+ret=0
+./check -T -nocache -raw || ret=1
+./check -T -nocache -qcow2 || ret=1
+./check -T -nocache -qed|| ret=1
+./check -T -nocache -vmdk|| ret=1
+./check -T -nocache -vpc || ret=1
+
+exit $ret
commit 8959449bb9b16e3b19cf35823d3358eb7d461210
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu Mar 8 12:29:00 2012 +0100

    make check: Add qemu-iotests subset
    
    Run the 'quick' group from qemu-iotests during 'make check'.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/tests/Makefile b/tests/Makefile
index 74b29dc..571ad42 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -1,6 +1,9 @@
+export SRC_PATH
+
 CHECKS = check-qdict check-qfloat check-qint check-qstring check-qlist
 CHECKS += check-qjson test-qmp-output-visitor test-qmp-input-visitor
 CHECKS += test-string-input-visitor test-string-output-visitor test-coroutine
+CHECKS += $(SRC_PATH)/tests/qemu-iotests-quick.sh
 
 check-qint.o check-qstring.o check-qdict.o check-qlist.o check-qfloat.o check-qjson.o test-coroutine.o: $(GENERATED_HEADERS)
 
@@ -42,6 +45,8 @@ test-qmp-input-visitor: test-qmp-input-visitor.o $(qobject-obj-y) $(qapi-obj-y)
 test-qmp-commands.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h test-qmp-marshal.c test-qmp-commands.h) $(qapi-obj-y)
 test-qmp-commands: test-qmp-commands.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o $(qapi-dir)/test-qmp-marshal.o module.o
 
+$(SRC_PATH)/tests/qemu-iotests-quick.sh: qemu-img qemu-io
+
 .PHONY: check
 check: $(CHECKS)
 	$(call quiet-command, gtester $(CHECKS), "  CHECK")
diff --git a/tests/qemu-iotests-quick.sh b/tests/qemu-iotests-quick.sh
new file mode 100755
index 0000000..cf90de0
--- /dev/null
+++ b/tests/qemu-iotests-quick.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# We don't know which of the system emulator binaries there is (or if there is
+# any at all), so the 'quick' group doesn't contain any tests that require
+# running qemu proper. Assign a fake binary name so that qemu-iotests doesn't
+# complain about the missing binary.
+export QEMU_PROG="this_should_be_unused"
+
+export QEMU_IMG_PROG="$(pwd)/qemu-img"
+export QEMU_IO_PROG="$(pwd)/qemu-io"
+
+cd $SRC_PATH/tests/qemu-iotests
+
+ret=0
+./check -T -nocache -qcow2 -g quick || ret=1
+
+exit $ret
commit 3811f63acdc0584e053d09f7070063ed0a9bafe6
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu Mar 8 12:26:52 2012 +0100

    qemu-iotests: Mark some tests as quick
    
    This creates a new test group 'quick' for some test case that take at
    most a couple of seconds each, so that the group can be run during a
    quick 'make check'
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index fcf869d..b549f10 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -8,32 +8,32 @@
 # test-group association ... one line per test
 #
 001 rw auto
-002 rw auto
+002 rw auto quick
 003 rw auto
-004 rw auto
+004 rw auto quick
 005 img auto
 006 img auto
 007 snapshot auto
 008 rw auto
 009 rw auto
 010 rw auto
-011 rw auto
-012 auto
+011 rw auto quick
+012 auto quick
 013 rw auto
 014 rw auto
 015 rw snapshot auto
-016 rw auto
-017 rw backing auto
+016 rw auto quick
+017 rw backing auto quick
 018 rw backing auto
-019 rw backing auto
-020 rw backing auto
+019 rw backing auto quick
+020 rw backing auto quick
 021 io auto
 022 rw snapshot auto
 023 rw auto
-024 rw backing auto
-025 rw auto
+024 rw backing auto quick
+025 rw auto quick
 026 rw blkdbg auto
-027 rw auto
+027 rw auto quick
 028 rw backing auto
-029 rw auto
+029 rw auto quick
 030 rw auto
commit 259b21731050eccfe1fd4da949a9633ec7547b04
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 6 12:44:45 2012 +0100

    qcow2: Add error messages in qcow2_truncate
    
    qemu-img resize has some limitations with qcow2, but the user is only
    told that "this image format does not support resize". Quite confusing,
    so add some more detailed error_report() calls and change "this image
    format" into "this image".
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index 6f53ec6..7aece65 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1120,16 +1120,19 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset)
     int ret, new_l1_size;
 
     if (offset & 511) {
+        error_report("The new size must be a multiple of 512");
         return -EINVAL;
     }
 
     /* cannot proceed if image has snapshots */
     if (s->nb_snapshots) {
+        error_report("Can't resize an image which has snapshots");
         return -ENOTSUP;
     }
 
     /* shrinking is currently not supported */
     if (offset < bs->total_sectors * 512) {
+        error_report("qcow2 doesn't support shrinking images yet");
         return -ENOTSUP;
     }
 
diff --git a/qemu-img.c b/qemu-img.c
index 8df3564..0e48b35 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1614,7 +1614,7 @@ static int img_resize(int argc, char **argv)
         printf("Image resized.\n");
         break;
     case -ENOTSUP:
-        error_report("This image format does not support resize");
+        error_report("This image does not support resize");
         break;
     case -EACCES:
         error_report("Image is read-only");
commit e88774971c33671477c9eb4a4cf1e65a047c9838
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Mar 5 18:10:11 2012 +0000

    block: handle -EBUSY in bdrv_commit_all()
    
    Monitor operations that manipulate image files must not execute while a
    background job (like image streaming) is in progress.  This prevents
    corruptions from happening when two pieces of code are manipulating the
    image file without knowledge of each other.
    
    The monitor "commit" command raises QERR_DEVICE_IN_USE when
    bdrv_commit() returns -EBUSY but "commit all" has no error handling.
    This is easy to fix, although note that we do not deliver a detailed
    error about which device was busy in the "commit all" case.
    
    Suggested-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-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 52ffe14..b88ee90 100644
--- a/block.c
+++ b/block.c
@@ -1244,13 +1244,17 @@ ro_cleanup:
     return ret;
 }
 
-void bdrv_commit_all(void)
+int bdrv_commit_all(void)
 {
     BlockDriverState *bs;
 
     QTAILQ_FOREACH(bs, &bdrv_states, list) {
-        bdrv_commit(bs);
+        int ret = bdrv_commit(bs);
+        if (ret < 0) {
+            return ret;
+        }
     }
+    return 0;
 }
 
 struct BdrvTrackedRequest {
diff --git a/block.h b/block.h
index 48d0bf3..415bb17 100644
--- a/block.h
+++ b/block.h
@@ -165,7 +165,7 @@ int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
 void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
 void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs);
 int bdrv_commit(BlockDriverState *bs);
-void bdrv_commit_all(void);
+int bdrv_commit_all(void);
 int bdrv_change_backing_file(BlockDriverState *bs,
     const char *backing_file, const char *backing_fmt);
 void bdrv_register(BlockDriver *bdrv);
diff --git a/blockdev.c b/blockdev.c
index 96a893b..0e8666a 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -627,12 +627,15 @@ void do_commit(Monitor *mon, const QDict *qdict)
 {
     const char *device = qdict_get_str(qdict, "device");
     BlockDriverState *bs;
+    int ret;
 
     if (!strcmp(device, "all")) {
-        bdrv_commit_all();
+        ret = bdrv_commit_all();
+        if (ret == -EBUSY) {
+            qerror_report(QERR_DEVICE_IN_USE, device);
+            return;
+        }
     } else {
-        int ret;
-
         bs = bdrv_find(device);
         if (!bs) {
             qerror_report(QERR_DEVICE_NOT_FOUND, device);
commit 3cce16f44dc51b8695a144b7b0437548f886276e
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu Mar 1 18:36:21 2012 +0100

    qcow2: Add some tracing
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
index 340a6f2..710d4b1 100644
--- a/block/qcow2-cache.c
+++ b/block/qcow2-cache.c
@@ -25,6 +25,7 @@
 #include "block_int.h"
 #include "qemu-common.h"
 #include "qcow2.h"
+#include "trace.h"
 
 typedef struct Qcow2CachedTable {
     void*   table;
@@ -100,6 +101,9 @@ static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
         return 0;
     }
 
+    trace_qcow2_cache_entry_flush(qemu_coroutine_self(),
+                                  c == s->l2_table_cache, i);
+
     if (c->depends) {
         ret = qcow2_cache_flush_dependency(bs, c);
     } else if (c->depends_on_flush) {
@@ -132,10 +136,13 @@ static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
 
 int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c)
 {
+    BDRVQcowState *s = bs->opaque;
     int result = 0;
     int ret;
     int i;
 
+    trace_qcow2_cache_flush(qemu_coroutine_self(), c == s->l2_table_cache);
+
     for (i = 0; i < c->size; i++) {
         ret = qcow2_cache_entry_flush(bs, c, i);
         if (ret < 0 && result != -ENOSPC) {
@@ -218,6 +225,9 @@ static int qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c,
     int i;
     int ret;
 
+    trace_qcow2_cache_get(qemu_coroutine_self(), c == s->l2_table_cache,
+                          offset, read_from_disk);
+
     /* Check if the table is already cached */
     for (i = 0; i < c->size; i++) {
         if (c->entries[i].offset == offset) {
@@ -227,6 +237,8 @@ static int qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c,
 
     /* If not, write a table back and replace it */
     i = qcow2_cache_find_entry_to_replace(c);
+    trace_qcow2_cache_get_replace_entry(qemu_coroutine_self(),
+                                        c == s->l2_table_cache, i);
     if (i < 0) {
         return i;
     }
@@ -236,6 +248,8 @@ static int qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c,
         return ret;
     }
 
+    trace_qcow2_cache_get_read(qemu_coroutine_self(),
+                               c == s->l2_table_cache, i);
     c->entries[i].offset = 0;
     if (read_from_disk) {
         if (c == s->l2_table_cache) {
@@ -258,6 +272,10 @@ found:
     c->entries[i].cache_hits++;
     c->entries[i].ref++;
     *table = c->entries[i].table;
+
+    trace_qcow2_cache_get_done(qemu_coroutine_self(),
+                               c == s->l2_table_cache, i);
+
     return 0;
 }
 
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 07a2e93..a791bbe 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -27,6 +27,7 @@
 #include "qemu-common.h"
 #include "block_int.h"
 #include "block/qcow2.h"
+#include "trace.h"
 
 int qcow2_grow_l1_table(BlockDriverState *bs, int min_size, bool exact_size)
 {
@@ -170,6 +171,8 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
 
     old_l2_offset = s->l1_table[l1_index];
 
+    trace_qcow2_l2_allocate(bs, l1_index);
+
     /* allocate a new l2 entry */
 
     l2_offset = qcow2_alloc_clusters(bs, s->l2_size * sizeof(uint64_t));
@@ -184,6 +187,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
 
     /* allocate a new entry in the l2 cache */
 
+    trace_qcow2_l2_allocate_get_empty(bs, l1_index);
     ret = qcow2_cache_get_empty(bs, s->l2_table_cache, l2_offset, (void**) table);
     if (ret < 0) {
         return ret;
@@ -216,6 +220,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
     /* write the l2 table to the file */
     BLKDBG_EVENT(bs->file, BLKDBG_L2_ALLOC_WRITE);
 
+    trace_qcow2_l2_allocate_write_l2(bs, l1_index);
     qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
     ret = qcow2_cache_flush(bs, s->l2_table_cache);
     if (ret < 0) {
@@ -223,6 +228,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
     }
 
     /* update the L1 entry */
+    trace_qcow2_l2_allocate_write_l1(bs, l1_index);
     s->l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED;
     ret = write_l1_entry(bs, l1_index);
     if (ret < 0) {
@@ -230,9 +236,11 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
     }
 
     *table = l2_table;
+    trace_qcow2_l2_allocate_done(bs, l1_index, 0);
     return 0;
 
 fail:
+    trace_qcow2_l2_allocate_done(bs, l1_index, ret);
     qcow2_cache_put(bs, s->l2_table_cache, (void**) table);
     s->l1_table[l1_index] = old_l2_offset;
     return ret;
@@ -584,6 +592,8 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
     uint64_t cluster_offset = m->cluster_offset;
     bool cow = false;
 
+    trace_qcow2_cluster_link_l2(qemu_coroutine_self(), m->nb_clusters);
+
     if (m->nb_clusters == 0)
         return 0;
 
@@ -695,6 +705,9 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
     unsigned int nb_clusters, i = 0;
     QCowL2Meta *old_alloc;
 
+    trace_qcow2_alloc_clusters_offset(qemu_coroutine_self(), offset,
+                                      n_start, n_end);
+
     ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index);
     if (ret < 0) {
         return ret;
@@ -793,7 +806,7 @@ again:
     QLIST_INSERT_HEAD(&s->cluster_allocs, m, next_in_flight);
 
     /* allocate a new cluster */
-
+    trace_qcow2_cluster_alloc_phys(qemu_coroutine_self());
     cluster_offset = qcow2_alloc_clusters(bs, nb_clusters * s->cluster_size);
     if (cluster_offset < 0) {
         ret = cluster_offset;
diff --git a/block/qcow2.c b/block/qcow2.c
index eb5ea48..6f53ec6 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -29,6 +29,7 @@
 #include "block/qcow2.h"
 #include "qemu-error.h"
 #include "qerror.h"
+#include "trace.h"
 
 /*
   Differences with QCOW:
@@ -569,6 +570,9 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
         .nb_clusters = 0,
     };
 
+    trace_qcow2_writev_start_req(qemu_coroutine_self(), sector_num,
+                                 remaining_sectors);
+
     qemu_co_queue_init(&l2meta.dependent_requests);
 
     qemu_iovec_init(&hd_qiov, qiov->niov);
@@ -579,6 +583,7 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
 
     while (remaining_sectors != 0) {
 
+        trace_qcow2_writev_start_part(qemu_coroutine_self());
         index_in_cluster = sector_num & (s->cluster_sectors - 1);
         n_end = index_in_cluster + remaining_sectors;
         if (s->crypt_method &&
@@ -619,6 +624,8 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
 
         BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
         qemu_co_mutex_unlock(&s->lock);
+        trace_qcow2_writev_data(qemu_coroutine_self(),
+                                (cluster_offset >> 9) + index_in_cluster);
         ret = bdrv_co_writev(bs->file,
                              (cluster_offset >> 9) + index_in_cluster,
                              cur_nr_sectors, &hd_qiov);
@@ -637,6 +644,7 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
         remaining_sectors -= cur_nr_sectors;
         sector_num += cur_nr_sectors;
         bytes_done += cur_nr_sectors * 512;
+        trace_qcow2_writev_done_part(qemu_coroutine_self(), cur_nr_sectors);
     }
     ret = 0;
 
@@ -647,6 +655,7 @@ fail:
 
     qemu_iovec_destroy(&hd_qiov);
     qemu_vfree(cluster_data);
+    trace_qcow2_writev_done_req(qemu_coroutine_self(), ret);
 
     return ret;
 }
diff --git a/trace-events b/trace-events
index c5d0f0f..d818ff1 100644
--- a/trace-events
+++ b/trace-events
@@ -312,6 +312,30 @@ scsi_request_sense(int target, int lun, int tag) "target %d lun %d tag %d"
 # vl.c
 vm_state_notify(int running, int reason) "running %d reason %d"
 
+# block/qcow2.c
+qcow2_writev_start_req(void *co, int64_t sector, int nb_sectors) "co %p sector %" PRIx64 " nb_sectors %d"
+qcow2_writev_done_req(void *co, int ret) "co %p ret %d"
+qcow2_writev_start_part(void *co) "co %p"
+qcow2_writev_done_part(void *co, int cur_nr_sectors) "co %p cur_nr_sectors %d"
+qcow2_writev_data(void *co, uint64_t offset) "co %p offset %" PRIx64
+
+qcow2_alloc_clusters_offset(void *co, uint64_t offset, int n_start, int n_end) "co %p offet %" PRIx64 " n_start %d n_end %d"
+qcow2_cluster_alloc_phys(void *co) "co %p"
+qcow2_cluster_link_l2(void *co, int nb_clusters) "co %p nb_clusters %d"
+
+qcow2_l2_allocate(void *bs, int l1_index) "bs %p l1_index %d"
+qcow2_l2_allocate_get_empty(void *bs, int l1_index) "bs %p l1_index %d"
+qcow2_l2_allocate_write_l2(void *bs, int l1_index) "bs %p l1_index %d"
+qcow2_l2_allocate_write_l1(void *bs, int l1_index) "bs %p l1_index %d"
+qcow2_l2_allocate_done(void *bs, int l1_index, int ret) "bs %p l1_index %d ret %d"
+
+qcow2_cache_get(void *co, int c, uint64_t offset, bool read_from_disk) "co %p is_l2_cache %d offset %" PRIx64 " read_from_disk %d"
+qcow2_cache_get_replace_entry(void *co, int c, int i) "co %p is_l2_cache %d index %d"
+qcow2_cache_get_read(void *co, int c, int i) "co %p is_l2_cache %d index %d"
+qcow2_cache_get_done(void *co, int c, int i) "co %p is_l2_cache %d index %d"
+qcow2_cache_flush(void *co, int c) "co %p is_l2_cache %d"
+qcow2_cache_entry_flush(void *co, int c, int i) "co %p is_l2_cache %d index %d"
+
 # block/qed-l2-cache.c
 qed_alloc_l2_cache_entry(void *l2_cache, void *entry) "l2_cache %p entry %p"
 qed_unref_l2_cache_entry(void *entry, int ref) "entry %p ref %d"
commit 14fe292d86da90b79e2fb56a4986d27346339a00
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Feb 27 13:16:01 2012 +0000

    qed: do not evict in-use L2 table cache entries
    
    The L2 table cache reduces QED metadata reads that would be required
    when translating LBAs to offsets into the image file.  Since requests
    execute in parallel it is possible to share an L2 table between multiple
    requests.
    
    There is a potential data corruption issue when an in-use L2 table is
    evicted from the cache because the following situation occurs:
    
      1. An allocating write performs an update to L2 table "A".
    
      2. Another request needs L2 table "B" and causes table "A" to be
         evicted.
    
      3. A new read request needs L2 table "A" but it is not cached.
    
    As a result the L2 update from #1 can overlap with the L2 fetch from #3.
    We must avoid doing overlapping I/O requests here since the worst case
    outcome is that the L2 fetch completes before the L2 update and yields
    stale data.  In that case we would effectively discard the L2 update and
    lose data clusters!
    
    Thanks to Benoît Canet <benoit.canet at gmail.com> for extensive testing
    and debugging which lead to discovery of this bug.
    
    Reported-by: Benoît Canet <benoit.canet at gmail.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Tested-by: Benoît Canet <benoit.canet at gmail.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qed-l2-cache.c b/block/qed-l2-cache.c
index 02b81a2..e9b2aae 100644
--- a/block/qed-l2-cache.c
+++ b/block/qed-l2-cache.c
@@ -161,11 +161,25 @@ void qed_commit_l2_cache_entry(L2TableCache *l2_cache, CachedL2Table *l2_table)
         return;
     }
 
+    /* Evict an unused cache entry so we have space.  If all entries are in use
+     * we can grow the cache temporarily and we try to shrink back down later.
+     */
     if (l2_cache->n_entries >= MAX_L2_CACHE_SIZE) {
-        entry = QTAILQ_FIRST(&l2_cache->entries);
-        QTAILQ_REMOVE(&l2_cache->entries, entry, node);
-        l2_cache->n_entries--;
-        qed_unref_l2_cache_entry(entry);
+        CachedL2Table *next;
+        QTAILQ_FOREACH_SAFE(entry, &l2_cache->entries, node, next) {
+            if (entry->ref > 1) {
+                continue;
+            }
+
+            QTAILQ_REMOVE(&l2_cache->entries, entry, node);
+            l2_cache->n_entries--;
+            qed_unref_l2_cache_entry(entry);
+
+            /* Stop evicting when we've shrunk back to max size */
+            if (l2_cache->n_entries < MAX_L2_CACHE_SIZE) {
+                break;
+            }
+        }
     }
 
     l2_cache->n_entries++;
commit d0895d6e390d59d3dc6edab771335adfea263029
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Mar 1 12:21:43 2012 +0100

    Group snapshot: Fix format name for backing file
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index d78aa51..96a893b 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -800,7 +800,8 @@ void qmp_blockdev_group_snapshot_sync(SnapshotDevList *dev_list,
         /* create new image w/backing file */
         ret = bdrv_img_create(snapshot_file, format,
                               states->old_bs->filename,
-                              drv->format_name, NULL, -1, flags);
+                              states->old_bs->drv->format_name,
+                              NULL, -1, flags);
         if (ret) {
             error_set(errp, QERR_OPEN_FILE_FAILED, snapshot_file);
             goto delete_and_fail;
commit 727500181a2b2470a676e021205d170ede23beb7
Author: Alon Levy <alevy at redhat.com>
Date:   Sun Mar 11 18:11:27 2012 +0200

    vga: add trace event for ppm_save
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/vga.c b/hw/vga.c
index 5994f43..6dc98f6 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -30,6 +30,7 @@
 #include "pixel_ops.h"
 #include "qemu-timer.h"
 #include "xen.h"
+#include "trace.h"
 
 //#define DEBUG_VGA
 //#define DEBUG_VGA_MEM
@@ -2372,6 +2373,7 @@ int ppm_save(const char *filename, struct DisplaySurface *ds)
     int ret;
     char *linebuf, *pbuf;
 
+    trace_ppm_save(filename, ds);
     f = fopen(filename, "wb");
     if (!f)
         return -1;
diff --git a/trace-events b/trace-events
index 94c4a6f..dfe28ed 100644
--- a/trace-events
+++ b/trace-events
@@ -662,3 +662,6 @@ dma_map_wait(void *dbs) "dbs=%p"
 # console.h
 displaysurface_free(void *display_state, void *display_surface) "state=%p surface=%p"
 displaysurface_resize(void *display_state, void *display_surface, int width, int height) "state=%p surface=%p %dx%d"
+
+# vga.c
+ppm_save(const char *filename, void *display_surface) "%s surface=%p"
commit cdbc19dd8d2fd32d9a96401aaaed0c19da7896ca
Author: Alon Levy <alevy at redhat.com>
Date:   Sun Mar 11 18:11:26 2012 +0200

    console: add some trace events
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/console.h b/console.h
index a95b581..4334db5 100644
--- a/console.h
+++ b/console.h
@@ -5,6 +5,7 @@
 #include "qdict.h"
 #include "notify.h"
 #include "monitor.h"
+#include "trace.h"
 
 /* keyboard/mouse support */
 
@@ -202,11 +203,13 @@ static inline DisplaySurface* qemu_create_displaysurface(DisplayState *ds, int w
 
 static inline DisplaySurface* qemu_resize_displaysurface(DisplayState *ds, int width, int height)
 {
+    trace_displaysurface_resize(ds, ds->surface, width, height);
     return ds->allocator->resize_displaysurface(ds->surface, width, height);
 }
 
 static inline void qemu_free_displaysurface(DisplayState *ds)
 {
+    trace_displaysurface_free(ds, ds->surface);
     ds->allocator->free_displaysurface(ds->surface);
 }
 
diff --git a/trace-events b/trace-events
index c5d0f0f..94c4a6f 100644
--- a/trace-events
+++ b/trace-events
@@ -658,3 +658,7 @@ dma_aio_cancel(void *dbs) "dbs=%p"
 dma_complete(void *dbs, int ret, void *cb) "dbs=%p ret=%d cb=%p"
 dma_bdrv_cb(void *dbs, int ret) "dbs=%p ret=%d"
 dma_map_wait(void *dbs) "dbs=%p"
+
+# console.h
+displaysurface_free(void *display_state, void *display_surface) "state=%p surface=%p"
+displaysurface_resize(void *display_state, void *display_surface, int width, int height) "state=%p surface=%p %dx%d"
commit f922ea46ba95596ffee0155712f8e243229ed583
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Mar 10 13:37:34 2012 +0100

    maintainers: Add docs/tracing.txt to Tracing
    
    The topic of whether and by whom docs/tracing.txt is maintained was
    brought up. It currently does not have an official maintainer.
    
    Add it to the tracing section so that Stefan gets cc'ed on patches.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Cc: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/MAINTAINERS b/MAINTAINERS
index d249947..f83d07c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -548,6 +548,7 @@ Tracing
 M: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
 S: Maintained
 F: trace/
+F: docs/tracing.txt
 T: git://github.com/stefanha/qemu.git tracing
 
 Checkpatch
commit 324883aafed5163d7669358f8051fd85f805cf0d
Author: Jun Koi <junkoi2004 at gmail.com>
Date:   Thu Mar 8 16:24:52 2012 +0800

    docs: correct ./configure line in tracing.txt
    
    This patch corrects the configure's trace option in docs/tracing.txt.
    
    Signed-off-by: Jun Koi <junkoi2004 at gmail.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/docs/tracing.txt b/docs/tracing.txt
index a92716f..c541133 100644
--- a/docs/tracing.txt
+++ b/docs/tracing.txt
@@ -9,7 +9,7 @@ for debugging, profiling, and observing execution.
 
 1. Build with the 'simple' trace backend:
 
-    ./configure --trace-backend=simple
+    ./configure --enable-trace-backend=simple
     make
 
 2. Create a file with the events you want to trace:
commit db3bf8696358e105903b00432cad0aa50d3c0cb6
Author: Jun Koi <junkoi2004 at gmail.com>
Date:   Thu Mar 8 14:20:37 2012 +0800

    trace: make trace_thread_create() use its function arg
    
    This patch makes trace_thread_create() to use its function arg to
    initialize thread.  The other choice is to make this a function to use
    void arg, but i prefer this way.
    
    Signed-off-by: Jun Koi <junkoi2004 at gmail.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/trace/simple.c b/trace/simple.c
index bbc9930..33ae486 100644
--- a/trace/simple.c
+++ b/trace/simple.c
@@ -363,7 +363,7 @@ static GThread *trace_thread_create(GThreadFunc fn)
     sigfillset(&set);
     pthread_sigmask(SIG_SETMASK, &set, &oldset);
 #endif
-    thread = g_thread_create(writeout_thread, NULL, FALSE, NULL);
+    thread = g_thread_create(fn, NULL, FALSE, NULL);
 #ifndef _WIN32
     pthread_sigmask(SIG_SETMASK, &oldset, NULL);
 #endif
commit bcec43324d02d586a8bc0c9093623636e870ad19
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Tue Sep 27 09:00:22 2011 +0100

    tracetool: Omit useless QEMU_*_ENABLED() check
    
    SystemTap provides a "semaphore" that can optionally be tested before
    executing a trace event.  The purpose of this mechanism is to skip
    expensive tracing code when the trace event is disabled.
    
    For example, some applications may have trace events that format or
    convert strings for trace events.  This expensive processing should only
    be done in the case where the trace event is enabled.
    
    Since QEMU's generated trace events never have such special-purpose
    code, there is no reason to add the semaphore check.
    
    Reviewed-by: Masami Hiramatsu <masami.hiramatsu.pt at hitachi.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/scripts/tracetool b/scripts/tracetool
index 701b517..65bd0a1 100755
--- a/scripts/tracetool
+++ b/scripts/tracetool
@@ -415,9 +415,7 @@ linetoh_dtrace()
     # Define an empty function for the trace event
     cat <<EOF
 static inline void trace_$name($args) {
-    if (QEMU_${nameupper}_ENABLED()) {
-        QEMU_${nameupper}($argnames);
-    }
+    QEMU_${nameupper}($argnames);
 }
 EOF
 }
commit b7d66a761f44a725352e19b64c587924647e6f83
Author: Lluís Vilanova <vilanova at ac.upc.edu>
Date:   Tue Dec 6 17:38:15 2011 +0100

    trace: Provide a per-event status define for conditional compilation
    
    Adds a 'TRACE_${NAME}_ENABLED' preprocessor define for each tracing event in
    "trace.h".
    
    This lets the user conditionally compile code with a relatively high execution
    cost that is only necessary when producing the tracing information for an event
    that is enabled.
    
    Note that events using this define will probably have the "disable" property by
    default, in order to avoid such costs on regular builds.
    
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/docs/tracing.txt b/docs/tracing.txt
index ea29f2c..a92716f 100644
--- a/docs/tracing.txt
+++ b/docs/tracing.txt
@@ -98,12 +98,6 @@ respectively.  This ensures portability between 32- and 64-bit platforms.
 4. Name trace events after their function.  If there are multiple trace events
    in one function, append a unique distinguisher at the end of the name.
 
-5. If specific trace events are going to be called a huge number of times, this
-   might have a noticeable performance impact even when the trace events are
-   programmatically disabled. In this case you should declare the trace event
-   with the "disable" property, which will effectively disable it at compile
-   time (using the "nop" backend).
-
 == Generic interface and monitor commands ==
 
 You can programmatically query and control the dynamic state of trace events
@@ -234,3 +228,43 @@ probes:
                       --target-type system \
                       --target-arch x86_64 \
                       <trace-events >qemu.stp
+
+== Trace event properties ==
+
+Each event in the "trace-events" file can be prefixed with a space-separated
+list of zero or more of the following event properties.
+
+=== "disable" ===
+
+If a specific trace event is going to be invoked a huge number of times, this
+might have a noticeable performance impact even when the event is
+programmatically disabled.
+
+In this case you should declare such event with the "disable" property. This
+will effectively disable the event at compile time (by using the "nop" backend),
+thus having no performance impact at all on regular builds (i.e., unless you
+edit the "trace-events" file).
+
+In addition, there might be cases where relatively complex computations must be
+performed to generate values that are only used as arguments for a trace
+function. In these cases you can use the macro 'TRACE_${EVENT_NAME}_ENABLED' to
+guard such computations and avoid its compilation when the event is disabled:
+
+    #include "trace.h"  /* needed for trace event prototype */
+    
+    void *qemu_vmalloc(size_t size)
+    {
+        void *ptr;
+        size_t align = QEMU_VMALLOC_ALIGN;
+    
+        if (size < align) {
+            align = getpagesize();
+        }
+        ptr = qemu_memalign(align, size);
+        if (TRACE_QEMU_VMALLOC_ENABLED) { /* preprocessor macro */
+            void *complex;
+            /* some complex computations to produce the 'complex' value */
+            trace_qemu_vmalloc(size, ptr, complex);
+        }
+        return ptr;
+    }
diff --git a/scripts/tracetool b/scripts/tracetool
index 4c9951d..701b517 100755
--- a/scripts/tracetool
+++ b/scripts/tracetool
@@ -519,7 +519,7 @@ linetostap_end_dtrace()
 # Process stdin by calling begin, line, and end functions for the backend
 convert()
 {
-    local begin process_line end str disable
+    local begin process_line end str name NAME enabled
     begin="lineto$1_begin_$backend"
     process_line="lineto$1_$backend"
     end="lineto$1_end_$backend"
@@ -534,8 +534,15 @@ convert()
         # Process the line.  The nop backend handles disabled lines.
         if has_property "$str" "disable"; then
             "lineto$1_nop" "$str"
+            enabled=0
         else
             "$process_line" "$str"
+            enabled=1
+        fi
+        if [ "$1" = "h" ]; then
+            name=$(get_name "$str")
+            NAME=$(echo $name | tr '[:lower:]' '[:upper:]')
+            echo "#define TRACE_${NAME}_ENABLED ${enabled}"
         fi
     done
 
commit a348f108842fb928563865c9918642900cd0d477
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sun Feb 5 10:19:07 2012 +0000

    Add missing const attributes for MemoryRegionOps
    
    Most MemoryRegionOps already had the const attribute.
    This patch adds it to the remaining ones.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/cuda.c b/hw/cuda.c
index 4077436..233ab66 100644
--- a/hw/cuda.c
+++ b/hw/cuda.c
@@ -634,7 +634,7 @@ static uint32_t cuda_readl (void *opaque, target_phys_addr_t addr)
     return 0;
 }
 
-static MemoryRegionOps cuda_ops = {
+static const MemoryRegionOps cuda_ops = {
     .old_mmio = {
         .write = {
             cuda_writeb,
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 041ce1e..a883a92 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -367,7 +367,7 @@ static void ahci_mem_write(void *opaque, target_phys_addr_t addr,
 
 }
 
-static MemoryRegionOps ahci_mem_ops = {
+static const MemoryRegionOps ahci_mem_ops = {
     .read = ahci_mem_read,
     .write = ahci_mem_write,
     .endianness = DEVICE_LITTLE_ENDIAN,
@@ -403,7 +403,7 @@ static void ahci_idp_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static MemoryRegionOps ahci_idp_ops = {
+static const MemoryRegionOps ahci_idp_ops = {
     .read = ahci_idp_read,
     .write = ahci_idp_write,
     .endianness = DEVICE_LITTLE_ENDIAN,
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index 743ec02..bf8ece4 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -65,7 +65,7 @@ static void cmd646_cmd_write(void *opaque, target_phys_addr_t addr,
     ide_cmd_write(cmd646bar->bus, addr + 2, data);
 }
 
-static MemoryRegionOps cmd646_cmd_ops = {
+static const MemoryRegionOps cmd646_cmd_ops = {
     .read = cmd646_cmd_read,
     .write = cmd646_cmd_write,
     .endianness = DEVICE_LITTLE_ENDIAN,
@@ -104,7 +104,7 @@ static void cmd646_data_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static MemoryRegionOps cmd646_data_ops = {
+static const MemoryRegionOps cmd646_data_ops = {
     .read = cmd646_data_read,
     .write = cmd646_data_write,
     .endianness = DEVICE_LITTLE_ENDIAN,
@@ -193,7 +193,7 @@ static void bmdma_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static MemoryRegionOps cmd646_bmdma_ops = {
+static const MemoryRegionOps cmd646_bmdma_ops = {
     .read = bmdma_read,
     .write = bmdma_write,
 };
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index abbc41b..a4df244 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -291,7 +291,7 @@ static uint32_t pmac_ide_readl (void *opaque,target_phys_addr_t addr)
     return retval;
 }
 
-static MemoryRegionOps pmac_ide_ops = {
+static const MemoryRegionOps pmac_ide_ops = {
     .old_mmio = {
         .write = {
             pmac_ide_writeb,
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index 1030fcc..bcaa400 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -79,7 +79,7 @@ static void bmdma_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static MemoryRegionOps piix_bmdma_ops = {
+static const MemoryRegionOps piix_bmdma_ops = {
     .read = bmdma_read,
     .write = bmdma_write,
 };
diff --git a/hw/ide/via.c b/hw/ide/via.c
index 2886bc6..eec5136 100644
--- a/hw/ide/via.c
+++ b/hw/ide/via.c
@@ -82,7 +82,7 @@ static void bmdma_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static MemoryRegionOps via_bmdma_ops = {
+static const MemoryRegionOps via_bmdma_ops = {
     .read = bmdma_read,
     .write = bmdma_write,
 };
diff --git a/hw/mipsnet.c b/hw/mipsnet.c
index 50d92f8..3107246 100644
--- a/hw/mipsnet.c
+++ b/hw/mipsnet.c
@@ -224,7 +224,7 @@ static NetClientInfo net_mipsnet_info = {
     .cleanup = mipsnet_cleanup,
 };
 
-static MemoryRegionOps mipsnet_ioport_ops = {
+static const MemoryRegionOps mipsnet_ioport_ops = {
     .read = mipsnet_ioport_read,
     .write = mipsnet_ioport_write,
     .impl.min_access_size = 1,
diff --git a/hw/opencores_eth.c b/hw/opencores_eth.c
index 9b036cb..4c76969 100644
--- a/hw/opencores_eth.c
+++ b/hw/opencores_eth.c
@@ -692,12 +692,12 @@ static void open_eth_desc_write(void *opaque,
 }
 
 
-static MemoryRegionOps open_eth_reg_ops = {
+static const MemoryRegionOps open_eth_reg_ops = {
     .read = open_eth_reg_read,
     .write = open_eth_reg_write,
 };
 
-static MemoryRegionOps open_eth_desc_ops = {
+static const MemoryRegionOps open_eth_desc_ops = {
     .read = open_eth_desc_read,
     .write = open_eth_desc_write,
 };
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index cfdd9dd..374dcf8 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -281,7 +281,7 @@ static void spapr_io_write(void *opaque, target_phys_addr_t addr,
     assert(0);
 }
 
-static MemoryRegionOps spapr_io_ops = {
+static const MemoryRegionOps spapr_io_ops = {
     .endianness = DEVICE_LITTLE_ENDIAN,
     .read = spapr_io_read,
     .write = spapr_io_write
commit 9d6fca70c771ac50a641aa2558e3a19c4e2b09b8
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Mar 10 19:59:04 2012 +0100

    tcg: Improve tcg_out_label and fix its usage for w64
    
    tcg_out_label is always called with a third argument of pointer type
    which was casted to tcg_target_long.
    
    These casts can be avoided by changing the prototype of tcg_out_label.
    
    There was also a cast to long. For most hosts with
    sizeof(long) == sizeof(tcg_target_long) == sizeof(void *) this did not
    matter, but for w64 it was wrong. This is fixed now.
    
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Cc: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index 59d4d12..71f4a8a 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -1052,7 +1052,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
 
     /* TLB Miss.  */
     /* label1: */
-    tcg_out_label(s, lab1, (tcg_target_long)s->code_ptr);
+    tcg_out_label(s, lab1, s->code_ptr);
 
     argreg = TCG_REG_R26;
     tcg_out_mov(s, TCG_TYPE_I32, argreg--, addrlo_reg);
@@ -1089,7 +1089,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
     }
 
     /* label2: */
-    tcg_out_label(s, lab2, (tcg_target_long)s->code_ptr);
+    tcg_out_label(s, lab2, s->code_ptr);
 #else
     tcg_out_qemu_ld_direct(s, datalo_reg, datahi_reg, addrlo_reg,
                            (GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_R0), opc);
@@ -1171,7 +1171,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
 
     /* TLB Miss.  */
     /* label1: */
-    tcg_out_label(s, lab1, (tcg_target_long)s->code_ptr);
+    tcg_out_label(s, lab1, s->code_ptr);
 
     argreg = TCG_REG_R26;
     tcg_out_mov(s, TCG_TYPE_I32, argreg--, addrlo_reg);
@@ -1215,7 +1215,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
     tcg_out_call(s, qemu_st_helpers[opc]);
 
     /* label2: */
-    tcg_out_label(s, lab2, (tcg_target_long)s->code_ptr);
+    tcg_out_label(s, lab2, s->code_ptr);
 #else
     /* There are no indexed stores, so if GUEST_BASE is set we must do the add
        explicitly.  Careful to avoid R20, which is used for the bswaps to follow.  */
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index dc81572..1dbe240 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -875,7 +875,7 @@ static void tcg_out_brcond2(TCGContext *s, const TCGArg *args,
     default:
         tcg_abort();
     }
-    tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
+    tcg_out_label(s, label_next, s->code_ptr);
 }
 #endif
 
@@ -917,10 +917,10 @@ static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
 
         tcg_out_movi(s, TCG_TYPE_I32, args[0], 0);
         tcg_out_jxx(s, JCC_JMP, label_over, 1);
-        tcg_out_label(s, label_true, (tcg_target_long)s->code_ptr);
+        tcg_out_label(s, label_true, s->code_ptr);
 
         tcg_out_movi(s, TCG_TYPE_I32, args[0], 1);
-        tcg_out_label(s, label_over, (tcg_target_long)s->code_ptr);
+        tcg_out_label(s, label_over, s->code_ptr);
     } else {
         /* When the destination does not overlap one of the arguments,
            clear the destination first, jump if cond false, and emit an
@@ -934,7 +934,7 @@ static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
         tcg_out_brcond2(s, new_args, const_args+1, 1);
 
         tgen_arithi(s, ARITH_ADD, args[0], 1, 0);
-        tcg_out_label(s, label_over, (tcg_target_long)s->code_ptr);
+        tcg_out_label(s, label_over, s->code_ptr);
     }
 }
 #endif
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 5cd5a3b..4461fb4 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -582,7 +582,7 @@ static void tcg_out_brcond2_i32(TCGContext *s, TCGCond cond,
     }
     tcg_out_nop(s);
 
-    tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
+    tcg_out_label(s, label_next, s->code_ptr);
 }
 #endif
 
@@ -628,7 +628,7 @@ static void tcg_out_setcond_i32(TCGContext *s, TCGCond cond, TCGArg ret,
         tcg_out_branch_i32(s, INSN_COND(tcg_cond_to_bcond[cond], 1), t);
         tcg_out_movi_imm13(s, ret, 1);
         tcg_out_movi_imm13(s, ret, 0);
-        tcg_out_label(s, t, (tcg_target_long)s->code_ptr);
+        tcg_out_label(s, t, s->code_ptr);
 #endif
         return;
     }
@@ -683,7 +683,7 @@ static void tcg_out_setcond2_i32(TCGContext *s, TCGCond cond, TCGArg ret,
 
         tcg_out_setcond_i32(s, tcg_unsigned_cond(cond), ret, al, bl, blconst);
 
-        tcg_out_label(s, lab, (tcg_target_long)s->code_ptr);
+        tcg_out_label(s, lab, s->code_ptr);
         break;
     }
 }
diff --git a/tcg/tcg.c b/tcg/tcg.c
index cd2db3c..531db55 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -128,11 +128,11 @@ static void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
     }
 }
 
-static void tcg_out_label(TCGContext *s, int label_index, 
-                          tcg_target_long value)
+static void tcg_out_label(TCGContext *s, int label_index, void *ptr)
 {
     TCGLabel *l;
     TCGRelocation *r;
+    tcg_target_long value = (tcg_target_long)ptr;
 
     l = &s->labels[label_index];
     if (l->has_value)
@@ -2123,7 +2123,7 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
             break;
         case INDEX_op_set_label:
             tcg_reg_alloc_bb_end(s, s->reserved_regs);
-            tcg_out_label(s, args[0], (long)s->code_ptr);
+            tcg_out_label(s, args[0], s->code_ptr);
             break;
         case INDEX_op_call:
             dead_args = s->op_dead_args[op_index];
commit f7cf5d5b7175ee8ee26a90cdbfbb9d5ccc560416
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Mar 10 11:14:32 2012 +0100

    configure: Test for libiberty.a (mingw32)
    
    MinGW-w64 and some versions of MinGW32 don't provide libiberty.a,
    so add this library only if it was found.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/configure b/configure
index 66a65d9..39d2b54 100755
--- a/configure
+++ b/configure
@@ -511,7 +511,13 @@ if test "$mingw32" = "yes" ; then
   QEMU_CFLAGS="-DWIN32_LEAN_AND_MEAN -DWINVER=0x501 $QEMU_CFLAGS"
   # enable C99/POSIX format strings (needs mingw32-runtime 3.15 or later)
   QEMU_CFLAGS="-D__USE_MINGW_ANSI_STDIO=1 $QEMU_CFLAGS"
-  LIBS="-lwinmm -lws2_32 -liberty -liphlpapi $LIBS"
+  LIBS="-lwinmm -lws2_32 -liphlpapi $LIBS"
+cat > $TMPC << EOF
+int main(void) { return 0; }
+EOF
+  if compile_prog "" "-liberty" ; then
+    LIBS="-liberty $LIBS"
+  fi
   prefix="c:/Program Files/Qemu"
   mandir="\${prefix}"
   datadir="\${prefix}"
commit 371c6489000c2eba959aaebcb134a12ffec93c88
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Mar 10 11:14:31 2012 +0100

    w64: Don't redefine lseek, ftruncate
    
    MinGW-w64 already defines lseek and ftruncate (and uses the 64 bit
    variants). The conditional compilation avoids redefinitions
    (which would be wrong) and compiler warnings.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/qemu-common.h b/qemu-common.h
index dbfce6f..b0fdf5c 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -93,9 +93,13 @@ typedef int (*fprintf_function)(FILE *f, const char *fmt, ...)
 
 #ifdef _WIN32
 #define fsync _commit
-#define lseek _lseeki64
+#if !defined(lseek)
+# define lseek _lseeki64
+#endif
 int qemu_ftruncate64(int, int64_t);
-#define ftruncate qemu_ftruncate64
+#if !defined(ftruncate)
+# define ftruncate qemu_ftruncate64
+#endif
 
 static inline char *realpath(const char *path, char *resolved_path)
 {
commit e04b28996110bd6acfc059e9f2c8c5aba5119a46
Author: Stefan Weil <sw at weilnetz.de>
Date:   Mon Mar 5 21:15:19 2012 +0100

    cache-utils: Add missing include file for uintptr_t
    
    Commit 021ecd8b9db37927059f5d3234b51ed766706437 breaks the build for
    PPC hosts because it uses uintptr_t without the necessary include file.
    
    uintptr_t is defined in stdint.h, so add this include.
    
    Cc: Alexander Graf <agraf at suse.de>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cache-utils.h b/cache-utils.h
index 04a6e2e..2c57f78 100644
--- a/cache-utils.h
+++ b/cache-utils.h
@@ -2,6 +2,9 @@
 #define QEMU_CACHE_UTILS_H
 
 #if defined(_ARCH_PPC)
+
+#include <stdint.h> /* uintptr_t */
+
 struct qemu_cache_conf {
     unsigned long dcache_bsize;
     unsigned long icache_bsize;
commit 250b086efbf25301a8dc34c3d557c163d7ff14b2
Author: Lluís Vilanova <vilanova at ac.upc.edu>
Date:   Tue Mar 6 19:50:38 2012 +0100

    build: Include config-host.mak as soon as possible
    
    Current code depends on variables defined in config-host.mak before it is
    actually included.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Cc: Anthony Liguori <aliguori at us.ibm.com>
    Cc: Paul Brook <paul at codesourcery.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile b/Makefile
index 49c775b..408065e 100644
--- a/Makefile
+++ b/Makefile
@@ -3,13 +3,7 @@
 # Always point to the root of the build tree (needs GNU make).
 BUILD_DIR=$(CURDIR)
 
-GENERATED_HEADERS = config-host.h trace.h qemu-options.def
-ifeq ($(TRACE_BACKEND),dtrace)
-GENERATED_HEADERS += trace-dtrace.h
-endif
-GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h
-GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c
-
+# All following code might depend on configuration variables
 ifneq ($(wildcard config-host.mak),)
 # Put the all: rule here so that config-host.mak can contain dependencies.
 all: build-all
@@ -24,6 +18,13 @@ config-host.mak:
 	@exit 1
 endif
 
+GENERATED_HEADERS = config-host.h trace.h qemu-options.def
+ifeq ($(TRACE_BACKEND),dtrace)
+GENERATED_HEADERS += trace-dtrace.h
+endif
+GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h
+GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c
+
 # Don't try to regenerate Makefile or configure
 # We don't generate any of them
 Makefile: ;
commit 00e94dbc7fd0110b0555d59592b004333adfb4b8
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Mar 6 18:32:35 2012 +0100

    gdbstub: Do not kill target in system emulation mode
    
    Too many VM kittens were killed since 7d03f82f81. Another one just died
    under my fat fingers.
    
    When you quit a kgdb session, does the Linux kernel power off? Or when
    you terminate gdb attached to a hardware debugger, does your board
    vanish in space? No.
    
    So let's stop terminating QEMU when the gdbstub receives a kill commando
    in system emulation mode. Real termination can still be achieved via
    "monitor quit". We keep the behavior for user mode emulation which is
    arguably more like a gdbserver scenario.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/gdbstub.c b/gdbstub.c
index 7d470b6..ef95ac2 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2062,9 +2062,11 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
             goto unknown_command;
         }
     case 'k':
+#ifdef CONFIG_USER_ONLY
         /* Kill the target */
         fprintf(stderr, "\nQEMU: Terminated via GDBstub\n");
         exit(0);
+#endif
     case 'D':
         /* Detach packet */
         gdb_breakpoint_remove_all();
commit 3f2cbf0d1a1340bed4a63e05b044c46df93f4768
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Mar 6 15:22:02 2012 +0100

    target-i386: Mask NX bit from cpu_get_phys_page_debug result
    
    This was a long pending bug, now revealed by the assert in
    phys_page_find that stumbled over the large page index returned by
    cpu_get_phys_page_debug for NX-marked pages: We need to mask out NX and
    all user-definable bits 52..62 from PDEs and the final PTE to avoid
    corrupting physical addresses.
    
    Reviewed-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 196b0c5..36e3d29 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -241,6 +241,7 @@
 #define PG_DIRTY_MASK	 (1 << PG_DIRTY_BIT)
 #define PG_PSE_MASK	 (1 << PG_PSE_BIT)
 #define PG_GLOBAL_MASK	 (1 << PG_GLOBAL_BIT)
+#define PG_HI_USER_MASK  0x7ff0000000000000LL
 #define PG_NX_MASK	 (1LL << PG_NX_BIT)
 
 #define PG_ERROR_W_BIT     1
diff --git a/target-i386/helper.c b/target-i386/helper.c
index af6bba2..f4f3c27 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -885,8 +885,8 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
             if (!(pml4e & PG_PRESENT_MASK))
                 return -1;
 
-            pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) &
-                env->a20_mask;
+            pdpe_addr = ((pml4e & ~0xfff & ~(PG_NX_MASK | PG_HI_USER_MASK)) +
+                         (((addr >> 30) & 0x1ff) << 3)) & env->a20_mask;
             pdpe = ldq_phys(pdpe_addr);
             if (!(pdpe & PG_PRESENT_MASK))
                 return -1;
@@ -900,8 +900,8 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
                 return -1;
         }
 
-        pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
-            env->a20_mask;
+        pde_addr = ((pdpe & ~0xfff & ~(PG_NX_MASK | PG_HI_USER_MASK)) +
+                    (((addr >> 21) & 0x1ff) << 3)) & env->a20_mask;
         pde = ldq_phys(pde_addr);
         if (!(pde & PG_PRESENT_MASK)) {
             return -1;
@@ -912,11 +912,12 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
             pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
         } else {
             /* 4 KB page */
-            pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
-                env->a20_mask;
+            pte_addr = ((pde & ~0xfff & ~(PG_NX_MASK | PG_HI_USER_MASK)) +
+                        (((addr >> 12) & 0x1ff) << 3)) & env->a20_mask;
             page_size = 4096;
             pte = ldq_phys(pte_addr);
         }
+        pte &= ~(PG_NX_MASK | PG_HI_USER_MASK);
         if (!(pte & PG_PRESENT_MASK))
             return -1;
     } else {
commit d03ee40185ae8f6d6993ef58f96e0eb956f3cc33
Author: Alon Levy <alevy at redhat.com>
Date:   Mon Mar 5 15:13:28 2012 +0200

    qapi-schema.json: fix comment for type ObjectPropretyInfo
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qapi-schema.json b/qapi-schema.json
index 93ee2a4..dd9e0e5 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1256,7 +1256,7 @@
 { 'command': 'migrate_set_speed', 'data': {'value': 'int'} }
 
 ##
-# @DevicePropertyInfo:
+# @ObjectPropertyInfo:
 #
 # @name: the name of the property
 #
commit 419e1bdfefecdb161d7a78c7b7da1e70074bd61a
Author: Alon Levy <alevy at redhat.com>
Date:   Mon Mar 5 15:13:27 2012 +0200

    qapi-schema: fix typos and explain 'spice' auth
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qapi-schema.json b/qapi-schema.json
index 5f293c4..93ee2a4 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -616,11 +616,12 @@
 # @connection-id: SPICE connection id number.  All channels with the same id
 #                 belong to the same SPICE session.
 #
-# @connection-type: SPICE channel type number.  "1" is the main control channel,
-#                   filter for this one if you want track spice sessions only
+# @connection-type: SPICE channel type number.  "1" is the main control
+#                   channel, filter for this one if you want to track spice
+#                   sessions only
 #
-# @channel-id: SPICE channel ID number.  Usually "0", might be different needed
-#              when multiple channels of the same type exist, such as multiple
+# @channel-id: SPICE channel ID number.  Usually "0", might be different when
+#              multiple channels of the same type exist, such as multiple
 #              display channels in a multihead setup
 #
 # @tls: true if the channel is encrypted, false otherwise.
@@ -649,8 +650,9 @@
 # @tls-port: #optional The SPICE server's TLS port number.
 #
 # @auth: #optional the current authentication type used by the server
-#        'none' if no authentication is being used
-#        'spice' (TODO: describe)
+#        'none'  if no authentication is being used
+#        'spice' uses SASL or direct TLS authentication, depending on command
+#                line options
 #
 # @channels: a list of @SpiceChannel for each active spice channel
 #
commit 156b12d73983aa3c75ee1a82d5343787bb48e579
Author: Alon Levy <alevy at redhat.com>
Date:   Fri Feb 24 23:22:03 2012 +0200

    qjson.h: include compiler.h for GCC_FMT_ATTR
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qjson.h b/qjson.h
index 65b10ea..1190d8a 100644
--- a/qjson.h
+++ b/qjson.h
@@ -15,6 +15,7 @@
 #define QJSON_H
 
 #include <stdarg.h>
+#include "compiler.h"
 #include "qobject.h"
 #include "qstring.h"
 
commit dac6b1b22cbad29ca34735a1e56c9feb9586e3c0
Merge: bf75fec... 979ae16...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Mar 9 12:30:20 2012 -0600

    Merge remote-tracking branch 'stefanha/trivial-patches' into staging
    
    * stefanha/trivial-patches:
      configure: Quote the configure args printed in config.log
      osdep: Remove local definition of macro offsetof
      libcacard: Spelling and grammar fixes in documentation
      Spelling fixes in comments (it's -> its)
      vnc: Add break statement
      libcacard: Use format specifier %u instead of %d for unsigned values
      Fix sign of sscanf format specifiers
      block/vmdk: Fix warning from splint (comparision of unsigned value)
      qmp: Fix spelling fourty -> forty
      qom: Fix spelling in documentation
      sh7750: Remove redundant 'struct' from MemoryRegionOps

commit bf75fec175d00885c7ae06e5917bde86110c386a
Merge: 9f1d43b... 7e68075...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Mar 9 12:29:55 2012 -0600

    Merge remote-tracking branch 'qemu-kvm/uq/master' into staging
    
    * qemu-kvm/uq/master:
      kvm: fill in padding to help valgrind
      kvm: x86: Add user space part for in-kernel i8254
      kvm: Add kvm_has_pit_state2 helper
      i8254: Open-code timer restore
      i8254: Factor out base class for KVM reuse

commit 9f1d43b133d6bac0539f0c99497fe59d561a02ea
Merge: 0202181... cf21a4a...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Mar 9 12:29:40 2012 -0600

    Merge remote-tracking branch 'kraxel/usb.42' into staging
    
    * kraxel/usb.42:
      xhci: fix port status
      xhci: fix control xfers
      usb: add shortcut for control transfers
      usb-host: enable pipelineing for bulk endpoints.
      usb: add pipelining option to usb endpoints
      usb: queue can have async packets
      uhci_fill_queue: zap debug printf
      usb: add USB_RET_IOERROR
      usb: return BABBLE rather then NAK when we receive too much data
      usb-ehci: Cleanup itd error handling
      usb-ehci: Fix and simplify nakcnt handling
      usb-ehci: Remove dead nakcnt code
      usb-ehci: Fix cerr tracking
      usb-ehci: Any packet completion except for NAK should set the interrupt
      usb-ehci: Rip the queues when the async or period schedule is halted
      usb-ehci: Drop cached qhs when the doorbell gets rung
      usb-ehci: always call ehci_queues_rip_unused for period queues
      usb-ehci: split our qh queue into async and periodic queues
      usb-ehci: Never follow table entries with the T-bit set
      usb-redir: Set ep type and interface

commit 0202181245297a9e847c05f4a18623219d95e93e
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Mar 2 16:49:44 2012 +0100

    libcacard: Fix compilation with gcc-4.7
    
    VCARD_ATR_PREFIX is used as part of an array initializer so it should
    not have () around it, so far this happened to work, but gcc-4.7 does
    not like it.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/libcacard/vcardt.h b/libcacard/vcardt.h
index d4d8e2e..d3e9522 100644
--- a/libcacard/vcardt.h
+++ b/libcacard/vcardt.h
@@ -26,8 +26,8 @@ typedef struct VCardEmulStruct VCardEmul;
 #define MAX_CHANNEL 4
 
 /* create an ATR with appropriate historical bytes */
-#define VCARD_ATR_PREFIX(size) (0x3b, 0x68+(size), 0x00, 0xff, \
-                               'V', 'C', 'A', 'R', 'D', '_')
+#define VCARD_ATR_PREFIX(size) 0x3b, 0x68+(size), 0x00, 0xff, \
+                               'V', 'C', 'A', 'R', 'D', '_'
 
 
 typedef enum {
commit 0d10f627089066fc58894c1fa4b066503ed6bac3
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Mar 9 06:29:15 2012 -0600

    xilinx_zynq: fix the build
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/zynq_slcr.c b/hw/zynq_slcr.c
index b785f04..4f97575 100644
--- a/hw/zynq_slcr.c
+++ b/hw/zynq_slcr.c
@@ -311,7 +311,7 @@ static inline uint32_t zynq_slcr_read_imp(void *opaque,
     case 0xA50:
         return s->dmac_ram;
     case 0xA60 ... 0xA8C:
-        return s->afi[0][(offset - 0x700) / 4];
+        return s->afi[0][(offset - 0xA60) / 4];
     case 0xA90 ... 0xA98:
         return s->ocm[(offset - 0xA90) / 4];
     case 0xAA0:
@@ -454,7 +454,7 @@ static void zynq_slcr_write(void *opaque, target_phys_addr_t offset,
             s->dmac_ram = val;
             break;
         case 0xA60 ... 0xA8C:
-            s->afi[0][(offset - 0x700) / 4] = val;
+            s->afi[0][(offset - 0xA60) / 4] = val;
             break;
         case 0xA90:
             s->ocm[0] = val;
commit 97161e177b4ea2730dff13c4df01475762ab6048
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Mar 8 19:16:39 2012 +0200

    memory: get rid of cpu_register_io_memory()
    
    The return value of cpu_register_io_memory() is no longer used anywhere, so
    we can remove it and all associated data and code.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/cpu-all.h b/cpu-all.h
index 80e6d42..b87f2ce 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -498,14 +498,6 @@ extern RAMList ram_list;
 extern const char *mem_path;
 extern int mem_prealloc;
 
-/* physical memory access */
-
-/* MMIO pages are identified by a combination of an IO device index and
-   3 flags.  The ROMD code stores the page ram offset in iotlb entry, 
-   so only a limited number of ids are avaiable.  */
-
-#define IO_MEM_NB_ENTRIES  (1 << TARGET_PAGE_BITS)
-
 /* Flags stored in the low bits of the TLB virtual address.  These are
    defined so that fast path ram access is all zeros.  */
 /* Zero if TLB entry is valid.  */
diff --git a/exec-all.h b/exec-all.h
index 4e8c7f5..3ec60a2 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -304,7 +304,6 @@ uint64_t io_mem_read(struct MemoryRegion *mr, target_phys_addr_t addr,
                      unsigned size);
 void io_mem_write(struct MemoryRegion *mr, target_phys_addr_t addr,
                   uint64_t value, unsigned size);
-extern struct MemoryRegion *io_mem_region[IO_MEM_NB_ENTRIES];
 
 void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
               void *retaddr);
diff --git a/exec-obsolete.h b/exec-obsolete.h
index 4dbe476..792c831 100644
--- a/exec-obsolete.h
+++ b/exec-obsolete.h
@@ -32,9 +32,6 @@ void qemu_ram_free(ram_addr_t addr);
 void qemu_ram_free_from_ptr(ram_addr_t addr);
 
 struct MemoryRegion;
-int cpu_register_io_memory(MemoryRegion *mr);
-void cpu_unregister_io_memory(int table_address);
-
 struct MemoryRegionSection;
 void cpu_register_physical_memory_log(struct MemoryRegionSection *section,
                                       bool readonly);
diff --git a/exec.c b/exec.c
index 6e14048..0c86bce 100644
--- a/exec.c
+++ b/exec.c
@@ -214,9 +214,6 @@ static PhysPageEntry phys_map = { .ptr = PHYS_MAP_NODE_NIL, .is_leaf = 0 };
 static void io_mem_init(void);
 static void memory_map_init(void);
 
-/* io memory support */
-MemoryRegion *io_mem_region[IO_MEM_NB_ENTRIES];
-static char io_mem_used[IO_MEM_NB_ENTRIES];
 static MemoryRegion io_mem_watch;
 #endif
 
@@ -3503,53 +3500,6 @@ static subpage_t *subpage_init(target_phys_addr_t base)
     return mmio;
 }
 
-static int get_free_io_mem_idx(void)
-{
-    int i;
-
-    for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
-        if (!io_mem_used[i]) {
-            io_mem_used[i] = 1;
-            return i;
-        }
-    fprintf(stderr, "RAN out out io_mem_idx, max %d !\n", IO_MEM_NB_ENTRIES);
-    return -1;
-}
-
-/* mem_read and mem_write are arrays of functions containing the
-   function to access byte (index 0), word (index 1) and dword (index
-   2). Functions can be omitted with a NULL function pointer.
-   If io_index is non zero, the corresponding io zone is
-   modified. If it is zero, a new io zone is allocated. The return
-   value can be used with cpu_register_physical_memory(). (-1) is
-   returned if error. */
-static int cpu_register_io_memory_fixed(int io_index, MemoryRegion *mr)
-{
-    if (io_index <= 0) {
-        io_index = get_free_io_mem_idx();
-        if (io_index == -1)
-            return io_index;
-    } else {
-        if (io_index >= IO_MEM_NB_ENTRIES)
-            return -1;
-    }
-
-    io_mem_region[io_index] = mr;
-
-    return io_index;
-}
-
-int cpu_register_io_memory(MemoryRegion *mr)
-{
-    return cpu_register_io_memory_fixed(0, mr);
-}
-
-void cpu_unregister_io_memory(int io_index)
-{
-    io_mem_region[io_index] = NULL;
-    io_mem_used[io_index] = 0;
-}
-
 static uint16_t dummy_section(MemoryRegion *mr)
 {
     MemoryRegionSection section = {
@@ -3569,11 +3519,7 @@ MemoryRegion *iotlb_to_region(target_phys_addr_t index)
 
 static void io_mem_init(void)
 {
-    int i;
-
-    /* Must be first: */
     memory_region_init_io(&io_mem_ram, &error_mem_ops, NULL, "ram", UINT64_MAX);
-    assert(io_mem_ram.ram_addr == 0);
     memory_region_init_io(&io_mem_rom, &rom_mem_ops, NULL, "rom", UINT64_MAX);
     memory_region_init_io(&io_mem_unassigned, &unassigned_mem_ops, NULL,
                           "unassigned", UINT64_MAX);
@@ -3581,9 +3527,6 @@ static void io_mem_init(void)
                           "notdirty", UINT64_MAX);
     memory_region_init_io(&io_mem_subpage_ram, &subpage_ram_ops, NULL,
                           "subpage-ram", UINT64_MAX);
-    for (i=0; i<5; i++)
-        io_mem_used[i] = 1;
-
     memory_region_init_io(&io_mem_watch, &watch_mem_ops, NULL,
                           "watch", UINT64_MAX);
 }
diff --git a/memory.c b/memory.c
index bc76f55..22b0352 100644
--- a/memory.c
+++ b/memory.c
@@ -781,13 +781,11 @@ static void memory_region_destructor_ram_from_ptr(MemoryRegion *mr)
 
 static void memory_region_destructor_iomem(MemoryRegion *mr)
 {
-    cpu_unregister_io_memory(mr->ram_addr);
 }
 
 static void memory_region_destructor_rom_device(MemoryRegion *mr)
 {
     qemu_ram_free(mr->ram_addr & TARGET_PAGE_MASK);
-    cpu_unregister_io_memory(mr->ram_addr & ~TARGET_PAGE_MASK);
 }
 
 static bool memory_region_wrong_endianness(MemoryRegion *mr)
@@ -942,7 +940,7 @@ void memory_region_init_io(MemoryRegion *mr,
     mr->opaque = opaque;
     mr->terminates = true;
     mr->destructor = memory_region_destructor_iomem;
-    mr->ram_addr = cpu_register_io_memory(mr);
+    mr->ram_addr = ~(ram_addr_t)0;
 }
 
 void memory_region_init_ram(MemoryRegion *mr,
@@ -992,7 +990,6 @@ void memory_region_init_rom_device(MemoryRegion *mr,
     mr->rom_device = true;
     mr->destructor = memory_region_destructor_rom_device;
     mr->ram_addr = qemu_ram_alloc(size, mr);
-    mr->ram_addr |= cpu_register_io_memory(mr);
 }
 
 static uint64_t invalid_read(void *opaque, target_phys_addr_t addr,
commit 37ec01d43343fc20b6e1ce34f82ec617020a9849
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Mar 8 18:08:35 2012 +0200

    memory: dispatch directly via MemoryRegion
    
    Instead of indirecting via io_mem_region, dispatch directly
    through the MemoryRegion obtained from the iotlb or phys_page_find().
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec-all.h b/exec-all.h
index 3ffe9dd..4e8c7f5 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -299,10 +299,11 @@ extern void *tci_tb_ptr;
 
 #if !defined(CONFIG_USER_ONLY)
 
-target_phys_addr_t section_to_ioaddr(target_phys_addr_t section_io_addr);
-uint64_t io_mem_read(int index, target_phys_addr_t addr, unsigned size);
-void io_mem_write(int index, target_phys_addr_t addr, uint64_t value,
-                  unsigned size);
+struct MemoryRegion *iotlb_to_region(target_phys_addr_t index);
+uint64_t io_mem_read(struct MemoryRegion *mr, target_phys_addr_t addr,
+                     unsigned size);
+void io_mem_write(struct MemoryRegion *mr, target_phys_addr_t addr,
+                  uint64_t value, unsigned size);
 extern struct MemoryRegion *io_mem_region[IO_MEM_NB_ENTRIES];
 
 void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
diff --git a/exec.c b/exec.c
index f26d1b0..6e14048 100644
--- a/exec.c
+++ b/exec.c
@@ -3399,7 +3399,7 @@ static uint64_t subpage_read(void *opaque, target_phys_addr_t addr,
     addr += mmio->base;
     addr -= section->offset_within_address_space;
     addr += section->offset_within_region;
-    return io_mem_read(section->mr->ram_addr, addr, len);
+    return io_mem_read(section->mr, addr, len);
 }
 
 static void subpage_write(void *opaque, target_phys_addr_t addr,
@@ -3418,7 +3418,7 @@ static void subpage_write(void *opaque, target_phys_addr_t addr,
     addr += mmio->base;
     addr -= section->offset_within_address_space;
     addr += section->offset_within_region;
-    io_mem_write(section->mr->ram_addr, addr, value, len);
+    io_mem_write(section->mr, addr, value, len);
 }
 
 static const MemoryRegionOps subpage_ops = {
@@ -3562,13 +3562,9 @@ static uint16_t dummy_section(MemoryRegion *mr)
     return phys_section_add(&section);
 }
 
-target_phys_addr_t section_to_ioaddr(target_phys_addr_t section_io_addr)
+MemoryRegion *iotlb_to_region(target_phys_addr_t index)
 {
-    MemoryRegionSection *section;
-
-    section = &phys_sections[section_io_addr & ~TARGET_PAGE_MASK];
-    return (section_io_addr & TARGET_PAGE_MASK)
-        | (section->mr->ram_addr & ~TARGET_PAGE_MASK);
+    return phys_sections[index & ~TARGET_PAGE_MASK].mr;
 }
 
 static void io_mem_init(void)
@@ -3838,7 +3834,7 @@ int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
 void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
                             int len, int is_write)
 {
-    int l, io_index;
+    int l;
     uint8_t *ptr;
     uint32_t val;
     target_phys_addr_t page;
@@ -3854,25 +3850,23 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
         if (is_write) {
             if (!memory_region_is_ram(section->mr)) {
                 target_phys_addr_t addr1;
-                io_index = memory_region_get_ram_addr(section->mr)
-                    & (IO_MEM_NB_ENTRIES - 1);
                 addr1 = section_addr(section, addr);
                 /* XXX: could force cpu_single_env to NULL to avoid
                    potential bugs */
                 if (l >= 4 && ((addr1 & 3) == 0)) {
                     /* 32 bit write access */
                     val = ldl_p(buf);
-                    io_mem_write(io_index, addr1, val, 4);
+                    io_mem_write(section->mr, addr1, val, 4);
                     l = 4;
                 } else if (l >= 2 && ((addr1 & 1) == 0)) {
                     /* 16 bit write access */
                     val = lduw_p(buf);
-                    io_mem_write(io_index, addr1, val, 2);
+                    io_mem_write(section->mr, addr1, val, 2);
                     l = 2;
                 } else {
                     /* 8 bit write access */
                     val = ldub_p(buf);
-                    io_mem_write(io_index, addr1, val, 1);
+                    io_mem_write(section->mr, addr1, val, 1);
                     l = 1;
                 }
             } else if (!section->readonly) {
@@ -3895,22 +3889,20 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
             if (!is_ram_rom_romd(section)) {
                 target_phys_addr_t addr1;
                 /* I/O case */
-                io_index = memory_region_get_ram_addr(section->mr)
-                    & (IO_MEM_NB_ENTRIES - 1);
                 addr1 = section_addr(section, addr);
                 if (l >= 4 && ((addr1 & 3) == 0)) {
                     /* 32 bit read access */
-                    val = io_mem_read(io_index, addr1, 4);
+                    val = io_mem_read(section->mr, addr1, 4);
                     stl_p(buf, val);
                     l = 4;
                 } else if (l >= 2 && ((addr1 & 1) == 0)) {
                     /* 16 bit read access */
-                    val = io_mem_read(io_index, addr1, 2);
+                    val = io_mem_read(section->mr, addr1, 2);
                     stw_p(buf, val);
                     l = 2;
                 } else {
                     /* 8 bit read access */
-                    val = io_mem_read(io_index, addr1, 1);
+                    val = io_mem_read(section->mr, addr1, 1);
                     stb_p(buf, val);
                     l = 1;
                 }
@@ -4106,7 +4098,6 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
 static inline uint32_t ldl_phys_internal(target_phys_addr_t addr,
                                          enum device_endian endian)
 {
-    int io_index;
     uint8_t *ptr;
     uint32_t val;
     MemoryRegionSection *section;
@@ -4115,10 +4106,8 @@ static inline uint32_t ldl_phys_internal(target_phys_addr_t addr,
 
     if (!is_ram_rom_romd(section)) {
         /* I/O case */
-        io_index = memory_region_get_ram_addr(section->mr)
-            & (IO_MEM_NB_ENTRIES - 1);
         addr = section_addr(section, addr);
-        val = io_mem_read(io_index, addr, 4);
+        val = io_mem_read(section->mr, addr, 4);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
             val = bswap32(val);
@@ -4167,7 +4156,6 @@ uint32_t ldl_be_phys(target_phys_addr_t addr)
 static inline uint64_t ldq_phys_internal(target_phys_addr_t addr,
                                          enum device_endian endian)
 {
-    int io_index;
     uint8_t *ptr;
     uint64_t val;
     MemoryRegionSection *section;
@@ -4176,18 +4164,16 @@ static inline uint64_t ldq_phys_internal(target_phys_addr_t addr,
 
     if (!is_ram_rom_romd(section)) {
         /* I/O case */
-        io_index = memory_region_get_ram_addr(section->mr)
-            & (IO_MEM_NB_ENTRIES - 1);
         addr = section_addr(section, addr);
 
         /* XXX This is broken when device endian != cpu endian.
                Fix and add "endian" variable check */
 #ifdef TARGET_WORDS_BIGENDIAN
-        val = io_mem_read(io_index, addr, 4) << 32;
-        val |= io_mem_read(io_index, addr + 4, 4);
+        val = io_mem_read(section->mr, addr, 4) << 32;
+        val |= io_mem_read(section->mr, addr + 4, 4);
 #else
-        val = io_mem_read(io_index, addr, 4);
-        val |= io_mem_read(io_index, addr + 4, 4) << 32;
+        val = io_mem_read(section->mr, addr, 4);
+        val |= io_mem_read(section->mr, addr + 4, 4) << 32;
 #endif
     } else {
         /* RAM case */
@@ -4236,7 +4222,6 @@ uint32_t ldub_phys(target_phys_addr_t addr)
 static inline uint32_t lduw_phys_internal(target_phys_addr_t addr,
                                           enum device_endian endian)
 {
-    int io_index;
     uint8_t *ptr;
     uint64_t val;
     MemoryRegionSection *section;
@@ -4245,10 +4230,8 @@ static inline uint32_t lduw_phys_internal(target_phys_addr_t addr,
 
     if (!is_ram_rom_romd(section)) {
         /* I/O case */
-        io_index = memory_region_get_ram_addr(section->mr)
-            & (IO_MEM_NB_ENTRIES - 1);
         addr = section_addr(section, addr);
-        val = io_mem_read(io_index, addr, 2);
+        val = io_mem_read(section->mr, addr, 2);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
             val = bswap16(val);
@@ -4298,20 +4281,17 @@ uint32_t lduw_be_phys(target_phys_addr_t addr)
    bits are used to track modified PTEs */
 void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
 {
-    int io_index;
     uint8_t *ptr;
     MemoryRegionSection *section;
 
     section = phys_page_find(addr >> TARGET_PAGE_BITS);
 
     if (!memory_region_is_ram(section->mr) || section->readonly) {
+        addr = section_addr(section, addr);
         if (memory_region_is_ram(section->mr)) {
-            io_index = io_mem_rom.ram_addr;
-        } else {
-            io_index = memory_region_get_ram_addr(section->mr);
+            section = &phys_sections[phys_section_rom];
         }
-        addr = section_addr(section, addr);
-        io_mem_write(io_index, addr, val, 4);
+        io_mem_write(section->mr, addr, val, 4);
     } else {
         unsigned long addr1 = (memory_region_get_ram_addr(section->mr)
                                & TARGET_PAGE_MASK)
@@ -4333,26 +4313,22 @@ void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
 
 void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
 {
-    int io_index;
     uint8_t *ptr;
     MemoryRegionSection *section;
 
     section = phys_page_find(addr >> TARGET_PAGE_BITS);
 
     if (!memory_region_is_ram(section->mr) || section->readonly) {
+        addr = section_addr(section, addr);
         if (memory_region_is_ram(section->mr)) {
-                io_index = io_mem_rom.ram_addr;
-        } else {
-            io_index = memory_region_get_ram_addr(section->mr)
-                & (IO_MEM_NB_ENTRIES - 1);
+            section = &phys_sections[phys_section_rom];
         }
-        addr = section_addr(section, addr);
 #ifdef TARGET_WORDS_BIGENDIAN
-        io_mem_write(io_index, addr, val >> 32, 4);
-        io_mem_write(io_index, addr + 4, (uint32_t)val, 4);
+        io_mem_write(section->mr, addr, val >> 32, 4);
+        io_mem_write(section->mr, addr + 4, (uint32_t)val, 4);
 #else
-        io_mem_write(io_index, addr, (uint32_t)val, 4);
-        io_mem_write(io_index, addr + 4, val >> 32, 4);
+        io_mem_write(section->mr, addr, (uint32_t)val, 4);
+        io_mem_write(section->mr, addr + 4, val >> 32, 4);
 #endif
     } else {
         ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section->mr)
@@ -4366,20 +4342,16 @@ void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
 static inline void stl_phys_internal(target_phys_addr_t addr, uint32_t val,
                                      enum device_endian endian)
 {
-    int io_index;
     uint8_t *ptr;
     MemoryRegionSection *section;
 
     section = phys_page_find(addr >> TARGET_PAGE_BITS);
 
     if (!memory_region_is_ram(section->mr) || section->readonly) {
+        addr = section_addr(section, addr);
         if (memory_region_is_ram(section->mr)) {
-            io_index = io_mem_rom.ram_addr;
-        } else {
-            io_index = memory_region_get_ram_addr(section->mr)
-                & (IO_MEM_NB_ENTRIES - 1);
+            section = &phys_sections[phys_section_rom];
         }
-        addr = section_addr(section, addr);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
             val = bswap32(val);
@@ -4389,7 +4361,7 @@ static inline void stl_phys_internal(target_phys_addr_t addr, uint32_t val,
             val = bswap32(val);
         }
 #endif
-        io_mem_write(io_index, addr, val, 4);
+        io_mem_write(section->mr, addr, val, 4);
     } else {
         unsigned long addr1;
         addr1 = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
@@ -4443,20 +4415,16 @@ void stb_phys(target_phys_addr_t addr, uint32_t val)
 static inline void stw_phys_internal(target_phys_addr_t addr, uint32_t val,
                                      enum device_endian endian)
 {
-    int io_index;
     uint8_t *ptr;
     MemoryRegionSection *section;
 
     section = phys_page_find(addr >> TARGET_PAGE_BITS);
 
     if (!memory_region_is_ram(section->mr) || section->readonly) {
+        addr = section_addr(section, addr);
         if (memory_region_is_ram(section->mr)) {
-            io_index = io_mem_rom.ram_addr;
-        } else {
-            io_index = memory_region_get_ram_addr(section->mr)
-                & (IO_MEM_NB_ENTRIES - 1);
+            section = &phys_sections[phys_section_rom];
         }
-        addr = section_addr(section, addr);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
             val = bswap16(val);
@@ -4466,7 +4434,7 @@ static inline void stw_phys_internal(target_phys_addr_t addr, uint32_t val,
             val = bswap16(val);
         }
 #endif
-        io_mem_write(io_index, addr, val, 2);
+        io_mem_write(section->mr, addr, val, 2);
     } else {
         unsigned long addr1;
         addr1 = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
@@ -4678,6 +4646,7 @@ tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong addr)
 {
     int mmu_idx, page_index, pd;
     void *p;
+    MemoryRegion *mr;
 
     page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
     mmu_idx = cpu_mmu_index(env1);
@@ -4686,8 +4655,9 @@ tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong addr)
         ldub_code(addr);
     }
     pd = env1->iotlb[mmu_idx][page_index] & ~TARGET_PAGE_MASK;
-    if (pd != io_mem_ram.ram_addr && pd != io_mem_rom.ram_addr
-        && !io_mem_region[pd]->rom_device) {
+    mr = iotlb_to_region(pd);
+    if (mr != &io_mem_ram && mr != &io_mem_rom
+        && mr != &io_mem_notdirty && !mr->rom_device) {
 #if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC)
         cpu_unassigned_access(env1, addr, 0, 1, 0, 4);
 #else
diff --git a/memory.c b/memory.c
index 4c3dc49..bc76f55 100644
--- a/memory.c
+++ b/memory.c
@@ -1501,15 +1501,15 @@ void set_system_io_map(MemoryRegion *mr)
     memory_region_update_topology(NULL);
 }
 
-uint64_t io_mem_read(int io_index, target_phys_addr_t addr, unsigned size)
+uint64_t io_mem_read(MemoryRegion *mr, target_phys_addr_t addr, unsigned size)
 {
-    return memory_region_dispatch_read(io_mem_region[io_index], addr, size);
+    return memory_region_dispatch_read(mr, addr, size);
 }
 
-void io_mem_write(int io_index, target_phys_addr_t addr,
+void io_mem_write(MemoryRegion *mr, target_phys_addr_t addr,
                   uint64_t val, unsigned size)
 {
-    memory_region_dispatch_write(io_mem_region[io_index], addr, val, size);
+    memory_region_dispatch_write(mr, addr, val, size);
 }
 
 typedef struct MemoryRegionList MemoryRegionList;
diff --git a/softmmu_template.h b/softmmu_template.h
index 7c7e15b..e395020 100644
--- a/softmmu_template.h
+++ b/softmmu_template.h
@@ -62,27 +62,27 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr,
                                               void *retaddr)
 {
     DATA_TYPE res;
-    int index;
-    index = physaddr & (IO_MEM_NB_ENTRIES - 1);
+    MemoryRegion *mr = iotlb_to_region(physaddr);
+
     physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
     env->mem_io_pc = (unsigned long)retaddr;
-    if (index != io_mem_ram.ram_addr && index != io_mem_rom.ram_addr
-        && index != io_mem_unassigned.ram_addr
-        && index != io_mem_notdirty.ram_addr
+    if (mr != &io_mem_ram && mr != &io_mem_rom
+        && mr != &io_mem_unassigned
+        && mr != &io_mem_notdirty
             && !can_do_io(env)) {
         cpu_io_recompile(env, retaddr);
     }
 
     env->mem_io_vaddr = addr;
 #if SHIFT <= 2
-    res = io_mem_read(index, physaddr, 1 << SHIFT);
+    res = io_mem_read(mr, physaddr, 1 << SHIFT);
 #else
 #ifdef TARGET_WORDS_BIGENDIAN
-    res = io_mem_read(index, physaddr, 4) << 32;
-    res |= io_mem_read(index, physaddr + 4, 4);
+    res = io_mem_read(mr, physaddr, 4) << 32;
+    res |= io_mem_read(mr, physaddr + 4, 4);
 #else
-    res = io_mem_read(index, physaddr, 4);
-    res |= io_mem_read(index, physaddr + 4, 4) << 32;
+    res = io_mem_read(mr, physaddr, 4);
+    res |= io_mem_read(mr, physaddr + 4, 4) << 32;
 #endif
 #endif /* SHIFT > 2 */
     return res;
@@ -110,7 +110,7 @@ DATA_TYPE REGPARM glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
             if ((addr & (DATA_SIZE - 1)) != 0)
                 goto do_unaligned_access;
             retaddr = GETPC();
-            ioaddr = section_to_ioaddr(env->iotlb[mmu_idx][index]);
+            ioaddr = env->iotlb[mmu_idx][index];
             res = glue(io_read, SUFFIX)(ioaddr, addr, retaddr);
         } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
             /* slow unaligned access (it spans two pages or IO) */
@@ -164,7 +164,7 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
             /* IO access */
             if ((addr & (DATA_SIZE - 1)) != 0)
                 goto do_unaligned_access;
-            ioaddr = section_to_ioaddr(env->iotlb[mmu_idx][index]);
+            ioaddr = env->iotlb[mmu_idx][index];
             res = glue(io_read, SUFFIX)(ioaddr, addr, retaddr);
         } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
         do_unaligned_access:
@@ -207,12 +207,12 @@ static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr,
                                           target_ulong addr,
                                           void *retaddr)
 {
-    int index;
-    index = physaddr & (IO_MEM_NB_ENTRIES - 1);
+    MemoryRegion *mr = iotlb_to_region(physaddr);
+
     physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
-    if (index != io_mem_ram.ram_addr && index != io_mem_rom.ram_addr
-        && index != io_mem_unassigned.ram_addr
-        && index != io_mem_notdirty.ram_addr
+    if (mr != &io_mem_ram && mr != &io_mem_rom
+        && mr != &io_mem_unassigned
+        && mr != &io_mem_notdirty
             && !can_do_io(env)) {
         cpu_io_recompile(env, retaddr);
     }
@@ -220,14 +220,14 @@ static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr,
     env->mem_io_vaddr = addr;
     env->mem_io_pc = (unsigned long)retaddr;
 #if SHIFT <= 2
-    io_mem_write(index, physaddr, val, 1 << SHIFT);
+    io_mem_write(mr, physaddr, val, 1 << SHIFT);
 #else
 #ifdef TARGET_WORDS_BIGENDIAN
-    io_mem_write(index, physaddr, (val >> 32), 4);
-    io_mem_write(index, physaddr + 4, (uint32_t)val, 4);
+    io_mem_write(mr, physaddr, (val >> 32), 4);
+    io_mem_write(mr, physaddr + 4, (uint32_t)val, 4);
 #else
-    io_mem_write(index, physaddr, (uint32_t)val, 4);
-    io_mem_write(index, physaddr + 4, val >> 32, 4);
+    io_mem_write(mr, physaddr, (uint32_t)val, 4);
+    io_mem_write(mr, physaddr + 4, val >> 32, 4);
 #endif
 #endif /* SHIFT > 2 */
 }
@@ -251,7 +251,7 @@ void REGPARM glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr,
             if ((addr & (DATA_SIZE - 1)) != 0)
                 goto do_unaligned_access;
             retaddr = GETPC();
-            ioaddr = section_to_ioaddr(env->iotlb[mmu_idx][index]);
+            ioaddr = env->iotlb[mmu_idx][index];
             glue(io_write, SUFFIX)(ioaddr, val, addr, retaddr);
         } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
         do_unaligned_access:
@@ -303,7 +303,7 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
             /* IO access */
             if ((addr & (DATA_SIZE - 1)) != 0)
                 goto do_unaligned_access;
-            ioaddr = section_to_ioaddr(env->iotlb[mmu_idx][index]);
+            ioaddr = env->iotlb[mmu_idx][index];
             glue(io_write, SUFFIX)(ioaddr, val, addr, retaddr);
         } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
         do_unaligned_access:
commit ce5d64c2d0aa2aaf2ef60e9af48b0bf57852470b
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Mar 8 18:50:18 2012 +0200

    exec: fix code tlb entry misused as iotlb in get_page_addr_code()
    
    get_page_addr_code() reads a code tlb entry, but interprets it as an
    iotlb entry.  This works by accident since the low bits of a RAM code
    tlb entry are clear, and match a RAM iotlb entry.  This accident is
    about to unhappen, so fix the code to use an iotlb entry (using the
    code entry with TLB_MMIO may fail if the page is a watchpoint).
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index a35eb4f..f26d1b0 100644
--- a/exec.c
+++ b/exec.c
@@ -4685,7 +4685,7 @@ tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong addr)
                  (addr & TARGET_PAGE_MASK))) {
         ldub_code(addr);
     }
-    pd = env1->tlb_table[mmu_idx][page_index].addr_code & ~TARGET_PAGE_MASK;
+    pd = env1->iotlb[mmu_idx][page_index] & ~TARGET_PAGE_MASK;
     if (pd != io_mem_ram.ram_addr && pd != io_mem_rom.ram_addr
         && !io_mem_region[pd]->rom_device) {
 #if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC)
commit 979ae168e5fac830fcf8ca63fed732051af0611a
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Mar 7 12:16:29 2012 +0000

    configure: Quote the configure args printed in config.log
    
    Use the same mechanism we use for printing the configure command
    line to config-host.mak to print it to config.log. This fixes a
    bug where the config.log version didn't quote arguments with spaces.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/configure b/configure
index ed3d907..66a65d9 100755
--- a/configure
+++ b/configure
@@ -22,7 +22,9 @@ rm -f config.log
 
 # Print a helpful header at the top of config.log
 echo "# QEMU configure log $(date)" >> config.log
-echo "# produced by $0 $*" >> config.log
+printf "# Configured with:" >> config.log
+printf " '%s'" "$0" "$@" >> config.log
+echo >> config.log
 echo "#" >> config.log
 
 compile_object() {
commit 82246040eaaeec8c53e87b2beff5488f6078bf35
Author: Stefan Weil <sw at weilnetz.de>
Date:   Mon Mar 5 07:22:31 2012 +0100

    osdep: Remove local definition of macro offsetof
    
    The macro offsetof is defined in stddef.h. It is conforming to
    the standards C89, C99 and POSIX.1-2001 (see man page), so it
    is a sufficiently old standard.
    
    Therefore chances are very high that QEMU never needs a local
    definition of this macro.
    
    osdep.h already includes stddef.h, so this patch simply removes
    the unneeded code from the files configure and osdep.h.
    
    If we ever need the local definition again, it should be added
    to compiler.h (the macro is usually provided with the compiler,
    it is not OS specific).
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/configure b/configure
index e19b6e3..ed3d907 100755
--- a/configure
+++ b/configure
@@ -2524,17 +2524,6 @@ if test "$darwin" != "yes" -a "$mingw32" != "yes" -a "$solaris" != yes -a \
 fi
 
 ##########################################
-# check if the compiler defines offsetof
-
-need_offsetof=yes
-cat > $TMPC << EOF
-#include <stddef.h>
-int main(void) { struct s { int f; }; return offsetof(struct s, f); }
-EOF
-if compile_prog "" "" ; then
-    need_offsetof=no
-fi
-
 # spice probe
 if test "$spice" != "no" ; then
   cat > $TMPC << EOF
@@ -3199,9 +3188,6 @@ fi
 if test "$tcg_interpreter" = "yes" ; then
   echo "CONFIG_TCG_INTERPRETER=y" >> $config_host_mak
 fi
-if test "$need_offsetof" = "yes" ; then
-  echo "CONFIG_NEED_OFFSETOF=y" >> $config_host_mak
-fi
 if test "$fdatasync" = "yes" ; then
   echo "CONFIG_FDATASYNC=y" >> $config_host_mak
 fi
diff --git a/osdep.h b/osdep.h
index 432b91e..0350383 100644
--- a/osdep.h
+++ b/osdep.h
@@ -26,9 +26,6 @@
 #define unlikely(x)   __builtin_expect(!!(x), 0)
 #endif
 
-#ifdef CONFIG_NEED_OFFSETOF
-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *) 0)->MEMBER)
-#endif
 #ifndef container_of
 #define container_of(ptr, type, member) ({                      \
         const typeof(((type *) 0)->member) *__mptr = (ptr);     \
commit 4a84ebe6a6b64c823e33876e3cda3c0813b2e1bb
Author: Stefan Weil <sw at weilnetz.de>
Date:   Mon Feb 27 22:57:24 2012 +0100

    libcacard: Spelling and grammar fixes in documentation
    
    * it's -> its
    
    * it's -> it is (that's no fix, but makes future checks easier)
    
    * this functions -> this function
    
    * replacable -> replaceable
    
    * reader's -> readers
    
    * logins into -> logs into
    
    v2:
    Also replace 'aid' by 'AID' (thanks to Peter Maydell for this hint).
    
    v3:
    Fix sentence (contributed by Alon Levy / Robert Relyea).
    
    Cc: Alon Levy <alevy at redhat.com>
    Cc: Robert Relyea <rrelyea at redhat.com>
    Cc: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/docs/libcacard.txt b/docs/libcacard.txt
index f7d7519..8db421d 100644
--- a/docs/libcacard.txt
+++ b/docs/libcacard.txt
@@ -10,7 +10,7 @@ such as signing, card removal/insertion, etc. are mapped to real, physical
 cards which are shared with the client machine the emulator is running on, or
 the cards could be pure software constructs.
 
-The emulator is structured to allow multiple replacable or additional pieces,
+The emulator is structured to allow multiple replaceable or additional pieces,
 so it can be easily modified for future requirements. The primary envisioned
 modifications are:
 
@@ -32,7 +32,7 @@ be emulated as well, including PIV, newer versions of CAC, PKCS #15, etc.
 --------------------
 Replacing the Socket Based Virtual Reader Interface.
 
-The current implementation contains a replacable module vscclient.c. The
+The current implementation contains a replaceable module vscclient.c. The
 current vscclient.c implements a sockets interface to the virtual ccid reader
 on the guest. CCID commands that are pertinent to emulation are passed
 across the socket, and their responses are passed back along that same socket.
@@ -42,7 +42,7 @@ implements a program with a main entry. It also handles argument parsing for
 the emulator.
 
 An application that wants to use the virtual reader can replace vscclient.c
-with it's own implementation that connects to it's own CCID reader.  The calls
+with its own implementation that connects to its own CCID reader.  The calls
 that the CCID reader can call are:
 
       VReaderList * vreader_get_reader_list();
@@ -72,12 +72,12 @@ that the CCID reader can call are:
       VReader * vreader_list_get_reader(VReaderListEntry *)
 
   This function returns the reader stored in the reader List entry. Caller gets
-  a new reference to a reader. The caller must free it's reference when it is
+  a new reference to a reader. The caller must free its reference when it is
   finished with vreader_free().
 
       void vreader_free(VReader *reader);
 
-   This function frees a reference to a reader. Reader's are reference counted
+   This function frees a reference to a reader. Readers are reference counted
    and are automatically deleted when the last reference is freed.
 
       void vreader_list_delete(VReaderList *list);
@@ -87,7 +87,7 @@ that the CCID reader can call are:
 
       VReaderStatus vreader_power_on(VReader *reader, char *atr, int *len);
 
-  This functions simulates a card power on. Virtual cards do not care about
+  This function simulates a card power on. A virtual card does not care about
   the actual voltage and other physical parameters, but it does care that the
   card is actually on or off. Cycling the card causes the card to reset. If
   the caller provides enough space, vreader_power_on will return the ATR of
@@ -104,7 +104,7 @@ that the CCID reader can call are:
                                        unsigned char *receive_buf,
                                        int receive_buf_len);
 
-  This functions send a raw apdu to a card and returns the card's response.
+  This function sends a raw apdu to a card and returns the card's response.
   The CCID front end should return the response back. Most of the emulation
   is driven from these APDUs.
 
@@ -217,10 +217,10 @@ the card using the following functions:
          VCardStatus vcard_add_applet(VCard *card, VCardApplet *applet);
 
   Add an applet onto the list of applets attached to the card. Once an applet
-  has been added, it can be selected by it's aid, and then commands will be
-  routed to it VCardProcessAPDU function. This function adopts the applet the
-  passed int applet. Note: 2 applets with the same AID should not be added to
-  the same card. It's permissible to add more than one applet. Multiple applets
+  has been added, it can be selected by its AID, and then commands will be
+  routed to it VCardProcessAPDU function. This function adopts the applet that
+  is passed into it. Note: 2 applets with the same AID should not be added to
+  the same card. It is permissible to add more than one applet. Multiple applets
   may have the same VCardPRocessAPDU entry point.
 
 The certs and keys should be attached to private data associated with one or
@@ -335,7 +335,7 @@ and applet.
          VCard7816Status vcard_emul_login(VCard *card, unsigned char *pin,
                                           int pin_len);
 
-    This function logins into the card and return the standard 7816 status
+    This function logs into the card and returns the standard 7816 status
     word depending on the success or failure of the call.
 
          void vcard_emul_delete_key(VCardKey *key);
@@ -424,7 +424,7 @@ functions:
       cert_len, and keys are all arrays of length cert_count. These are the
       the same of the parameters xxxx_card_init() accepts.
 
-   Finally the card is associated with it's reader by the call:
+   Finally the card is associated with its reader by the call:
 
             VReaderStatus vreader_insert_card(VReader *vreader, VCard *vcard);
 
commit 93148aa5c341810b0ecefdbe4e760fddb38d9085
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sun Feb 26 18:46:12 2012 +0100

    Spelling fixes in comments (it's -> its)
    
    * it's -> its (fixed for all files)
    * dont -> don't (only fixed in a line which was touched by the previous fix)
    * distrub -> disturb (fixed in the same line)
    
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/configure b/configure
index a5eb832..e19b6e3 100755
--- a/configure
+++ b/configure
@@ -232,7 +232,7 @@ for opt do
 done
 # OS specific
 # Using uname is really, really broken.  Once we have the right set of checks
-# we can eliminate it's usage altogether
+# we can eliminate its usage altogether.
 
 cc="${CC-${cross_prefix}gcc}"
 ar="${AR-${cross_prefix}ar}"
diff --git a/hw/exynos4210_mct.c b/hw/exynos4210_mct.c
index 01e3fb8..7474fcf 100644
--- a/hw/exynos4210_mct.c
+++ b/hw/exynos4210_mct.c
@@ -888,7 +888,7 @@ static void exynos4210_ltick_event(void *opaque)
     static uint64_t time2[2] = {0};
 #endif
 
-    /* Call tick_timer event handler, it will update it's tcntb and icntb */
+    /* Call tick_timer event handler, it will update its tcntb and icntb. */
     exynos4210_ltick_timer_event(&s->tick_timer);
 
     /* get tick_timer cnt */
diff --git a/hw/usb-ccid.c b/hw/usb-ccid.c
index ce01e34..ced687f 100644
--- a/hw/usb-ccid.c
+++ b/hw/usb-ccid.c
@@ -5,7 +5,7 @@
  *
  * Written by Alon Levy, with contributions from Robert Relyea.
  *
- * Based on usb-serial.c, see it's copyright and attributions below.
+ * Based on usb-serial.c, see its copyright and attributions below.
  *
  * This work is licensed under the terms of the GNU GPL, version 2.1 or later.
  * See the COPYING file in the top-level directory.
diff --git a/include/qemu/object.h b/include/qemu/object.h
index dd7f3c0..ec2d294 100644
--- a/include/qemu/object.h
+++ b/include/qemu/object.h
@@ -124,7 +124,7 @@ typedef struct InterfaceInfo InterfaceInfo;
  *
  * Once all of the parent classes have been initialized, #TypeInfo::class_init
  * is called to let the class being instantiated provide default initialize for
- * it's virtual functions.  Here is how the above example might be modified
+ * its virtual functions.  Here is how the above example might be modified
  * to introduce an overridden virtual function:
  *
  * <example>
@@ -527,7 +527,7 @@ Type type_register_static(const TypeInfo *info);
  * type_register:
  * @info: The #TypeInfo of the new type
  *
- * Unlike type_register_static(), this call does not require @info or it's
+ * Unlike type_register_static(), this call does not require @info or its
  * string members to continue to exist after the call returns.
  *
  * Returns: 0 on failure, the new #Type on success.
diff --git a/kvm-all.c b/kvm-all.c
index 77eadf6..549828a 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -35,7 +35,7 @@
 #include <sys/eventfd.h>
 #endif
 
-/* KVM uses PAGE_SIZE in it's definition of COALESCED_MMIO_MAX */
+/* KVM uses PAGE_SIZE in its definition of COALESCED_MMIO_MAX */
 #define PAGE_SIZE TARGET_PAGE_SIZE
 
 //#define DEBUG_KVM
diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c
index 0adae13..b64c93d 100644
--- a/libcacard/vscclient.c
+++ b/libcacard/vscclient.c
@@ -129,7 +129,7 @@ event_thread(void *arg)
                 vevent_delete(event);
                 continue;
             }
-            /* this reader hasn't been told it's status from qemu yet, wait for
+            /* this reader hasn't been told its status from qemu yet, wait for
              * that status */
             while (pending_reader != NULL) {
                 qemu_cond_wait(&pending_reader_condition, &pending_reader_lock);
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 79a39dc..cefd2ff 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -2700,7 +2700,7 @@ get_sigframe(struct target_sigaction *ka, CPUState *regs, size_t frame_size)
     sp = regs->active_tc.gpr[29];
 
     /*
-     * FPU emulator may have it's own trampoline active just
+     * FPU emulator may have its own trampoline active just
      * above the user stack, 16-bytes before the next lowest
      * 16 byte boundary.  Try to avoid trashing it.
      */
diff --git a/qemu-file.h b/qemu-file.h
index 8da1021..31b83f6 100644
--- a/qemu-file.h
+++ b/qemu-file.h
@@ -47,7 +47,7 @@ typedef int (QEMUFileGetBufferFunc)(void *opaque, uint8_t *buf,
  */
 typedef int (QEMUFileCloseFunc)(void *opaque);
 
-/* Called to determine if the file has exceeded it's bandwidth allocation.  The
+/* Called to determine if the file has exceeded its bandwidth allocation.  The
  * bandwidth capping is a soft limit, not a hard limit.
  */
 typedef int (QEMUFileRateLimit)(void *opaque);
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index c51b9cb..87e9799 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1930,7 +1930,7 @@ target_ulong helper_evpe(void)
 
     do {
         if (other_cpu != env
-           /* If the VPE is WFI, dont distrub it's sleep.  */
+           /* If the VPE is WFI, don't disturb its sleep.  */
            && !mips_vpe_is_wfi(other_cpu)) {
             /* Enable the VPE.  */
             other_cpu->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
commit 0ea5c0cdb0d87b5848cbe749598716bc62fd334a
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Feb 25 14:57:03 2012 +0100

    vnc: Add break statement
    
    This was not a bug, but it is not common practice to omit the break statement
    from the last case statement before an empty default case.
    
    Any change of the default case would introduce a bug.
    
    This was reported as a warning by splint.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/ui/vnc-enc-hextile-template.h b/ui/vnc-enc-hextile-template.h
index b9f9f5e..a7310e1 100644
--- a/ui/vnc-enc-hextile-template.h
+++ b/ui/vnc-enc-hextile-template.h
@@ -175,6 +175,7 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
 	    /* we really don't have to invalidate either the bg or fg
 	       but we've lost the old values.  oh well. */
 	}
+        break;
     default:
 	break;
     }
commit ba79c88604e3b602967705a66f683ff892980111
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Feb 25 14:54:17 2012 +0100

    libcacard: Use format specifier %u instead of %d for unsigned values
    
    splint reported warnings for those code statements.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c
index e317a25..0adae13 100644
--- a/libcacard/vscclient.c
+++ b/libcacard/vscclient.c
@@ -66,7 +66,7 @@ send_msg(
     qemu_mutex_lock(&write_lock);
 
     if (verbose > 10) {
-        printf("sending type=%d id=%d, len =%d (0x%x)\n",
+        printf("sending type=%d id=%u, len =%u (0x%x)\n",
                type, reader_id, length, length);
     }
 
@@ -167,7 +167,7 @@ event_thread(void *arg)
         case VEVENT_READER_REMOVE:
             /* future, tell qemu that an old CCID reader has been removed */
             if (verbose > 10) {
-                printf(" READER REMOVE: %d\n", reader_id);
+                printf(" READER REMOVE: %u\n", reader_id);
             }
             send_msg(VSC_ReaderRemove, reader_id, NULL, 0);
             break;
@@ -178,7 +178,7 @@ event_thread(void *arg)
             vreader_power_on(event->reader, atr, &atr_len);
             /* ATR call functions as a Card Insert event */
             if (verbose > 10) {
-                printf(" CARD INSERT %d: ", reader_id);
+                printf(" CARD INSERT %u: ", reader_id);
                 print_byte_array(atr, atr_len);
             }
             send_msg(VSC_ATR, reader_id, atr, atr_len);
@@ -186,7 +186,7 @@ event_thread(void *arg)
         case VEVENT_CARD_REMOVE:
             /* Card removed */
             if (verbose > 10) {
-                printf(" CARD REMOVE %d:\n", reader_id);
+                printf(" CARD REMOVE %u:\n", reader_id);
             }
             send_msg(VSC_CardRemove, reader_id, NULL, 0);
             break;
@@ -256,7 +256,7 @@ do_command(void)
                        reader ? vreader_get_name(reader)
                        : "invalid reader", error);
             } else {
-                printf("no reader by id %d found\n", reader_id);
+                printf("no reader by id %u found\n", reader_id);
             }
         } else if (strncmp(string, "remove", 6) == 0) {
             if (string[6] == ' ') {
@@ -269,7 +269,7 @@ do_command(void)
                         reader ? vreader_get_name(reader)
                         : "invalid reader", error);
             } else {
-                printf("no reader by id %d found\n", reader_id);
+                printf("no reader by id %u found\n", reader_id);
             }
         } else if (strncmp(string, "select", 6) == 0) {
             if (string[6] == ' ') {
@@ -280,11 +280,11 @@ do_command(void)
                 reader = vreader_get_reader_by_id(reader_id);
             }
             if (reader) {
-                printf("Selecting reader %d, %s\n", reader_id,
+                printf("Selecting reader %u, %s\n", reader_id,
                         vreader_get_name(reader));
                 default_reader_id = reader_id;
             } else {
-                printf("Reader with id %d not found\n", reader_id);
+                printf("Reader with id %u not found\n", reader_id);
             }
         } else if (strncmp(string, "debug", 5) == 0) {
             if (string[5] == ' ') {
@@ -303,7 +303,7 @@ do_command(void)
                 if (reader_id == -1) {
                     continue;
                 }
-                printf("%3d %s %s\n", reader_id,
+                printf("%3u %s %s\n", reader_id,
                        vreader_card_is_present(reader) == VREADER_OK ?
                        "CARD_PRESENT" : "            ",
                        vreader_get_name(reader));
@@ -563,7 +563,7 @@ main(
         mhHeader.reader_id = ntohl(mhHeader.reader_id);
         mhHeader.length = ntohl(mhHeader.length);
         if (verbose) {
-            printf("Header: type=%d, reader_id=%d length=%d (0x%x)\n",
+            printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n",
                     mhHeader.type, mhHeader.reader_id, mhHeader.length,
                                                mhHeader.length);
         }
commit aa102231f09af7e5e2cc1376499991ac2ea00115
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Mar 8 17:06:55 2012 +0200

    memory: store section indices in iotlb instead of io indices
    
    A step towards eliminating io indices.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec-all.h b/exec-all.h
index 51d01f2..3ffe9dd 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -299,6 +299,7 @@ extern void *tci_tb_ptr;
 
 #if !defined(CONFIG_USER_ONLY)
 
+target_phys_addr_t section_to_ioaddr(target_phys_addr_t section_io_addr);
 uint64_t io_mem_read(int index, target_phys_addr_t addr, unsigned size);
 void io_mem_write(int index, target_phys_addr_t addr, uint64_t value,
                   unsigned size);
diff --git a/exec.c b/exec.c
index 1fb0158..a35eb4f 100644
--- a/exec.c
+++ b/exec.c
@@ -191,6 +191,9 @@ typedef struct PhysPageEntry PhysPageEntry;
 static MemoryRegionSection *phys_sections;
 static unsigned phys_sections_nb, phys_sections_nb_alloc;
 static uint16_t phys_section_unassigned;
+static uint16_t phys_section_notdirty;
+static uint16_t phys_section_rom;
+static uint16_t phys_section_watch;
 
 struct PhysPageEntry {
     uint16_t is_leaf : 1;
@@ -2214,9 +2217,9 @@ void tlb_set_page(CPUState *env, target_ulong vaddr,
         iotlb = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
             + section_addr(section, paddr);
         if (!section->readonly)
-            iotlb |= io_mem_notdirty.ram_addr;
+            iotlb |= phys_section_notdirty;
         else
-            iotlb |= io_mem_rom.ram_addr;
+            iotlb |= phys_section_rom;
     } else {
         /* IO handlers are currently passed a physical address.
            It would be nice to pass an offset from the base address
@@ -2224,7 +2227,7 @@ void tlb_set_page(CPUState *env, target_ulong vaddr,
            and avoid full address decoding in every device.
            We can't use the high bits of pd for this because
            IO_MEM_ROMD uses these as a ram address.  */
-        iotlb = memory_region_get_ram_addr(section->mr) & ~TARGET_PAGE_MASK;
+        iotlb = section - phys_sections;
         iotlb += section_addr(section, paddr);
     }
 
@@ -2235,7 +2238,7 @@ void tlb_set_page(CPUState *env, target_ulong vaddr,
         if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) {
             /* Avoid trapping reads of pages with a write breakpoint. */
             if ((prot & PAGE_WRITE) || (wp->flags & BP_MEM_READ)) {
-                iotlb = io_mem_watch.ram_addr + paddr;
+                iotlb = phys_section_watch + paddr;
                 address |= TLB_MMIO;
                 break;
             }
@@ -3559,6 +3562,15 @@ static uint16_t dummy_section(MemoryRegion *mr)
     return phys_section_add(&section);
 }
 
+target_phys_addr_t section_to_ioaddr(target_phys_addr_t section_io_addr)
+{
+    MemoryRegionSection *section;
+
+    section = &phys_sections[section_io_addr & ~TARGET_PAGE_MASK];
+    return (section_io_addr & TARGET_PAGE_MASK)
+        | (section->mr->ram_addr & ~TARGET_PAGE_MASK);
+}
+
 static void io_mem_init(void)
 {
     int i;
@@ -3586,6 +3598,9 @@ static void core_begin(MemoryListener *listener)
     phys_sections_clear();
     phys_map.ptr = PHYS_MAP_NODE_NIL;
     phys_section_unassigned = dummy_section(&io_mem_unassigned);
+    phys_section_notdirty = dummy_section(&io_mem_notdirty);
+    phys_section_rom = dummy_section(&io_mem_rom);
+    phys_section_watch = dummy_section(&io_mem_watch);
 }
 
 static void core_commit(MemoryListener *listener)
diff --git a/softmmu_template.h b/softmmu_template.h
index 97020f8..7c7e15b 100644
--- a/softmmu_template.h
+++ b/softmmu_template.h
@@ -110,7 +110,7 @@ DATA_TYPE REGPARM glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
             if ((addr & (DATA_SIZE - 1)) != 0)
                 goto do_unaligned_access;
             retaddr = GETPC();
-            ioaddr = env->iotlb[mmu_idx][index];
+            ioaddr = section_to_ioaddr(env->iotlb[mmu_idx][index]);
             res = glue(io_read, SUFFIX)(ioaddr, addr, retaddr);
         } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
             /* slow unaligned access (it spans two pages or IO) */
@@ -164,7 +164,7 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
             /* IO access */
             if ((addr & (DATA_SIZE - 1)) != 0)
                 goto do_unaligned_access;
-            ioaddr = env->iotlb[mmu_idx][index];
+            ioaddr = section_to_ioaddr(env->iotlb[mmu_idx][index]);
             res = glue(io_read, SUFFIX)(ioaddr, addr, retaddr);
         } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
         do_unaligned_access:
@@ -251,7 +251,7 @@ void REGPARM glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr,
             if ((addr & (DATA_SIZE - 1)) != 0)
                 goto do_unaligned_access;
             retaddr = GETPC();
-            ioaddr = env->iotlb[mmu_idx][index];
+            ioaddr = section_to_ioaddr(env->iotlb[mmu_idx][index]);
             glue(io_write, SUFFIX)(ioaddr, val, addr, retaddr);
         } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
         do_unaligned_access:
@@ -303,7 +303,7 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
             /* IO access */
             if ((addr & (DATA_SIZE - 1)) != 0)
                 goto do_unaligned_access;
-            ioaddr = env->iotlb[mmu_idx][index];
+            ioaddr = section_to_ioaddr(env->iotlb[mmu_idx][index]);
             glue(io_write, SUFFIX)(ioaddr, val, addr, retaddr);
         } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
         do_unaligned_access:
commit f3705d53296d78b14f5823472ae2add16a25a0a5
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Mar 8 16:16:34 2012 +0200

    memory: make phys_page_find() return an unadjusted section
    
    We'd like to store the section index in the iotlb, so we can't
    adjust it before returning.  Return an unadjusted section and
    instead introduce section_addr(), which does the adjustment later.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index 1e5bbd6..1fb0158 100644
--- a/exec.c
+++ b/exec.c
@@ -480,13 +480,11 @@ static void phys_page_set(target_phys_addr_t index, target_phys_addr_t nb,
     phys_page_set_level(&phys_map, &index, &nb, leaf, P_L2_LEVELS - 1);
 }
 
-static MemoryRegionSection phys_page_find(target_phys_addr_t index)
+static MemoryRegionSection *phys_page_find(target_phys_addr_t index)
 {
     PhysPageEntry lp = phys_map;
     PhysPageEntry *p;
     int i;
-    MemoryRegionSection section;
-    target_phys_addr_t delta;
     uint16_t s_index = phys_section_unassigned;
 
     for (i = P_L2_LEVELS - 1; i >= 0 && !lp.is_leaf; i--) {
@@ -499,15 +497,15 @@ static MemoryRegionSection phys_page_find(target_phys_addr_t index)
 
     s_index = lp.ptr;
 not_found:
-    section = phys_sections[s_index];
-    index <<= TARGET_PAGE_BITS;
-    assert(section.offset_within_address_space <= index
-           && index <= section.offset_within_address_space + section.size-1);
-    delta = index - section.offset_within_address_space;
-    section.offset_within_address_space += delta;
-    section.offset_within_region += delta;
-    section.size -= delta;
-    return section;
+    return &phys_sections[s_index];
+}
+
+static target_phys_addr_t section_addr(MemoryRegionSection *section,
+                                       target_phys_addr_t addr)
+{
+    addr -= section->offset_within_address_space;
+    addr += section->offset_within_region;
+    return addr;
 }
 
 static void tlb_protect_code(ram_addr_t ram_addr);
@@ -1468,17 +1466,16 @@ static void breakpoint_invalidate(CPUState *env, target_ulong pc)
 {
     target_phys_addr_t addr;
     ram_addr_t ram_addr;
-    MemoryRegionSection section;
+    MemoryRegionSection *section;
 
     addr = cpu_get_phys_page_debug(env, pc);
     section = phys_page_find(addr >> TARGET_PAGE_BITS);
-    if (!(memory_region_is_ram(section.mr)
-          || (section.mr->rom_device && section.mr->readable))) {
+    if (!(memory_region_is_ram(section->mr)
+          || (section->mr->rom_device && section->mr->readable))) {
         return;
     }
-    ram_addr = (memory_region_get_ram_addr(section.mr)
-                + section.offset_within_region) & TARGET_PAGE_MASK;
-    ram_addr |= (pc & ~TARGET_PAGE_MASK);
+    ram_addr = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
+        + section_addr(section, addr);
     tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
 }
 #endif
@@ -2181,7 +2178,7 @@ void tlb_set_page(CPUState *env, target_ulong vaddr,
                   target_phys_addr_t paddr, int prot,
                   int mmu_idx, target_ulong size)
 {
-    MemoryRegionSection section;
+    MemoryRegionSection *section;
     unsigned int index;
     target_ulong address;
     target_ulong code_address;
@@ -2202,21 +2199,21 @@ void tlb_set_page(CPUState *env, target_ulong vaddr,
 #endif
 
     address = vaddr;
-    if (!is_ram_rom_romd(&section)) {
+    if (!is_ram_rom_romd(section)) {
         /* IO memory case (romd handled later) */
         address |= TLB_MMIO;
     }
-    if (is_ram_rom_romd(&section)) {
-        addend = (unsigned long)(memory_region_get_ram_ptr(section.mr)
-                                 + section.offset_within_region);
+    if (is_ram_rom_romd(section)) {
+        addend = (unsigned long)memory_region_get_ram_ptr(section->mr)
+                                 + section_addr(section, paddr);
     } else {
         addend = 0;
     }
-    if (is_ram_rom(&section)) {
+    if (is_ram_rom(section)) {
         /* Normal RAM.  */
-        iotlb = (memory_region_get_ram_addr(section.mr)
-                 + section.offset_within_region) & TARGET_PAGE_MASK;
-        if (!section.readonly)
+        iotlb = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
+            + section_addr(section, paddr);
+        if (!section->readonly)
             iotlb |= io_mem_notdirty.ram_addr;
         else
             iotlb |= io_mem_rom.ram_addr;
@@ -2227,8 +2224,8 @@ void tlb_set_page(CPUState *env, target_ulong vaddr,
            and avoid full address decoding in every device.
            We can't use the high bits of pd for this because
            IO_MEM_ROMD uses these as a ram address.  */
-        iotlb = memory_region_get_ram_addr(section.mr) & ~TARGET_PAGE_MASK;
-        iotlb += section.offset_within_region;
+        iotlb = memory_region_get_ram_addr(section->mr) & ~TARGET_PAGE_MASK;
+        iotlb += section_addr(section, paddr);
     }
 
     code_address = address;
@@ -2261,14 +2258,14 @@ void tlb_set_page(CPUState *env, target_ulong vaddr,
         te->addr_code = -1;
     }
     if (prot & PAGE_WRITE) {
-        if ((memory_region_is_ram(section.mr) && section.readonly)
-            || is_romd(&section)) {
+        if ((memory_region_is_ram(section->mr) && section->readonly)
+            || is_romd(section)) {
             /* Write access calls the I/O callback.  */
             te->addr_write = address | TLB_MMIO;
-        } else if (memory_region_is_ram(section.mr)
+        } else if (memory_region_is_ram(section->mr)
                    && !cpu_physical_memory_is_dirty(
-                           section.mr->ram_addr
-                           + section.offset_within_region)) {
+                           section->mr->ram_addr
+                           + section_addr(section, paddr))) {
             te->addr_write = address | TLB_NOTDIRTY;
         } else {
             te->addr_write = address;
@@ -2631,22 +2628,22 @@ static void register_subpage(MemoryRegionSection *section)
     subpage_t *subpage;
     target_phys_addr_t base = section->offset_within_address_space
         & TARGET_PAGE_MASK;
-    MemoryRegionSection existing = phys_page_find(base >> TARGET_PAGE_BITS);
+    MemoryRegionSection *existing = phys_page_find(base >> TARGET_PAGE_BITS);
     MemoryRegionSection subsection = {
         .offset_within_address_space = base,
         .size = TARGET_PAGE_SIZE,
     };
     target_phys_addr_t start, end;
 
-    assert(existing.mr->subpage || existing.mr == &io_mem_unassigned);
+    assert(existing->mr->subpage || existing->mr == &io_mem_unassigned);
 
-    if (!(existing.mr->subpage)) {
+    if (!(existing->mr->subpage)) {
         subpage = subpage_init(base);
         subsection.mr = &subpage->iomem;
         phys_page_set(base >> TARGET_PAGE_BITS, 1,
                       phys_section_add(&subsection));
     } else {
-        subpage = container_of(existing.mr, subpage_t, iomem);
+        subpage = container_of(existing->mr, subpage_t, iomem);
     }
     start = section->offset_within_address_space & ~TARGET_PAGE_MASK;
     end = start + section->size;
@@ -3830,7 +3827,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
     uint8_t *ptr;
     uint32_t val;
     target_phys_addr_t page;
-    MemoryRegionSection section;
+    MemoryRegionSection *section;
 
     while (len > 0) {
         page = addr & TARGET_PAGE_MASK;
@@ -3840,12 +3837,11 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
         section = phys_page_find(page >> TARGET_PAGE_BITS);
 
         if (is_write) {
-            if (!memory_region_is_ram(section.mr)) {
+            if (!memory_region_is_ram(section->mr)) {
                 target_phys_addr_t addr1;
-                io_index = memory_region_get_ram_addr(section.mr)
+                io_index = memory_region_get_ram_addr(section->mr)
                     & (IO_MEM_NB_ENTRIES - 1);
-                addr1 = (addr & ~TARGET_PAGE_MASK)
-                    + section.offset_within_region;
+                addr1 = section_addr(section, addr);
                 /* XXX: could force cpu_single_env to NULL to avoid
                    potential bugs */
                 if (l >= 4 && ((addr1 & 3) == 0)) {
@@ -3864,11 +3860,10 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
                     io_mem_write(io_index, addr1, val, 1);
                     l = 1;
                 }
-            } else if (!section.readonly) {
+            } else if (!section->readonly) {
                 ram_addr_t addr1;
-                addr1 = (memory_region_get_ram_addr(section.mr)
-                         + section.offset_within_region)
-                    | (addr & ~TARGET_PAGE_MASK);
+                addr1 = memory_region_get_ram_addr(section->mr)
+                    + section_addr(section, addr);
                 /* RAM case */
                 ptr = qemu_get_ram_ptr(addr1);
                 memcpy(ptr, buf, l);
@@ -3882,13 +3877,12 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
                 qemu_put_ram_ptr(ptr);
             }
         } else {
-            if (!is_ram_rom_romd(&section)) {
+            if (!is_ram_rom_romd(section)) {
                 target_phys_addr_t addr1;
                 /* I/O case */
-                io_index = memory_region_get_ram_addr(section.mr)
+                io_index = memory_region_get_ram_addr(section->mr)
                     & (IO_MEM_NB_ENTRIES - 1);
-                addr1 = (addr & ~TARGET_PAGE_MASK)
-                    + section.offset_within_region;
+                addr1 = section_addr(section, addr);
                 if (l >= 4 && ((addr1 & 3) == 0)) {
                     /* 32 bit read access */
                     val = io_mem_read(io_index, addr1, 4);
@@ -3907,9 +3901,9 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
                 }
             } else {
                 /* RAM case */
-                ptr = qemu_get_ram_ptr(section.mr->ram_addr
-                                       + section.offset_within_region);
-                memcpy(buf, ptr + (addr & ~TARGET_PAGE_MASK), l);
+                ptr = qemu_get_ram_ptr(section->mr->ram_addr)
+                    + section_addr(section, addr);
+                memcpy(buf, ptr, l);
                 qemu_put_ram_ptr(ptr);
             }
         }
@@ -3926,7 +3920,7 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr,
     int l;
     uint8_t *ptr;
     target_phys_addr_t page;
-    MemoryRegionSection section;
+    MemoryRegionSection *section;
 
     while (len > 0) {
         page = addr & TARGET_PAGE_MASK;
@@ -3935,13 +3929,12 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr,
             l = len;
         section = phys_page_find(page >> TARGET_PAGE_BITS);
 
-        if (!is_ram_rom_romd(&section)) {
+        if (!is_ram_rom_romd(section)) {
             /* do nothing */
         } else {
             unsigned long addr1;
-            addr1 = (memory_region_get_ram_addr(section.mr)
-                     + section.offset_within_region)
-                + (addr & ~TARGET_PAGE_MASK);
+            addr1 = memory_region_get_ram_addr(section->mr)
+                + section_addr(section, addr);
             /* ROM/RAM case */
             ptr = qemu_get_ram_ptr(addr1);
             memcpy(ptr, buf, l);
@@ -4014,7 +4007,7 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
     target_phys_addr_t todo = 0;
     int l;
     target_phys_addr_t page;
-    MemoryRegionSection section;
+    MemoryRegionSection *section;
     ram_addr_t raddr = RAM_ADDR_MAX;
     ram_addr_t rlen;
     void *ret;
@@ -4026,7 +4019,7 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
             l = len;
         section = phys_page_find(page >> TARGET_PAGE_BITS);
 
-        if (!(memory_region_is_ram(section.mr) && !section.readonly)) {
+        if (!(memory_region_is_ram(section->mr) && !section->readonly)) {
             if (todo || bounce.buffer) {
                 break;
             }
@@ -4041,9 +4034,8 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
             return bounce.buffer;
         }
         if (!todo) {
-            raddr = memory_region_get_ram_addr(section.mr)
-                + section.offset_within_region
-                + (addr & ~TARGET_PAGE_MASK);
+            raddr = memory_region_get_ram_addr(section->mr)
+                + section_addr(section, addr);
         }
 
         len -= l;
@@ -4102,15 +4094,15 @@ static inline uint32_t ldl_phys_internal(target_phys_addr_t addr,
     int io_index;
     uint8_t *ptr;
     uint32_t val;
-    MemoryRegionSection section;
+    MemoryRegionSection *section;
 
     section = phys_page_find(addr >> TARGET_PAGE_BITS);
 
-    if (!is_ram_rom_romd(&section)) {
+    if (!is_ram_rom_romd(section)) {
         /* I/O case */
-        io_index = memory_region_get_ram_addr(section.mr)
+        io_index = memory_region_get_ram_addr(section->mr)
             & (IO_MEM_NB_ENTRIES - 1);
-        addr = (addr & ~TARGET_PAGE_MASK) + section.offset_within_region;
+        addr = section_addr(section, addr);
         val = io_mem_read(io_index, addr, 4);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
@@ -4123,10 +4115,9 @@ static inline uint32_t ldl_phys_internal(target_phys_addr_t addr,
 #endif
     } else {
         /* RAM case */
-        ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section.mr)
+        ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section->mr)
                                 & TARGET_PAGE_MASK)
-                               + section.offset_within_region) +
-            (addr & ~TARGET_PAGE_MASK);
+                               + section_addr(section, addr));
         switch (endian) {
         case DEVICE_LITTLE_ENDIAN:
             val = ldl_le_p(ptr);
@@ -4164,15 +4155,15 @@ static inline uint64_t ldq_phys_internal(target_phys_addr_t addr,
     int io_index;
     uint8_t *ptr;
     uint64_t val;
-    MemoryRegionSection section;
+    MemoryRegionSection *section;
 
     section = phys_page_find(addr >> TARGET_PAGE_BITS);
 
-    if (!is_ram_rom_romd(&section)) {
+    if (!is_ram_rom_romd(section)) {
         /* I/O case */
-        io_index = memory_region_get_ram_addr(section.mr)
+        io_index = memory_region_get_ram_addr(section->mr)
             & (IO_MEM_NB_ENTRIES - 1);
-        addr = (addr & ~TARGET_PAGE_MASK) + section.offset_within_region;
+        addr = section_addr(section, addr);
 
         /* XXX This is broken when device endian != cpu endian.
                Fix and add "endian" variable check */
@@ -4185,10 +4176,9 @@ static inline uint64_t ldq_phys_internal(target_phys_addr_t addr,
 #endif
     } else {
         /* RAM case */
-        ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section.mr)
+        ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section->mr)
                                 & TARGET_PAGE_MASK)
-                               + section.offset_within_region)
-            + (addr & ~TARGET_PAGE_MASK);
+                               + section_addr(section, addr));
         switch (endian) {
         case DEVICE_LITTLE_ENDIAN:
             val = ldq_le_p(ptr);
@@ -4234,15 +4224,15 @@ static inline uint32_t lduw_phys_internal(target_phys_addr_t addr,
     int io_index;
     uint8_t *ptr;
     uint64_t val;
-    MemoryRegionSection section;
+    MemoryRegionSection *section;
 
     section = phys_page_find(addr >> TARGET_PAGE_BITS);
 
-    if (!is_ram_rom_romd(&section)) {
+    if (!is_ram_rom_romd(section)) {
         /* I/O case */
-        io_index = memory_region_get_ram_addr(section.mr)
+        io_index = memory_region_get_ram_addr(section->mr)
             & (IO_MEM_NB_ENTRIES - 1);
-        addr = (addr & ~TARGET_PAGE_MASK) + section.offset_within_region;
+        addr = section_addr(section, addr);
         val = io_mem_read(io_index, addr, 2);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
@@ -4255,10 +4245,9 @@ static inline uint32_t lduw_phys_internal(target_phys_addr_t addr,
 #endif
     } else {
         /* RAM case */
-        ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section.mr)
+        ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section->mr)
                                 & TARGET_PAGE_MASK)
-                               + section.offset_within_region)
-            + (addr & ~TARGET_PAGE_MASK);
+                               + section_addr(section, addr));
         switch (endian) {
         case DEVICE_LITTLE_ENDIAN:
             val = lduw_le_p(ptr);
@@ -4296,23 +4285,22 @@ void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
 {
     int io_index;
     uint8_t *ptr;
-    MemoryRegionSection section;
+    MemoryRegionSection *section;
 
     section = phys_page_find(addr >> TARGET_PAGE_BITS);
 
-    if (!memory_region_is_ram(section.mr) || section.readonly) {
-        if (memory_region_is_ram(section.mr)) {
+    if (!memory_region_is_ram(section->mr) || section->readonly) {
+        if (memory_region_is_ram(section->mr)) {
             io_index = io_mem_rom.ram_addr;
         } else {
-            io_index = memory_region_get_ram_addr(section.mr);
+            io_index = memory_region_get_ram_addr(section->mr);
         }
-        addr = (addr & ~TARGET_PAGE_MASK) + section.offset_within_region;
+        addr = section_addr(section, addr);
         io_mem_write(io_index, addr, val, 4);
     } else {
-        unsigned long addr1 = (memory_region_get_ram_addr(section.mr)
+        unsigned long addr1 = (memory_region_get_ram_addr(section->mr)
                                & TARGET_PAGE_MASK)
-            + section.offset_within_region
-            + (addr & ~TARGET_PAGE_MASK);
+            + section_addr(section, addr);
         ptr = qemu_get_ram_ptr(addr1);
         stl_p(ptr, val);
 
@@ -4332,18 +4320,18 @@ void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
 {
     int io_index;
     uint8_t *ptr;
-    MemoryRegionSection section;
+    MemoryRegionSection *section;
 
     section = phys_page_find(addr >> TARGET_PAGE_BITS);
 
-    if (!memory_region_is_ram(section.mr) || section.readonly) {
-        if (memory_region_is_ram(section.mr)) {
+    if (!memory_region_is_ram(section->mr) || section->readonly) {
+        if (memory_region_is_ram(section->mr)) {
                 io_index = io_mem_rom.ram_addr;
         } else {
-            io_index = memory_region_get_ram_addr(section.mr)
+            io_index = memory_region_get_ram_addr(section->mr)
                 & (IO_MEM_NB_ENTRIES - 1);
         }
-        addr = (addr & ~TARGET_PAGE_MASK) + section.offset_within_region;
+        addr = section_addr(section, addr);
 #ifdef TARGET_WORDS_BIGENDIAN
         io_mem_write(io_index, addr, val >> 32, 4);
         io_mem_write(io_index, addr + 4, (uint32_t)val, 4);
@@ -4352,10 +4340,9 @@ void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
         io_mem_write(io_index, addr + 4, val >> 32, 4);
 #endif
     } else {
-        ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section.mr)
+        ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section->mr)
                                 & TARGET_PAGE_MASK)
-                               + section.offset_within_region)
-            + (addr & ~TARGET_PAGE_MASK);
+                               + section_addr(section, addr));
         stq_p(ptr, val);
     }
 }
@@ -4366,18 +4353,18 @@ static inline void stl_phys_internal(target_phys_addr_t addr, uint32_t val,
 {
     int io_index;
     uint8_t *ptr;
-    MemoryRegionSection section;
+    MemoryRegionSection *section;
 
     section = phys_page_find(addr >> TARGET_PAGE_BITS);
 
-    if (!memory_region_is_ram(section.mr) || section.readonly) {
-        if (memory_region_is_ram(section.mr)) {
+    if (!memory_region_is_ram(section->mr) || section->readonly) {
+        if (memory_region_is_ram(section->mr)) {
             io_index = io_mem_rom.ram_addr;
         } else {
-            io_index = memory_region_get_ram_addr(section.mr)
+            io_index = memory_region_get_ram_addr(section->mr)
                 & (IO_MEM_NB_ENTRIES - 1);
         }
-        addr = (addr & ~TARGET_PAGE_MASK) + section.offset_within_region;
+        addr = section_addr(section, addr);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
             val = bswap32(val);
@@ -4390,9 +4377,8 @@ static inline void stl_phys_internal(target_phys_addr_t addr, uint32_t val,
         io_mem_write(io_index, addr, val, 4);
     } else {
         unsigned long addr1;
-        addr1 = (memory_region_get_ram_addr(section.mr) & TARGET_PAGE_MASK)
-            + section.offset_within_region
-            + (addr & ~TARGET_PAGE_MASK);
+        addr1 = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
+            + section_addr(section, addr);
         /* RAM case */
         ptr = qemu_get_ram_ptr(addr1);
         switch (endian) {
@@ -4444,18 +4430,18 @@ static inline void stw_phys_internal(target_phys_addr_t addr, uint32_t val,
 {
     int io_index;
     uint8_t *ptr;
-    MemoryRegionSection section;
+    MemoryRegionSection *section;
 
     section = phys_page_find(addr >> TARGET_PAGE_BITS);
 
-    if (!memory_region_is_ram(section.mr) || section.readonly) {
-        if (memory_region_is_ram(section.mr)) {
+    if (!memory_region_is_ram(section->mr) || section->readonly) {
+        if (memory_region_is_ram(section->mr)) {
             io_index = io_mem_rom.ram_addr;
         } else {
-            io_index = memory_region_get_ram_addr(section.mr)
+            io_index = memory_region_get_ram_addr(section->mr)
                 & (IO_MEM_NB_ENTRIES - 1);
         }
-        addr = (addr & ~TARGET_PAGE_MASK) + section.offset_within_region;
+        addr = section_addr(section, addr);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
             val = bswap16(val);
@@ -4468,8 +4454,8 @@ static inline void stw_phys_internal(target_phys_addr_t addr, uint32_t val,
         io_mem_write(io_index, addr, val, 2);
     } else {
         unsigned long addr1;
-        addr1 = (memory_region_get_ram_addr(section.mr) & TARGET_PAGE_MASK)
-            + section.offset_within_region + (addr & ~TARGET_PAGE_MASK);
+        addr1 = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
+            + section_addr(section, addr);
         /* RAM case */
         ptr = qemu_get_ram_ptr(addr1);
         switch (endian) {
commit 1c467855da1c5568e8968fe1b9dd3b4ad9f8637a
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Feb 25 14:11:46 2012 +0100

    Fix sign of sscanf format specifiers
    
    All values read by sscanf are unsigned, so replace %d by %u.
    
    This signed / unsigned mismatch was detected by splint.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/cursor.c b/cursor.c
index efc5917..76e262c 100644
--- a/cursor.c
+++ b/cursor.c
@@ -15,7 +15,8 @@ static QEMUCursor *cursor_parse_xpm(const char *xpm[])
     uint8_t idx;
 
     /* parse header line: width, height, #colors, #chars */
-    if (sscanf(xpm[line], "%d %d %d %d", &width, &height, &colors, &chars) != 4) {
+    if (sscanf(xpm[line], "%u %u %u %u",
+               &width, &height, &colors, &chars) != 4) {
         fprintf(stderr, "%s: header parse error: \"%s\"\n",
                 __FUNCTION__, xpm[line]);
         return NULL;
commit 75d1234103d47e59311203bf5e73f85b2e0fd983
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Feb 25 14:01:42 2012 +0100

    block/vmdk: Fix warning from splint (comparision of unsigned value)
    
    l1_entry_sectors will never be less than 0.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index 5623ac1..45c003a 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -453,7 +453,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
     }
     l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte)
                         * le64_to_cpu(header.granularity);
-    if (l1_entry_sectors <= 0) {
+    if (l1_entry_sectors == 0) {
         return -EINVAL;
     }
     l1_size = (le64_to_cpu(header.capacity) + l1_entry_sectors - 1)
commit beae9d79906c657f584f7e1e173ab8935d320969
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Feb 25 13:47:10 2012 +0100

    qmp: Fix spelling fourty -> forty
    
    This was found by codespell.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Acked-by: Luiz Capitulino <lcapitulino at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/test-qmp-output-visitor.c b/test-qmp-output-visitor.c
index c94c208..5452cd4 100644
--- a/test-qmp-output-visitor.c
+++ b/test-qmp-output-visitor.c
@@ -221,8 +221,8 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
     QObject *obj;
     QDict *qdict, *dict1, *dict2, *dict3, *userdef;
     const char *string = "user def string";
-    const char *strings[] = { "fourty two", "fourty three", "fourty four",
-                              "fourty five" };
+    const char *strings[] = { "forty two", "forty three", "forty four",
+                              "forty five" };
 
     ud2 = g_malloc0(sizeof(*ud2));
     ud2->string0 = g_strdup(strings[0]);
commit 441dd5ebd5001deec3930273904e8079a36592ee
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Feb 25 13:47:09 2012 +0100

    qom: Fix spelling in documentation
    
    This fixes a new spelling issue which was detected by codespell.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/include/qemu/object.h b/include/qemu/object.h
index 69e4b7b..dd7f3c0 100644
--- a/include/qemu/object.h
+++ b/include/qemu/object.h
@@ -288,7 +288,7 @@ struct Object
  *   implementing an explicit class type if they are not adding additional
  *   virtual functions.
  * @class_init: This function is called after all parent class initialization
- *   has occured to allow a class to set its default virtual method pointers.  
+ *   has occurred to allow a class to set its default virtual method pointers.
  *   This is also the function to use to override virtual methods from a parent
  *   class.
  * @class_finalize: This function is called during class destruction and is
commit 12f30833b91f80f12ba5bc86305eabec0e0e66c6
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Feb 25 13:37:13 2012 +0100

    sh7750: Remove redundant 'struct' from MemoryRegionOps
    
    The 'struct' is not needed, and all other MemoryRegionOps don't use it.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/sh7750.c b/hw/sh7750.c
index 4f4d8e7..e712928 100644
--- a/hw/sh7750.c
+++ b/hw/sh7750.c
@@ -712,7 +712,7 @@ static void sh7750_mmct_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static const struct MemoryRegionOps sh7750_mmct_ops = {
+static const MemoryRegionOps sh7750_mmct_ops = {
     .read = sh7750_mmct_read,
     .write = sh7750_mmct_write,
     .endianness = DEVICE_NATIVE_ENDIAN,
diff --git a/hw/sh_intc.c b/hw/sh_intc.c
index b24ec77..7d31ced 100644
--- a/hw/sh_intc.c
+++ b/hw/sh_intc.c
@@ -283,7 +283,7 @@ static void sh_intc_write(void *opaque, target_phys_addr_t offset,
 #endif
 }
 
-static const struct MemoryRegionOps sh_intc_ops = {
+static const MemoryRegionOps sh_intc_ops = {
     .read = sh_intc_read,
     .write = sh_intc_write,
     .endianness = DEVICE_NATIVE_ENDIAN,
commit cf21a4aef712075d313da4ea924a3376574c16e5
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Mar 1 15:14:12 2012 +0100

    xhci: fix port status
    
    Don't signal port status change if the usb device isn't in attached
    state.  Happens with usb-host devices with the pass-through device
    being plugged out at the host.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-xhci.c b/hw/usb-xhci.c
index 8305489..e8f1b6e 100644
--- a/hw/usb-xhci.c
+++ b/hw/usb-xhci.c
@@ -2279,7 +2279,7 @@ static void xhci_update_port(XHCIState *xhci, XHCIPort *port, int is_detach)
     int nr = port->port.index + 1;
 
     port->portsc = PORTSC_PP;
-    if (port->port.dev && !is_detach) {
+    if (port->port.dev && port->port.dev->attached && !is_detach) {
         port->portsc |= PORTSC_CCS;
         switch (port->port.dev->speed) {
         case USB_SPEED_LOW:
commit 2850ca9ed1023ce30ecd0582a66ded7a180e7616
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Mar 1 15:51:51 2012 +0100

    xhci: fix control xfers
    
    Use the new, direct control transfer submission method instead of
    bypassing the usb core by calling usb_device_handle_control directly.
    The later fails for async control transfers.
    
    This patch gets xhci + usb-host combo going.

diff --git a/hw/usb-xhci.c b/hw/usb-xhci.c
index fc5b542..8305489 100644
--- a/hw/usb-xhci.c
+++ b/hw/usb-xhci.c
@@ -1470,8 +1470,8 @@ static USBDevice *xhci_find_device(XHCIPort *port, uint8_t addr)
 static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
 {
     XHCITRB *trb_setup, *trb_status;
-    uint8_t bmRequestType, bRequest;
-    uint16_t wValue, wLength, wIndex;
+    uint8_t bmRequestType;
+    uint16_t wLength;
     XHCIPort *port;
     USBDevice *dev;
     int ret;
@@ -1508,9 +1508,6 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
     }
 
     bmRequestType = trb_setup->parameter;
-    bRequest = trb_setup->parameter >> 8;
-    wValue = trb_setup->parameter >> 16;
-    wIndex = trb_setup->parameter >> 32;
     wLength = trb_setup->parameter >> 48;
 
     if (xfer->data && xfer->data_alloced < wLength) {
@@ -1537,12 +1534,12 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
     xfer->iso_xfer = false;
 
     xhci_setup_packet(xfer, dev);
+    xfer->packet.parameter = trb_setup->parameter;
     if (!xfer->in_xfer) {
         xhci_xfer_data(xfer, xfer->data, wLength, 0, 1, 0);
     }
-    ret = usb_device_handle_control(dev, &xfer->packet,
-                                    (bmRequestType << 8) | bRequest,
-                                    wValue, wIndex, wLength, xfer->data);
+
+    ret = usb_handle_packet(dev, &xfer->packet);
 
     xhci_complete_packet(xfer, ret);
     if (!xfer->running_async && !xfer->running_retry) {
commit 1b4b29a11483a050855838014413c91e9c1f8c19
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Mar 2 13:22:29 2012 +0100

    usb: add shortcut for control transfers
    
    Add a more direct code path to submit control transfers.  Instead of
    feeding three usb packets (setup, data, ack) to usb_handle_packet and
    have the do_token_* functions in usb.c poke the control transfer
    parameters out of it just submit a single packet carrying the actual
    data with the control xfer parameters filled into USBPacket->parameters.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb.c b/hw/usb.c
index 800d912..1ec2e90 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -95,6 +95,7 @@ void usb_wakeup(USBEndpoint *ep)
 #define SETUP_STATE_SETUP 1
 #define SETUP_STATE_DATA  2
 #define SETUP_STATE_ACK   3
+#define SETUP_STATE_PARAM 4
 
 static int do_token_setup(USBDevice *s, USBPacket *p)
 {
@@ -226,6 +227,50 @@ static int do_token_out(USBDevice *s, USBPacket *p)
     }
 }
 
+static int do_parameter(USBDevice *s, USBPacket *p)
+{
+    int request, value, index;
+    int i, ret = 0;
+
+    for (i = 0; i < 8; i++) {
+        s->setup_buf[i] = p->parameter >> (i*8);
+    }
+
+    s->setup_state = SETUP_STATE_PARAM;
+    s->setup_len   = (s->setup_buf[7] << 8) | s->setup_buf[6];
+    s->setup_index = 0;
+
+    request = (s->setup_buf[0] << 8) | s->setup_buf[1];
+    value   = (s->setup_buf[3] << 8) | s->setup_buf[2];
+    index   = (s->setup_buf[5] << 8) | s->setup_buf[4];
+
+    if (s->setup_len > sizeof(s->data_buf)) {
+        fprintf(stderr,
+                "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
+                s->setup_len, sizeof(s->data_buf));
+        return USB_RET_STALL;
+    }
+
+    if (p->pid == USB_TOKEN_OUT) {
+        usb_packet_copy(p, s->data_buf, s->setup_len);
+    }
+
+    ret = usb_device_handle_control(s, p, request, value, index,
+                                    s->setup_len, s->data_buf);
+    if (ret < 0) {
+        return ret;
+    }
+
+    if (ret < s->setup_len) {
+        s->setup_len = ret;
+    }
+    if (p->pid == USB_TOKEN_IN) {
+        usb_packet_copy(p, s->data_buf, s->setup_len);
+    }
+
+    return ret;
+}
+
 /* ctrl complete function for devices which use usb_generic_handle_packet and
    may return USB_RET_ASYNC from their handle_control callback. Device code
    which does this *must* call this function instead of the normal
@@ -250,6 +295,16 @@ void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p)
         p->result = 0;
         break;
 
+    case SETUP_STATE_PARAM:
+        if (p->result < s->setup_len) {
+            s->setup_len = p->result;
+        }
+        if (p->pid == USB_TOKEN_IN) {
+            p->result = 0;
+            usb_packet_copy(p, s->data_buf, s->setup_len);
+        }
+        break;
+
     default:
         break;
     }
@@ -292,6 +347,9 @@ static int usb_process_one(USBPacket *p)
 
     if (p->ep->nr == 0) {
         /* control pipe */
+        if (p->parameter) {
+            return do_parameter(dev, p);
+        }
         switch (p->pid) {
         case USB_TOKEN_SETUP:
             return do_token_setup(dev, p);
@@ -416,6 +474,7 @@ void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep)
     p->pid = pid;
     p->ep = ep;
     p->result = 0;
+    p->parameter = 0;
     qemu_iovec_reset(&p->iov);
     usb_packet_set_state(p, USB_PACKET_SETUP);
 }
diff --git a/hw/usb.h b/hw/usb.h
index f6df0ad..d60d03d 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -327,6 +327,7 @@ struct USBPacket {
     int pid;
     USBEndpoint *ep;
     QEMUIOVector iov;
+    uint64_t parameter; /* control transfers */
     int result; /* transfer length or USB_RET_* status code */
     /* Internal use by the USB layer.  */
     USBPacketState state;
commit 9424d4e7c67d9d0cbc50fc8a1d00db31772c37c5
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Mar 1 14:42:34 2012 +0100

    usb-host: enable pipelineing for bulk endpoints.
    
    We really don't want to wait for packets finish before submitting the
    next, we want keep the data flow running.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/usb-linux.c b/usb-linux.c
index 050ea7a..90919c2 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -1192,6 +1192,9 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
                    USB_ENDPOINT_XFER_INVALID);
             usb_ep_set_type(&s->dev, pid, ep, type);
             usb_ep_set_ifnum(&s->dev, pid, ep, interface);
+            if (type == USB_ENDPOINT_XFER_BULK) {
+                usb_ep_set_pipeline(&s->dev, pid, ep, true);
+            }
 
             epd = get_endp(s, pid, ep);
             epd->halted = 0;
commit 7936e0f0d2fcd05bf5a78985a53b6b2276115749
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Mar 1 14:39:28 2012 +0100

    usb: add pipelining option to usb endpoints
    
    With this patch applied USB drivers can enable pipelining per endpoint.
    With pipelining enabled the usb core will continue submitting packets
    even when there are still async transfers in flight instead of passing
    them on one by one.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb.c b/hw/usb.c
index fc41d62..800d912 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -323,7 +323,7 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
     assert(p->state == USB_PACKET_SETUP);
     assert(p->ep != NULL);
 
-    if (QTAILQ_EMPTY(&p->ep->queue)) {
+    if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline) {
         ret = usb_process_one(p);
         if (ret == USB_RET_ASYNC) {
             usb_packet_set_state(p, USB_PACKET_ASYNC);
@@ -468,6 +468,7 @@ void usb_ep_init(USBDevice *dev)
     dev->ep_ctl.type = USB_ENDPOINT_XFER_CONTROL;
     dev->ep_ctl.ifnum = 0;
     dev->ep_ctl.dev = dev;
+    dev->ep_ctl.pipeline = false;
     QTAILQ_INIT(&dev->ep_ctl.queue);
     for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
         dev->ep_in[ep].nr = ep + 1;
@@ -480,6 +481,8 @@ void usb_ep_init(USBDevice *dev)
         dev->ep_out[ep].ifnum = 0;
         dev->ep_in[ep].dev = dev;
         dev->ep_out[ep].dev = dev;
+        dev->ep_in[ep].pipeline = false;
+        dev->ep_out[ep].pipeline = false;
         QTAILQ_INIT(&dev->ep_in[ep].queue);
         QTAILQ_INIT(&dev->ep_out[ep].queue);
     }
@@ -593,3 +596,9 @@ int usb_ep_get_max_packet_size(USBDevice *dev, int pid, int ep)
     struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
     return uep->max_packet_size;
 }
+
+void usb_ep_set_pipeline(USBDevice *dev, int pid, int ep, bool enabled)
+{
+    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+    uep->pipeline = enabled;
+}
diff --git a/hw/usb.h b/hw/usb.h
index 1a30ebb..f6df0ad 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -177,6 +177,7 @@ struct USBEndpoint {
     uint8_t type;
     uint8_t ifnum;
     int max_packet_size;
+    bool pipeline;
     USBDevice *dev;
     QTAILQ_HEAD(, USBPacket) queue;
 };
@@ -364,6 +365,7 @@ void usb_ep_set_ifnum(USBDevice *dev, int pid, int ep, uint8_t ifnum);
 void usb_ep_set_max_packet_size(USBDevice *dev, int pid, int ep,
                                 uint16_t raw);
 int usb_ep_get_max_packet_size(USBDevice *dev, int pid, int ep);
+void usb_ep_set_pipeline(USBDevice *dev, int pid, int ep, bool enabled);
 
 void usb_attach(USBPort *port);
 void usb_detach(USBPort *port);
commit eb9d4673e3594baaa857a4c033fc7c21f4ea904b
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Feb 28 15:36:06 2012 +0100

    usb: queue can have async packets
    
    This can happen today in case the ->complete() callback queues up the
    next packet.  Also we'll support pipelining soon, which allows to have
    multiple packets per queue in flight (aka ASYNC) state.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb.c b/hw/usb.c
index 57fc5e3..fc41d62 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -356,6 +356,9 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p)
 
     while (!QTAILQ_EMPTY(&ep->queue)) {
         p = QTAILQ_FIRST(&ep->queue);
+        if (p->state == USB_PACKET_ASYNC) {
+            break;
+        }
         assert(p->state == USB_PACKET_QUEUED);
         ret = usb_process_one(p);
         if (ret == USB_RET_ASYNC) {
commit 7c308b7e38812b49e3e9eccdb74b01989cdf7b78
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Feb 27 16:41:57 2012 +0100

    uhci_fill_queue: zap debug printf

diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 2c6ed38..304b84b 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -951,7 +951,6 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td)
     UHCI_TD ptd;
     int ret;
 
-    fprintf(stderr, "%s: -- %x\n", __func__, token);
     while (is_valid(plink)) {
         pci_dma_read(&s->dev, plink & ~0xf, &ptd, sizeof(ptd));
         le32_to_cpus(&ptd.link);
commit d61000a8b1d99c5155440b727ea32f12a4988120
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Mar 2 21:27:20 2012 +0100

    usb: add USB_RET_IOERROR
    
    We already have USB_RET_NAK, but that means that a device does not want
    to send/receive right now. But with host / network redirection we can
    actually have a transaction fail due to some io error, rather then ie
    the device just not having any data atm.
    
    This patch adds a new error code named USB_RET_IOERROR for this, and uses
    it were appropriate.
    
    Notes:
    -Currently all usb-controllers handle this the same as NODEV, but that
     may change in the future, OHCI could indicate a CRC error instead for example.
    -This patch does not touch hw/usb-musb.c, that is because the code in there
     handles STALL and NAK specially and has a if status < 0 generic catch all
     for all other errors
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 825fcc0..df742f7 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1299,6 +1299,7 @@ static void ehci_execute_complete(EHCIQueue *q)
 
     if (q->usb_status < 0) {
         switch(q->usb_status) {
+        case USB_RET_IOERROR:
         case USB_RET_NODEV:
             q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_XACTERR);
             set_field(&q->qh.token, 0, QTD_TOKEN_CERR);
@@ -1471,6 +1472,7 @@ static int ehci_process_itd(EHCIState *ehci,
                 default:
                     fprintf(stderr, "Unexpected iso usb result: %d\n", ret);
                     /* Fall through */
+                case USB_RET_IOERROR:
                 case USB_RET_NODEV:
                     /* 3.3.2: XACTERR is only allowed on IN transactions */
                     if (dir) {
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 7aa19fe..20aaa74 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -837,6 +837,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
                         OHCI_CC_DATAUNDERRUN);
         } else {
             switch (ret) {
+            case USB_RET_IOERROR:
             case USB_RET_NODEV:
                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
                             OHCI_CC_DEVICENOTRESPONDING);
@@ -1052,6 +1053,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
             OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAUNDERRUN);
         } else {
             switch (ret) {
+            case USB_RET_IOERROR:
             case USB_RET_NODEV:
                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING);
             case USB_RET_NAK:
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 70e3881..2c6ed38 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -765,6 +765,7 @@ out:
             break;
 	return 1;
 
+    case USB_RET_IOERROR:
     case USB_RET_NODEV:
     default:
 	break;
diff --git a/hw/usb.h b/hw/usb.h
index 8e83697..1a30ebb 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -39,11 +39,12 @@
 #define USB_TOKEN_IN    0x69 /* device -> host */
 #define USB_TOKEN_OUT   0xe1 /* host -> device */
 
-#define USB_RET_NODEV  (-1)
-#define USB_RET_NAK    (-2)
-#define USB_RET_STALL  (-3)
-#define USB_RET_BABBLE (-4)
-#define USB_RET_ASYNC  (-5)
+#define USB_RET_NODEV   (-1)
+#define USB_RET_NAK     (-2)
+#define USB_RET_STALL   (-3)
+#define USB_RET_BABBLE  (-4)
+#define USB_RET_IOERROR (-5)
+#define USB_RET_ASYNC   (-6)
 
 #define USB_SPEED_LOW   0
 #define USB_SPEED_FULL  1
diff --git a/usb-linux.c b/usb-linux.c
index 38df9e6..050ea7a 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -369,7 +369,7 @@ static void async_complete(void *opaque)
                 break;
 
             default:
-                p->result = USB_RET_NAK;
+                p->result = USB_RET_IOERROR;
                 break;
             }
 
@@ -729,7 +729,7 @@ static int urb_status_to_usb_ret(int status)
     case -EOVERFLOW:
         return USB_RET_BABBLE;
     default:
-        return USB_RET_NAK;
+        return USB_RET_IOERROR;
     }
 }
 
diff --git a/usb-redir.c b/usb-redir.c
index c52311a..8e9f175 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -431,7 +431,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
             /* Check iso_error for stream errors, otherwise its an underrun */
             status = dev->endpoint[EP2I(ep)].iso_error;
             dev->endpoint[EP2I(ep)].iso_error = 0;
-            return status ? USB_RET_NAK : 0;
+            return status ? USB_RET_IOERROR : 0;
         }
         DPRINTF2("iso-token-in ep %02X status %d len %d queue-size: %d\n", ep,
                  isop->status, isop->len, dev->endpoint[EP2I(ep)].bufpq_size);
@@ -439,7 +439,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
         status = isop->status;
         if (status != usb_redir_success) {
             bufp_free(dev, isop, ep);
-            return USB_RET_NAK;
+            return USB_RET_IOERROR;
         }
 
         len = isop->len;
@@ -1018,11 +1018,14 @@ static int usbredir_handle_status(USBRedirDevice *dev,
         return USB_RET_STALL;
     case usb_redir_cancelled:
         WARNING("returning cancelled packet to HC?\n");
+        return USB_RET_NAK;
     case usb_redir_inval:
+        WARNING("got invalid param error from usb-host?\n");
+        return USB_RET_NAK;
     case usb_redir_ioerror:
     case usb_redir_timeout:
     default:
-        return USB_RET_NAK;
+        return USB_RET_IOERROR;
     }
 }
 
commit 4d819a9bde7f52e7421d4128dc69c296c9fd017a
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Mar 2 21:27:19 2012 +0100

    usb: return BABBLE rather then NAK when we receive too much data
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/usb-linux.c b/usb-linux.c
index 47994f3..38df9e6 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -364,6 +364,10 @@ static void async_complete(void *opaque)
                 p->result = USB_RET_STALL;
                 break;
 
+            case -EOVERFLOW:
+                p->result = USB_RET_BABBLE;
+                break;
+
             default:
                 p->result = USB_RET_NAK;
                 break;
@@ -722,6 +726,8 @@ static int urb_status_to_usb_ret(int status)
     switch (status) {
     case -EPIPE:
         return USB_RET_STALL;
+    case -EOVERFLOW:
+        return USB_RET_BABBLE;
     default:
         return USB_RET_NAK;
     }
@@ -759,7 +765,7 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
             } else if (aurb[i].urb.iso_frame_desc[j].actual_length
                        > p->iov.size) {
                 printf("husb: received iso data is larger then packet\n");
-                len = USB_RET_NAK;
+                len = USB_RET_BABBLE;
             /* All good copy data over */
             } else {
                 len = aurb[i].urb.iso_frame_desc[j].actual_length;
diff --git a/usb-redir.c b/usb-redir.c
index a87de6e..c52311a 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -447,7 +447,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
             ERROR("received iso data is larger then packet ep %02X (%d > %d)\n",
                   ep, len, (int)p->iov.size);
             bufp_free(dev, isop, ep);
-            return USB_RET_NAK;
+            return USB_RET_BABBLE;
         }
         usb_packet_copy(p, isop->data, len);
         bufp_free(dev, isop, ep);
@@ -566,7 +566,7 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
         if (len > p->iov.size) {
             ERROR("received int data is larger then packet ep %02X\n", ep);
             bufp_free(dev, intp, ep);
-            return USB_RET_NAK;
+            return USB_RET_BABBLE;
         }
         usb_packet_copy(p, intp->data, len);
         bufp_free(dev, intp, ep);
commit 5eafd438c9e3b7b698c4a4ec755f52d8dfb870ae
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Mar 2 21:27:18 2012 +0100

    usb-ehci: Cleanup itd error handling
    
    All error statuses except for NAK are handled in a switch case, move the
    handling of NAK into the same switch case.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 9197298..825fcc0 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1466,20 +1466,7 @@ static int ehci_process_itd(EHCIState *ehci,
             }
             qemu_sglist_destroy(&ehci->isgl);
 
-            if (ret == USB_RET_NAK) {
-                /* no data for us, so do a zero-length transfer */
-                ret = 0;
-            }
-
-            if (ret >= 0) {
-                if (!dir) {
-                    /* OUT */
-                    set_field(&itd->transact[i], len - ret, ITD_XACT_LENGTH);
-                } else {
-                    /* IN */
-                    set_field(&itd->transact[i], ret, ITD_XACT_LENGTH);
-                }
-            } else {
+            if (ret < 0) {
                 switch (ret) {
                 default:
                     fprintf(stderr, "Unexpected iso usb result: %d\n", ret);
@@ -1495,6 +1482,19 @@ static int ehci_process_itd(EHCIState *ehci,
                     itd->transact[i] |= ITD_XACT_BABBLE;
                     ehci_record_interrupt(ehci, USBSTS_ERRINT);
                     break;
+                case USB_RET_NAK:
+                    /* no data for us, so do a zero-length transfer */
+                    ret = 0;
+                    break;
+                }
+            }
+            if (ret >= 0) {
+                if (!dir) {
+                    /* OUT */
+                    set_field(&itd->transact[i], len - ret, ITD_XACT_LENGTH);
+                } else {
+                    /* IN */
+                    set_field(&itd->transact[i], ret, ITD_XACT_LENGTH);
                 }
             }
             if (itd->transact[i] & ITD_XACT_IOC) {
commit 553a6a59f6931bf3a034945e0c1585f4b05d6000
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Mar 2 21:27:17 2012 +0100

    usb-ehci: Fix and simplify nakcnt handling
    
    The nakcnt code in ehci_execute_complete() marked transactions as finished
    when a packet completed with a result of USB_RET_NAK, but USB_RET_NAK
    means that the device cannot receive / send data at that time and that
    the transaction should be retried later, which is also what the usb-uhci
    and usb-ohci code does.
    
    Note that there already was some special code in place to handle this
    for interrupt endpoints in the form of doing a return from
    ehci_execute_complete() when reload == 0, but that for bulk transactions
    this was not handled correctly (where as for example the usb-ccid device does
    return USB_RET_NAK for bulk packets).
    
    Besides that the code in ehci_execute_complete() decrement nakcnt by 1
    on a packet result of USB_RET_NAK, but
    -since the transaction got marked as finished,
     nakcnt would never be decremented again
    -there is no code checking for nakcnt becoming 0
    -there is no use in re-trying the transaction within the same usb frame /
     usb-ehci frame-timer call, since the status of emulated devices won't change
     as long as the usb-ehci frame-timer is running
    So we should simply set the nakcnt to 0 when we get a USB_RET_NAK, thus
    claiming that we've tried reload times (or as many times as possible if
    reload is 0).
    
    Besides the code in ehci_execute_complete() handling USB_RET_NAK there
    was also code handling it in ehci_state_executing(), which calls
    ehci_execute_complete(), and then does its own handling on top of the handling
    in ehci_execute_complete(), this code would decrement nakcnt *again* (if not
    already 0), or restore the reload value (which was never changed) on success.
    
    Since the double decrement was wrong to begin with, and is no longer needed
    now that we set nakcnt directly to 0 on USB_RET_NAK, and the restore of reload
    is not needed either, this patch simply removes all nakcnt handling from
    ehci_state_executing().
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 07bcd1f..9197298 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1291,8 +1291,6 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
 
 static void ehci_execute_complete(EHCIQueue *q)
 {
-    int reload;
-
     assert(q->async != EHCI_ASYNC_INFLIGHT);
     q->async = EHCI_ASYNC_NONE;
 
@@ -1311,16 +1309,8 @@ static void ehci_execute_complete(EHCIQueue *q)
             ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
             break;
         case USB_RET_NAK:
-            /* 4.10.3 */
-            reload = get_field(q->qh.epchar, QH_EPCHAR_RL);
-            if ((q->pid == USB_TOKEN_IN) && reload) {
-                int nakcnt = get_field(q->qh.altnext_qtd, QH_ALTNEXT_NAKCNT);
-                nakcnt--;
-                set_field(&q->qh.altnext_qtd, nakcnt, QH_ALTNEXT_NAKCNT);
-            } else if (!reload) {
-                return;
-            }
-            break;
+            set_field(&q->qh.altnext_qtd, 0, QH_ALTNEXT_NAKCNT);
+            return; /* We're not done yet with this transaction */
         case USB_RET_BABBLE:
             q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_BABBLE);
             ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
@@ -1353,7 +1343,7 @@ static void ehci_execute_complete(EHCIQueue *q)
     q->qh.token ^= QTD_TOKEN_DTOGGLE;
     q->qh.token &= ~QTD_TOKEN_ACTIVE;
 
-    if ((q->usb_status != USB_RET_NAK) && (q->qh.token & QTD_TOKEN_IOC)) {
+    if (q->qh.token & QTD_TOKEN_IOC) {
         ehci_record_interrupt(q->ehci, USBSTS_INT);
     }
 }
@@ -1877,7 +1867,6 @@ out:
 static int ehci_state_executing(EHCIQueue *q, int async)
 {
     int again = 0;
-    int reload, nakcnt;
 
     ehci_execute_complete(q);
     if (q->usb_status == USB_RET_ASYNC) {
@@ -1897,21 +1886,8 @@ static int ehci_state_executing(EHCIQueue *q, int async)
         // counter decrements to 0
     }
 
-    reload = get_field(q->qh.epchar, QH_EPCHAR_RL);
-    if (reload) {
-        nakcnt = get_field(q->qh.altnext_qtd, QH_ALTNEXT_NAKCNT);
-        if (q->usb_status == USB_RET_NAK) {
-            if (nakcnt) {
-                nakcnt--;
-            }
-        } else {
-            nakcnt = reload;
-        }
-        set_field(&q->qh.altnext_qtd, nakcnt, QH_ALTNEXT_NAKCNT);
-    }
-
     /* 4.10.5 */
-    if ((q->usb_status == USB_RET_NAK) || (q->qh.token & QTD_TOKEN_ACTIVE)) {
+    if (q->usb_status == USB_RET_NAK) {
         ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
     } else {
         ehci_set_state(q->ehci, async, EST_WRITEBACK);
commit aa73fcdcc1bf4157121716e2eb3230130b0d1232
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Mar 2 21:27:16 2012 +0100

    usb-ehci: Remove dead nakcnt code
    
    This patch removes 2 bits of dead nakcnt code:
    
    1) usb_ehci_execute calls ehci_qh_do_overlay which does:
    nakcnt = reload;
    and then has a block of code which is conditional on:
    if (reload && !nakcnt) {
    which ofcourse is never true now as nakcnt == reload.
    
    2) ehci_state_fetchqh does:
    nakcnt = reload;
    but before nakcnt is ever used ehci_state_fetchqh is always followed
    by a ehci_qh_do_overlay call which also does:
    nakcnt = reload;
    So doing this from ehci_state_fetchqh is redundant.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 2685adc..07bcd1f 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1615,7 +1615,6 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
 {
     uint32_t entry;
     EHCIQueue *q;
-    int reload;
 
     entry = ehci_get_fetch_addr(ehci, async);
     q = ehci_find_queue_by_qh(ehci, entry, async);
@@ -1673,11 +1672,6 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
     }
 #endif
 
-    reload = get_field(q->qh.epchar, QH_EPCHAR_RL);
-    if (reload) {
-        set_field(&q->qh.altnext_qtd, reload, QH_ALTNEXT_NAKCNT);
-    }
-
     if (q->qh.token & QTD_TOKEN_HALT) {
         ehci_set_state(ehci, async, EST_HORIZONTALQH);
 
@@ -1837,25 +1831,11 @@ static void ehci_flush_qh(EHCIQueue *q)
 static int ehci_state_execute(EHCIQueue *q, int async)
 {
     int again = 0;
-    int reload, nakcnt;
-    int smask;
 
     if (ehci_qh_do_overlay(q) != 0) {
         return -1;
     }
 
-    smask = get_field(q->qh.epcap, QH_EPCAP_SMASK);
-
-    if (!smask) {
-        reload = get_field(q->qh.epchar, QH_EPCHAR_RL);
-        nakcnt = get_field(q->qh.altnext_qtd, QH_ALTNEXT_NAKCNT);
-        if (reload && !nakcnt) {
-            ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
-            again = 1;
-            goto out;
-        }
-    }
-
     // TODO verify enough time remains in the uframe as in 4.4.1.1
     // TODO write back ptr to async list when done or out of time
     // TODO Windows does not seem to ever set the MULT field
commit dd54cfe0bcf30d1f3a34e9c397f619d423fe0c5b
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Mar 2 21:27:15 2012 +0100

    usb-ehci: Fix cerr tracking
    
    cerr should only be decremented on errors which cause XactErr to be set, and
    when that happens the failing transaction should be retried until cerr reaches
    0 and only then should USBSTS_ERRINT be set (and inactive cleared and
    USBSTS_INT set if requested).
    
    Since we don't have any hardware level errors (and in case of redirection
    the real hardware has already retried), re-trying makes no sense, so
    immediately set cerr to 0 on errors which set XactErr.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 507e4a8..2685adc 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1291,7 +1291,7 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
 
 static void ehci_execute_complete(EHCIQueue *q)
 {
-    int c_err, reload;
+    int reload;
 
     assert(q->async != EHCI_ASYNC_INFLIGHT);
     q->async = EHCI_ASYNC_NONE;
@@ -1300,15 +1300,10 @@ static void ehci_execute_complete(EHCIQueue *q)
             q->qhaddr, q->qh.next, q->qtdaddr, q->usb_status);
 
     if (q->usb_status < 0) {
-err:
-        /* TO-DO: put this is in a function that can be invoked below as well */
-        c_err = get_field(q->qh.token, QTD_TOKEN_CERR);
-        c_err--;
-        set_field(&q->qh.token, c_err, QTD_TOKEN_CERR);
-
         switch(q->usb_status) {
         case USB_RET_NODEV:
             q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_XACTERR);
+            set_field(&q->qh.token, 0, QTD_TOKEN_CERR);
             ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
             break;
         case USB_RET_STALL:
@@ -1336,15 +1331,13 @@ err:
             assert(0);
             break;
         }
+    } else if ((q->usb_status > q->tbytes) && (q->pid == USB_TOKEN_IN)) {
+        q->usb_status = USB_RET_BABBLE;
+        q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_BABBLE);
+        ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
     } else {
-        // DPRINTF("Short packet condition\n");
         // TODO check 4.12 for splits
 
-        if ((q->usb_status > q->tbytes) && (q->pid == USB_TOKEN_IN)) {
-            q->usb_status = USB_RET_BABBLE;
-            goto err;
-        }
-
         if (q->tbytes && q->pid == USB_TOKEN_IN) {
             q->tbytes -= q->usb_status;
         } else {
commit 2763cbc751c494dd2f58f902ad80a8048f9cfd7b
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Mar 2 21:27:14 2012 +0100

    usb-ehci: Any packet completion except for NAK should set the interrupt
    
    As clearly stated in the 2.3.2 of the EHCI spec, any time USBERRINT get
    sets then if the td has its IOC bit set USBINT should be set as well.
    
    This means that for any status except for USB_RET_NAK we should set
    USBINT if the IOC bit is set.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index d386b84..507e4a8 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1360,7 +1360,7 @@ err:
     q->qh.token ^= QTD_TOKEN_DTOGGLE;
     q->qh.token &= ~QTD_TOKEN_ACTIVE;
 
-    if ((q->usb_status >= 0) && (q->qh.token & QTD_TOKEN_IOC)) {
+    if ((q->usb_status != USB_RET_NAK) && (q->qh.token & QTD_TOKEN_IOC)) {
         ehci_record_interrupt(q->ehci, USBSTS_INT);
     }
 }
commit e850c2b45306b59d179c4df93d91edc1c3c45106
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Mar 2 21:27:13 2012 +0100

    usb-ehci: Rip the queues when the async or period schedule is halted
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index b349003..d386b84 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1076,7 +1076,8 @@ 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);
-            // TODO - should finish out some stuff before setting halt
+            ehci_queues_rip_all(s, 0);
+            ehci_queues_rip_all(s, 1);
             ehci_set_usbsts(s, USBSTS_HALT);
         }
 
@@ -2088,6 +2089,7 @@ static void ehci_advance_async_state(EHCIState *ehci)
 
     case EST_ACTIVE:
         if ( !(ehci->usbcmd & USBCMD_ASE)) {
+            ehci_queues_rip_all(ehci, async);
             ehci_clear_usbsts(ehci, USBSTS_ASS);
             ehci_set_state(ehci, async, EST_INACTIVE);
             break;
@@ -2148,6 +2150,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
 
     case EST_ACTIVE:
         if ( !(ehci->frindex & 7) && !(ehci->usbcmd & USBCMD_PSE)) {
+            ehci_queues_rip_all(ehci, async);
             ehci_clear_usbsts(ehci, USBSTS_PSS);
             ehci_set_state(ehci, async, EST_INACTIVE);
             break;
commit 4be23939ab0d7019c7e59a37485b416fbbf0f073
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Mar 2 21:27:12 2012 +0100

    usb-ehci: Drop cached qhs when the doorbell gets rung
    
    The purpose of the IAAD bit / the doorbell is to make the ehci controller
    forget about cached qhs, this is mainly used when cancelling transactions,
    the qh is unlinked from the async schedule and then the doorbell gets rung,
    once the doorbell is acked by the controller the hcd knows that the qh is
    no longer in use and that it can do something else with the memory, such
    as re-use it for a new qh! But we keep our struct representing this qh around
    for circa 250 ms. This allows for a (mightily large) race window where the
    following could happen:
    -hcd submits a qh at address 0xdeadbeef
    -our ehci code sees the qh, sends a request to a usb-device, gets a result
     of USB_RET_ASYNC, sets the async_state of the qh to EHCI_ASYNC_INFLIGHT
    -hcd unlinks the qh at address 0xdeadbeef
    -hcd rings the doorbell, wait for us to ack it
    -hcd re-uses the qh at address 0xdeadbeef
    -our ehci code sees the qh, looks in the async_queue, sees there already is
     a qh at address 0xdeadbeef there with async_state of EHCI_ASYNC_INFLIGHT,
     does nothing
    -the *original* (which the hcd thinks it has cancelled) transaction finishes
    -our ehci code sees the qh on yet another pass through the async list,
     looks in the async_queue, sees there already is a qh at address 0xdeadbeef
     there with async_state of EHCI_ASYNC_COMPLETED, and finished the transaction
     with the results of the *original* transaction.
    
    Not good (tm), this patch fixes this race by removing all qhs which have not
    been seen during the last cycle through the async list immidiately when the
    doorbell is rung.
    
    Note this patch does not fix any actually observed problem, but upon
    reading of the EHCI spec it became apparent to me that the above race could
    happen and the usb-ehci behavior from before this patch is not good.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index d384fcc..b349003 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -697,7 +697,7 @@ static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr,
     return NULL;
 }
 
-static void ehci_queues_rip_unused(EHCIState *ehci, int async)
+static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
 {
     EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
     EHCIQueue *q, *tmp;
@@ -708,7 +708,7 @@ static void ehci_queues_rip_unused(EHCIState *ehci, int async)
             q->ts = ehci->last_run_ns;
             continue;
         }
-        if (ehci->last_run_ns < q->ts + 250000000) {
+        if (!flush && ehci->last_run_ns < q->ts + 250000000) {
             /* allow 0.25 sec idle */
             continue;
         }
@@ -1537,7 +1537,7 @@ static int ehci_state_waitlisthead(EHCIState *ehci,  int async)
         ehci_set_usbsts(ehci, USBSTS_REC);
     }
 
-    ehci_queues_rip_unused(ehci, async);
+    ehci_queues_rip_unused(ehci, async, 0);
 
     /*  Find the head of the list (4.9.1.1) */
     for(i = 0; i < MAX_QH; i++) {
@@ -2093,18 +2093,7 @@ static void ehci_advance_async_state(EHCIState *ehci)
             break;
         }
 
-        /* If the doorbell is set, the guest wants to make a change to the
-         * schedule. The host controller needs to release cached data.
-         * (section 4.8.2)
-         */
-        if (ehci->usbcmd & USBCMD_IAAD) {
-            DPRINTF("ASYNC: doorbell request acknowledged\n");
-            ehci->usbcmd &= ~USBCMD_IAAD;
-            ehci_set_interrupt(ehci, USBSTS_IAA);
-            break;
-        }
-
-        /* make sure guest has acknowledged */
+        /* make sure guest has acknowledged the doorbell interrupt */
         /* TO-DO: is this really needed? */
         if (ehci->usbsts & USBSTS_IAA) {
             DPRINTF("IAA status bit still set.\n");
@@ -2118,6 +2107,18 @@ static void ehci_advance_async_state(EHCIState *ehci)
 
         ehci_set_state(ehci, async, EST_WAITLISTHEAD);
         ehci_advance_state(ehci, async);
+
+        /* If the doorbell is set, the guest wants to make a change to the
+         * schedule. The host controller needs to release cached data.
+         * (section 4.8.2)
+         */
+        if (ehci->usbcmd & USBCMD_IAAD) {
+            /* Remove all unseen qhs from the async qhs queue */
+            ehci_queues_rip_unused(ehci, async, 1);
+            DPRINTF("ASYNC: doorbell request acknowledged\n");
+            ehci->usbcmd &= ~USBCMD_IAAD;
+            ehci_set_interrupt(ehci, USBSTS_IAA);
+        }
         break;
 
     default:
@@ -2167,7 +2168,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
         ehci_set_fetch_addr(ehci, async,entry);
         ehci_set_state(ehci, async, EST_FETCHENTRY);
         ehci_advance_state(ehci, async);
-        ehci_queues_rip_unused(ehci, async);
+        ehci_queues_rip_unused(ehci, async, 0);
         break;
 
     default:
commit 7bce354e148b0ae0ceae7582574810adc6fab4e4
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Mar 2 21:27:11 2012 +0100

    usb-ehci: always call ehci_queues_rip_unused for period queues
    
    Before this patch USB 2 devices with interrupt endpoints were not working
    properly. The problem is that to avoid loops we stop processing as soon
    as we encounter a queue-head (qh) we've already seen since qhs can be linked
    in a circular fashion, this is tracked by the seen flag in our qh struct.
    
    The resetting of the seen flag is done from ehci_queues_rip_unused which
    before this patch was only called when executing the statemachine for the
    async schedule.
    
    But packets for interrupt endpoints are part of the periodic schedule! So what
    would happen is that when there were no ctrl or bulk packets for a USB 2
    device with an interrupt endpoint, the async schedule would become non
    active, then ehci_queues_rip_unused would no longer get called and when
    processing the qhs for the interrupt endpoints from the periodic schedule
    their seen bit would still be 1 and they would be skipped.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 840022d..d384fcc 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -2167,6 +2167,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
         ehci_set_fetch_addr(ehci, async,entry);
         ehci_set_state(ehci, async, EST_FETCHENTRY);
         ehci_advance_state(ehci, async);
+        ehci_queues_rip_unused(ehci, async);
         break;
 
     default:
commit df5d5c5c9eeaedb7705b4df6f5ee8083f39cf7b5
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Mar 2 21:27:10 2012 +0100

    usb-ehci: split our qh queue into async and periodic queues
    
    qhs can be part of both the async and the periodic schedule, as is shown
    in later patches in this series it is useful to keep track of the qhs on
    a per schedule basis.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index d41b80e..840022d 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -347,7 +347,6 @@ enum async_state {
 struct EHCIQueue {
     EHCIState *ehci;
     QTAILQ_ENTRY(EHCIQueue) next;
-    bool async_schedule;
     uint32_t seen;
     uint64_t ts;
 
@@ -367,6 +366,8 @@ struct EHCIQueue {
     int usb_status;
 };
 
+typedef QTAILQ_HEAD(EHCIQueueHead, EHCIQueue) EHCIQueueHead;
+
 struct EHCIState {
     PCIDevice dev;
     USBBus bus;
@@ -410,7 +411,8 @@ struct EHCIState {
     USBPort ports[NB_PORTS];
     USBPort *companion_ports[NB_PORTS];
     uint32_t usbsts_pending;
-    QTAILQ_HEAD(, EHCIQueue) queues;
+    EHCIQueueHead aqueues;
+    EHCIQueueHead pqueues;
 
     uint32_t a_fetch_addr;   // which address to look at next
     uint32_t p_fetch_addr;   // which address to look at next
@@ -660,31 +662,34 @@ static void ehci_trace_sitd(EHCIState *s, target_phys_addr_t addr,
 
 static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async)
 {
+    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
     EHCIQueue *q;
 
     q = g_malloc0(sizeof(*q));
     q->ehci = ehci;
-    q->async_schedule = async;
-    QTAILQ_INSERT_HEAD(&ehci->queues, q, next);
+    QTAILQ_INSERT_HEAD(head, q, next);
     trace_usb_ehci_queue_action(q, "alloc");
     return q;
 }
 
-static void ehci_free_queue(EHCIQueue *q)
+static void ehci_free_queue(EHCIQueue *q, int async)
 {
+    EHCIQueueHead *head = async ? &q->ehci->aqueues : &q->ehci->pqueues;
     trace_usb_ehci_queue_action(q, "free");
     if (q->async == EHCI_ASYNC_INFLIGHT) {
         usb_cancel_packet(&q->packet);
     }
-    QTAILQ_REMOVE(&q->ehci->queues, q, next);
+    QTAILQ_REMOVE(head, q, next);
     g_free(q);
 }
 
-static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr)
+static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr,
+                                        int async)
 {
+    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
     EHCIQueue *q;
 
-    QTAILQ_FOREACH(q, &ehci->queues, next) {
+    QTAILQ_FOREACH(q, head, next) {
         if (addr == q->qhaddr) {
             return q;
         }
@@ -692,11 +697,12 @@ static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr)
     return NULL;
 }
 
-static void ehci_queues_rip_unused(EHCIState *ehci)
+static void ehci_queues_rip_unused(EHCIState *ehci, int async)
 {
+    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
     EHCIQueue *q, *tmp;
 
-    QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
+    QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
         if (q->seen) {
             q->seen = 0;
             q->ts = ehci->last_run_ns;
@@ -706,29 +712,31 @@ static void ehci_queues_rip_unused(EHCIState *ehci)
             /* allow 0.25 sec idle */
             continue;
         }
-        ehci_free_queue(q);
+        ehci_free_queue(q, async);
     }
 }
 
-static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev)
+static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async)
 {
+    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
     EHCIQueue *q, *tmp;
 
-    QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
+    QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
         if (!usb_packet_is_inflight(&q->packet) ||
             q->packet.ep->dev != dev) {
             continue;
         }
-        ehci_free_queue(q);
+        ehci_free_queue(q, async);
     }
 }
 
-static void ehci_queues_rip_all(EHCIState *ehci)
+static void ehci_queues_rip_all(EHCIState *ehci, int async)
 {
+    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
     EHCIQueue *q, *tmp;
 
-    QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
-        ehci_free_queue(q);
+    QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
+        ehci_free_queue(q, async);
     }
 }
 
@@ -773,7 +781,8 @@ static void ehci_detach(USBPort *port)
         return;
     }
 
-    ehci_queues_rip_device(s, port->dev);
+    ehci_queues_rip_device(s, port->dev, 0);
+    ehci_queues_rip_device(s, port->dev, 1);
 
     *portsc &= ~(PORTSC_CONNECT|PORTSC_PED);
     *portsc |= PORTSC_CSC;
@@ -793,7 +802,8 @@ static void ehci_child_detach(USBPort *port, USBDevice *child)
         return;
     }
 
-    ehci_queues_rip_device(s, child);
+    ehci_queues_rip_device(s, child, 0);
+    ehci_queues_rip_device(s, child, 1);
 }
 
 static void ehci_wakeup(USBPort *port)
@@ -911,7 +921,8 @@ static void ehci_reset(void *opaque)
             usb_device_reset(devs[i]);
         }
     }
-    ehci_queues_rip_all(s);
+    ehci_queues_rip_all(s, 0);
+    ehci_queues_rip_all(s, 1);
     qemu_del_timer(s->frame_timer);
 }
 
@@ -1526,7 +1537,7 @@ static int ehci_state_waitlisthead(EHCIState *ehci,  int async)
         ehci_set_usbsts(ehci, USBSTS_REC);
     }
 
-    ehci_queues_rip_unused(ehci);
+    ehci_queues_rip_unused(ehci, async);
 
     /*  Find the head of the list (4.9.1.1) */
     for(i = 0; i < MAX_QH; i++) {
@@ -1613,7 +1624,7 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
     int reload;
 
     entry = ehci_get_fetch_addr(ehci, async);
-    q = ehci_find_queue_by_qh(ehci, entry);
+    q = ehci_find_queue_by_qh(ehci, entry, async);
     if (NULL == q) {
         q = ehci_alloc_queue(ehci, async);
     }
@@ -2064,7 +2075,7 @@ static void ehci_advance_state(EHCIState *ehci,
 
 static void ehci_advance_async_state(EHCIState *ehci)
 {
-    int async = 1;
+    const int async = 1;
 
     switch(ehci_get_state(ehci, async)) {
     case EST_INACTIVE:
@@ -2121,7 +2132,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
 {
     uint32_t entry;
     uint32_t list;
-    int async = 0;
+    const int async = 0;
 
     // 4.6
 
@@ -2354,7 +2365,8 @@ static int usb_ehci_initfn(PCIDevice *dev)
     }
 
     s->frame_timer = qemu_new_timer_ns(vm_clock, ehci_frame_timer, s);
-    QTAILQ_INIT(&s->queues);
+    QTAILQ_INIT(&s->aqueues);
+    QTAILQ_INIT(&s->pqueues);
 
     qemu_register_reset(ehci_reset, s);
 
commit 2a5ff735dc1074171a0cbb1dc228d6d6e907f571
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Mar 2 21:27:09 2012 +0100

    usb-ehci: Never follow table entries with the T-bit set
    
    Before this patch the T-bit was not checked in 2 places, while it should be.
    
    Once we properly check the T-bit everywhere we no longer need the weird
    entry < 0x1000 and entry > 0x1000 checks, so this patch removes them.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index afc8ccf..d41b80e 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1568,8 +1568,7 @@ static int ehci_state_fetchentry(EHCIState *ehci, int async)
     int again = 0;
     uint32_t entry = ehci_get_fetch_addr(ehci, async);
 
-    if (entry < 0x1000) {
-        DPRINTF("fetchentry: entry invalid (0x%08x)\n", entry);
+    if (NLPTR_TBIT(entry)) {
         ehci_set_state(ehci, async, EST_ACTIVE);
         goto out;
     }
@@ -1677,7 +1676,8 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
     if (q->qh.token & QTD_TOKEN_HALT) {
         ehci_set_state(ehci, async, EST_HORIZONTALQH);
 
-    } else if ((q->qh.token & QTD_TOKEN_ACTIVE) && (q->qh.current_qtd > 0x1000)) {
+    } else if ((q->qh.token & QTD_TOKEN_ACTIVE) &&
+               (NLPTR_TBIT(q->qh.current_qtd) == 0)) {
         q->qtdaddr = q->qh.current_qtd;
         ehci_set_state(ehci, async, EST_FETCHQTD);
 
@@ -1756,7 +1756,6 @@ static int ehci_state_advqueue(EHCIQueue *q, int async)
      * want data and alt-next qTD is valid
      */
     if (((q->qh.token & QTD_TOKEN_TBYTES_MASK) != 0) &&
-        (q->qh.altnext_qtd > 0x1000) &&
         (NLPTR_TBIT(q->qh.altnext_qtd) == 0)) {
         q->qtdaddr = q->qh.altnext_qtd;
         ehci_set_state(q->ehci, async, EST_FETCHQTD);
@@ -1764,8 +1763,7 @@ static int ehci_state_advqueue(EHCIQueue *q, int async)
     /*
      *  next qTD is valid
      */
-    } else if ((q->qh.next_qtd > 0x1000) &&
-               (NLPTR_TBIT(q->qh.next_qtd) == 0)) {
+    } else if (NLPTR_TBIT(q->qh.next_qtd) == 0) {
         q->qtdaddr = q->qh.next_qtd;
         ehci_set_state(q->ehci, async, EST_FETCHQTD);
 
commit 0454b611bb129ada92d16cfb9bec5fd6e1df5ab0
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Mar 2 21:27:08 2012 +0100

    usb-redir: Set ep type and interface
    
    Since we don't use usb_desc.c we need to do this ourselves. This fixes
    iso transfers no longer working for USB 2 devices due to the ep->type
    check in ehci.c
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/usb-redir.c b/usb-redir.c
index 755492f..a87de6e 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -1122,6 +1122,7 @@ static void usbredir_device_disconnect(void *priv)
     for (i = 0; i < MAX_ENDPOINTS; i++) {
         QTAILQ_INIT(&dev->endpoint[i].bufpq);
     }
+    usb_ep_init(&dev->dev);
     dev->interface_info.interface_count = 0;
 }
 
@@ -1148,6 +1149,7 @@ static void usbredir_ep_info(void *priv,
     struct usb_redir_ep_info_header *ep_info)
 {
     USBRedirDevice *dev = priv;
+    struct USBEndpoint *usb_ep;
     int i;
 
     for (i = 0; i < MAX_ENDPOINTS; i++) {
@@ -1172,7 +1174,13 @@ static void usbredir_ep_info(void *priv,
         default:
             ERROR("Received invalid endpoint type\n");
             usbredir_device_disconnect(dev);
+            return;
         }
+        usb_ep = usb_ep_get(&dev->dev,
+                            (i & 0x10) ? USB_TOKEN_IN : USB_TOKEN_OUT,
+                            i & 0x0f);
+        usb_ep->type = dev->endpoint[i].type;
+        usb_ep->ifnum = dev->endpoint[i].interface;
     }
 }
 
commit 7e680753cfa2986e0a8b3b222b6bf0b003c5eb69
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Wed Feb 29 17:54:29 2012 +0200

    kvm: fill in padding to help valgrind
    
    valgrind warns about padding fields which are passed
    to vcpu ioctls uninitialized.
    This is not an error in practice because kvm ignored padding.
    Since the ioctls in question are off data path and
    the cost is zero anyway, initialize padding to 0
    to suppress these errors.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index 278085f..21c7dd2 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -448,6 +448,7 @@ int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
 
         zone.addr = start;
         zone.size = size;
+        zone.pad = 0;
 
         ret = kvm_vm_ioctl(s, KVM_REGISTER_COALESCED_MMIO, &zone);
     }
@@ -465,6 +466,7 @@ int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
 
         zone.addr = start;
         zone.size = size;
+        zone.pad = 0;
 
         ret = kvm_vm_ioctl(s, KVM_UNREGISTER_COALESCED_MMIO, &zone);
     }
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 9a73207..619d773 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -555,6 +555,7 @@ int kvm_arch_init_vcpu(CPUState *env)
 
     qemu_add_vm_change_state_handler(cpu_update_state, env);
 
+    cpuid_data.cpuid.padding = 0;
     r = kvm_vcpu_ioctl(env, KVM_SET_CPUID2, &cpuid_data);
     if (r) {
         return r;
@@ -740,6 +741,7 @@ static void set_seg(struct kvm_segment *lhs, const SegmentCache *rhs)
     lhs->g = (flags & DESC_G_MASK) != 0;
     lhs->avl = (flags & DESC_AVL_MASK) != 0;
     lhs->unusable = 0;
+    lhs->padding = 0;
 }
 
 static void get_seg(SegmentCache *lhs, const struct kvm_segment *rhs)
@@ -919,8 +921,10 @@ static int kvm_put_sregs(CPUState *env)
 
     sregs.idt.limit = env->idt.limit;
     sregs.idt.base = env->idt.base;
+    memset(sregs.idt.padding, 0, sizeof sregs.idt.padding);
     sregs.gdt.limit = env->gdt.limit;
     sregs.gdt.base = env->gdt.base;
+    memset(sregs.gdt.padding, 0, sizeof sregs.gdt.padding);
 
     sregs.cr0 = env->cr[0];
     sregs.cr2 = env->cr[2];
@@ -1392,6 +1396,7 @@ static int kvm_put_vcpu_events(CPUState *env, int level)
     events.exception.nr = env->exception_injected;
     events.exception.has_error_code = env->has_error_code;
     events.exception.error_code = env->error_code;
+    events.exception.pad = 0;
 
     events.interrupt.injected = (env->interrupt_injected >= 0);
     events.interrupt.nr = env->interrupt_injected;
@@ -1400,6 +1405,7 @@ static int kvm_put_vcpu_events(CPUState *env, int level)
     events.nmi.injected = env->nmi_injected;
     events.nmi.pending = env->nmi_pending;
     events.nmi.masked = !!(env->hflags2 & HF2_NMI_MASK);
+    events.nmi.pad = 0;
 
     events.sipi_vector = env->sipi_vector;
 
commit 5d17c0d2df4998598e6002b27b8e47e792899a0f
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Mar 2 20:28:49 2012 +0100

    kvm: x86: Add user space part for in-kernel i8254
    
    This provides the required user space stubs to enable the in-kernel
    i8254 emulation of KVM.
    
    The in-kernel model supports lost tick compensation according to the
    "delay" policy. This is enabled by default and can be switched off via a
    device property.
    
    Depending on the feature set of the host kernel (before 2.6.32), we may
    have to disable the HPET or lack sound output from the PC speaker.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/Makefile.target b/Makefile.target
index 5f3fc40..1bd25a8 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -244,7 +244,7 @@ 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
+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
diff --git a/hw/i8254.h b/hw/i8254.h
index a1d2e98..ba6b598 100644
--- a/hw/i8254.h
+++ b/hw/i8254.h
@@ -51,6 +51,17 @@ static inline ISADevice *pit_init(ISABus *bus, int base, int isa_irq,
     return dev;
 }
 
+static inline ISADevice *kvm_pit_init(ISABus *bus, int base)
+{
+    ISADevice *dev;
+
+    dev = isa_create(bus, "kvm-pit");
+    qdev_prop_set_uint32(&dev->qdev, "iobase", base);
+    qdev_init_nofail(&dev->qdev);
+
+    return dev;
+}
+
 void pit_set_gate(ISADevice *dev, int channel, int val);
 void pit_get_channel_info(ISADevice *dev, int channel, PITChannelInfo *info);
 
diff --git a/hw/kvm/i8254.c b/hw/kvm/i8254.c
new file mode 100644
index 0000000..bb5fe07
--- /dev/null
+++ b/hw/kvm/i8254.c
@@ -0,0 +1,254 @@
+/*
+ * KVM in-kernel PIT (i8254) support
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2012      Jan Kiszka, Siemens AG
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu-timer.h"
+#include "hw/i8254.h"
+#include "hw/i8254_internal.h"
+#include "kvm.h"
+
+#define KVM_PIT_REINJECT_BIT 0
+
+typedef struct KVMPITState {
+    PITCommonState pit;
+    LostTickPolicy lost_tick_policy;
+} KVMPITState;
+
+static void kvm_pit_get(PITCommonState *s)
+{
+    struct kvm_pit_state2 kpit;
+    struct kvm_pit_channel_state *kchan;
+    struct PITChannelState *sc;
+    int i, ret;
+
+    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;
+    } else {
+        /*
+         * kvm_pit_state2 is superset of kvm_pit_state struct,
+         * so we can use it for KVM_GET_PIT as well.
+         */
+        ret = kvm_vm_ioctl(kvm_state, KVM_GET_PIT, &kpit);
+        if (ret < 0) {
+            fprintf(stderr, "KVM_GET_PIT failed: %s\n", strerror(ret));
+            abort();
+        }
+    }
+    for (i = 0; i < 3; i++) {
+        kchan = &kpit.channels[i];
+        sc = &s->channels[i];
+        sc->count = kchan->count;
+        sc->latched_count = kchan->latched_count;
+        sc->count_latched = kchan->count_latched;
+        sc->status_latched = kchan->status_latched;
+        sc->status = kchan->status;
+        sc->read_state = kchan->read_state;
+        sc->write_state = kchan->write_state;
+        sc->write_latch = kchan->write_latch;
+        sc->rw_mode = kchan->rw_mode;
+        sc->mode = kchan->mode;
+        sc->bcd = kchan->bcd;
+        sc->gate = kchan->gate;
+        sc->count_load_time = kchan->count_load_time;
+    }
+
+    sc = &s->channels[0];
+    sc->next_transition_time =
+        pit_get_next_transition_time(sc, sc->count_load_time);
+}
+
+static void kvm_pit_put(PITCommonState *s)
+{
+    struct kvm_pit_state2 kpit;
+    struct kvm_pit_channel_state *kchan;
+    struct PITChannelState *sc;
+    int i, ret;
+
+    kpit.flags = s->channels[0].irq_disabled ? KVM_PIT_FLAGS_HPET_LEGACY : 0;
+    for (i = 0; i < 3; i++) {
+        kchan = &kpit.channels[i];
+        sc = &s->channels[i];
+        kchan->count = sc->count;
+        kchan->latched_count = sc->latched_count;
+        kchan->count_latched = sc->count_latched;
+        kchan->status_latched = sc->status_latched;
+        kchan->status = sc->status;
+        kchan->read_state = sc->read_state;
+        kchan->write_state = sc->write_state;
+        kchan->write_latch = sc->write_latch;
+        kchan->rw_mode = sc->rw_mode;
+        kchan->mode = sc->mode;
+        kchan->bcd = sc->bcd;
+        kchan->gate = sc->gate;
+        kchan->count_load_time = sc->count_load_time;
+    }
+
+    ret = kvm_vm_ioctl(kvm_state,
+                       kvm_has_pit_state2() ? KVM_SET_PIT2 : KVM_SET_PIT,
+                       &kpit);
+    if (ret < 0) {
+        fprintf(stderr, "%s failed: %s\n",
+                kvm_has_pit_state2() ? "KVM_SET_PIT2" : "KVM_SET_PIT",
+                strerror(ret));
+        abort();
+    }
+}
+
+static void kvm_pit_set_gate(PITCommonState *s, PITChannelState *sc, int val)
+{
+    kvm_pit_get(s);
+
+    switch (sc->mode) {
+    default:
+    case 0:
+    case 4:
+        /* XXX: just disable/enable counting */
+        break;
+    case 1:
+    case 2:
+    case 3:
+    case 5:
+        if (sc->gate < val) {
+            /* restart counting on rising edge */
+            sc->count_load_time = qemu_get_clock_ns(vm_clock);
+        }
+        break;
+    }
+    sc->gate = val;
+
+    kvm_pit_put(s);
+}
+
+static void kvm_pit_get_channel_info(PITCommonState *s, PITChannelState *sc,
+                                     PITChannelInfo *info)
+{
+    kvm_pit_get(s);
+
+    pit_get_channel_info_common(s, sc, info);
+}
+
+static void kvm_pit_reset(DeviceState *dev)
+{
+    PITCommonState *s = DO_UPCAST(PITCommonState, dev.qdev, dev);
+
+    pit_reset_common(s);
+
+    kvm_pit_put(s);
+}
+
+static void kvm_pit_irq_control(void *opaque, int n, int enable)
+{
+    PITCommonState *pit = opaque;
+    PITChannelState *s = &pit->channels[0];
+
+    kvm_pit_get(pit);
+
+    s->irq_disabled = !enable;
+
+    kvm_pit_put(pit);
+}
+
+static int kvm_pit_initfn(PITCommonState *pit)
+{
+    KVMPITState *s = DO_UPCAST(KVMPITState, pit, pit);
+    struct kvm_pit_config config = {
+        .flags = 0,
+    };
+    int ret;
+
+    if (kvm_check_extension(kvm_state, KVM_CAP_PIT2)) {
+        ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_PIT2, &config);
+    } else {
+        ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_PIT);
+    }
+    if (ret < 0) {
+        fprintf(stderr, "Create kernel PIC irqchip failed: %s\n",
+                strerror(ret));
+        return ret;
+    }
+    switch (s->lost_tick_policy) {
+    case LOST_TICK_DELAY:
+        break; /* enabled by default */
+    case LOST_TICK_DISCARD:
+        if (kvm_check_extension(kvm_state, KVM_CAP_REINJECT_CONTROL)) {
+            struct kvm_reinject_control control = { .pit_reinject = 0 };
+
+            ret = kvm_vm_ioctl(kvm_state, KVM_REINJECT_CONTROL, &control);
+            if (ret < 0) {
+                fprintf(stderr,
+                        "Can't disable in-kernel PIT reinjection: %s\n",
+                        strerror(ret));
+                return ret;
+            }
+        }
+        break;
+    default:
+        return -EINVAL;
+    }
+
+    memory_region_init_reservation(&pit->ioports, "kvm-pit", 4);
+
+    qdev_init_gpio_in(&pit->dev.qdev, kvm_pit_irq_control, 1);
+
+    return 0;
+}
+
+static Property kvm_pit_properties[] = {
+    DEFINE_PROP_HEX32("iobase", KVMPITState, pit.iobase,  -1),
+    DEFINE_PROP_LOSTTICKPOLICY("lost_tick_policy", KVMPITState,
+                               lost_tick_policy, LOST_TICK_DELAY),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void kvm_pit_class_init(ObjectClass *klass, void *data)
+{
+    PITCommonClass *k = PIT_COMMON_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    k->init = kvm_pit_initfn;
+    k->set_channel_gate = kvm_pit_set_gate;
+    k->get_channel_info = kvm_pit_get_channel_info;
+    k->pre_save = kvm_pit_get;
+    k->post_load = kvm_pit_put;
+    dc->reset = kvm_pit_reset;
+    dc->props = kvm_pit_properties;
+}
+
+static TypeInfo kvm_pit_info = {
+    .name          = "kvm-pit",
+    .parent        = TYPE_PIT_COMMON,
+    .instance_size = sizeof(KVMPITState),
+    .class_init = kvm_pit_class_init,
+};
+
+static void kvm_pit_register(void)
+{
+    type_register_static(&kvm_pit_info);
+}
+
+type_init(kvm_pit_register)
diff --git a/hw/pc.c b/hw/pc.c
index 12c02f2..bb9867b 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1096,7 +1096,13 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
 
     register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
 
-    if (!no_hpet) {
+    /*
+     * Check if an HPET shall be created.
+     *
+     * Without KVM_CAP_PIT_STATE2, we cannot switch off the in-kernel PIT
+     * when the HPET wants to take over. Thus we have to disable the latter.
+     */
+    if (!no_hpet && (!kvm_irqchip_in_kernel() || kvm_has_pit_state2())) {
         hpet = sysbus_try_create_simple("hpet", HPET_BASE, NULL);
 
         if (hpet) {
@@ -1112,7 +1118,11 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
 
     qemu_register_boot_set(pc_boot_set, *rtc_state);
 
-    pit = pit_init(isa_bus, 0x40, pit_isa_irq, pit_alt_irq);
+    if (kvm_irqchip_in_kernel()) {
+        pit = kvm_pit_init(isa_bus, 0x40);
+    } else {
+        pit = pit_init(isa_bus, 0x40, pit_isa_irq, pit_alt_irq);
+    }
     if (hpet) {
         /* connect PIT to output control line of the HPET */
         qdev_connect_gpio_out(hpet, 0, qdev_get_gpio_in(&pit->qdev, 0));
commit 8a7c73932e03f13f29dea8622e15f1ded478d407
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Mar 2 20:28:48 2012 +0100

    kvm: Add kvm_has_pit_state2 helper
    
    To be used for in-kernel PIT emulation.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index 77eadf6..278085f 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -76,6 +76,7 @@ struct KVMState
     struct kvm_sw_breakpoint_head kvm_sw_breakpoints;
 #endif
     int pit_in_kernel;
+    int pit_state2;
     int xsave, xcrs;
     int many_ioeventfds;
     int irqchip_inject_ioctl;
@@ -1058,6 +1059,10 @@ int kvm_init(void)
     s->xcrs = kvm_check_extension(s, KVM_CAP_XCRS);
 #endif
 
+#ifdef KVM_CAP_PIT_STATE2
+    s->pit_state2 = kvm_check_extension(s, KVM_CAP_PIT_STATE2);
+#endif
+
     ret = kvm_arch_init(s);
     if (ret < 0) {
         goto err;
@@ -1390,6 +1395,11 @@ int kvm_has_xcrs(void)
     return kvm_state->xcrs;
 }
 
+int kvm_has_pit_state2(void)
+{
+    return kvm_state->pit_state2;
+}
+
 int kvm_has_many_ioeventfds(void)
 {
     if (!kvm_enabled()) {
diff --git a/kvm-stub.c b/kvm-stub.c
index f63a0d2..1f1c686 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -78,6 +78,11 @@ int kvm_allows_irq0_override(void)
     return 1;
 }
 
+int kvm_has_pit_state2(void)
+{
+    return 0;
+}
+
 void kvm_setup_guest_memory(void *start, size_t size)
 {
 }
diff --git a/kvm.h b/kvm.h
index f9f1dc8..8ef4476 100644
--- a/kvm.h
+++ b/kvm.h
@@ -54,6 +54,7 @@ int kvm_has_robust_singlestep(void);
 int kvm_has_debugregs(void);
 int kvm_has_xsave(void);
 int kvm_has_xcrs(void);
+int kvm_has_pit_state2(void);
 int kvm_has_many_ioeventfds(void);
 int kvm_has_gsi_routing(void);
 
commit 3fbc1c0c1309a6cc2a0699fbf5e286d32250a0be
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Mar 2 20:28:47 2012 +0100

    i8254: Open-code timer restore
    
    Same as for the APIC: To enable migration between accelerated and
    non-accelerated models, we need to arm the channel 0 timer only inside
    the emulated PIT model. The common code just saves/restores that timer
    to the the next_transition_time field.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/i8254.c b/hw/i8254.c
index 9fde344..77bd5e8 100644
--- a/hw/i8254.c
+++ b/hw/i8254.c
@@ -300,6 +300,17 @@ static const MemoryRegionOps pit_ioport_ops = {
     .old_portio = pit_portio
 };
 
+static void pit_post_load(PITCommonState *s)
+{
+    PITChannelState *sc = &s->channels[0];
+
+    if (sc->next_transition_time != -1) {
+        qemu_mod_timer(sc->irq_timer, sc->next_transition_time);
+    } else {
+        qemu_del_timer(sc->irq_timer);
+    }
+}
+
 static int pit_initfn(PITCommonState *pit)
 {
     PITChannelState *s;
@@ -329,6 +340,7 @@ static void pit_class_initfn(ObjectClass *klass, void *data)
     k->init = pit_initfn;
     k->set_channel_gate = pit_set_channel_gate;
     k->get_channel_info = pit_get_channel_info_common;
+    k->post_load = pit_post_load;
     dc->reset = pit_reset;
     dc->props = pit_properties;
 }
diff --git a/hw/i8254_common.c b/hw/i8254_common.c
index 6373e87..a03d7cd 100644
--- a/hw/i8254_common.c
+++ b/hw/i8254_common.c
@@ -211,6 +211,7 @@ static const VMStateDescription vmstate_pit_channel = {
 static int pit_load_old(QEMUFile *f, void *opaque, int version_id)
 {
     PITCommonState *pit = opaque;
+    PITCommonClass *c = PIT_COMMON_GET_CLASS(pit);
     PITChannelState *s;
     int i;
 
@@ -234,11 +235,13 @@ static int pit_load_old(QEMUFile *f, void *opaque, int version_id)
         qemu_get_8s(f, &s->gate);
         s->count_load_time = qemu_get_be64(f);
         s->irq_disabled = 0;
-        if (s->irq_timer) {
+        if (i == 0) {
             s->next_transition_time = qemu_get_be64(f);
-            qemu_get_timer(f, s->irq_timer);
         }
     }
+    if (c->post_load) {
+        c->post_load(pit);
+    }
     return 0;
 }
 
@@ -275,7 +278,8 @@ static const VMStateDescription vmstate_pit_common = {
         VMSTATE_UINT32_V(channels[0].irq_disabled, PITCommonState, 3),
         VMSTATE_STRUCT_ARRAY(channels, PITCommonState, 3, 2,
                              vmstate_pit_channel, PITChannelState),
-        VMSTATE_TIMER(channels[0].irq_timer, PITCommonState),
+        VMSTATE_INT64(channels[0].next_transition_time,
+                      PITCommonState), /* formerly irq_timer */
         VMSTATE_END_OF_LIST()
     }
 };
commit d11e859e4afe9b8b12f4478ab4ae3204d2d665ce
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Mar 2 20:28:46 2012 +0100

    i8254: Factor out base class for KVM reuse
    
    Applying the concept used for the *PICs once again: establish a base
    class for the i8254 that can be used both by the current user space
    emulation and the upcoming KVM in-kernel version. We share most of the
    public interface of the i8254, specifically to the pcspk, vmstate, reset
    and certain init parts.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index 808de6a..b39d76c 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -210,7 +210,7 @@ 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.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-uhci.o
diff --git a/hw/i8254.c b/hw/i8254.c
index f30396a..9fde344 100644
--- a/hw/i8254.c
+++ b/hw/i8254.c
@@ -26,6 +26,7 @@
 #include "isa.h"
 #include "qemu-timer.h"
 #include "i8254.h"
+#include "i8254_internal.h"
 
 //#define DEBUG_PIT
 
@@ -34,34 +35,6 @@
 #define RW_STATE_WORD0 3
 #define RW_STATE_WORD1 4
 
-typedef struct PITChannelState {
-    int count; /* can be 65536 */
-    uint16_t latched_count;
-    uint8_t count_latched;
-    uint8_t status_latched;
-    uint8_t status;
-    uint8_t read_state;
-    uint8_t write_state;
-    uint8_t write_latch;
-    uint8_t rw_mode;
-    uint8_t mode;
-    uint8_t bcd; /* not supported */
-    uint8_t gate; /* timer start */
-    int64_t count_load_time;
-    /* irq handling */
-    int64_t next_transition_time;
-    QEMUTimer *irq_timer;
-    qemu_irq irq;
-    uint32_t irq_disabled;
-} PITChannelState;
-
-typedef struct PITState {
-    ISADevice dev;
-    MemoryRegion ioports;
-    uint32_t iobase;
-    PITChannelState channels[3];
-} PITState;
-
 static void pit_irq_timer_update(PITChannelState *s, int64_t current_time);
 
 static int pit_get_count(PITChannelState *s)
@@ -89,99 +62,11 @@ static int pit_get_count(PITChannelState *s)
     return counter;
 }
 
-/* get pit output bit */
-static int pit_get_out(PITChannelState *s, int64_t current_time)
-{
-    uint64_t d;
-    int out;
-
-    d = muldiv64(current_time - s->count_load_time, PIT_FREQ,
-                 get_ticks_per_sec());
-    switch(s->mode) {
-    default:
-    case 0:
-        out = (d >= s->count);
-        break;
-    case 1:
-        out = (d < s->count);
-        break;
-    case 2:
-        if ((d % s->count) == 0 && d != 0)
-            out = 1;
-        else
-            out = 0;
-        break;
-    case 3:
-        out = (d % s->count) < ((s->count + 1) >> 1);
-        break;
-    case 4:
-    case 5:
-        out = (d == s->count);
-        break;
-    }
-    return out;
-}
-
-/* return -1 if no transition will occur.  */
-static int64_t pit_get_next_transition_time(PITChannelState *s,
-                                            int64_t current_time)
-{
-    uint64_t d, next_time, base;
-    int period2;
-
-    d = muldiv64(current_time - s->count_load_time, PIT_FREQ,
-                 get_ticks_per_sec());
-    switch(s->mode) {
-    default:
-    case 0:
-    case 1:
-        if (d < s->count)
-            next_time = s->count;
-        else
-            return -1;
-        break;
-    case 2:
-        base = (d / s->count) * s->count;
-        if ((d - base) == 0 && d != 0)
-            next_time = base + s->count;
-        else
-            next_time = base + s->count + 1;
-        break;
-    case 3:
-        base = (d / s->count) * s->count;
-        period2 = ((s->count + 1) >> 1);
-        if ((d - base) < period2)
-            next_time = base + period2;
-        else
-            next_time = base + s->count;
-        break;
-    case 4:
-    case 5:
-        if (d < s->count)
-            next_time = s->count;
-        else if (d == s->count)
-            next_time = s->count + 1;
-        else
-            return -1;
-        break;
-    }
-    /* convert to timer units */
-    next_time = s->count_load_time + muldiv64(next_time, get_ticks_per_sec(),
-                                              PIT_FREQ);
-    /* fix potential rounding problems */
-    /* XXX: better solution: use a clock at PIT_FREQ Hz */
-    if (next_time <= current_time)
-        next_time = current_time + 1;
-    return next_time;
-}
-
 /* val must be 0 or 1 */
-void pit_set_gate(ISADevice *dev, int channel, int val)
+static void pit_set_channel_gate(PITCommonState *s, PITChannelState *sc,
+                                 int val)
 {
-    PITState *pit = DO_UPCAST(PITState, dev, dev);
-    PITChannelState *s = &pit->channels[channel];
-
-    switch(s->mode) {
+    switch (sc->mode) {
     default:
     case 0:
     case 4:
@@ -189,34 +74,23 @@ void pit_set_gate(ISADevice *dev, int channel, int val)
         break;
     case 1:
     case 5:
-        if (s->gate < val) {
+        if (sc->gate < val) {
             /* restart counting on rising edge */
-            s->count_load_time = qemu_get_clock_ns(vm_clock);
-            pit_irq_timer_update(s, s->count_load_time);
+            sc->count_load_time = qemu_get_clock_ns(vm_clock);
+            pit_irq_timer_update(sc, sc->count_load_time);
         }
         break;
     case 2:
     case 3:
-        if (s->gate < val) {
+        if (sc->gate < val) {
             /* restart counting on rising edge */
-            s->count_load_time = qemu_get_clock_ns(vm_clock);
-            pit_irq_timer_update(s, s->count_load_time);
+            sc->count_load_time = qemu_get_clock_ns(vm_clock);
+            pit_irq_timer_update(sc, sc->count_load_time);
         }
         /* XXX: disable/enable counting */
         break;
     }
-    s->gate = val;
-}
-
-void pit_get_channel_info(ISADevice *dev, int channel, PITChannelInfo *info)
-{
-    PITState *pit = DO_UPCAST(PITState, dev, dev);
-    PITChannelState *s = &pit->channels[channel];
-
-    info->gate = s->gate;
-    info->mode = s->mode;
-    info->initial_count = s->count;
-    info->out = pit_get_out(s, qemu_get_clock_ns(vm_clock));
+    sc->gate = val;
 }
 
 static inline void pit_load_count(PITChannelState *s, int val)
@@ -239,7 +113,7 @@ static void pit_latch_count(PITChannelState *s)
 
 static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 {
-    PITState *pit = opaque;
+    PITCommonState *pit = opaque;
     int channel, access;
     PITChannelState *s;
 
@@ -306,7 +180,7 @@ static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 
 static uint32_t pit_ioport_read(void *opaque, uint32_t addr)
 {
-    PITState *pit = opaque;
+    PITCommonState *pit = opaque;
     int ret, count;
     PITChannelState *s;
 
@@ -387,94 +261,16 @@ static void pit_irq_timer(void *opaque)
     pit_irq_timer_update(s, s->next_transition_time);
 }
 
-static const VMStateDescription vmstate_pit_channel = {
-    .name = "pit channel",
-    .version_id = 2,
-    .minimum_version_id = 2,
-    .minimum_version_id_old = 2,
-    .fields      = (VMStateField []) {
-        VMSTATE_INT32(count, PITChannelState),
-        VMSTATE_UINT16(latched_count, PITChannelState),
-        VMSTATE_UINT8(count_latched, PITChannelState),
-        VMSTATE_UINT8(status_latched, PITChannelState),
-        VMSTATE_UINT8(status, PITChannelState),
-        VMSTATE_UINT8(read_state, PITChannelState),
-        VMSTATE_UINT8(write_state, PITChannelState),
-        VMSTATE_UINT8(write_latch, PITChannelState),
-        VMSTATE_UINT8(rw_mode, PITChannelState),
-        VMSTATE_UINT8(mode, PITChannelState),
-        VMSTATE_UINT8(bcd, PITChannelState),
-        VMSTATE_UINT8(gate, PITChannelState),
-        VMSTATE_INT64(count_load_time, PITChannelState),
-        VMSTATE_INT64(next_transition_time, PITChannelState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static int pit_load_old(QEMUFile *f, void *opaque, int version_id)
+static void pit_reset(DeviceState *dev)
 {
-    PITState *pit = opaque;
+    PITCommonState *pit = DO_UPCAST(PITCommonState, dev.qdev, dev);
     PITChannelState *s;
-    int i;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    for(i = 0; i < 3; i++) {
-        s = &pit->channels[i];
-        s->count=qemu_get_be32(f);
-        qemu_get_be16s(f, &s->latched_count);
-        qemu_get_8s(f, &s->count_latched);
-        qemu_get_8s(f, &s->status_latched);
-        qemu_get_8s(f, &s->status);
-        qemu_get_8s(f, &s->read_state);
-        qemu_get_8s(f, &s->write_state);
-        qemu_get_8s(f, &s->write_latch);
-        qemu_get_8s(f, &s->rw_mode);
-        qemu_get_8s(f, &s->mode);
-        qemu_get_8s(f, &s->bcd);
-        qemu_get_8s(f, &s->gate);
-        s->count_load_time=qemu_get_be64(f);
-        s->irq_disabled = 0;
-        if (s->irq_timer) {
-            s->next_transition_time=qemu_get_be64(f);
-            qemu_get_timer(f, s->irq_timer);
-        }
-    }
-    return 0;
-}
 
-static const VMStateDescription vmstate_pit = {
-    .name = "i8254",
-    .version_id = 3,
-    .minimum_version_id = 2,
-    .minimum_version_id_old = 1,
-    .load_state_old = pit_load_old,
-    .fields      = (VMStateField []) {
-        VMSTATE_UINT32_V(channels[0].irq_disabled, PITState, 3),
-        VMSTATE_STRUCT_ARRAY(channels, PITState, 3, 2, vmstate_pit_channel, PITChannelState),
-        VMSTATE_TIMER(channels[0].irq_timer, PITState),
-        VMSTATE_END_OF_LIST()
-    }
-};
+    pit_reset_common(pit);
 
-static void pit_reset(DeviceState *dev)
-{
-    PITState *pit = container_of(dev, PITState, dev.qdev);
-    PITChannelState *s;
-    int i;
-
-    for(i = 0;i < 3; i++) {
-        s = &pit->channels[i];
-        s->mode = 3;
-        s->gate = (i != 2);
-        s->count_load_time = qemu_get_clock_ns(vm_clock);
-        s->count = 0x10000;
-        if (i == 0 && !s->irq_disabled) {
-            s->next_transition_time =
-                pit_get_next_transition_time(s, s->count_load_time);
-            qemu_mod_timer(s->irq_timer, s->next_transition_time);
-        }
+    s = &pit->channels[0];
+    if (!s->irq_disabled) {
+        qemu_mod_timer(s->irq_timer, s->next_transition_time);
     }
 }
 
@@ -482,7 +278,7 @@ static void pit_reset(DeviceState *dev)
  * reenable it when legacy mode is left again. */
 static void pit_irq_control(void *opaque, int n, int enable)
 {
-    PITState *pit = opaque;
+    PITCommonState *pit = opaque;
     PITChannelState *s = &pit->channels[0];
 
     if (enable) {
@@ -504,46 +300,43 @@ static const MemoryRegionOps pit_ioport_ops = {
     .old_portio = pit_portio
 };
 
-static int pit_initfn(ISADevice *dev)
+static int pit_initfn(PITCommonState *pit)
 {
-    PITState *pit = DO_UPCAST(PITState, dev, dev);
     PITChannelState *s;
 
     s = &pit->channels[0];
     /* the timer 0 is connected to an IRQ */
     s->irq_timer = qemu_new_timer_ns(vm_clock, pit_irq_timer, s);
-    qdev_init_gpio_out(&dev->qdev, &s->irq, 1);
+    qdev_init_gpio_out(&pit->dev.qdev, &s->irq, 1);
 
     memory_region_init_io(&pit->ioports, &pit_ioport_ops, pit, "pit", 4);
-    isa_register_ioport(dev, &pit->ioports, pit->iobase);
-
-    qdev_init_gpio_in(&dev->qdev, pit_irq_control, 1);
 
-    qdev_set_legacy_instance_id(&dev->qdev, pit->iobase, 2);
+    qdev_init_gpio_in(&pit->dev.qdev, pit_irq_control, 1);
 
     return 0;
 }
 
 static Property pit_properties[] = {
-    DEFINE_PROP_HEX32("iobase", PITState, iobase,  -1),
+    DEFINE_PROP_HEX32("iobase", PITCommonState, iobase,  -1),
     DEFINE_PROP_END_OF_LIST(),
 };
 
 static void pit_class_initfn(ObjectClass *klass, void *data)
 {
+    PITCommonClass *k = PIT_COMMON_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
-    ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
-    ic->init = pit_initfn;
-    dc->no_user = 1;
+
+    k->init = pit_initfn;
+    k->set_channel_gate = pit_set_channel_gate;
+    k->get_channel_info = pit_get_channel_info_common;
     dc->reset = pit_reset;
-    dc->vmsd = &vmstate_pit;
     dc->props = pit_properties;
 }
 
 static TypeInfo pit_info = {
     .name          = "isa-pit",
-    .parent        = TYPE_ISA_DEVICE,
-    .instance_size = sizeof(PITState),
+    .parent        = TYPE_PIT_COMMON,
+    .instance_size = sizeof(PITCommonState),
     .class_init    = pit_class_initfn,
 };
 
diff --git a/hw/i8254_common.c b/hw/i8254_common.c
new file mode 100644
index 0000000..6373e87
--- /dev/null
+++ b/hw/i8254_common.c
@@ -0,0 +1,307 @@
+/*
+ * QEMU 8253/8254 - common bits of emulated and KVM kernel model
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2012      Jan Kiszka, Siemens AG
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw.h"
+#include "pc.h"
+#include "isa.h"
+#include "qemu-timer.h"
+#include "i8254.h"
+#include "i8254_internal.h"
+
+/* val must be 0 or 1 */
+void pit_set_gate(ISADevice *dev, int channel, int val)
+{
+    PITCommonState *pit = PIT_COMMON(dev);
+    PITChannelState *s = &pit->channels[channel];
+    PITCommonClass *c = PIT_COMMON_GET_CLASS(pit);
+
+    c->set_channel_gate(pit, s, val);
+}
+
+/* get pit output bit */
+int pit_get_out(PITChannelState *s, int64_t current_time)
+{
+    uint64_t d;
+    int out;
+
+    d = muldiv64(current_time - s->count_load_time, PIT_FREQ,
+                 get_ticks_per_sec());
+    switch (s->mode) {
+    default:
+    case 0:
+        out = (d >= s->count);
+        break;
+    case 1:
+        out = (d < s->count);
+        break;
+    case 2:
+        if ((d % s->count) == 0 && d != 0) {
+            out = 1;
+        } else {
+            out = 0;
+        }
+        break;
+    case 3:
+        out = (d % s->count) < ((s->count + 1) >> 1);
+        break;
+    case 4:
+    case 5:
+        out = (d == s->count);
+        break;
+    }
+    return out;
+}
+
+/* return -1 if no transition will occur.  */
+int64_t pit_get_next_transition_time(PITChannelState *s, int64_t current_time)
+{
+    uint64_t d, next_time, base;
+    int period2;
+
+    d = muldiv64(current_time - s->count_load_time, PIT_FREQ,
+                 get_ticks_per_sec());
+    switch (s->mode) {
+    default:
+    case 0:
+    case 1:
+        if (d < s->count) {
+            next_time = s->count;
+        } else {
+            return -1;
+        }
+        break;
+    case 2:
+        base = (d / s->count) * s->count;
+        if ((d - base) == 0 && d != 0) {
+            next_time = base + s->count;
+        } else {
+            next_time = base + s->count + 1;
+        }
+        break;
+    case 3:
+        base = (d / s->count) * s->count;
+        period2 = ((s->count + 1) >> 1);
+        if ((d - base) < period2) {
+            next_time = base + period2;
+        } else {
+            next_time = base + s->count;
+        }
+        break;
+    case 4:
+    case 5:
+        if (d < s->count) {
+            next_time = s->count;
+        } else if (d == s->count) {
+            next_time = s->count + 1;
+        } else {
+            return -1;
+        }
+        break;
+    }
+    /* convert to timer units */
+    next_time = s->count_load_time + muldiv64(next_time, get_ticks_per_sec(),
+                                              PIT_FREQ);
+    /* fix potential rounding problems */
+    /* XXX: better solution: use a clock at PIT_FREQ Hz */
+    if (next_time <= current_time) {
+        next_time = current_time + 1;
+    }
+    return next_time;
+}
+
+void pit_get_channel_info_common(PITCommonState *s, PITChannelState *sc,
+                                 PITChannelInfo *info)
+{
+    info->gate = sc->gate;
+    info->mode = sc->mode;
+    info->initial_count = sc->count;
+    info->out = pit_get_out(sc, qemu_get_clock_ns(vm_clock));
+}
+
+void pit_get_channel_info(ISADevice *dev, int channel, PITChannelInfo *info)
+{
+    PITCommonState *pit = PIT_COMMON(dev);
+    PITChannelState *s = &pit->channels[channel];
+    PITCommonClass *c = PIT_COMMON_GET_CLASS(pit);
+
+    c->get_channel_info(pit, s, info);
+}
+
+void pit_reset_common(PITCommonState *pit)
+{
+    PITChannelState *s;
+    int i;
+
+    for (i = 0; i < 3; i++) {
+        s = &pit->channels[i];
+        s->mode = 3;
+        s->gate = (i != 2);
+        s->count_load_time = qemu_get_clock_ns(vm_clock);
+        s->count = 0x10000;
+        if (i == 0 && !s->irq_disabled) {
+            s->next_transition_time =
+                pit_get_next_transition_time(s, s->count_load_time);
+        }
+    }
+}
+
+static int pit_init_common(ISADevice *dev)
+{
+    PITCommonState *pit = PIT_COMMON(dev);
+    PITCommonClass *c = PIT_COMMON_GET_CLASS(pit);
+    int ret;
+
+    ret = c->init(pit);
+    if (ret < 0) {
+        return ret;
+    }
+
+    isa_register_ioport(dev, &pit->ioports, pit->iobase);
+
+    qdev_set_legacy_instance_id(&dev->qdev, pit->iobase, 2);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_pit_channel = {
+    .name = "pit channel",
+    .version_id = 2,
+    .minimum_version_id = 2,
+    .minimum_version_id_old = 2,
+    .fields = (VMStateField[]) {
+        VMSTATE_INT32(count, PITChannelState),
+        VMSTATE_UINT16(latched_count, PITChannelState),
+        VMSTATE_UINT8(count_latched, PITChannelState),
+        VMSTATE_UINT8(status_latched, PITChannelState),
+        VMSTATE_UINT8(status, PITChannelState),
+        VMSTATE_UINT8(read_state, PITChannelState),
+        VMSTATE_UINT8(write_state, PITChannelState),
+        VMSTATE_UINT8(write_latch, PITChannelState),
+        VMSTATE_UINT8(rw_mode, PITChannelState),
+        VMSTATE_UINT8(mode, PITChannelState),
+        VMSTATE_UINT8(bcd, PITChannelState),
+        VMSTATE_UINT8(gate, PITChannelState),
+        VMSTATE_INT64(count_load_time, PITChannelState),
+        VMSTATE_INT64(next_transition_time, PITChannelState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static int pit_load_old(QEMUFile *f, void *opaque, int version_id)
+{
+    PITCommonState *pit = opaque;
+    PITChannelState *s;
+    int i;
+
+    if (version_id != 1) {
+        return -EINVAL;
+    }
+
+    for (i = 0; i < 3; i++) {
+        s = &pit->channels[i];
+        s->count = qemu_get_be32(f);
+        qemu_get_be16s(f, &s->latched_count);
+        qemu_get_8s(f, &s->count_latched);
+        qemu_get_8s(f, &s->status_latched);
+        qemu_get_8s(f, &s->status);
+        qemu_get_8s(f, &s->read_state);
+        qemu_get_8s(f, &s->write_state);
+        qemu_get_8s(f, &s->write_latch);
+        qemu_get_8s(f, &s->rw_mode);
+        qemu_get_8s(f, &s->mode);
+        qemu_get_8s(f, &s->bcd);
+        qemu_get_8s(f, &s->gate);
+        s->count_load_time = qemu_get_be64(f);
+        s->irq_disabled = 0;
+        if (s->irq_timer) {
+            s->next_transition_time = qemu_get_be64(f);
+            qemu_get_timer(f, s->irq_timer);
+        }
+    }
+    return 0;
+}
+
+static void pit_dispatch_pre_save(void *opaque)
+{
+    PITCommonState *s = opaque;
+    PITCommonClass *c = PIT_COMMON_GET_CLASS(s);
+
+    if (c->pre_save) {
+        c->pre_save(s);
+    }
+}
+
+static int pit_dispatch_post_load(void *opaque, int version_id)
+{
+    PITCommonState *s = opaque;
+    PITCommonClass *c = PIT_COMMON_GET_CLASS(s);
+
+    if (c->post_load) {
+        c->post_load(s);
+    }
+    return 0;
+}
+
+static const VMStateDescription vmstate_pit_common = {
+    .name = "i8254",
+    .version_id = 3,
+    .minimum_version_id = 2,
+    .minimum_version_id_old = 1,
+    .load_state_old = pit_load_old,
+    .pre_save = pit_dispatch_pre_save,
+    .post_load = pit_dispatch_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_V(channels[0].irq_disabled, PITCommonState, 3),
+        VMSTATE_STRUCT_ARRAY(channels, PITCommonState, 3, 2,
+                             vmstate_pit_channel, PITChannelState),
+        VMSTATE_TIMER(channels[0].irq_timer, PITCommonState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void pit_common_class_init(ObjectClass *klass, void *data)
+{
+    ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    ic->init = pit_init_common;
+    dc->vmsd = &vmstate_pit_common;
+    dc->no_user = 1;
+}
+
+static TypeInfo pit_common_type = {
+    .name          = TYPE_PIT_COMMON,
+    .parent        = TYPE_ISA_DEVICE,
+    .instance_size = sizeof(PITCommonState),
+    .class_size    = sizeof(PITCommonClass),
+    .class_init    = pit_common_class_init,
+    .abstract      = true,
+};
+
+static void register_devices(void)
+{
+    type_register_static(&pit_common_type);
+}
+
+type_init(register_devices);
diff --git a/hw/i8254_internal.h b/hw/i8254_internal.h
new file mode 100644
index 0000000..686f0c2
--- /dev/null
+++ b/hw/i8254_internal.h
@@ -0,0 +1,85 @@
+/*
+ * QEMU 8253/8254 - internal interfaces
+ *
+ * Copyright (c) 2011 Jan Kiszka, Siemens AG
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef QEMU_I8254_INTERNAL_H
+#define QEMU_I8254_INTERNAL_H
+
+#include "hw.h"
+#include "pc.h"
+#include "isa.h"
+
+typedef struct PITChannelState {
+    int count; /* can be 65536 */
+    uint16_t latched_count;
+    uint8_t count_latched;
+    uint8_t status_latched;
+    uint8_t status;
+    uint8_t read_state;
+    uint8_t write_state;
+    uint8_t write_latch;
+    uint8_t rw_mode;
+    uint8_t mode;
+    uint8_t bcd; /* not supported */
+    uint8_t gate; /* timer start */
+    int64_t count_load_time;
+    /* irq handling */
+    int64_t next_transition_time;
+    QEMUTimer *irq_timer;
+    qemu_irq irq;
+    uint32_t irq_disabled;
+} PITChannelState;
+
+typedef struct PITCommonState {
+    ISADevice dev;
+    MemoryRegion ioports;
+    uint32_t iobase;
+    PITChannelState channels[3];
+} PITCommonState;
+
+#define TYPE_PIT_COMMON "pit-common"
+#define PIT_COMMON(obj) \
+     OBJECT_CHECK(PITCommonState, (obj), TYPE_PIT_COMMON)
+#define PIT_COMMON_CLASS(klass) \
+     OBJECT_CLASS_CHECK(PITCommonClass, (klass), TYPE_PIT_COMMON)
+#define PIT_COMMON_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(PITCommonClass, (obj), TYPE_PIT_COMMON)
+
+typedef struct PITCommonClass {
+    ISADeviceClass parent_class;
+
+    int (*init)(PITCommonState *s);
+    void (*set_channel_gate)(PITCommonState *s, PITChannelState *sc, int val);
+    void (*get_channel_info)(PITCommonState *s, PITChannelState *sc,
+                             PITChannelInfo *info);
+    void (*pre_save)(PITCommonState *s);
+    void (*post_load)(PITCommonState *s);
+} PITCommonClass;
+
+int pit_get_out(PITChannelState *s, int64_t current_time);
+int64_t pit_get_next_transition_time(PITChannelState *s, int64_t current_time);
+void pit_get_channel_info_common(PITCommonState *s, PITChannelState *sc,
+                                 PITChannelInfo *info);
+void pit_reset_common(PITCommonState *s);
+
+#endif /* !QEMU_I8254_INTERNAL_H */
commit e32605062cd62c2a958ad28a6ad7de4eeab12027
Author: Peter A. G. Crosthwaite <peter.crosthwaite at petalogix.com>
Date:   Mon Mar 5 14:39:13 2012 +1000

    xilinx_zynq: machine model initial version
    
    Xilinx zynq-7000 machine model. Also includes device model for the zynq-specific
    system level control register (SLCR) module.
    
    Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite at petalogix.com>
    Acked-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/MAINTAINERS b/MAINTAINERS
index 0b3b3d8..d249947 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -251,6 +251,13 @@ M: Peter Maydell <peter.maydell at linaro.org>
 S: Maintained
 F: hw/versatilepb.c
 
+Xilinx Zynq
+M: Peter Crosthwaite <peter.crosthwaite at petalogix.com>
+S: Maintained
+F: hw/xilinx_zynq.c
+F: hw/zynq_slcr.c
+F: hw/cadence_*
+
 CRIS Machines
 -------------
 Axis Dev88
diff --git a/Makefile.target b/Makefile.target
index 4dd415c..5f3fc40 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -349,6 +349,7 @@ obj-arm-y += versatile_pci.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 += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
 obj-arm-y += exynos4210_gic.o exynos4210_combiner.o exynos4210.o
 obj-arm-y += exynos4_boards.o exynos4210_uart.o exynos4210_pwm.o
diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c
new file mode 100644
index 0000000..ea13e8c
--- /dev/null
+++ b/hw/xilinx_zynq.c
@@ -0,0 +1,157 @@
+/*
+ * Xilinx Zynq Baseboard System emulation.
+ *
+ * Copyright (c) 2010 Xilinx.
+ * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.croshtwaite at petalogix.com)
+ * Copyright (c) 2012 Petalogix Pty Ltd.
+ * Written by Haibing Ma
+ *
+ * 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.
+ *
+ * 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 "sysbus.h"
+#include "arm-misc.h"
+#include "net.h"
+#include "exec-memory.h"
+#include "sysemu.h"
+#include "boards.h"
+#include "flash.h"
+#include "blockdev.h"
+#include "loader.h"
+
+#define FLASH_SIZE (64 * 1024 * 1024)
+#define FLASH_SECTOR_SIZE (128 * 1024)
+
+#define IRQ_OFFSET 32 /* pic interrupts start from index 32 */
+
+static struct arm_boot_info zynq_binfo = {};
+
+static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    qemu_check_nic_model(nd, "cadence_gem");
+    dev = qdev_create(NULL, "cadence_gem");
+    qdev_set_nic_properties(dev, nd);
+    qdev_init_nofail(dev);
+    s = sysbus_from_qdev(dev);
+    sysbus_mmio_map(s, 0, base);
+    sysbus_connect_irq(s, 0, irq);
+}
+
+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)
+{
+    CPUState *env = NULL;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ext_ram = g_new(MemoryRegion, 1);
+    MemoryRegion *ocm_ram = g_new(MemoryRegion, 1);
+    DeviceState *dev;
+    SysBusDevice *busdev;
+    qemu_irq *irqp;
+    qemu_irq pic[64];
+    NICInfo *nd;
+    int n;
+    qemu_irq cpu_irq;
+
+    if (!cpu_model) {
+        cpu_model = "cortex-a9";
+    }
+
+    env = cpu_init(cpu_model);
+    if (!env) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    irqp = arm_pic_init_cpu(env);
+    cpu_irq = irqp[ARM_PIC_CPU_IRQ];
+
+    /* max 2GB ram */
+    if (ram_size > 0x80000000) {
+        ram_size = 0x80000000;
+    }
+
+    /* DDR remapped to address zero.  */
+    memory_region_init_ram(ext_ram, "zynq.ext_ram", ram_size);
+    vmstate_register_ram_global(ext_ram);
+    memory_region_add_subregion(address_space_mem, 0, ext_ram);
+
+    /* 256K of on-chip memory */
+    memory_region_init_ram(ocm_ram, "zynq.ocm_ram", 256 << 10);
+    vmstate_register_ram_global(ocm_ram);
+    memory_region_add_subregion(address_space_mem, 0xFFFC0000, ocm_ram);
+
+    DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0);
+
+    /* AMD */
+    pflash_cfi02_register(0xe2000000, NULL, "zynq.pflash", FLASH_SIZE,
+                          dinfo ? dinfo->bdrv : NULL, FLASH_SECTOR_SIZE,
+                          FLASH_SIZE/FLASH_SECTOR_SIZE, 1,
+                          1, 0x0066, 0x0022, 0x0000, 0x0000, 0x0555, 0x2aa,
+                              0);
+
+    dev = qdev_create(NULL, "xilinx,zynq_slcr");
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xF8000000);
+
+    dev = qdev_create(NULL, "a9mpcore_priv");
+    qdev_prop_set_uint32(dev, "num-cpu", 1);
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xF8F00000);
+    sysbus_connect_irq(busdev, 0, cpu_irq);
+
+    for (n = 0; n < 64; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    sysbus_create_simple("cadence_uart", 0xE0000000, pic[59-IRQ_OFFSET]);
+    sysbus_create_simple("cadence_uart", 0xE0001000, pic[82-IRQ_OFFSET]);
+
+    sysbus_create_varargs("cadence_ttc", 0xF8001000,
+            pic[42-IRQ_OFFSET], pic[43-IRQ_OFFSET], pic[44-IRQ_OFFSET], NULL);
+    sysbus_create_varargs("cadence_ttc", 0xF8002000,
+            pic[69-IRQ_OFFSET], pic[70-IRQ_OFFSET], pic[71-IRQ_OFFSET], NULL);
+
+    for (n = 0; n < nb_nics; n++) {
+        nd = &nd_table[n];
+        if (n == 0) {
+            gem_init(nd, 0xE000B000, pic[54-IRQ_OFFSET]);
+        } else if (n == 1) {
+            gem_init(nd, 0xE000C000, pic[77-IRQ_OFFSET]);
+        }
+    }
+
+    zynq_binfo.ram_size = ram_size;
+    zynq_binfo.kernel_filename = kernel_filename;
+    zynq_binfo.kernel_cmdline = kernel_cmdline;
+    zynq_binfo.initrd_filename = initrd_filename;
+    zynq_binfo.nb_cpus = 1;
+    zynq_binfo.board_id = 0xd32;
+    zynq_binfo.loader_start = 0;
+    arm_load_kernel(first_cpu, &zynq_binfo);
+}
+
+static QEMUMachine zynq_machine = {
+    .name = "xilinx-zynq-a9",
+    .desc = "Xilinx Zynq Platform Baseboard for Cortex-A9",
+    .init = zynq_init,
+    .use_scsi = 1,
+    .max_cpus = 1,
+    .no_sdcard = 1
+};
+
+static void zynq_machine_init(void)
+{
+    qemu_register_machine(&zynq_machine);
+}
+
+machine_init(zynq_machine_init);
diff --git a/hw/zynq_slcr.c b/hw/zynq_slcr.c
new file mode 100644
index 0000000..b785f04
--- /dev/null
+++ b/hw/zynq_slcr.c
@@ -0,0 +1,535 @@
+/*
+ * Status and system control registers for Xilinx Zynq Platform
+ *
+ * Copyright (c) 2011 Michal Simek <monstr at monstr.eu>
+ * Copyright (c) 2012 PetaLogix Pty Ltd.
+ * Based on hw/arm_sysctl.c, 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw.h"
+#include "qemu-timer.h"
+#include "sysbus.h"
+#include "sysemu.h"
+
+#ifdef ZYNQ_ARM_SLCR_ERR_DEBUG
+#define DB_PRINT(...) do { \
+    fprintf(stderr,  ": %s: ", __func__); \
+    fprintf(stderr, ## __VA_ARGS__); \
+    } while (0);
+#else
+    #define DB_PRINT(...)
+#endif
+
+#define XILINX_LOCK_KEY 0x767b
+#define XILINX_UNLOCK_KEY 0xdf0d
+
+typedef enum {
+  ARM_PLL_CTRL,
+  DDR_PLL_CTRL,
+  IO_PLL_CTRL,
+  PLL_STATUS,
+  ARM_PPL_CFG,
+  DDR_PLL_CFG,
+  IO_PLL_CFG,
+  PLL_BG_CTRL,
+  PLL_MAX
+} PLLValues;
+
+typedef enum {
+  ARM_CLK_CTRL,
+  DDR_CLK_CTRL,
+  DCI_CLK_CTRL,
+  APER_CLK_CTRL,
+  USB0_CLK_CTRL,
+  USB1_CLK_CTRL,
+  GEM0_RCLK_CTRL,
+  GEM1_RCLK_CTRL,
+  GEM0_CLK_CTRL,
+  GEM1_CLK_CTRL,
+  SMC_CLK_CTRL,
+  LQSPI_CLK_CTRL,
+  SDIO_CLK_CTRL,
+  UART_CLK_CTRL,
+  SPI_CLK_CTRL,
+  CAN_CLK_CTRL,
+  CAN_MIOCLK_CTRL,
+  DBG_CLK_CTRL,
+  PCAP_CLK_CTRL,
+  TOPSW_CLK_CTRL,
+  CLK_MAX
+} ClkValues;
+
+typedef enum {
+  CLK_CTRL,
+  THR_CTRL,
+  THR_CNT,
+  THR_STA,
+  FPGA_MAX
+} FPGAValues;
+
+typedef enum {
+  SYNC_CTRL,
+  SYNC_STATUS,
+  BANDGAP_TRIP,
+  CC_TEST,
+  PLL_PREDIVISOR,
+  CLK_621_TRUE,
+  PICTURE_DBG,
+  PICTURE_DBG_UCNT,
+  PICTURE_DBG_LCNT,
+  MISC_MAX
+} MiscValues;
+
+typedef enum {
+  PSS,
+  DDDR,
+  DMAC,
+  USB,
+  GEM,
+  SDIO,
+  SPI,
+  CAN,
+  I2C,
+  UART,
+  GPIO,
+  LQSPI,
+  SMC,
+  OCM,
+  DEVCI,
+  FPGA,
+  A9_CPU,
+  RS_AWDT,
+  RST_REASON,
+  RST_REASON_CLR,
+  REBOOT_STATUS,
+  BOOT_MODE,
+  RESET_MAX
+} ResetValues;
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+
+    union {
+        struct {
+            uint16_t scl;
+            uint16_t lockval;
+            uint32_t pll[PLL_MAX]; /* 0x100 - 0x11C */
+            uint32_t clk[CLK_MAX]; /* 0x120 - 0x16C */
+            uint32_t fpga[4][FPGA_MAX]; /* 0x170 - 0x1AC */
+            uint32_t misc[MISC_MAX]; /* 0x1B0 - 0x1D8 */
+            uint32_t reset[RESET_MAX]; /* 0x200 - 0x25C */
+            uint32_t apu_ctrl; /* 0x300 */
+            uint32_t wdt_clk_sel; /* 0x304 */
+            uint32_t tz_ocm[3]; /* 0x400 - 0x408 */
+            uint32_t tz_ddr; /* 0x430 */
+            uint32_t tz_dma[3]; /* 0x440 - 0x448 */
+            uint32_t tz_misc[3]; /* 0x450 - 0x458 */
+            uint32_t tz_fpga[2]; /* 0x484 - 0x488 */
+            uint32_t dbg_ctrl; /* 0x500 */
+            uint32_t pss_idcode; /* 0x530 */
+            uint32_t ddr[8]; /* 0x600 - 0x620 - 0x604-missing */
+            uint32_t mio[54]; /* 0x700 - 0x7D4 */
+            uint32_t mio_func[4]; /* 0x800 - 0x810 */
+            uint32_t sd[2]; /* 0x830 - 0x834 */
+            uint32_t lvl_shftr_en; /* 0x900 */
+            uint32_t ocm_cfg; /* 0x910 */
+            uint32_t cpu_ram[8]; /* 0xA00 - 0xA1C */
+            uint32_t iou[7]; /* 0xA30 - 0xA48 */
+            uint32_t dmac_ram; /* 0xA50 */
+            uint32_t afi[4][3]; /* 0xA60 - 0xA8C */
+            uint32_t ocm[3]; /* 0xA90 - 0xA98 */
+            uint32_t devci_ram; /* 0xAA0 */
+            uint32_t csg_ram; /* 0xAB0 */
+            uint32_t gpiob[12]; /* 0xB00 - 0xB2C */
+            uint32_t ddriob[14]; /* 0xB40 - 0xB74 */
+        };
+        uint8_t data[0x1000];
+    };
+} ZynqSLCRState;
+
+static void zynq_slcr_reset(DeviceState *d)
+{
+    int i;
+    ZynqSLCRState *s =
+            FROM_SYSBUS(ZynqSLCRState, sysbus_from_qdev(d));
+
+    DB_PRINT("RESET\n");
+
+    s->lockval = 1;
+    /* 0x100 - 0x11C */
+    s->pll[ARM_PLL_CTRL] = 0x0001A008;
+    s->pll[DDR_PLL_CTRL] = 0x0001A008;
+    s->pll[IO_PLL_CTRL] = 0x0001A008;
+    s->pll[PLL_STATUS] = 0x0000003F;
+    s->pll[ARM_PPL_CFG] = 0x00014000;
+    s->pll[DDR_PLL_CFG] = 0x00014000;
+    s->pll[IO_PLL_CFG] = 0x00014000;
+
+    /* 0x120 - 0x16C */
+    s->clk[ARM_CLK_CTRL] = 0x1F000400;
+    s->clk[DDR_CLK_CTRL] = 0x18400003;
+    s->clk[DCI_CLK_CTRL] = 0x01E03201;
+    s->clk[APER_CLK_CTRL] = 0x01FFCCCD;
+    s->clk[USB0_CLK_CTRL] = s->clk[USB1_CLK_CTRL] = 0x00101941;
+    s->clk[GEM0_RCLK_CTRL] = s->clk[GEM1_RCLK_CTRL] = 0x00000001;
+    s->clk[GEM0_CLK_CTRL] = s->clk[GEM1_CLK_CTRL] = 0x00003C01;
+    s->clk[SMC_CLK_CTRL] = 0x00003C01;
+    s->clk[LQSPI_CLK_CTRL] = 0x00002821;
+    s->clk[SDIO_CLK_CTRL] = 0x00001E03;
+    s->clk[UART_CLK_CTRL] = 0x00003F03;
+    s->clk[SPI_CLK_CTRL] = 0x00003F03;
+    s->clk[CAN_CLK_CTRL] = 0x00501903;
+    s->clk[DBG_CLK_CTRL] = 0x00000F03;
+    s->clk[PCAP_CLK_CTRL] = 0x00000F01;
+
+    /* 0x170 - 0x1AC */
+    s->fpga[0][CLK_CTRL] = s->fpga[1][CLK_CTRL] = s->fpga[2][CLK_CTRL] =
+            s->fpga[3][CLK_CTRL] = 0x00101800;
+    s->fpga[0][THR_STA] = s->fpga[1][THR_STA] = s->fpga[2][THR_STA] =
+            s->fpga[3][THR_STA] = 0x00010000;
+
+    /* 0x1B0 - 0x1D8 */
+    s->misc[BANDGAP_TRIP] = 0x0000001F;
+    s->misc[PLL_PREDIVISOR] = 0x00000001;
+    s->misc[CLK_621_TRUE] = 0x00000001;
+
+    /* 0x200 - 0x25C */
+    s->reset[FPGA] = 0x01F33F0F;
+    s->reset[RST_REASON] = 0x00000040;
+
+    /* 0x700 - 0x7D4 */
+    for (i = 0; i < 54; i++) {
+        s->mio[i] = 0x00001601;
+    }
+    for (i = 2; i <= 8; i++) {
+        s->mio[i] = 0x00000601;
+    }
+
+    /* MIO_MST_TRI0, MIO_MST_TRI1 */
+    s->mio_func[2] = s->mio_func[3] = 0xFFFFFFFF;
+
+    s->cpu_ram[0] = s->cpu_ram[1] = s->cpu_ram[3] =
+            s->cpu_ram[4] = s->cpu_ram[7] = 0x00010101;
+    s->cpu_ram[2] = s->cpu_ram[5] = 0x01010101;
+    s->cpu_ram[6] = 0x00000001;
+
+    s->iou[0] = s->iou[1] = s->iou[2] = s->iou[3] = 0x09090909;
+    s->iou[4] = s->iou[5] = 0x00090909;
+    s->iou[6] = 0x00000909;
+
+    s->dmac_ram = 0x00000009;
+
+    s->afi[0][0] = s->afi[0][1] = 0x09090909;
+    s->afi[1][0] = s->afi[1][1] = 0x09090909;
+    s->afi[2][0] = s->afi[2][1] = 0x09090909;
+    s->afi[3][0] = s->afi[3][1] = 0x09090909;
+    s->afi[0][2] = s->afi[1][2] = s->afi[2][2] = s->afi[3][2] = 0x00000909;
+
+    s->ocm[0] = 0x01010101;
+    s->ocm[1] = s->ocm[2] = 0x09090909;
+
+    s->devci_ram = 0x00000909;
+    s->csg_ram = 0x00000001;
+
+    s->ddriob[0] = s->ddriob[1] = s->ddriob[2] = s->ddriob[3] = 0x00000e00;
+    s->ddriob[4] = s->ddriob[5] = s->ddriob[6] = 0x00000e00;
+    s->ddriob[12] = 0x00000021;
+}
+
+static inline uint32_t zynq_slcr_read_imp(void *opaque,
+    target_phys_addr_t offset)
+{
+    ZynqSLCRState *s = (ZynqSLCRState *)opaque;
+
+    switch (offset) {
+    case 0x0: /* SCL */
+        return s->scl;
+    case 0x4: /* LOCK */
+    case 0x8: /* UNLOCK */
+        DB_PRINT("Reading SCLR_LOCK/UNLOCK is not enabled\n");
+        return 0;
+    case 0x0C: /* LOCKSTA */
+        return s->lockval;
+    case 0x100 ... 0x11C:
+        return s->pll[(offset - 0x100) / 4];
+    case 0x120 ... 0x16C:
+        return s->clk[(offset - 0x120) / 4];
+    case 0x170 ... 0x1AC:
+        return s->fpga[0][(offset - 0x170) / 4];
+    case 0x1B0 ... 0x1D8:
+        return s->misc[(offset - 0x1B0) / 4];
+    case 0x200 ... 0x258:
+        return s->reset[(offset - 0x200) / 4];
+    case 0x25c:
+        return 1;
+    case 0x300:
+        return s->apu_ctrl;
+    case 0x304:
+        return s->wdt_clk_sel;
+    case 0x400 ... 0x408:
+        return s->tz_ocm[(offset - 0x400) / 4];
+    case 0x430:
+        return s->tz_ddr;
+    case 0x440 ... 0x448:
+        return s->tz_dma[(offset - 0x440) / 4];
+    case 0x450 ... 0x458:
+        return s->tz_misc[(offset - 0x450) / 4];
+    case 0x484 ... 0x488:
+        return s->tz_fpga[(offset - 0x484) / 4];
+    case 0x500:
+        return s->dbg_ctrl;
+    case 0x530:
+        return s->pss_idcode;
+    case 0x600 ... 0x620:
+        if (offset == 0x604) {
+            goto bad_reg;
+        }
+        return s->ddr[(offset - 0x600) / 4];
+    case 0x700 ... 0x7D4:
+        return s->mio[(offset - 0x700) / 4];
+    case 0x800 ... 0x810:
+        return s->mio_func[(offset - 0x800) / 4];
+    case 0x830 ... 0x834:
+        return s->sd[(offset - 0x830) / 4];
+    case 0x900:
+        return s->lvl_shftr_en;
+    case 0x910:
+        return s->ocm_cfg;
+    case 0xA00 ... 0xA1C:
+        return s->cpu_ram[(offset - 0xA00) / 4];
+    case 0xA30 ... 0xA48:
+        return s->iou[(offset - 0xA30) / 4];
+    case 0xA50:
+        return s->dmac_ram;
+    case 0xA60 ... 0xA8C:
+        return s->afi[0][(offset - 0x700) / 4];
+    case 0xA90 ... 0xA98:
+        return s->ocm[(offset - 0xA90) / 4];
+    case 0xAA0:
+        return s->devci_ram;
+    case 0xAB0:
+        return s->csg_ram;
+    case 0xB00 ... 0xB2C:
+        return s->gpiob[(offset - 0xB00) / 4];
+    case 0xB40 ... 0xB74:
+        return s->ddriob[(offset - 0xB40) / 4];
+    default:
+    bad_reg:
+        DB_PRINT("Bad register offset 0x%x\n", (int)offset);
+        return 0;
+    }
+}
+
+static uint64_t zynq_slcr_read(void *opaque, target_phys_addr_t offset,
+    unsigned size)
+{
+    uint32_t ret = zynq_slcr_read_imp(opaque, offset);
+
+    DB_PRINT("addr: %08x data: %08x\n", offset, ret);
+    return ret;
+}
+
+static void zynq_slcr_write(void *opaque, target_phys_addr_t offset,
+                          uint64_t val, unsigned size)
+{
+    ZynqSLCRState *s = (ZynqSLCRState *)opaque;
+
+    DB_PRINT("offset: %08x data: %08x\n", offset, (unsigned)val);
+
+    switch (offset) {
+    case 0x00: /* SCL */
+        s->scl = val & 0x1;
+    return;
+    case 0x4: /* SLCR_LOCK */
+        if ((val & 0xFFFF) == XILINX_LOCK_KEY) {
+            DB_PRINT("XILINX LOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset,
+                (unsigned)val & 0xFFFF);
+            s->lockval = 1;
+        } else {
+            DB_PRINT("WRONG XILINX LOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
+                (int)offset, (unsigned)val & 0xFFFF);
+        }
+        return;
+    case 0x8: /* SLCR_UNLOCK */
+        if ((val & 0xFFFF) == XILINX_UNLOCK_KEY) {
+            DB_PRINT("XILINX UNLOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset,
+                (unsigned)val & 0xFFFF);
+            s->lockval = 0;
+        } else {
+            DB_PRINT("WRONG XILINX UNLOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
+                (int)offset, (unsigned)val & 0xFFFF);
+        }
+        return;
+    case 0xc: /* LOCKSTA */
+        DB_PRINT("Writing SCLR_LOCKSTA is not enabled\n");
+        return;
+    }
+
+    if (!s->lockval) {
+        switch (offset) {
+        case 0x100 ... 0x11C:
+            if (offset == 0x10C) {
+                goto bad_reg;
+            }
+            s->pll[(offset - 0x100) / 4] = val;
+            break;
+        case 0x120 ... 0x16C:
+            s->clk[(offset - 0x120) / 4] = val;
+            break;
+        case 0x170 ... 0x1AC:
+            s->fpga[0][(offset - 0x170) / 4] = val;
+            break;
+        case 0x1B0 ... 0x1D8:
+            s->misc[(offset - 0x1B0) / 4] = val;
+            break;
+        case 0x200 ... 0x25C:
+            if (offset == 0x250) {
+                goto bad_reg;
+            }
+            s->reset[(offset - 0x200) / 4] = val;
+            break;
+        case 0x300:
+            s->apu_ctrl = val;
+            break;
+        case 0x304:
+            s->wdt_clk_sel = val;
+            break;
+        case 0x400 ... 0x408:
+            s->tz_ocm[(offset - 0x400) / 4] = val;
+            break;
+        case 0x430:
+            s->tz_ddr = val;
+            break;
+        case 0x440 ... 0x448:
+            s->tz_dma[(offset - 0x440) / 4] = val;
+            break;
+        case 0x450 ... 0x458:
+            s->tz_misc[(offset - 0x450) / 4] = val;
+            break;
+        case 0x484 ... 0x488:
+            s->tz_fpga[(offset - 0x484) / 4] = val;
+            break;
+        case 0x500:
+            s->dbg_ctrl = val;
+            break;
+        case 0x530:
+            s->pss_idcode = val;
+            break;
+        case 0x600 ... 0x620:
+            if (offset == 0x604) {
+                goto bad_reg;
+            }
+            s->ddr[(offset - 0x600) / 4] = val;
+            break;
+        case 0x700 ... 0x7D4:
+            s->mio[(offset - 0x700) / 4] = val;
+            break;
+        case 0x800 ... 0x810:
+            s->mio_func[(offset - 0x800) / 4] = val;
+            break;
+        case 0x830 ... 0x834:
+            s->sd[(offset - 0x830) / 4] = val;
+            break;
+        case 0x900:
+            s->lvl_shftr_en = val;
+            break;
+        case 0x910:
+            break;
+        case 0xA00 ... 0xA1C:
+            s->cpu_ram[(offset - 0xA00) / 4] = val;
+            break;
+        case 0xA30 ... 0xA48:
+            s->iou[(offset - 0xA30) / 4] = val;
+            break;
+        case 0xA50:
+            s->dmac_ram = val;
+            break;
+        case 0xA60 ... 0xA8C:
+            s->afi[0][(offset - 0x700) / 4] = val;
+            break;
+        case 0xA90:
+            s->ocm[0] = val;
+            break;
+        case 0xAA0:
+            s->devci_ram = val;
+            break;
+        case 0xAB0:
+            s->csg_ram = val;
+            break;
+        case 0xB00 ... 0xB2C:
+            if (offset == 0xB20 || offset == 0xB2C) {
+                goto bad_reg;
+            }
+            s->gpiob[(offset - 0xB00) / 4] = val;
+            break;
+        case 0xB40 ... 0xB74:
+            s->ddriob[(offset - 0xB40) / 4] = val;
+            break;
+        default:
+        bad_reg:
+            DB_PRINT("Bad register write %x <= %08x\n", (int)offset, val);
+        }
+    } else {
+        DB_PRINT("SCLR registers are locked. Unlock them first\n");
+    }
+}
+
+static const MemoryRegionOps slcr_ops = {
+    .read = zynq_slcr_read,
+    .write = zynq_slcr_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int zynq_slcr_init(SysBusDevice *dev)
+{
+    ZynqSLCRState *s = FROM_SYSBUS(ZynqSLCRState, dev);
+
+    memory_region_init_io(&s->iomem, &slcr_ops, s, "slcr", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_zynq_slcr = {
+    .name = "zynq_slcr",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT8_ARRAY(data, ZynqSLCRState, 0x1000),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void zynq_slcr_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sdc->init = zynq_slcr_init;
+    dc->vmsd = &vmstate_zynq_slcr;
+    dc->reset = zynq_slcr_reset;
+}
+
+static TypeInfo zynq_slcr_info = {
+    .class_init = zynq_slcr_class_init,
+    .name  = "xilinx,zynq_slcr",
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size  = sizeof(ZynqSLCRState),
+};
+
+static void zynq_slcr_register_types(void)
+{
+    type_register_static(&zynq_slcr_info);
+}
+
+type_init(zynq_slcr_register_types)
commit e9f186e514a70557d695cadd2c2287ef97737023
Author: Peter A. G. Crosthwaite <peter.crosthwaite at petalogix.com>
Date:   Mon Mar 5 14:39:12 2012 +1000

    cadence_gem: initial version of device model
    
    Device model for cadence gem ethernet controller.
    
    Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite at petalogix.com>
    Signed-off-by: John Linn <john.linn at xilinx.com>
    Acked-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index d1235da..4dd415c 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -348,6 +348,7 @@ 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 += cadence_uart.o
 obj-arm-y += cadence_ttc.o
+obj-arm-y += cadence_gem.o
 obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
 obj-arm-y += exynos4210_gic.o exynos4210_combiner.o exynos4210.o
 obj-arm-y += exynos4_boards.o exynos4210_uart.o exynos4210_pwm.o
diff --git a/hw/cadence_gem.c b/hw/cadence_gem.c
new file mode 100644
index 0000000..e2140ae
--- /dev/null
+++ b/hw/cadence_gem.c
@@ -0,0 +1,1233 @@
+/*
+ * QEMU Xilinx GEM emulation
+ *
+ * Copyright (c) 2011 Xilinx, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <zlib.h> /* For crc32 */
+
+#include "sysbus.h"
+#include "net.h"
+#include "net/checksum.h"
+
+#ifdef CADENCE_GEM_ERR_DEBUG
+#define DB_PRINT(...) do { \
+    fprintf(stderr,  ": %s: ", __func__); \
+    fprintf(stderr, ## __VA_ARGS__); \
+    } while (0);
+#else
+    #define DB_PRINT(...)
+#endif
+
+#define GEM_NWCTRL        (0x00000000/4) /* Network Control reg */
+#define GEM_NWCFG         (0x00000004/4) /* Network Config reg */
+#define GEM_NWSTATUS      (0x00000008/4) /* Network Status reg */
+#define GEM_USERIO        (0x0000000C/4) /* User IO reg */
+#define GEM_DMACFG        (0x00000010/4) /* DMA Control reg */
+#define GEM_TXSTATUS      (0x00000014/4) /* TX Status reg */
+#define GEM_RXQBASE       (0x00000018/4) /* RX Q Base address reg */
+#define GEM_TXQBASE       (0x0000001C/4) /* TX Q Base address reg */
+#define GEM_RXSTATUS      (0x00000020/4) /* RX Status reg */
+#define GEM_ISR           (0x00000024/4) /* Interrupt Status reg */
+#define GEM_IER           (0x00000028/4) /* Interrupt Enable reg */
+#define GEM_IDR           (0x0000002C/4) /* Interrupt Disable reg */
+#define GEM_IMR           (0x00000030/4) /* Interrupt Mask reg */
+#define GEM_PHYMNTNC      (0x00000034/4) /* Phy Maintaince reg */
+#define GEM_RXPAUSE       (0x00000038/4) /* RX Pause Time reg */
+#define GEM_TXPAUSE       (0x0000003C/4) /* TX Pause Time reg */
+#define GEM_TXPARTIALSF   (0x00000040/4) /* TX Partial Store and Forward */
+#define GEM_RXPARTIALSF   (0x00000044/4) /* RX Partial Store and Forward */
+#define GEM_HASHLO        (0x00000080/4) /* Hash Low address reg */
+#define GEM_HASHHI        (0x00000084/4) /* Hash High address reg */
+#define GEM_SPADDR1LO     (0x00000088/4) /* Specific addr 1 low reg */
+#define GEM_SPADDR1HI     (0x0000008C/4) /* Specific addr 1 high reg */
+#define GEM_SPADDR2LO     (0x00000090/4) /* Specific addr 2 low reg */
+#define GEM_SPADDR2HI     (0x00000094/4) /* Specific addr 2 high reg */
+#define GEM_SPADDR3LO     (0x00000098/4) /* Specific addr 3 low reg */
+#define GEM_SPADDR3HI     (0x0000009C/4) /* Specific addr 3 high reg */
+#define GEM_SPADDR4LO     (0x000000A0/4) /* Specific addr 4 low reg */
+#define GEM_SPADDR4HI     (0x000000A4/4) /* Specific addr 4 high reg */
+#define GEM_TIDMATCH1     (0x000000A8/4) /* Type ID1 Match reg */
+#define GEM_TIDMATCH2     (0x000000AC/4) /* Type ID2 Match reg */
+#define GEM_TIDMATCH3     (0x000000B0/4) /* Type ID3 Match reg */
+#define GEM_TIDMATCH4     (0x000000B4/4) /* Type ID4 Match reg */
+#define GEM_WOLAN         (0x000000B8/4) /* Wake on LAN reg */
+#define GEM_IPGSTRETCH    (0x000000BC/4) /* IPG Stretch reg */
+#define GEM_SVLAN         (0x000000C0/4) /* Stacked VLAN reg */
+#define GEM_MODID         (0x000000FC/4) /* Module ID reg */
+#define GEM_OCTTXLO       (0x00000100/4) /* Octects transmitted Low reg */
+#define GEM_OCTTXHI       (0x00000104/4) /* Octects transmitted High reg */
+#define GEM_TXCNT         (0x00000108/4) /* Error-free Frames transmitted */
+#define GEM_TXBCNT        (0x0000010C/4) /* Error-free Broadcast Frames */
+#define GEM_TXMCNT        (0x00000110/4) /* Error-free Multicast Frame */
+#define GEM_TXPAUSECNT    (0x00000114/4) /* Pause Frames Transmitted */
+#define GEM_TX64CNT       (0x00000118/4) /* Error-free 64 TX */
+#define GEM_TX65CNT       (0x0000011C/4) /* Error-free 65-127 TX */
+#define GEM_TX128CNT      (0x00000120/4) /* Error-free 128-255 TX */
+#define GEM_TX256CNT      (0x00000124/4) /* Error-free 256-511 */
+#define GEM_TX512CNT      (0x00000128/4) /* Error-free 512-1023 TX */
+#define GEM_TX1024CNT     (0x0000012C/4) /* Error-free 1024-1518 TX */
+#define GEM_TX1519CNT     (0x00000130/4) /* Error-free larger than 1519 TX */
+#define GEM_TXURUNCNT     (0x00000134/4) /* TX under run error counter */
+#define GEM_SINGLECOLLCNT (0x00000138/4) /* Single Collision Frames */
+#define GEM_MULTCOLLCNT   (0x0000013C/4) /* Multiple Collision Frames */
+#define GEM_EXCESSCOLLCNT (0x00000140/4) /* Excessive Collision Frames */
+#define GEM_LATECOLLCNT   (0x00000144/4) /* Late Collision Frames */
+#define GEM_DEFERTXCNT    (0x00000148/4) /* Deferred Transmission Frames */
+#define GEM_CSENSECNT     (0x0000014C/4) /* Carrier Sense Error Counter */
+#define GEM_OCTRXLO       (0x00000150/4) /* Octects Received register Low */
+#define GEM_OCTRXHI       (0x00000154/4) /* Octects Received register High */
+#define GEM_RXCNT         (0x00000158/4) /* Error-free Frames Received */
+#define GEM_RXBROADCNT    (0x0000015C/4) /* Error-free Broadcast Frames RX */
+#define GEM_RXMULTICNT    (0x00000160/4) /* Error-free Multicast Frames RX */
+#define GEM_RXPAUSECNT    (0x00000164/4) /* Pause Frames Received Counter */
+#define GEM_RX64CNT       (0x00000168/4) /* Error-free 64 byte Frames RX */
+#define GEM_RX65CNT       (0x0000016C/4) /* Error-free 65-127B Frames RX */
+#define GEM_RX128CNT      (0x00000170/4) /* Error-free 128-255B Frames RX */
+#define GEM_RX256CNT      (0x00000174/4) /* Error-free 256-512B Frames RX */
+#define GEM_RX512CNT      (0x00000178/4) /* Error-free 512-1023B Frames RX */
+#define GEM_RX1024CNT     (0x0000017C/4) /* Error-free 1024-1518B Frames RX */
+#define GEM_RX1519CNT     (0x00000180/4) /* Error-free 1519-max Frames RX */
+#define GEM_RXUNDERCNT    (0x00000184/4) /* Undersize Frames Received */
+#define GEM_RXOVERCNT     (0x00000188/4) /* Oversize Frames Received */
+#define GEM_RXJABCNT      (0x0000018C/4) /* Jabbers Received Counter */
+#define GEM_RXFCSCNT      (0x00000190/4) /* Frame Check seq. Error Counter */
+#define GEM_RXLENERRCNT   (0x00000194/4) /* Length Field Error Counter */
+#define GEM_RXSYMERRCNT   (0x00000198/4) /* Symbol Error Counter */
+#define GEM_RXALIGNERRCNT (0x0000019C/4) /* Alignment Error Counter */
+#define GEM_RXRSCERRCNT   (0x000001A0/4) /* Receive Resource Error Counter */
+#define GEM_RXORUNCNT     (0x000001A4/4) /* Receive Overrun Counter */
+#define GEM_RXIPCSERRCNT  (0x000001A8/4) /* IP header Checksum Error Counter */
+#define GEM_RXTCPCCNT     (0x000001AC/4) /* TCP Checksum Error Counter */
+#define GEM_RXUDPCCNT     (0x000001B0/4) /* UDP Checksum Error Counter */
+
+#define GEM_1588S         (0x000001D0/4) /* 1588 Timer Seconds */
+#define GEM_1588NS        (0x000001D4/4) /* 1588 Timer Nanoseconds */
+#define GEM_1588ADJ       (0x000001D8/4) /* 1588 Timer Adjust */
+#define GEM_1588INC       (0x000001DC/4) /* 1588 Timer Increment */
+#define GEM_PTPETXS       (0x000001E0/4) /* PTP Event Frame Transmitted (s) */
+#define GEM_PTPETXNS      (0x000001E4/4) /* PTP Event Frame Transmitted (ns) */
+#define GEM_PTPERXS       (0x000001E8/4) /* PTP Event Frame Received (s) */
+#define GEM_PTPERXNS      (0x000001EC/4) /* PTP Event Frame Received (ns) */
+#define GEM_PTPPTXS       (0x000001E0/4) /* PTP Peer Frame Transmitted (s) */
+#define GEM_PTPPTXNS      (0x000001E4/4) /* PTP Peer Frame Transmitted (ns) */
+#define GEM_PTPPRXS       (0x000001E8/4) /* PTP Peer Frame Received (s) */
+#define GEM_PTPPRXNS      (0x000001EC/4) /* PTP Peer Frame Received (ns) */
+
+/* Design Configuration Registers */
+#define GEM_DESCONF       (0x00000280/4)
+#define GEM_DESCONF2      (0x00000284/4)
+#define GEM_DESCONF3      (0x00000288/4)
+#define GEM_DESCONF4      (0x0000028C/4)
+#define GEM_DESCONF5      (0x00000290/4)
+#define GEM_DESCONF6      (0x00000294/4)
+#define GEM_DESCONF7      (0x00000298/4)
+
+#define GEM_MAXREG        (0x00000640/4) /* Last valid GEM address */
+
+/*****************************************/
+#define GEM_NWCTRL_TXSTART     0x00000200 /* Transmit Enable */
+#define GEM_NWCTRL_TXENA       0x00000008 /* Transmit Enable */
+#define GEM_NWCTRL_RXENA       0x00000004 /* Receive Enable */
+#define GEM_NWCTRL_LOCALLOOP   0x00000002 /* Local Loopback */
+
+#define GEM_NWCFG_STRIP_FCS    0x00020000 /* Strip FCS field */
+#define GEM_NWCFG_LERR_DISC    0x00010000 /* Discard RX frames with lenth err */
+#define GEM_NWCFG_BUFF_OFST_M  0x0000C000 /* Receive buffer offset mask */
+#define GEM_NWCFG_BUFF_OFST_S  14         /* Receive buffer offset shift */
+#define GEM_NWCFG_UCAST_HASH   0x00000080 /* accept unicast if hash match */
+#define GEM_NWCFG_MCAST_HASH   0x00000040 /* accept multicast if hash match */
+#define GEM_NWCFG_BCAST_REJ    0x00000020 /* Reject broadcast packets */
+#define GEM_NWCFG_PROMISC      0x00000010 /* Accept all packets */
+
+#define GEM_DMACFG_RBUFSZ_M    0x007F0000 /* DMA RX Buffer Size mask */
+#define GEM_DMACFG_RBUFSZ_S    16         /* DMA RX Buffer Size shift */
+#define GEM_DMACFG_RBUFSZ_MUL  64         /* DMA RX Buffer Size multiplier */
+#define GEM_DMACFG_TXCSUM_OFFL 0x00000800 /* Transmit checksum offload */
+
+#define GEM_TXSTATUS_TXCMPL    0x00000020 /* Transmit Complete */
+#define GEM_TXSTATUS_USED      0x00000001 /* sw owned descriptor encountered */
+
+#define GEM_RXSTATUS_FRMRCVD   0x00000002 /* Frame received */
+#define GEM_RXSTATUS_NOBUF     0x00000001 /* Buffer unavailable */
+
+/* GEM_ISR GEM_IER GEM_IDR GEM_IMR */
+#define GEM_INT_TXCMPL        0x00000080 /* Transmit Complete */
+#define GEM_INT_TXUSED         0x00000008
+#define GEM_INT_RXUSED         0x00000004
+#define GEM_INT_RXCMPL        0x00000002
+
+#define GEM_PHYMNTNC_OP_R      0x20000000 /* read operation */
+#define GEM_PHYMNTNC_OP_W      0x10000000 /* write operation */
+#define GEM_PHYMNTNC_ADDR      0x0F800000 /* Address bits */
+#define GEM_PHYMNTNC_ADDR_SHFT 23
+#define GEM_PHYMNTNC_REG       0x007C0000 /* register bits */
+#define GEM_PHYMNTNC_REG_SHIFT 18
+
+/* Marvell PHY definitions */
+#define BOARD_PHY_ADDRESS    23 /* PHY address we will emulate a device at */
+
+#define PHY_REG_CONTROL      0
+#define PHY_REG_STATUS       1
+#define PHY_REG_PHYID1       2
+#define PHY_REG_PHYID2       3
+#define PHY_REG_ANEGADV      4
+#define PHY_REG_LINKPABIL    5
+#define PHY_REG_ANEGEXP      6
+#define PHY_REG_NEXTP        7
+#define PHY_REG_LINKPNEXTP   8
+#define PHY_REG_100BTCTRL    9
+#define PHY_REG_1000BTSTAT   10
+#define PHY_REG_EXTSTAT      15
+#define PHY_REG_PHYSPCFC_CTL 16
+#define PHY_REG_PHYSPCFC_ST  17
+#define PHY_REG_INT_EN       18
+#define PHY_REG_INT_ST       19
+#define PHY_REG_EXT_PHYSPCFC_CTL  20
+#define PHY_REG_RXERR        21
+#define PHY_REG_EACD         22
+#define PHY_REG_LED          24
+#define PHY_REG_LED_OVRD     25
+#define PHY_REG_EXT_PHYSPCFC_CTL2 26
+#define PHY_REG_EXT_PHYSPCFC_ST   27
+#define PHY_REG_CABLE_DIAG   28
+
+#define PHY_REG_CONTROL_RST  0x8000
+#define PHY_REG_CONTROL_LOOP 0x4000
+#define PHY_REG_CONTROL_ANEG 0x1000
+
+#define PHY_REG_STATUS_LINK     0x0004
+#define PHY_REG_STATUS_ANEGCMPL 0x0020
+
+#define PHY_REG_INT_ST_ANEGCMPL 0x0800
+#define PHY_REG_INT_ST_LINKC    0x0400
+#define PHY_REG_INT_ST_ENERGY   0x0010
+
+/***********************************************************************/
+#define GEM_RX_REJECT  1
+#define GEM_RX_ACCEPT  0
+
+/***********************************************************************/
+
+#define DESC_1_USED 0x80000000
+#define DESC_1_LENGTH 0x00001FFF
+
+#define DESC_1_TX_WRAP 0x40000000
+#define DESC_1_TX_LAST 0x00008000
+
+#define DESC_0_RX_WRAP 0x00000002
+#define DESC_0_RX_OWNERSHIP 0x00000001
+
+#define DESC_1_RX_SOF 0x00004000
+#define DESC_1_RX_EOF 0x00008000
+
+static inline unsigned tx_desc_get_buffer(unsigned *desc)
+{
+    return desc[0];
+}
+
+static inline unsigned tx_desc_get_used(unsigned *desc)
+{
+    return (desc[1] & DESC_1_USED) ? 1 : 0;
+}
+
+static inline void tx_desc_set_used(unsigned *desc)
+{
+    desc[1] |= DESC_1_USED;
+}
+
+static inline unsigned tx_desc_get_wrap(unsigned *desc)
+{
+    return (desc[1] & DESC_1_TX_WRAP) ? 1 : 0;
+}
+
+static inline unsigned tx_desc_get_last(unsigned *desc)
+{
+    return (desc[1] & DESC_1_TX_LAST) ? 1 : 0;
+}
+
+static inline unsigned tx_desc_get_length(unsigned *desc)
+{
+    return desc[1] & DESC_1_LENGTH;
+}
+
+static inline void print_gem_tx_desc(unsigned *desc)
+{
+    DB_PRINT("TXDESC:\n");
+    DB_PRINT("bufaddr: 0x%08x\n", *desc);
+    DB_PRINT("used_hw: %d\n", tx_desc_get_used(desc));
+    DB_PRINT("wrap:    %d\n", tx_desc_get_wrap(desc));
+    DB_PRINT("last:    %d\n", tx_desc_get_last(desc));
+    DB_PRINT("length:  %d\n", tx_desc_get_length(desc));
+}
+
+static inline unsigned rx_desc_get_buffer(unsigned *desc)
+{
+    return desc[0] & ~0x3UL;
+}
+
+static inline unsigned rx_desc_get_wrap(unsigned *desc)
+{
+    return desc[0] & DESC_0_RX_WRAP ? 1 : 0;
+}
+
+static inline unsigned rx_desc_get_ownership(unsigned *desc)
+{
+    return desc[0] & DESC_0_RX_OWNERSHIP ? 1 : 0;
+}
+
+static inline void rx_desc_set_ownership(unsigned *desc)
+{
+    desc[0] |= DESC_0_RX_OWNERSHIP;
+}
+
+static inline void rx_desc_set_sof(unsigned *desc)
+{
+    desc[1] |= DESC_1_RX_SOF;
+}
+
+static inline void rx_desc_set_eof(unsigned *desc)
+{
+    desc[1] |= DESC_1_RX_EOF;
+}
+
+static inline void rx_desc_set_length(unsigned *desc, unsigned len)
+{
+    desc[1] &= ~DESC_1_LENGTH;
+    desc[1] |= len;
+}
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    NICState *nic;
+    NICConf conf;
+    qemu_irq irq;
+
+    /* GEM registers backing store */
+    uint32_t regs[GEM_MAXREG];
+    /* Mask of register bits which are write only */
+    uint32_t regs_wo[GEM_MAXREG];
+    /* Mask of register bits which are read only */
+    uint32_t regs_ro[GEM_MAXREG];
+    /* Mask of register bits which are clear on read */
+    uint32_t regs_rtc[GEM_MAXREG];
+    /* Mask of register bits which are write 1 to clear */
+    uint32_t regs_w1c[GEM_MAXREG];
+
+    /* PHY registers backing store */
+    uint16_t phy_regs[32];
+
+    uint8_t phy_loop; /* Are we in phy loopback? */
+
+    /* The current DMA descriptor pointers */
+    target_phys_addr_t rx_desc_addr;
+    target_phys_addr_t tx_desc_addr;
+
+} GemState;
+
+/* The broadcast MAC address: 0xFFFFFFFFFFFF */
+const uint8_t broadcast_addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+
+/*
+ * gem_init_register_masks:
+ * One time initialization.
+ * Set masks to identify which register bits have magical clear properties
+ */
+static void gem_init_register_masks(GemState *s)
+{
+    /* Mask of register bits which are read only*/
+    memset(&s->regs_ro[0], 0, sizeof(s->regs_ro));
+    s->regs_ro[GEM_NWCTRL]   = 0xFFF80000;
+    s->regs_ro[GEM_NWSTATUS] = 0xFFFFFFFF;
+    s->regs_ro[GEM_DMACFG]   = 0xFE00F000;
+    s->regs_ro[GEM_TXSTATUS] = 0xFFFFFE08;
+    s->regs_ro[GEM_RXQBASE]  = 0x00000003;
+    s->regs_ro[GEM_TXQBASE]  = 0x00000003;
+    s->regs_ro[GEM_RXSTATUS] = 0xFFFFFFF0;
+    s->regs_ro[GEM_ISR]      = 0xFFFFFFFF;
+    s->regs_ro[GEM_IMR]      = 0xFFFFFFFF;
+    s->regs_ro[GEM_MODID]    = 0xFFFFFFFF;
+
+    /* Mask of register bits which are clear on read */
+    memset(&s->regs_rtc[0], 0, sizeof(s->regs_rtc));
+    s->regs_rtc[GEM_ISR]      = 0xFFFFFFFF;
+
+    /* Mask of register bits which are write 1 to clear */
+    memset(&s->regs_w1c[0], 0, sizeof(s->regs_w1c));
+    s->regs_w1c[GEM_TXSTATUS] = 0x000001F7;
+    s->regs_w1c[GEM_RXSTATUS] = 0x0000000F;
+
+    /* Mask of register bits which are write only */
+    memset(&s->regs_wo[0], 0, sizeof(s->regs_wo));
+    s->regs_wo[GEM_NWCTRL]   = 0x00073E60;
+    s->regs_wo[GEM_IER]      = 0x07FFFFFF;
+    s->regs_wo[GEM_IDR]      = 0x07FFFFFF;
+}
+
+/*
+ * phy_update_link:
+ * Make the emulated PHY link state match the QEMU "interface" state.
+ */
+static void phy_update_link(GemState *s)
+{
+    DB_PRINT("down %d\n", s->nic->nc.link_down);
+
+    /* Autonegotiation status mirrors link status.  */
+    if (s->nic->nc.link_down) {
+        s->phy_regs[PHY_REG_STATUS] &= ~(PHY_REG_STATUS_ANEGCMPL |
+                                         PHY_REG_STATUS_LINK);
+        s->phy_regs[PHY_REG_INT_ST] |= PHY_REG_INT_ST_LINKC;
+    } else {
+        s->phy_regs[PHY_REG_STATUS] |= (PHY_REG_STATUS_ANEGCMPL |
+                                         PHY_REG_STATUS_LINK);
+        s->phy_regs[PHY_REG_INT_ST] |= (PHY_REG_INT_ST_LINKC |
+                                        PHY_REG_INT_ST_ANEGCMPL |
+                                        PHY_REG_INT_ST_ENERGY);
+    }
+}
+
+static int gem_can_receive(VLANClientState *nc)
+{
+    GemState *s;
+
+    s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    DB_PRINT("\n");
+
+    /* Do nothing if receive is not enabled. */
+    if (!(s->regs[GEM_NWCTRL] & GEM_NWCTRL_RXENA)) {
+        return 0;
+    }
+
+    return 1;
+}
+
+/*
+ * gem_update_int_status:
+ * Raise or lower interrupt based on current status.
+ */
+static void gem_update_int_status(GemState *s)
+{
+    uint32_t new_interrupts = 0;
+    /* Packet transmitted ? */
+    if (s->regs[GEM_TXSTATUS] & GEM_TXSTATUS_TXCMPL) {
+        new_interrupts |= GEM_INT_TXCMPL;
+    }
+    /* End of TX ring ? */
+    if (s->regs[GEM_TXSTATUS] & GEM_TXSTATUS_USED) {
+        new_interrupts |= GEM_INT_TXUSED;
+    }
+
+    /* Frame received ? */
+    if (s->regs[GEM_RXSTATUS] & GEM_RXSTATUS_FRMRCVD) {
+        new_interrupts |= GEM_INT_RXCMPL;
+    }
+    /* RX ring full ? */
+    if (s->regs[GEM_RXSTATUS] & GEM_RXSTATUS_NOBUF) {
+        new_interrupts |= GEM_INT_RXUSED;
+    }
+
+    s->regs[GEM_ISR] |= new_interrupts & ~(s->regs[GEM_IMR]);
+
+    if (s->regs[GEM_ISR]) {
+        DB_PRINT("asserting int. (0x%08x)\n", s->regs[GEM_ISR]);
+        qemu_set_irq(s->irq, 1);
+    } else {
+        qemu_set_irq(s->irq, 0);
+    }
+}
+
+/*
+ * gem_receive_updatestats:
+ * Increment receive statistics.
+ */
+static void gem_receive_updatestats(GemState *s, const uint8_t *packet,
+                                    unsigned bytes)
+{
+    uint64_t octets;
+
+    /* Total octets (bytes) received */
+    octets = ((uint64_t)(s->regs[GEM_OCTRXLO]) << 32) |
+             s->regs[GEM_OCTRXHI];
+    octets += bytes;
+    s->regs[GEM_OCTRXLO] = octets >> 32;
+    s->regs[GEM_OCTRXHI] = octets;
+
+    /* Error-free Frames received */
+    s->regs[GEM_RXCNT]++;
+
+    /* Error-free Broadcast Frames counter */
+    if (!memcmp(packet, broadcast_addr, 6)) {
+        s->regs[GEM_RXBROADCNT]++;
+    }
+
+    /* Error-free Multicast Frames counter */
+    if (packet[0] == 0x01) {
+        s->regs[GEM_RXMULTICNT]++;
+    }
+
+    if (bytes <= 64) {
+        s->regs[GEM_RX64CNT]++;
+    } else if (bytes <= 127) {
+        s->regs[GEM_RX65CNT]++;
+    } else if (bytes <= 255) {
+        s->regs[GEM_RX128CNT]++;
+    } else if (bytes <= 511) {
+        s->regs[GEM_RX256CNT]++;
+    } else if (bytes <= 1023) {
+        s->regs[GEM_RX512CNT]++;
+    } else if (bytes <= 1518) {
+        s->regs[GEM_RX1024CNT]++;
+    } else {
+        s->regs[GEM_RX1519CNT]++;
+    }
+}
+
+/*
+ * Get the MAC Address bit from the specified position
+ */
+static unsigned get_bit(const uint8_t *mac, unsigned bit)
+{
+    unsigned byte;
+
+    byte = mac[bit / 8];
+    byte >>= (bit & 0x7);
+    byte &= 1;
+
+    return byte;
+}
+
+/*
+ * Calculate a GEM MAC Address hash index
+ */
+static unsigned calc_mac_hash(const uint8_t *mac)
+{
+    int index_bit, mac_bit;
+    unsigned hash_index;
+
+    hash_index = 0;
+    mac_bit = 5;
+    for (index_bit = 5; index_bit >= 0; index_bit--) {
+        hash_index |= (get_bit(mac,  mac_bit) ^
+                               get_bit(mac, mac_bit + 6) ^
+                               get_bit(mac, mac_bit + 12) ^
+                               get_bit(mac, mac_bit + 18) ^
+                               get_bit(mac, mac_bit + 24) ^
+                               get_bit(mac, mac_bit + 30) ^
+                               get_bit(mac, mac_bit + 36) ^
+                               get_bit(mac, mac_bit + 42)) << index_bit;
+        mac_bit--;
+    }
+
+    return hash_index;
+}
+
+/*
+ * gem_mac_address_filter:
+ * Accept or reject this destination address?
+ * Returns:
+ * GEM_RX_REJECT: reject
+ * GEM_RX_ACCEPT: accept
+ */
+static int gem_mac_address_filter(GemState *s, const uint8_t *packet)
+{
+    uint8_t *gem_spaddr;
+    int i;
+
+    /* Promiscuous mode? */
+    if (s->regs[GEM_NWCFG] & GEM_NWCFG_PROMISC) {
+        return GEM_RX_ACCEPT;
+    }
+
+    if (!memcmp(packet, broadcast_addr, 6)) {
+        /* Reject broadcast packets? */
+        if (s->regs[GEM_NWCFG] & GEM_NWCFG_BCAST_REJ) {
+            return GEM_RX_REJECT;
+        }
+        return GEM_RX_ACCEPT;
+    }
+
+    /* Accept packets -w- hash match? */
+    if ((packet[0] == 0x01 && (s->regs[GEM_NWCFG] & GEM_NWCFG_MCAST_HASH)) ||
+        (packet[0] != 0x01 && (s->regs[GEM_NWCFG] & GEM_NWCFG_UCAST_HASH))) {
+        unsigned hash_index;
+
+        hash_index = calc_mac_hash(packet);
+        if (hash_index < 32) {
+            if (s->regs[GEM_HASHLO] & (1<<hash_index)) {
+                return GEM_RX_ACCEPT;
+            }
+        } else {
+            hash_index -= 32;
+            if (s->regs[GEM_HASHHI] & (1<<hash_index)) {
+                return GEM_RX_ACCEPT;
+            }
+        }
+    }
+
+    /* Check all 4 specific addresses */
+    gem_spaddr = (uint8_t *)&(s->regs[GEM_SPADDR1LO]);
+    for (i = 0; i < 4; i++) {
+        if (!memcmp(packet, gem_spaddr, 6)) {
+            return GEM_RX_ACCEPT;
+        }
+
+        gem_spaddr += 8;
+    }
+
+    /* No address match; reject the packet */
+    return GEM_RX_REJECT;
+}
+
+/*
+ * gem_receive:
+ * Fit a packet handed to us by QEMU into the receive descriptor ring.
+ */
+static ssize_t gem_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
+{
+    unsigned    desc[2];
+    target_phys_addr_t packet_desc_addr, last_desc_addr;
+    GemState *s;
+    unsigned   rxbufsize, bytes_to_copy;
+    unsigned   rxbuf_offset;
+    uint8_t    rxbuf[2048];
+    uint8_t   *rxbuf_ptr;
+
+    s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    /* Do nothing if receive is not enabled. */
+    if (!(s->regs[GEM_NWCTRL] & GEM_NWCTRL_RXENA)) {
+        return -1;
+    }
+
+    /* Is this destination MAC address "for us" ? */
+    if (gem_mac_address_filter(s, buf) == GEM_RX_REJECT) {
+        return -1;
+    }
+
+    /* Discard packets with receive length error enabled ? */
+    if (s->regs[GEM_NWCFG] & GEM_NWCFG_LERR_DISC) {
+        unsigned type_len;
+
+        /* Fish the ethertype / length field out of the RX packet */
+        type_len = buf[12] << 8 | buf[13];
+        /* It is a length field, not an ethertype */
+        if (type_len < 0x600) {
+            if (size < type_len) {
+                /* discard */
+                return -1;
+            }
+        }
+    }
+
+    /*
+     * Determine configured receive buffer offset (probably 0)
+     */
+    rxbuf_offset = (s->regs[GEM_NWCFG] & GEM_NWCFG_BUFF_OFST_M) >>
+                   GEM_NWCFG_BUFF_OFST_S;
+
+    /* The configure size of each receive buffer.  Determines how many
+     * buffers needed to hold this packet.
+     */
+    rxbufsize = ((s->regs[GEM_DMACFG] & GEM_DMACFG_RBUFSZ_M) >>
+                 GEM_DMACFG_RBUFSZ_S) * GEM_DMACFG_RBUFSZ_MUL;
+    bytes_to_copy = size;
+
+    /* Strip of FCS field ? (usually yes) */
+    if (s->regs[GEM_NWCFG] & GEM_NWCFG_STRIP_FCS) {
+        rxbuf_ptr = (void *)buf;
+    } else {
+        unsigned crc_val;
+        int      crc_offset;
+
+        /* The application wants the FCS field, which QEMU does not provide.
+         * We must try and caclculate one.
+         */
+
+        memcpy(rxbuf, buf, size);
+        memset(rxbuf + size, 0, sizeof(rxbuf - size));
+        rxbuf_ptr = rxbuf;
+        crc_val = cpu_to_le32(crc32(0, rxbuf, MAX(size, 60)));
+        if (size < 60) {
+            crc_offset = 60;
+        } else {
+            crc_offset = size;
+        }
+        memcpy(rxbuf + crc_offset, &crc_val, sizeof(crc_val));
+
+        bytes_to_copy += 4;
+        size += 4;
+    }
+
+    /* Pad to minimum length */
+    if (size < 64) {
+        size = 64;
+    }
+
+    DB_PRINT("config bufsize: %d packet size: %ld\n", rxbufsize, size);
+
+    packet_desc_addr = s->rx_desc_addr;
+    while (1) {
+        DB_PRINT("read descriptor 0x%x\n", packet_desc_addr);
+        /* read current descriptor */
+        cpu_physical_memory_read(packet_desc_addr,
+                                 (uint8_t *)&desc[0], sizeof(desc));
+
+        /* Descriptor owned by software ? */
+        if (rx_desc_get_ownership(desc) == 1) {
+            DB_PRINT("descriptor 0x%x owned by sw.\n", packet_desc_addr);
+            s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_NOBUF;
+            /* Handle interrupt consequences */
+            gem_update_int_status(s);
+            return -1;
+        }
+
+        DB_PRINT("copy %d bytes to 0x%x\n", MIN(bytes_to_copy, rxbufsize),
+                rx_desc_get_buffer(desc));
+
+        /*
+         * Let's have QEMU lend a helping hand.
+         */
+        if (rx_desc_get_buffer(desc) == 0) {
+            DB_PRINT("Invalid RX buffer (NULL) for descriptor 0x%x\n",
+                       packet_desc_addr);
+            break;
+        }
+
+        /* Copy packet data to emulated DMA buffer */
+        cpu_physical_memory_write(rx_desc_get_buffer(desc) + rxbuf_offset,
+                                  rxbuf_ptr, MIN(bytes_to_copy, rxbufsize));
+        bytes_to_copy -= MIN(bytes_to_copy, rxbufsize);
+        rxbuf_ptr += MIN(bytes_to_copy, rxbufsize);
+        if (bytes_to_copy == 0) {
+            break;
+        }
+
+        /* Next descriptor */
+        if (rx_desc_get_wrap(desc)) {
+            packet_desc_addr = s->regs[GEM_RXQBASE];
+        } else {
+            packet_desc_addr += 8;
+        }
+    }
+
+    DB_PRINT("set length: %ld, EOF on descriptor 0x%x\n", size,
+            (unsigned)packet_desc_addr);
+
+    /* Update last descriptor with EOF and total length */
+    rx_desc_set_eof(desc);
+    rx_desc_set_length(desc, size);
+    cpu_physical_memory_write(packet_desc_addr,
+                              (uint8_t *)&desc[0], sizeof(desc));
+
+    /* Advance RX packet descriptor Q */
+    last_desc_addr = packet_desc_addr;
+    packet_desc_addr = s->rx_desc_addr;
+    s->rx_desc_addr = last_desc_addr;
+    if (rx_desc_get_wrap(desc)) {
+        s->rx_desc_addr = s->regs[GEM_RXQBASE];
+    } else {
+        s->rx_desc_addr += 8;
+    }
+
+    DB_PRINT("set SOF, OWN on descriptor 0x%08x\n", packet_desc_addr);
+
+    /* Count it */
+    gem_receive_updatestats(s, buf, size);
+
+    /* Update first descriptor (which could also be the last) */
+    /* read descriptor */
+    cpu_physical_memory_read(packet_desc_addr,
+                             (uint8_t *)&desc[0], sizeof(desc));
+    rx_desc_set_sof(desc);
+    rx_desc_set_ownership(desc);
+    cpu_physical_memory_write(packet_desc_addr,
+                              (uint8_t *)&desc[0], sizeof(desc));
+
+    s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_FRMRCVD;
+
+    /* Handle interrupt consequences */
+    gem_update_int_status(s);
+
+    return size;
+}
+
+/*
+ * gem_transmit_updatestats:
+ * Increment transmit statistics.
+ */
+static void gem_transmit_updatestats(GemState *s, const uint8_t *packet,
+                                     unsigned bytes)
+{
+    uint64_t octets;
+
+    /* Total octets (bytes) transmitted */
+    octets = ((uint64_t)(s->regs[GEM_OCTTXLO]) << 32) |
+             s->regs[GEM_OCTTXHI];
+    octets += bytes;
+    s->regs[GEM_OCTTXLO] = octets >> 32;
+    s->regs[GEM_OCTTXHI] = octets;
+
+    /* Error-free Frames transmitted */
+    s->regs[GEM_TXCNT]++;
+
+    /* Error-free Broadcast Frames counter */
+    if (!memcmp(packet, broadcast_addr, 6)) {
+        s->regs[GEM_TXBCNT]++;
+    }
+
+    /* Error-free Multicast Frames counter */
+    if (packet[0] == 0x01) {
+        s->regs[GEM_TXMCNT]++;
+    }
+
+    if (bytes <= 64) {
+        s->regs[GEM_TX64CNT]++;
+    } else if (bytes <= 127) {
+        s->regs[GEM_TX65CNT]++;
+    } else if (bytes <= 255) {
+        s->regs[GEM_TX128CNT]++;
+    } else if (bytes <= 511) {
+        s->regs[GEM_TX256CNT]++;
+    } else if (bytes <= 1023) {
+        s->regs[GEM_TX512CNT]++;
+    } else if (bytes <= 1518) {
+        s->regs[GEM_TX1024CNT]++;
+    } else {
+        s->regs[GEM_TX1519CNT]++;
+    }
+}
+
+/*
+ * gem_transmit:
+ * Fish packets out of the descriptor ring and feed them to QEMU
+ */
+static void gem_transmit(GemState *s)
+{
+    unsigned    desc[2];
+    target_phys_addr_t packet_desc_addr;
+    uint8_t     tx_packet[2048];
+    uint8_t     *p;
+    unsigned    total_bytes;
+
+    /* Do nothing if transmit is not enabled. */
+    if (!(s->regs[GEM_NWCTRL] & GEM_NWCTRL_TXENA)) {
+        return;
+    }
+
+    DB_PRINT("\n");
+
+    /* The packet we will hand off to qemu.
+     * Packets scattered across multiple descriptors are gathered to this
+     * one contiguous buffer first.
+     */
+    p = tx_packet;
+    total_bytes = 0;
+
+    /* read current descriptor */
+    packet_desc_addr = s->tx_desc_addr;
+    cpu_physical_memory_read(packet_desc_addr,
+                             (uint8_t *)&desc[0], sizeof(desc));
+    /* Handle all descriptors owned by hardware */
+    while (tx_desc_get_used(desc) == 0) {
+
+        /* Do nothing if transmit is not enabled. */
+        if (!(s->regs[GEM_NWCTRL] & GEM_NWCTRL_TXENA)) {
+            return;
+        }
+        print_gem_tx_desc(desc);
+
+        /* The real hardware would eat this (and possibly crash).
+         * For QEMU let's lend a helping hand.
+         */
+        if ((tx_desc_get_buffer(desc) == 0) ||
+            (tx_desc_get_length(desc) == 0)) {
+            DB_PRINT("Invalid TX descriptor @ 0x%x\n", packet_desc_addr);
+            break;
+        }
+
+        /* Gather this fragment of the packet from "dma memory" to our contig.
+         * buffer.
+         */
+        cpu_physical_memory_read(tx_desc_get_buffer(desc), p,
+                                 tx_desc_get_length(desc));
+        p += tx_desc_get_length(desc);
+        total_bytes += tx_desc_get_length(desc);
+
+        /* Last descriptor for this packet; hand the whole thing off */
+        if (tx_desc_get_last(desc)) {
+            /* Modify the 1st descriptor of this packet to be owned by
+             * the processor.
+             */
+            cpu_physical_memory_read(s->tx_desc_addr,
+                                     (uint8_t *)&desc[0], sizeof(desc));
+            tx_desc_set_used(desc);
+            cpu_physical_memory_write(s->tx_desc_addr,
+                                      (uint8_t *)&desc[0], sizeof(desc));
+            /* Advance the hardare current descriptor past this packet */
+            if (tx_desc_get_wrap(desc)) {
+                s->tx_desc_addr = s->regs[GEM_TXQBASE];
+            } else {
+                s->tx_desc_addr = packet_desc_addr + 8;
+            }
+            DB_PRINT("TX descriptor next: 0x%08x\n", s->tx_desc_addr);
+
+            s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_TXCMPL;
+
+            /* Handle interrupt consequences */
+            gem_update_int_status(s);
+
+            /* Is checksum offload enabled? */
+            if (s->regs[GEM_DMACFG] & GEM_DMACFG_TXCSUM_OFFL) {
+                net_checksum_calculate(tx_packet, total_bytes);
+            }
+
+            /* Update MAC statistics */
+            gem_transmit_updatestats(s, tx_packet, total_bytes);
+
+            /* Send the packet somewhere */
+            if (s->phy_loop) {
+                gem_receive(&s->nic->nc, tx_packet, total_bytes);
+            } else {
+                qemu_send_packet(&s->nic->nc, tx_packet, total_bytes);
+            }
+
+            /* Prepare for next packet */
+            p = tx_packet;
+            total_bytes = 0;
+        }
+
+        /* read next descriptor */
+        if (tx_desc_get_wrap(desc)) {
+            packet_desc_addr = s->regs[GEM_TXQBASE];
+        } else {
+            packet_desc_addr += 8;
+        }
+        cpu_physical_memory_read(packet_desc_addr,
+                                 (uint8_t *)&desc[0], sizeof(desc));
+    }
+
+    if (tx_desc_get_used(desc)) {
+        s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_USED;
+        gem_update_int_status(s);
+    }
+}
+
+static void gem_phy_reset(GemState *s)
+{
+    memset(&s->phy_regs[0], 0, sizeof(s->phy_regs));
+    s->phy_regs[PHY_REG_CONTROL] = 0x1140;
+    s->phy_regs[PHY_REG_STATUS] = 0x7969;
+    s->phy_regs[PHY_REG_PHYID1] = 0x0141;
+    s->phy_regs[PHY_REG_PHYID2] = 0x0CC2;
+    s->phy_regs[PHY_REG_ANEGADV] = 0x01E1;
+    s->phy_regs[PHY_REG_LINKPABIL] = 0xCDE1;
+    s->phy_regs[PHY_REG_ANEGEXP] = 0x000F;
+    s->phy_regs[PHY_REG_NEXTP] = 0x2001;
+    s->phy_regs[PHY_REG_LINKPNEXTP] = 0x40E6;
+    s->phy_regs[PHY_REG_100BTCTRL] = 0x0300;
+    s->phy_regs[PHY_REG_1000BTSTAT] = 0x7C00;
+    s->phy_regs[PHY_REG_EXTSTAT] = 0x3000;
+    s->phy_regs[PHY_REG_PHYSPCFC_CTL] = 0x0078;
+    s->phy_regs[PHY_REG_PHYSPCFC_ST] = 0xBC00;
+    s->phy_regs[PHY_REG_EXT_PHYSPCFC_CTL] = 0x0C60;
+    s->phy_regs[PHY_REG_LED] = 0x4100;
+    s->phy_regs[PHY_REG_EXT_PHYSPCFC_CTL2] = 0x000A;
+    s->phy_regs[PHY_REG_EXT_PHYSPCFC_ST] = 0x848B;
+
+    phy_update_link(s);
+}
+
+static void gem_reset(DeviceState *d)
+{
+    GemState *s = FROM_SYSBUS(GemState, sysbus_from_qdev(d));
+
+    DB_PRINT("\n");
+
+    /* Set post reset register values */
+    memset(&s->regs[0], 0, sizeof(s->regs));
+    s->regs[GEM_NWCFG] = 0x00080000;
+    s->regs[GEM_NWSTATUS] = 0x00000006;
+    s->regs[GEM_DMACFG] = 0x00020784;
+    s->regs[GEM_IMR] = 0x07ffffff;
+    s->regs[GEM_TXPAUSE] = 0x0000ffff;
+    s->regs[GEM_TXPARTIALSF] = 0x000003ff;
+    s->regs[GEM_RXPARTIALSF] = 0x000003ff;
+    s->regs[GEM_MODID] = 0x00020118;
+    s->regs[GEM_DESCONF] = 0x02500111;
+    s->regs[GEM_DESCONF2] = 0x2ab13fff;
+    s->regs[GEM_DESCONF5] = 0x002f2145;
+    s->regs[GEM_DESCONF6] = 0x00000200;
+
+    gem_phy_reset(s);
+
+    gem_update_int_status(s);
+}
+
+static uint16_t gem_phy_read(GemState *s, unsigned reg_num)
+{
+    DB_PRINT("reg: %d value: 0x%04x\n", reg_num, s->phy_regs[reg_num]);
+    return s->phy_regs[reg_num];
+}
+
+static void gem_phy_write(GemState *s, unsigned reg_num, uint16_t val)
+{
+    DB_PRINT("reg: %d value: 0x%04x\n", reg_num, val);
+
+    switch (reg_num) {
+    case PHY_REG_CONTROL:
+        if (val & PHY_REG_CONTROL_RST) {
+            /* Phy reset */
+            gem_phy_reset(s);
+            val &= ~(PHY_REG_CONTROL_RST | PHY_REG_CONTROL_LOOP);
+            s->phy_loop = 0;
+        }
+        if (val & PHY_REG_CONTROL_ANEG) {
+            /* Complete autonegotiation immediately */
+            val &= ~PHY_REG_CONTROL_ANEG;
+            s->phy_regs[PHY_REG_STATUS] |= PHY_REG_STATUS_ANEGCMPL;
+        }
+        if (val & PHY_REG_CONTROL_LOOP) {
+            DB_PRINT("PHY placed in loopback\n");
+            s->phy_loop = 1;
+        } else {
+            s->phy_loop = 0;
+        }
+        break;
+    }
+    s->phy_regs[reg_num] = val;
+}
+
+/*
+ * gem_read32:
+ * Read a GEM register.
+ */
+static uint64_t gem_read(void *opaque, target_phys_addr_t offset, unsigned size)
+{
+    GemState *s;
+    uint32_t retval;
+
+    s = (GemState *)opaque;
+
+    offset >>= 2;
+    retval = s->regs[offset];
+
+    DB_PRINT("offset: 0x%04x read: 0x%08x\n", offset*4, retval);
+
+    switch (offset) {
+    case GEM_ISR:
+        qemu_set_irq(s->irq, 0);
+        break;
+    case GEM_PHYMNTNC:
+        if (retval & GEM_PHYMNTNC_OP_R) {
+            uint32_t phy_addr, reg_num;
+
+            phy_addr = (retval & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT;
+            if (phy_addr == BOARD_PHY_ADDRESS) {
+                reg_num = (retval & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT;
+                retval &= 0xFFFF0000;
+                retval |= gem_phy_read(s, reg_num);
+            } else {
+                retval |= 0xFFFF; /* No device at this address */
+            }
+        }
+        break;
+    }
+
+    /* Squash read to clear bits */
+    s->regs[offset] &= ~(s->regs_rtc[offset]);
+
+    /* Do not provide write only bits */
+    retval &= ~(s->regs_wo[offset]);
+
+    DB_PRINT("0x%08x\n", retval);
+    return retval;
+}
+
+/*
+ * gem_write32:
+ * Write a GEM register.
+ */
+static void gem_write(void *opaque, target_phys_addr_t offset, uint64_t val,
+        unsigned size)
+{
+    GemState *s = (GemState *)opaque;
+    uint32_t readonly;
+
+    DB_PRINT("offset: 0x%04x write: 0x%08x ", offset, (unsigned)val);
+    offset >>= 2;
+
+    /* Squash bits which are read only in write value */
+    val &= ~(s->regs_ro[offset]);
+    /* Preserve (only) bits which are read only in register */
+    readonly = s->regs[offset];
+    readonly &= s->regs_ro[offset];
+
+    /* Squash bits which are write 1 to clear */
+    val &= ~(s->regs_w1c[offset] & val);
+
+    /* Copy register write to backing store */
+    s->regs[offset] = val | readonly;
+
+    /* Handle register write side effects */
+    switch (offset) {
+    case GEM_NWCTRL:
+        if (val & GEM_NWCTRL_TXSTART) {
+            gem_transmit(s);
+        }
+        if (!(val & GEM_NWCTRL_TXENA)) {
+            /* Reset to start of Q when transmit disabled. */
+            s->tx_desc_addr = s->regs[GEM_TXQBASE];
+        }
+        if (!(val & GEM_NWCTRL_RXENA)) {
+            /* Reset to start of Q when receive disabled. */
+            s->rx_desc_addr = s->regs[GEM_RXQBASE];
+        }
+        break;
+
+    case GEM_TXSTATUS:
+        gem_update_int_status(s);
+        break;
+    case GEM_RXQBASE:
+        s->rx_desc_addr = val;
+        break;
+    case GEM_TXQBASE:
+        s->tx_desc_addr = val;
+        break;
+    case GEM_RXSTATUS:
+        gem_update_int_status(s);
+        break;
+    case GEM_IER:
+        s->regs[GEM_IMR] &= ~val;
+        gem_update_int_status(s);
+        break;
+    case GEM_IDR:
+        s->regs[GEM_IMR] |= val;
+        gem_update_int_status(s);
+        break;
+    case GEM_PHYMNTNC:
+        if (val & GEM_PHYMNTNC_OP_W) {
+            uint32_t phy_addr, reg_num;
+
+            phy_addr = (val & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT;
+            if (phy_addr == BOARD_PHY_ADDRESS) {
+                reg_num = (val & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT;
+                gem_phy_write(s, reg_num, val);
+            }
+        }
+        break;
+    }
+
+    DB_PRINT("newval: 0x%08x\n", s->regs[offset]);
+}
+
+static const MemoryRegionOps gem_ops = {
+    .read = gem_read,
+    .write = gem_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void gem_cleanup(VLANClientState *nc)
+{
+    GemState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    DB_PRINT("\n");
+    s->nic = NULL;
+}
+
+static void gem_set_link(VLANClientState *nc)
+{
+    DB_PRINT("\n");
+    phy_update_link(DO_UPCAST(NICState, nc, nc)->opaque);
+}
+
+static NetClientInfo net_gem_info = {
+    .type = NET_CLIENT_TYPE_NIC,
+    .size = sizeof(NICState),
+    .can_receive = gem_can_receive,
+    .receive = gem_receive,
+    .cleanup = gem_cleanup,
+    .link_status_changed = gem_set_link,
+};
+
+static int gem_init(SysBusDevice *dev)
+{
+    GemState *s;
+
+    DB_PRINT("\n");
+
+    s = FROM_SYSBUS(GemState, dev);
+    gem_init_register_masks(s);
+    memory_region_init_io(&s->iomem, &gem_ops, s, "enet", sizeof(s->regs));
+    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->irq);
+    qemu_macaddr_default_if_unset(&s->conf.macaddr);
+
+    s->nic = qemu_new_nic(&net_gem_info, &s->conf,
+            object_get_typename(OBJECT(dev)), dev->qdev.id, s);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_cadence_gem = {
+    .name = "cadence_gem",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, GemState, GEM_MAXREG),
+        VMSTATE_UINT16_ARRAY(phy_regs, GemState, 32),
+        VMSTATE_UINT8(phy_loop, GemState),
+        VMSTATE_UINT32(rx_desc_addr, GemState),
+        VMSTATE_UINT32(tx_desc_addr, GemState),
+    }
+};
+
+static Property gem_properties[] = {
+    DEFINE_NIC_PROPERTIES(GemState, conf),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void gem_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sdc->init = gem_init;
+    dc->props = gem_properties;
+    dc->vmsd = &vmstate_cadence_gem;
+    dc->reset = gem_reset;
+}
+
+static TypeInfo gem_info = {
+    .class_init = gem_class_init,
+    .name  = "cadence_gem",
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size  = sizeof(GemState),
+};
+
+static void gem_register_types(void)
+{
+    type_register_static(&gem_info);
+}
+
+type_init(gem_register_types)
commit f3a6cc07124ab06905aac59bbfcafea5c71abd53
Author: Peter A. G. Crosthwaite <peter.crosthwaite at petalogix.com>
Date:   Mon Mar 5 14:39:11 2012 +1000

    cadence_ttc: initial version of device model
    
    Implemented cadence Triple Timer Counter (TCC)
    
    Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite at petalogix.com>
    Signed-off-by: John Linn <john.linn at xilinx.com>
    Acked-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index bb15b41..d1235da 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -347,6 +347,7 @@ 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 += cadence_uart.o
+obj-arm-y += cadence_ttc.o
 obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
 obj-arm-y += exynos4210_gic.o exynos4210_combiner.o exynos4210.o
 obj-arm-y += exynos4_boards.o exynos4210_uart.o exynos4210_pwm.o
diff --git a/hw/cadence_ttc.c b/hw/cadence_ttc.c
new file mode 100644
index 0000000..2b5477b
--- /dev/null
+++ b/hw/cadence_ttc.c
@@ -0,0 +1,489 @@
+/*
+ * Xilinx Zynq cadence TTC model
+ *
+ * Copyright (c) 2011 Xilinx Inc.
+ * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwaite at petalogix.com)
+ * Copyright (c) 2012 PetaLogix Pty Ltd.
+ * Written By Haibing Ma
+ *            M. Habib
+ *
+ * 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.
+ *
+ * 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 "sysbus.h"
+#include "qemu-timer.h"
+
+#ifdef CADENCE_TTC_ERR_DEBUG
+#define DB_PRINT(...) do { \
+    fprintf(stderr,  ": %s: ", __func__); \
+    fprintf(stderr, ## __VA_ARGS__); \
+    } while (0);
+#else
+    #define DB_PRINT(...)
+#endif
+
+#define COUNTER_INTR_IV     0x00000001
+#define COUNTER_INTR_M1     0x00000002
+#define COUNTER_INTR_M2     0x00000004
+#define COUNTER_INTR_M3     0x00000008
+#define COUNTER_INTR_OV     0x00000010
+#define COUNTER_INTR_EV     0x00000020
+
+#define COUNTER_CTRL_DIS    0x00000001
+#define COUNTER_CTRL_INT    0x00000002
+#define COUNTER_CTRL_DEC    0x00000004
+#define COUNTER_CTRL_MATCH  0x00000008
+#define COUNTER_CTRL_RST    0x00000010
+
+#define CLOCK_CTRL_PS_EN    0x00000001
+#define CLOCK_CTRL_PS_V     0x0000001e
+
+typedef struct {
+    QEMUTimer *timer;
+    int freq;
+
+    uint32_t reg_clock;
+    uint32_t reg_count;
+    uint32_t reg_value;
+    uint16_t reg_interval;
+    uint16_t reg_match[3];
+    uint32_t reg_intr;
+    uint32_t reg_intr_en;
+    uint32_t reg_event_ctrl;
+    uint32_t reg_event;
+
+    uint64_t cpu_time;
+    unsigned int cpu_time_valid;
+
+    qemu_irq irq;
+} CadenceTimerState;
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    CadenceTimerState timer[3];
+} CadenceTTCState;
+
+static void cadence_timer_update(CadenceTimerState *s)
+{
+    qemu_set_irq(s->irq, !!(s->reg_intr & s->reg_intr_en));
+}
+
+static CadenceTimerState *cadence_timer_from_addr(void *opaque,
+                                        target_phys_addr_t offset)
+{
+    unsigned int index;
+    CadenceTTCState *s = (CadenceTTCState *)opaque;
+
+    index = (offset >> 2) % 3;
+
+    return &s->timer[index];
+}
+
+static uint64_t cadence_timer_get_ns(CadenceTimerState *s, uint64_t timer_steps)
+{
+    /* timer_steps has max value of 0x100000000. double check it
+     * (or overflow can happen below) */
+    assert(timer_steps <= 1ULL << 32);
+
+    uint64_t r = timer_steps * 1000000000ULL;
+    if (s->reg_clock & CLOCK_CTRL_PS_EN) {
+        r >>= 16 - (((s->reg_clock & CLOCK_CTRL_PS_V) >> 1) + 1);
+    } else {
+        r >>= 16;
+    }
+    r /= (uint64_t)s->freq;
+    return r;
+}
+
+static uint64_t cadence_timer_get_steps(CadenceTimerState *s, uint64_t ns)
+{
+    uint64_t to_divide = 1000000000ULL;
+
+    uint64_t r = ns;
+     /* for very large intervals (> 8s) do some division first to stop
+      * overflow (costs some prescision) */
+    while (r >= 8ULL << 30 && to_divide > 1) {
+        r /= 1000;
+        to_divide /= 1000;
+    }
+    r <<= 16;
+    /* keep early-dividing as needed */
+    while (r >= 8ULL << 30 && to_divide > 1) {
+        r /= 1000;
+        to_divide /= 1000;
+    }
+    r *= (uint64_t)s->freq;
+    if (s->reg_clock & CLOCK_CTRL_PS_EN) {
+        r /= 1 << (((s->reg_clock & CLOCK_CTRL_PS_V) >> 1) + 1);
+    }
+
+    r /= to_divide;
+    return r;
+}
+
+/* determine if x is in between a and b, exclusive of a, inclusive of b */
+
+static inline int64_t is_between(int64_t x, int64_t a, int64_t b)
+{
+    if (a < b) {
+        return x > a && x <= b;
+    }
+    return x < a && x >= b;
+}
+
+static void cadence_timer_run(CadenceTimerState *s)
+{
+    int i;
+    int64_t event_interval, next_value;
+
+    assert(s->cpu_time_valid); /* cadence_timer_sync must be called first */
+
+    if (s->reg_count & COUNTER_CTRL_DIS) {
+        s->cpu_time_valid = 0;
+        return;
+    }
+
+    { /* figure out what's going to happen next (rollover or match) */
+        int64_t interval = (uint64_t)((s->reg_count & COUNTER_CTRL_INT) ?
+                (int64_t)s->reg_interval + 1 : 0x10000ULL) << 16;
+        next_value = (s->reg_count & COUNTER_CTRL_DEC) ? -1ULL : interval;
+        for (i = 0; i < 3; ++i) {
+            int64_t cand = (uint64_t)s->reg_match[i] << 16;
+            if (is_between(cand, (uint64_t)s->reg_value, next_value)) {
+                next_value = cand;
+            }
+        }
+    }
+    DB_PRINT("next timer event value: %09llx\n",
+            (unsigned long long)next_value);
+
+    event_interval = next_value - (int64_t)s->reg_value;
+    event_interval = (event_interval < 0) ? -event_interval : event_interval;
+
+    qemu_mod_timer(s->timer, s->cpu_time +
+                cadence_timer_get_ns(s, event_interval));
+}
+
+static void cadence_timer_sync(CadenceTimerState *s)
+{
+    int i;
+    int64_t r, x;
+    int64_t interval = ((s->reg_count & COUNTER_CTRL_INT) ?
+            (int64_t)s->reg_interval + 1 : 0x10000ULL) << 16;
+    uint64_t old_time = s->cpu_time;
+
+    s->cpu_time = qemu_get_clock_ns(vm_clock);
+    DB_PRINT("cpu time: %lld ns\n", (long long)old_time);
+
+    if (!s->cpu_time_valid || old_time == s->cpu_time) {
+        s->cpu_time_valid = 1;
+        return;
+    }
+
+    r = (int64_t)cadence_timer_get_steps(s, s->cpu_time - old_time);
+    x = (int64_t)s->reg_value + ((s->reg_count & COUNTER_CTRL_DEC) ? -r : r);
+
+    for (i = 0; i < 3; ++i) {
+        int64_t m = (int64_t)s->reg_match[i] << 16;
+        if (m > interval) {
+            continue;
+        }
+        /* check to see if match event has occurred. check m +/- interval
+         * to account for match events in wrap around cases */
+        if (is_between(m, s->reg_value, x) ||
+            is_between(m + interval, s->reg_value, x) ||
+            is_between(m - interval, s->reg_value, x)) {
+            s->reg_intr |= (2 << i);
+        }
+    }
+    while (x < 0) {
+        x += interval;
+    }
+    s->reg_value = (uint32_t)(x % interval);
+
+    if (s->reg_value != x) {
+        s->reg_intr |= (s->reg_count & COUNTER_CTRL_INT) ?
+            COUNTER_INTR_IV : COUNTER_INTR_OV;
+    }
+    cadence_timer_update(s);
+}
+
+static void cadence_timer_tick(void *opaque)
+{
+    CadenceTimerState *s = opaque;
+
+    DB_PRINT("\n");
+    cadence_timer_sync(s);
+    cadence_timer_run(s);
+}
+
+static uint32_t cadence_ttc_read_imp(void *opaque, target_phys_addr_t offset)
+{
+    CadenceTimerState *s = cadence_timer_from_addr(opaque, offset);
+    uint32_t value;
+
+    cadence_timer_sync(s);
+    cadence_timer_run(s);
+
+    switch (offset) {
+    case 0x00: /* clock control */
+    case 0x04:
+    case 0x08:
+        return s->reg_clock;
+
+    case 0x0c: /* counter control */
+    case 0x10:
+    case 0x14:
+        return s->reg_count;
+
+    case 0x18: /* counter value */
+    case 0x1c:
+    case 0x20:
+        return (uint16_t)(s->reg_value >> 16);
+
+    case 0x24: /* reg_interval counter */
+    case 0x28:
+    case 0x2c:
+        return s->reg_interval;
+
+    case 0x30: /* match 1 counter */
+    case 0x34:
+    case 0x38:
+        return s->reg_match[0];
+
+    case 0x3c: /* match 2 counter */
+    case 0x40:
+    case 0x44:
+        return s->reg_match[1];
+
+    case 0x48: /* match 3 counter */
+    case 0x4c:
+    case 0x50:
+        return s->reg_match[2];
+
+    case 0x54: /* interrupt register */
+    case 0x58:
+    case 0x5c:
+        /* cleared after read */
+        value = s->reg_intr;
+        s->reg_intr = 0;
+        return value;
+
+    case 0x60: /* interrupt enable */
+    case 0x64:
+    case 0x68:
+        return s->reg_intr_en;
+
+    case 0x6c:
+    case 0x70:
+    case 0x74:
+        return s->reg_event_ctrl;
+
+    case 0x78:
+    case 0x7c:
+    case 0x80:
+        return s->reg_event;
+
+    default:
+        return 0;
+    }
+}
+
+static uint64_t cadence_ttc_read(void *opaque, target_phys_addr_t offset,
+    unsigned size)
+{
+    uint32_t ret = cadence_ttc_read_imp(opaque, offset);
+
+    DB_PRINT("addr: %08x data: %08x\n", offset, ret);
+    return ret;
+}
+
+static void cadence_ttc_write(void *opaque, target_phys_addr_t offset,
+        uint64_t value, unsigned size)
+{
+    CadenceTimerState *s = cadence_timer_from_addr(opaque, offset);
+
+    DB_PRINT("addr: %08x data %08x\n", offset, (unsigned)value);
+
+    cadence_timer_sync(s);
+
+    switch (offset) {
+    case 0x00: /* clock control */
+    case 0x04:
+    case 0x08:
+        s->reg_clock = value & 0x3F;
+        break;
+
+    case 0x0c: /* counter control */
+    case 0x10:
+    case 0x14:
+        if (value & COUNTER_CTRL_RST) {
+            s->reg_value = 0;
+        }
+        s->reg_count = value & 0x3f & ~COUNTER_CTRL_RST;
+        break;
+
+    case 0x24: /* interval register */
+    case 0x28:
+    case 0x2c:
+        s->reg_interval = value & 0xffff;
+        break;
+
+    case 0x30: /* match register */
+    case 0x34:
+    case 0x38:
+        s->reg_match[0] = value & 0xffff;
+
+    case 0x3c: /* match register */
+    case 0x40:
+    case 0x44:
+        s->reg_match[1] = value & 0xffff;
+
+    case 0x48: /* match register */
+    case 0x4c:
+    case 0x50:
+        s->reg_match[2] = value & 0xffff;
+        break;
+
+    case 0x54: /* interrupt register */
+    case 0x58:
+    case 0x5c:
+        s->reg_intr &= (~value & 0xfff);
+        break;
+
+    case 0x60: /* interrupt enable */
+    case 0x64:
+    case 0x68:
+        s->reg_intr_en = value & 0x3f;
+        break;
+
+    case 0x6c: /* event control */
+    case 0x70:
+    case 0x74:
+        s->reg_event_ctrl = value & 0x07;
+        break;
+
+    default:
+        return;
+    }
+
+    cadence_timer_run(s);
+    cadence_timer_update(s);
+}
+
+static const MemoryRegionOps cadence_ttc_ops = {
+    .read = cadence_ttc_read,
+    .write = cadence_ttc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void cadence_timer_reset(CadenceTimerState *s)
+{
+   s->reg_count = 0x21;
+}
+
+static void cadence_timer_init(uint32_t freq, CadenceTimerState *s)
+{
+    memset(s, 0, sizeof(CadenceTimerState));
+    s->freq = freq;
+
+    cadence_timer_reset(s);
+
+    s->timer = qemu_new_timer_ns(vm_clock, cadence_timer_tick, s);
+}
+
+static int cadence_ttc_init(SysBusDevice *dev)
+{
+    CadenceTTCState *s = FROM_SYSBUS(CadenceTTCState, dev);
+    int i;
+
+    for (i = 0; i < 3; ++i) {
+        cadence_timer_init(2500000, &s->timer[i]);
+        sysbus_init_irq(dev, &s->timer[i].irq);
+    }
+
+    memory_region_init_io(&s->iomem, &cadence_ttc_ops, s, "timer", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    return 0;
+}
+
+static void cadence_timer_pre_save(void *opaque)
+{
+    cadence_timer_sync((CadenceTimerState *)opaque);
+}
+
+static int cadence_timer_post_load(void *opaque, int version_id)
+{
+    CadenceTimerState *s = opaque;
+
+    s->cpu_time_valid = 0;
+    cadence_timer_sync(s);
+    cadence_timer_run(s);
+    cadence_timer_update(s);
+    return 0;
+}
+
+static const VMStateDescription vmstate_cadence_timer = {
+    .name = "cadence_timer",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .pre_save = cadence_timer_pre_save,
+    .post_load = cadence_timer_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(reg_clock, CadenceTimerState),
+        VMSTATE_UINT32(reg_count, CadenceTimerState),
+        VMSTATE_UINT32(reg_value, CadenceTimerState),
+        VMSTATE_UINT16(reg_interval, CadenceTimerState),
+        VMSTATE_UINT16_ARRAY(reg_match, CadenceTimerState, 3),
+        VMSTATE_UINT32(reg_intr, CadenceTimerState),
+        VMSTATE_UINT32(reg_intr_en, CadenceTimerState),
+        VMSTATE_UINT32(reg_event_ctrl, CadenceTimerState),
+        VMSTATE_UINT32(reg_event, CadenceTimerState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_cadence_ttc = {
+    .name = "cadence_TTC",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_STRUCT_ARRAY(timer, CadenceTTCState, 3, 0,
+                            vmstate_cadence_timer,
+                            CadenceTimerState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void cadence_ttc_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sdc->init = cadence_ttc_init;
+    dc->vmsd = &vmstate_cadence_ttc;
+}
+
+static TypeInfo cadence_ttc_info = {
+    .name  = "cadence_ttc",
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size  = sizeof(CadenceTTCState),
+    .class_init = cadence_ttc_class_init,
+};
+
+static void cadence_ttc_register_types(void)
+{
+    type_register_static(&cadence_ttc_info);
+}
+
+type_init(cadence_ttc_register_types)
commit 35548b06cf55673e8059c720245e898dff661129
Author: Peter A. G. Crosthwaite <peter.crosthwaite at petalogix.com>
Date:   Mon Mar 5 14:39:10 2012 +1000

    cadence_uart: initial version of device model
    
    Implemented cadence UART serial controller
    
    Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite at petalogix.com>
    Signed-off-by: John Linn <john.linn at xilinx.com>
    Acked-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index f853883..bb15b41 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -346,6 +346,7 @@ 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 += cadence_uart.o
 obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
 obj-arm-y += exynos4210_gic.o exynos4210_combiner.o exynos4210.o
 obj-arm-y += exynos4_boards.o exynos4210_uart.o exynos4210_pwm.o
diff --git a/hw/cadence_uart.c b/hw/cadence_uart.c
new file mode 100644
index 0000000..d98e531
--- /dev/null
+++ b/hw/cadence_uart.c
@@ -0,0 +1,513 @@
+/*
+ * Device model for Cadence UART
+ *
+ * Copyright (c) 2010 Xilinx Inc.
+ * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwaite at petalogix.com)
+ * Copyright (c) 2012 PetaLogix Pty Ltd.
+ * Written by Haibing Ma
+ *            M.Habib
+ *
+ * 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.
+ *
+ * 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 "sysbus.h"
+#include "qemu-char.h"
+#include "qemu-timer.h"
+
+#ifdef CADENCE_UART_ERR_DEBUG
+#define DB_PRINT(...) do { \
+    fprintf(stderr,  ": %s: ", __func__); \
+    fprintf(stderr, ## __VA_ARGS__); \
+    } while (0);
+#else
+    #define DB_PRINT(...)
+#endif
+
+#define UART_SR_INTR_RTRIG     0x00000001
+#define UART_SR_INTR_REMPTY    0x00000002
+#define UART_SR_INTR_RFUL      0x00000004
+#define UART_SR_INTR_TEMPTY    0x00000008
+#define UART_SR_INTR_TFUL      0x00000010
+/* bits fields in CSR that correlate to CISR. If any of these bits are set in
+ * SR, then the same bit in CISR is set high too */
+#define UART_SR_TO_CISR_MASK   0x0000001F
+
+#define UART_INTR_ROVR         0x00000020
+#define UART_INTR_FRAME        0x00000040
+#define UART_INTR_PARE         0x00000080
+#define UART_INTR_TIMEOUT      0x00000100
+#define UART_INTR_DMSI         0x00000200
+
+#define UART_SR_RACTIVE    0x00000400
+#define UART_SR_TACTIVE    0x00000800
+#define UART_SR_FDELT      0x00001000
+
+#define UART_CR_RXRST       0x00000001
+#define UART_CR_TXRST       0x00000002
+#define UART_CR_RX_EN       0x00000004
+#define UART_CR_RX_DIS      0x00000008
+#define UART_CR_TX_EN       0x00000010
+#define UART_CR_TX_DIS      0x00000020
+#define UART_CR_RST_TO      0x00000040
+#define UART_CR_STARTBRK    0x00000080
+#define UART_CR_STOPBRK     0x00000100
+
+#define UART_MR_CLKS            0x00000001
+#define UART_MR_CHRL            0x00000006
+#define UART_MR_CHRL_SH         1
+#define UART_MR_PAR             0x00000038
+#define UART_MR_PAR_SH          3
+#define UART_MR_NBSTOP          0x000000C0
+#define UART_MR_NBSTOP_SH       6
+#define UART_MR_CHMODE          0x00000300
+#define UART_MR_CHMODE_SH       8
+#define UART_MR_UCLKEN          0x00000400
+#define UART_MR_IRMODE          0x00000800
+
+#define UART_DATA_BITS_6       (0x3 << UART_MR_CHRL_SH)
+#define UART_DATA_BITS_7       (0x2 << UART_MR_CHRL_SH)
+#define UART_PARITY_ODD        (0x1 << UART_MR_PAR_SH)
+#define UART_PARITY_EVEN       (0x0 << UART_MR_PAR_SH)
+#define UART_STOP_BITS_1       (0x3 << UART_MR_NBSTOP_SH)
+#define UART_STOP_BITS_2       (0x2 << UART_MR_NBSTOP_SH)
+#define NORMAL_MODE            (0x0 << UART_MR_CHMODE_SH)
+#define ECHO_MODE              (0x1 << UART_MR_CHMODE_SH)
+#define LOCAL_LOOPBACK         (0x2 << UART_MR_CHMODE_SH)
+#define REMOTE_LOOPBACK        (0x3 << UART_MR_CHMODE_SH)
+
+#define RX_FIFO_SIZE           16
+#define TX_FIFO_SIZE           16
+#define UART_INPUT_CLK         50000000
+
+#define R_CR       (0x00/4)
+#define R_MR       (0x04/4)
+#define R_IER      (0x08/4)
+#define R_IDR      (0x0C/4)
+#define R_IMR      (0x10/4)
+#define R_CISR     (0x14/4)
+#define R_BRGR     (0x18/4)
+#define R_RTOR     (0x1C/4)
+#define R_RTRIG    (0x20/4)
+#define R_MCR      (0x24/4)
+#define R_MSR      (0x28/4)
+#define R_SR       (0x2C/4)
+#define R_TX_RX    (0x30/4)
+#define R_BDIV     (0x34/4)
+#define R_FDEL     (0x38/4)
+#define R_PMIN     (0x3C/4)
+#define R_PWID     (0x40/4)
+#define R_TTRIG    (0x44/4)
+
+#define R_MAX (R_TTRIG + 1)
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t r[R_MAX];
+    uint8_t r_fifo[RX_FIFO_SIZE];
+    uint32_t rx_wpos;
+    uint32_t rx_count;
+    uint64_t char_tx_time;
+    CharDriverState *chr;
+    qemu_irq irq;
+    struct QEMUTimer *fifo_trigger_handle;
+    struct QEMUTimer *tx_time_handle;
+} UartState;
+
+static void uart_update_status(UartState *s)
+{
+    s->r[R_CISR] |= s->r[R_SR] & UART_SR_TO_CISR_MASK;
+    qemu_set_irq(s->irq, !!(s->r[R_IMR] & s->r[R_CISR]));
+}
+
+static void fifo_trigger_update(void *opaque)
+{
+    UartState *s = (UartState *)opaque;
+
+    s->r[R_CISR] |= UART_INTR_TIMEOUT;
+
+    uart_update_status(s);
+}
+
+static void uart_tx_redo(UartState *s)
+{
+    uint64_t new_tx_time = qemu_get_clock_ns(vm_clock);
+
+    qemu_mod_timer(s->tx_time_handle, new_tx_time + s->char_tx_time);
+
+    s->r[R_SR] |= UART_SR_INTR_TEMPTY;
+
+    uart_update_status(s);
+}
+
+static void uart_tx_write(void *opaque)
+{
+    UartState *s = (UartState *)opaque;
+
+    uart_tx_redo(s);
+}
+
+static void uart_rx_reset(UartState *s)
+{
+    s->rx_wpos = 0;
+    s->rx_count = 0;
+
+    s->r[R_SR] |= UART_SR_INTR_REMPTY;
+    s->r[R_SR] &= ~UART_SR_INTR_RFUL;
+}
+
+static void uart_tx_reset(UartState *s)
+{
+    s->r[R_SR] |= UART_SR_INTR_TEMPTY;
+    s->r[R_SR] &= ~UART_SR_INTR_TFUL;
+}
+
+static void uart_send_breaks(UartState *s)
+{
+    int break_enabled = 1;
+
+    qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
+                               &break_enabled);
+}
+
+static void uart_parameters_setup(UartState *s)
+{
+    QEMUSerialSetParams ssp;
+    unsigned int baud_rate, packet_size;
+
+    baud_rate = (s->r[R_MR] & UART_MR_CLKS) ?
+            UART_INPUT_CLK / 8 : UART_INPUT_CLK;
+
+    ssp.speed = baud_rate / (s->r[R_BRGR] * (s->r[R_BDIV] + 1));
+    packet_size = 1;
+
+    switch (s->r[R_MR] & UART_MR_PAR) {
+    case UART_PARITY_EVEN:
+        ssp.parity = 'E';
+        packet_size++;
+        break;
+    case UART_PARITY_ODD:
+        ssp.parity = 'O';
+        packet_size++;
+        break;
+    default:
+        ssp.parity = 'N';
+        break;
+    }
+
+    switch (s->r[R_MR] & UART_MR_CHRL) {
+    case UART_DATA_BITS_6:
+        ssp.data_bits = 6;
+        break;
+    case UART_DATA_BITS_7:
+        ssp.data_bits = 7;
+        break;
+    default:
+        ssp.data_bits = 8;
+        break;
+    }
+
+    switch (s->r[R_MR] & UART_MR_NBSTOP) {
+    case UART_STOP_BITS_1:
+        ssp.stop_bits = 1;
+        break;
+    default:
+        ssp.stop_bits = 2;
+        break;
+    }
+
+    packet_size += ssp.data_bits + ssp.stop_bits;
+    s->char_tx_time = (get_ticks_per_sec() / ssp.speed) * packet_size;
+    qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
+}
+
+static int uart_can_receive(void *opaque)
+{
+    UartState *s = (UartState *)opaque;
+
+    return RX_FIFO_SIZE - s->rx_count;
+}
+
+static void uart_ctrl_update(UartState *s)
+{
+    if (s->r[R_CR] & UART_CR_TXRST) {
+        uart_tx_reset(s);
+    }
+
+    if (s->r[R_CR] & UART_CR_RXRST) {
+        uart_rx_reset(s);
+    }
+
+    s->r[R_CR] &= ~(UART_CR_TXRST | UART_CR_RXRST);
+
+    if ((s->r[R_CR] & UART_CR_TX_EN) && !(s->r[R_CR] & UART_CR_TX_DIS)) {
+            uart_tx_redo(s);
+    }
+
+    if (s->r[R_CR] & UART_CR_STARTBRK && !(s->r[R_CR] & UART_CR_STOPBRK)) {
+        uart_send_breaks(s);
+    }
+}
+
+static void uart_write_rx_fifo(void *opaque, const uint8_t *buf, int size)
+{
+    UartState *s = (UartState *)opaque;
+    uint64_t new_rx_time = qemu_get_clock_ns(vm_clock);
+    int i;
+
+    if ((s->r[R_CR] & UART_CR_RX_DIS) || !(s->r[R_CR] & UART_CR_RX_EN)) {
+        return;
+    }
+
+    s->r[R_SR] &= ~UART_SR_INTR_REMPTY;
+
+    if (s->rx_count == RX_FIFO_SIZE) {
+        s->r[R_CISR] |= UART_INTR_ROVR;
+    } else {
+        for (i = 0; i < size; i++) {
+            s->r_fifo[s->rx_wpos] = buf[i];
+            s->rx_wpos = (s->rx_wpos + 1) % RX_FIFO_SIZE;
+            s->rx_count++;
+
+            if (s->rx_count == RX_FIFO_SIZE) {
+                s->r[R_SR] |= UART_SR_INTR_RFUL;
+                break;
+            }
+
+            if (s->rx_count >= s->r[R_RTRIG]) {
+                s->r[R_SR] |= UART_SR_INTR_RTRIG;
+            }
+        }
+        qemu_mod_timer(s->fifo_trigger_handle, new_rx_time +
+                                                (s->char_tx_time * 4));
+    }
+    uart_update_status(s);
+}
+
+static void uart_write_tx_fifo(UartState *s, const uint8_t *buf, int size)
+{
+    if ((s->r[R_CR] & UART_CR_TX_DIS) || !(s->r[R_CR] & UART_CR_TX_EN)) {
+        return;
+    }
+
+    while (size) {
+        size -= qemu_chr_fe_write(s->chr, buf, size);
+    }
+}
+
+static void uart_receive(void *opaque, const uint8_t *buf, int size)
+{
+    UartState *s = (UartState *)opaque;
+    uint32_t ch_mode = s->r[R_MR] & UART_MR_CHMODE;
+
+    if (ch_mode == NORMAL_MODE || ch_mode == ECHO_MODE) {
+        uart_write_rx_fifo(opaque, buf, size);
+    }
+    if (ch_mode == REMOTE_LOOPBACK || ch_mode == ECHO_MODE) {
+        uart_write_tx_fifo(s, buf, size);
+    }
+}
+
+static void uart_event(void *opaque, int event)
+{
+    UartState *s = (UartState *)opaque;
+    uint8_t buf = '\0';
+
+    if (event == CHR_EVENT_BREAK) {
+        uart_write_rx_fifo(opaque, &buf, 1);
+    }
+
+    uart_update_status(s);
+}
+
+static void uart_read_rx_fifo(UartState *s, uint32_t *c)
+{
+    if ((s->r[R_CR] & UART_CR_RX_DIS) || !(s->r[R_CR] & UART_CR_RX_EN)) {
+        return;
+    }
+
+    s->r[R_SR] &= ~UART_SR_INTR_RFUL;
+
+    if (s->rx_count) {
+        uint32_t rx_rpos =
+                (RX_FIFO_SIZE + s->rx_wpos - s->rx_count) % RX_FIFO_SIZE;
+        *c = s->r_fifo[rx_rpos];
+        s->rx_count--;
+
+        if (!s->rx_count) {
+            s->r[R_SR] |= UART_SR_INTR_REMPTY;
+        }
+    } else {
+        *c = 0;
+        s->r[R_SR] |= UART_SR_INTR_REMPTY;
+    }
+
+    if (s->rx_count < s->r[R_RTRIG]) {
+        s->r[R_SR] &= ~UART_SR_INTR_RTRIG;
+    }
+    uart_update_status(s);
+}
+
+static void uart_write(void *opaque, target_phys_addr_t offset,
+                          uint64_t value, unsigned size)
+{
+    UartState *s = (UartState *)opaque;
+
+    DB_PRINT(" offset:%x data:%08x\n", offset, (unsigned)value);
+    offset >>= 2;
+    switch (offset) {
+    case R_IER: /* ier (wts imr) */
+        s->r[R_IMR] |= value;
+        break;
+    case R_IDR: /* idr (wtc imr) */
+        s->r[R_IMR] &= ~value;
+        break;
+    case R_IMR: /* imr (read only) */
+        break;
+    case R_CISR: /* cisr (wtc) */
+        s->r[R_CISR] &= ~value;
+        break;
+    case R_TX_RX: /* UARTDR */
+        switch (s->r[R_MR] & UART_MR_CHMODE) {
+        case NORMAL_MODE:
+            uart_write_tx_fifo(s, (uint8_t *) &value, 1);
+            break;
+        case LOCAL_LOOPBACK:
+            uart_write_rx_fifo(opaque, (uint8_t *) &value, 1);
+            break;
+        }
+        break;
+    default:
+        s->r[offset] = value;
+    }
+
+    switch (offset) {
+    case R_CR:
+        uart_ctrl_update(s);
+        break;
+    case R_MR:
+        uart_parameters_setup(s);
+        break;
+    }
+}
+
+static uint64_t uart_read(void *opaque, target_phys_addr_t offset,
+        unsigned size)
+{
+    UartState *s = (UartState *)opaque;
+    uint32_t c = 0;
+
+    offset >>= 2;
+    if (offset > R_MAX) {
+        return 0;
+    } else if (offset == R_TX_RX) {
+        uart_read_rx_fifo(s, &c);
+        return c;
+    }
+    return s->r[offset];
+}
+
+static const MemoryRegionOps uart_ops = {
+    .read = uart_read,
+    .write = uart_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void cadence_uart_reset(UartState *s)
+{
+    s->r[R_CR] = 0x00000128;
+    s->r[R_IMR] = 0;
+    s->r[R_CISR] = 0;
+    s->r[R_RTRIG] = 0x00000020;
+    s->r[R_BRGR] = 0x0000000F;
+    s->r[R_TTRIG] = 0x00000020;
+
+    uart_rx_reset(s);
+    uart_tx_reset(s);
+
+    s->rx_count = 0;
+    s->rx_wpos = 0;
+}
+
+static int cadence_uart_init(SysBusDevice *dev)
+{
+    UartState *s = FROM_SYSBUS(UartState, dev);
+
+    memory_region_init_io(&s->iomem, &uart_ops, s, "uart", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->irq);
+
+    s->fifo_trigger_handle = qemu_new_timer_ns(vm_clock,
+            (QEMUTimerCB *)fifo_trigger_update, s);
+
+    s->tx_time_handle = qemu_new_timer_ns(vm_clock,
+            (QEMUTimerCB *)uart_tx_write, s);
+
+    s->char_tx_time = (get_ticks_per_sec() / 9600) * 10;
+
+    s->chr = qemu_char_get_next_serial();
+
+    cadence_uart_reset(s);
+
+    if (s->chr) {
+        qemu_chr_add_handlers(s->chr, uart_can_receive, uart_receive,
+                              uart_event, s);
+    }
+
+    return 0;
+}
+
+static int cadence_uart_post_load(void *opaque, int version_id)
+{
+    UartState *s = opaque;
+
+    uart_parameters_setup(s);
+    uart_update_status(s);
+    return 0;
+}
+
+static const VMStateDescription vmstate_cadence_uart = {
+    .name = "cadence_uart",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .post_load = cadence_uart_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(r, UartState, R_MAX),
+        VMSTATE_UINT8_ARRAY(r_fifo, UartState, RX_FIFO_SIZE),
+        VMSTATE_UINT32(rx_count, UartState),
+        VMSTATE_UINT32(rx_wpos, UartState),
+        VMSTATE_TIMER(fifo_trigger_handle, UartState),
+        VMSTATE_TIMER(tx_time_handle, UartState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void cadence_uart_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sdc->init = cadence_uart_init;
+    dc->vmsd = &vmstate_cadence_uart;
+}
+
+static TypeInfo cadence_uart_info = {
+    .name          = "cadence_uart",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(UartState),
+    .class_init    = cadence_uart_class_init,
+};
+
+static void cadence_uart_register_types(void)
+{
+    type_register_static(&cadence_uart_info);
+}
+
+type_init(cadence_uart_register_types)
commit da71ebd1450fcf6f0c424810a37ec6abee02a22b
Author: Peter A. G. Crosthwaite <peter.crosthwaite at petalogix.com>
Date:   Sun Mar 4 21:03:55 2012 +1000

    microblaze_boot: enabled -dtb argument
    
    Use the -dtb argument for passing is a custom dtb rather than the old
    hardcoded "mb.dtb"
    
    Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite at petalogix.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/hw/microblaze_boot.c b/hw/microblaze_boot.c
index 37fce50..b2f96df 100644
--- a/hw/microblaze_boot.c
+++ b/hw/microblaze_boot.c
@@ -59,23 +59,16 @@ static int microblaze_load_dtb(target_phys_addr_t addr,
                                       const char *kernel_cmdline,
                                       const char *dtb_filename)
 {
-    char *path;
     int fdt_size;
 #ifdef CONFIG_FDT
-    void *fdt;
+    void *fdt = NULL;
     int r;
 
-    /* Try the local "mb.dtb" override.  */
-    fdt = load_device_tree("mb.dtb", &fdt_size);
+    if (dtb_filename) {
+        fdt = load_device_tree(dtb_filename, &fdt_size);
+    }
     if (!fdt) {
-        path = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename);
-        if (path) {
-            fdt = load_device_tree(path, &fdt_size);
-            g_free(path);
-        }
-        if (!fdt) {
-            return 0;
-        }
+        return 0;
     }
 
     if (kernel_cmdline) {
@@ -90,15 +83,9 @@ static int microblaze_load_dtb(target_phys_addr_t addr,
 #else
     /* We lack libfdt so we cannot manipulate the fdt. Just pass on the blob
        to the kernel.  */
-    fdt_size = load_image_targphys("mb.dtb", addr, 0x10000);
-    if (fdt_size < 0) {
-        path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
-        if (path) {
-            fdt_size = load_image_targphys(path, addr, 0x10000);
-            g_free(path);
-        }
+    if (dtb_filename) {
+        fdt_size = load_image_targphys(dtb_filename, addr, 0x10000);
     }
-
     if (kernel_cmdline) {
         fprintf(stderr,
                 "Warning: missing libfdt, cannot pass cmdline to kernel!\n");
@@ -123,8 +110,15 @@ void microblaze_load_kernel(CPUState *env, target_phys_addr_t ddr_base,
 
     machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
     if (machine_opts) {
+        const char *dtb_arg;
         kernel_filename = qemu_opt_get(machine_opts, "kernel");
         kernel_cmdline = qemu_opt_get(machine_opts, "append");
+        dtb_arg = qemu_opt_get(machine_opts, "dtb");
+        if (dtb_arg) { /* Preference a -dtb argument */
+            dtb_filename = dtb_arg;
+        } else { /* default to pcbios dtb as passed by machine_init */
+            dtb_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename);
+        }
     }
 
     boot_info.machine_cpu_reset = machine_cpu_reset;
commit 379b5c7c3cf5891e8905b0a12c07566362b2588a
Author: Peter A. G. Crosthwaite <peter.crosthwaite at petalogix.com>
Date:   Sun Mar 4 21:03:54 2012 +1000

    qemu-options.hx: allow -dtb argument for all archs
    
    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/qemu-options.hx b/qemu-options.hx
index e38799c..daefce3 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2038,7 +2038,7 @@ first module.
 ETEXI
 
 DEF("dtb", HAS_ARG, QEMU_OPTION_dtb, \
-    "-dtb    file    use 'file' as device tree image\n", QEMU_ARCH_ARM)
+    "-dtb    file    use 'file' as device tree image\n", QEMU_ARCH_ALL)
 STEXI
 @item -dtb @var{file}
 @findex -dtb
commit cba1fd36554c4a95a1b0e0738b1eec7de3a7617a
Author: Peter A. G. Crosthwaite <peter.crosthwaite at petalogix.com>
Date:   Sun Mar 4 21:03:53 2012 +1000

    petalogix_s2adsp1800: macro'd magic numbers
    
    defined macros for the addresses of the peripherals in machine model
    
    Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite at petalogix.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index 99c3590..2cb0b1f 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -42,6 +42,13 @@
 
 #define BINARY_DEVICE_TREE_FILE "petalogix-s3adsp1800.dtb"
 
+#define MEMORY_BASEADDR 0x90000000
+#define FLASH_BASEADDR 0xa0000000
+#define INTC_BASEADDR 0x81800000
+#define TIMER_BASEADDR 0x83c00000
+#define UARTLITE_BASEADDR 0x84000000
+#define ETHLITE_BASEADDR 0x81000000
+
 static void machine_cpu_reset(CPUState *env)
 {
     /* FIXME: move to machine specfic cpu reset */
@@ -59,8 +66,7 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
     CPUState *env;
     DriveInfo *dinfo;
     int i;
-    /* FIXME: remove harcoded magic numbers */
-    target_phys_addr_t ddr_base = 0x90000000;
+    target_phys_addr_t ddr_base = MEMORY_BASEADDR;
     MemoryRegion *phys_lmb_bram = g_new(MemoryRegion, 1);
     MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
     qemu_irq irq[32], *cpu_irq;
@@ -83,22 +89,22 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
     memory_region_add_subregion(sysmem, ddr_base, phys_ram);
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
-    pflash_cfi01_register(0xa0000000,
+    pflash_cfi01_register(FLASH_BASEADDR,
                           NULL, "petalogix_s3adsp1800.flash", FLASH_SIZE,
                           dinfo ? dinfo->bdrv : NULL, (64 * 1024),
                           FLASH_SIZE >> 16,
                           1, 0x89, 0x18, 0x0000, 0x0, 1);
 
     cpu_irq = microblaze_pic_init_cpu(env);
-    dev = xilinx_intc_create(0x81800000, cpu_irq[0], 2);
+    dev = xilinx_intc_create(INTC_BASEADDR, cpu_irq[0], 2);
     for (i = 0; i < 32; i++) {
         irq[i] = qdev_get_gpio_in(dev, i);
     }
 
-    sysbus_create_simple("xilinx,uartlite", 0x84000000, irq[3]);
+    sysbus_create_simple("xilinx,uartlite", UARTLITE_BASEADDR, irq[3]);
     /* 2 timers at irq 2 @ 62 Mhz.  */
-    xilinx_timer_create(0x83c00000, irq[0], 2, 62 * 1000000);
-    xilinx_ethlite_create(&nd_table[0], 0x81000000, irq[1], 0, 0);
+    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,
                     BINARY_DEVICE_TREE_FILE, machine_cpu_reset);
commit 1f28fac87e8f1003cf77bb04e62e17e1236530b1
Author: Peter A. G. Crosthwaite <peter.crosthwaite at petalogix.com>
Date:   Sun Mar 4 21:03:52 2012 +1000

    petalogix_s2adsp1800: moved rst logic to rst fn
    
    This belongs in the machine specific reset function
    
    Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite at petalogix.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index 7c6e9b8..99c3590 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -42,6 +42,12 @@
 
 #define BINARY_DEVICE_TREE_FILE "petalogix-s3adsp1800.dtb"
 
+static void machine_cpu_reset(CPUState *env)
+{
+    /* FIXME: move to machine specfic cpu reset */
+    env->pvr.regs[10] = 0x0c000000; /* spartan 3a dsp family.  */
+}
+
 static void
 petalogix_s3adsp1800_init(ram_addr_t ram_size,
                           const char *boot_device,
@@ -53,6 +59,7 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
     CPUState *env;
     DriveInfo *dinfo;
     int i;
+    /* FIXME: remove harcoded magic numbers */
     target_phys_addr_t ddr_base = 0x90000000;
     MemoryRegion *phys_lmb_bram = g_new(MemoryRegion, 1);
     MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
@@ -65,9 +72,6 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
     }
     env = cpu_init(cpu_model);
 
-    /* FIXME: move to machine specfic cpu reset */
-    env->pvr.regs[10] = 0x0c000000; /* spartan 3a dsp family.  */
-
     /* Attach emulated BRAM through the LMB.  */
     memory_region_init_ram(phys_lmb_bram,
                            "petalogix_s3adsp1800.lmb_bram", LMB_BRAM_SIZE);
@@ -97,7 +101,7 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
     xilinx_ethlite_create(&nd_table[0], 0x81000000, irq[1], 0, 0);
 
     microblaze_load_kernel(env, ddr_base, ram_size,
-                    BINARY_DEVICE_TREE_FILE, NULL);
+                    BINARY_DEVICE_TREE_FILE, machine_cpu_reset);
 }
 
 static QEMUMachine petalogix_s3adsp1800_machine = {
commit d94e743476bf7d0d55ea6f4a90760054ce959030
Author: Peter A. G. Crosthwaite <peter.crosthwaite at petalogix.com>
Date:   Sun Mar 4 21:03:51 2012 +1000

    microblaze: factored out common boot code
    
    factored out the copy-pasted common boot code from the two microblaze platforms
    into a dedicated microblaze bootloader (microblaze_boot.o).
    
    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/Makefile.target b/Makefile.target
index 343eb78..f853883 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -307,6 +307,7 @@ 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
diff --git a/hw/microblaze_boot.c b/hw/microblaze_boot.c
new file mode 100644
index 0000000..37fce50
--- /dev/null
+++ b/hw/microblaze_boot.c
@@ -0,0 +1,183 @@
+/*
+ * Microblaze kernel loader
+ *
+ * Copyright (c) 2012 Peter Crosthwaite <peter.crosthwaite at petalogix.com>
+ * Copyright (c) 2012 PetaLogix
+ * Copyright (c) 2009 Edgar E. Iglesias.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu-option.h"
+#include "qemu-config.h"
+#include "qemu-common.h"
+#include "device_tree.h"
+#include "loader.h"
+#include "elf.h"
+
+#include "microblaze_boot.h"
+
+static struct
+{
+    void (*machine_cpu_reset)(CPUState *);
+    uint32_t bootstrap_pc;
+    uint32_t cmdline;
+    uint32_t fdt;
+} boot_info;
+
+static void main_cpu_reset(void *opaque)
+{
+    CPUState *env = opaque;
+
+    cpu_reset(env);
+    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);
+    }
+}
+
+static int microblaze_load_dtb(target_phys_addr_t addr,
+                                      uint32_t ramsize,
+                                      const char *kernel_cmdline,
+                                      const char *dtb_filename)
+{
+    char *path;
+    int fdt_size;
+#ifdef CONFIG_FDT
+    void *fdt;
+    int r;
+
+    /* Try the local "mb.dtb" override.  */
+    fdt = load_device_tree("mb.dtb", &fdt_size);
+    if (!fdt) {
+        path = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename);
+        if (path) {
+            fdt = load_device_tree(path, &fdt_size);
+            g_free(path);
+        }
+        if (!fdt) {
+            return 0;
+        }
+    }
+
+    if (kernel_cmdline) {
+        r = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
+                                                        kernel_cmdline);
+        if (r < 0) {
+            fprintf(stderr, "couldn't set /chosen/bootargs\n");
+        }
+    }
+
+    cpu_physical_memory_write(addr, (void *)fdt, fdt_size);
+#else
+    /* We lack libfdt so we cannot manipulate the fdt. Just pass on the blob
+       to the kernel.  */
+    fdt_size = load_image_targphys("mb.dtb", addr, 0x10000);
+    if (fdt_size < 0) {
+        path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
+        if (path) {
+            fdt_size = load_image_targphys(path, addr, 0x10000);
+            g_free(path);
+        }
+    }
+
+    if (kernel_cmdline) {
+        fprintf(stderr,
+                "Warning: missing libfdt, cannot pass cmdline to kernel!\n");
+    }
+#endif
+    return fdt_size;
+}
+
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+    return addr - 0x30000000LL;
+}
+
+void microblaze_load_kernel(CPUState *env, target_phys_addr_t ddr_base,
+                            uint32_t ramsize, const char *dtb_filename,
+                                  void (*machine_cpu_reset)(CPUState *))
+{
+
+    QemuOpts *machine_opts;
+    const char *kernel_filename = NULL;
+    const char *kernel_cmdline = NULL;
+
+    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
+    if (machine_opts) {
+        kernel_filename = qemu_opt_get(machine_opts, "kernel");
+        kernel_cmdline = qemu_opt_get(machine_opts, "append");
+    }
+
+    boot_info.machine_cpu_reset = machine_cpu_reset;
+    qemu_register_reset(main_cpu_reset, env);
+
+    if (kernel_filename) {
+        int kernel_size;
+        uint64_t entry, low, high;
+        uint32_t base32;
+        int big_endian = 0;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+        big_endian = 1;
+#endif
+
+        /* Boots a kernel elf binary.  */
+        kernel_size = load_elf(kernel_filename, NULL, NULL,
+                               &entry, &low, &high,
+                               big_endian, ELF_MACHINE, 0);
+        base32 = entry;
+        if (base32 == 0xc0000000) {
+            kernel_size = load_elf(kernel_filename, translate_kernel_address,
+                                   NULL, &entry, NULL, NULL,
+                                   big_endian, ELF_MACHINE, 0);
+        }
+        /* Always boot into physical ram.  */
+        boot_info.bootstrap_pc = ddr_base + (entry & 0x0fffffff);
+
+        /* If it wasn't an ELF image, try an u-boot image.  */
+        if (kernel_size < 0) {
+            target_phys_addr_t uentry, loadaddr;
+
+            kernel_size = load_uimage(kernel_filename, &uentry, &loadaddr, 0);
+            boot_info.bootstrap_pc = uentry;
+            high = (loadaddr + kernel_size + 3) & ~3;
+        }
+
+        /* Not an ELF image nor an u-boot image, try a RAW image.  */
+        if (kernel_size < 0) {
+            kernel_size = load_image_targphys(kernel_filename, ddr_base,
+                                              ram_size);
+            boot_info.bootstrap_pc = ddr_base;
+            high = (ddr_base + kernel_size + 3) & ~3;
+        }
+
+        boot_info.cmdline = high + 4096;
+        if (kernel_cmdline && strlen(kernel_cmdline)) {
+            pstrcpy_targphys("cmdline", boot_info.cmdline, 256, kernel_cmdline);
+        }
+        /* Provide a device-tree.  */
+        boot_info.fdt = boot_info.cmdline + 4096;
+        microblaze_load_dtb(boot_info.fdt, ram_size, kernel_cmdline,
+                                                     dtb_filename);
+    }
+
+}
diff --git a/hw/microblaze_boot.h b/hw/microblaze_boot.h
new file mode 100644
index 0000000..69d4ac6
--- /dev/null
+++ b/hw/microblaze_boot.h
@@ -0,0 +1,10 @@
+#ifndef __MICROBLAZE_BOOT__
+#define __MICROBLAZE_BOOT__
+
+#include "hw.h"
+
+void microblaze_load_kernel(CPUState *env, target_phys_addr_t ddr_base,
+                            uint32_t ramsize, const char *dtb_filename,
+                                  void (*machine_cpu_reset)(CPUState *));
+
+#endif /* __MICROBLAZE_BOOT __ */
diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c
index 98978f8..c87fa11 100644
--- a/hw/petalogix_ml605_mmu.c
+++ b/hw/petalogix_ml605_mmu.c
@@ -32,35 +32,30 @@
 #include "sysemu.h"
 #include "devices.h"
 #include "boards.h"
-#include "device_tree.h"
 #include "xilinx.h"
-#include "loader.h"
-#include "elf.h"
 #include "blockdev.h"
 #include "pc.h"
 #include "exec-memory.h"
 
+#include "microblaze_boot.h"
 #include "microblaze_pic_cpu.h"
 #include "xilinx_axidma.h"
 
 #define LMB_BRAM_SIZE  (128 * 1024)
 #define FLASH_SIZE     (32 * 1024 * 1024)
 
-static struct
-{
-    uint32_t bootstrap_pc;
-    uint32_t cmdline;
-    uint32_t fdt;
-} boot_info;
+#define BINARY_DEVICE_TREE_FILE "petalogix-ml605.dtb"
 
-static void main_cpu_reset(void *opaque)
-{
-    CPUState *env = opaque;
+#define MEMORY_BASEADDR 0x50000000
+#define FLASH_BASEADDR 0x86000000
+#define INTC_BASEADDR 0x81800000
+#define TIMER_BASEADDR 0x83c00000
+#define UART16550_BASEADDR 0x83e00000
+#define AXIENET_BASEADDR 0x82780000
+#define AXIDMA_BASEADDR 0x84600000
 
-    cpu_reset(env);
-    env->regs[5] = boot_info.cmdline;
-    env->regs[7] = boot_info.fdt;
-    env->sregs[SR_PC] = boot_info.bootstrap_pc;
+static void machine_cpu_reset(CPUState *env)
+{
     env->pvr.regs[10] = 0x0e000000; /* virtex 6 */
     /* setup pvr to match kernel setting */
     env->pvr.regs[5] |= PVR5_DCACHE_WRITEBACK_MASK;
@@ -71,70 +66,6 @@ static void main_cpu_reset(void *opaque)
     env->pvr.regs[5] = 0xc56be000;
 }
 
-#define BINARY_DEVICE_TREE_FILE "petalogix-ml605.dtb"
-static int petalogix_load_device_tree(target_phys_addr_t addr,
-                                      uint32_t ramsize,
-                                      target_phys_addr_t initrd_base,
-                                      target_phys_addr_t initrd_size,
-                                      const char *kernel_cmdline)
-{
-    char *path;
-    int fdt_size;
-#ifdef CONFIG_FDT
-    void *fdt;
-    int r;
-
-    /* Try the local "mb.dtb" override.  */
-    fdt = load_device_tree("mb.dtb", &fdt_size);
-    if (!fdt) {
-        path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
-        if (path) {
-            fdt = load_device_tree(path, &fdt_size);
-            g_free(path);
-        }
-        if (!fdt) {
-            return 0;
-        }
-    }
-
-    r = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline);
-    if (r < 0) {
-        fprintf(stderr, "couldn't set /chosen/bootargs\n");
-    }
-    cpu_physical_memory_write(addr, (void *)fdt, fdt_size);
-#else
-    /* We lack libfdt so we cannot manipulate the fdt. Just pass on the blob
-       to the kernel.  */
-    fdt_size = load_image_targphys("mb.dtb", addr, 0x10000);
-    if (fdt_size < 0) {
-        path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
-        if (path) {
-            fdt_size = load_image_targphys(path, addr, 0x10000);
-            g_free(path);
-        }
-    }
-
-    if (kernel_cmdline) {
-        fprintf(stderr,
-                "Warning: missing libfdt, cannot pass cmdline to kernel!\n");
-    }
-#endif
-    return fdt_size;
-}
-
-static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
-{
-    return addr - 0x30000000LL;
-}
-
-#define MEMORY_BASEADDR 0x50000000
-#define FLASH_BASEADDR 0x86000000
-#define INTC_BASEADDR 0x81800000
-#define TIMER_BASEADDR 0x83c00000
-#define UART16550_BASEADDR 0x83e00000
-#define AXIENET_BASEADDR 0x82780000
-#define AXIDMA_BASEADDR 0x84600000
-
 static void
 petalogix_ml605_init(ram_addr_t ram_size,
                           const char *boot_device,
@@ -145,7 +76,6 @@ petalogix_ml605_init(ram_addr_t ram_size,
     MemoryRegion *address_space_mem = get_system_memory();
     DeviceState *dev;
     CPUState *env;
-    int kernel_size;
     DriveInfo *dinfo;
     int i;
     target_phys_addr_t ddr_base = MEMORY_BASEADDR;
@@ -159,8 +89,6 @@ petalogix_ml605_init(ram_addr_t ram_size,
     }
     env = cpu_init(cpu_model);
 
-    qemu_register_reset(main_cpu_reset, env);
-
     /* Attach emulated BRAM through the LMB.  */
     memory_region_init_ram(phys_lmb_bram, "petalogix_ml605.lmb_bram",
                            LMB_BRAM_SIZE);
@@ -203,55 +131,9 @@ petalogix_ml605_init(ram_addr_t ram_size,
                                      irq[1], irq[0], 100 * 1000000);
     }
 
-    if (kernel_filename) {
-        uint64_t entry, low, high;
-        uint32_t base32;
-        int big_endian = 0;
-
-#ifdef TARGET_WORDS_BIGENDIAN
-        big_endian = 1;
-#endif
+    microblaze_load_kernel(env, ddr_base, ram_size, BINARY_DEVICE_TREE_FILE,
+                                                            machine_cpu_reset);
 
-        /* Boots a kernel elf binary.  */
-        kernel_size = load_elf(kernel_filename, NULL, NULL,
-                               &entry, &low, &high,
-                               big_endian, ELF_MACHINE, 0);
-        base32 = entry;
-        if (base32 == 0xc0000000) {
-            kernel_size = load_elf(kernel_filename, translate_kernel_address,
-                                   NULL, &entry, NULL, NULL,
-                                   big_endian, ELF_MACHINE, 0);
-        }
-        /* Always boot into physical ram.  */
-        boot_info.bootstrap_pc = ddr_base + (entry & 0x0fffffff);
-
-        /* If it wasn't an ELF image, try an u-boot image.  */
-        if (kernel_size < 0) {
-            target_phys_addr_t uentry, loadaddr;
-
-            kernel_size = load_uimage(kernel_filename, &uentry, &loadaddr, 0);
-            boot_info.bootstrap_pc = uentry;
-            high = (loadaddr + kernel_size + 3) & ~3;
-        }
-
-        /* Not an ELF image nor an u-boot image, try a RAW image.  */
-        if (kernel_size < 0) {
-            kernel_size = load_image_targphys(kernel_filename, ddr_base,
-                                              ram_size);
-            boot_info.bootstrap_pc = ddr_base;
-            high = (ddr_base + kernel_size + 3) & ~3;
-        }
-
-        boot_info.cmdline = high + 4096;
-        if (kernel_cmdline && strlen(kernel_cmdline)) {
-            pstrcpy_targphys("cmdline", boot_info.cmdline, 256, kernel_cmdline);
-        }
-        /* Provide a device-tree.  */
-        boot_info.fdt = boot_info.cmdline + 4096;
-        petalogix_load_device_tree(boot_info.fdt, ram_size,
-                                   0, 0,
-                                   kernel_cmdline);
-    }
 }
 
 static QEMUMachine petalogix_ml605_machine = {
diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index d448a41..7c6e9b8 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -30,88 +30,17 @@
 #include "sysemu.h"
 #include "devices.h"
 #include "boards.h"
-#include "device_tree.h"
 #include "xilinx.h"
-#include "loader.h"
-#include "elf.h"
 #include "blockdev.h"
 #include "exec-memory.h"
 
+#include "microblaze_boot.h"
 #include "microblaze_pic_cpu.h"
 
 #define LMB_BRAM_SIZE  (128 * 1024)
 #define FLASH_SIZE     (16 * 1024 * 1024)
 
-static struct
-{
-    uint32_t bootstrap_pc;
-    uint32_t cmdline;
-    uint32_t fdt;
-} boot_info;
-
-static void main_cpu_reset(void *opaque)
-{
-    CPUState *env = opaque;
-
-    cpu_reset(env);
-    env->regs[5] = boot_info.cmdline;
-    env->regs[7] = boot_info.fdt;
-    env->sregs[SR_PC] = boot_info.bootstrap_pc;
-}
-
 #define BINARY_DEVICE_TREE_FILE "petalogix-s3adsp1800.dtb"
-static int petalogix_load_device_tree(target_phys_addr_t addr,
-                                      uint32_t ramsize,
-                                      target_phys_addr_t initrd_base,
-                                      target_phys_addr_t initrd_size,
-                                      const char *kernel_cmdline)
-{
-    char *path;
-    int fdt_size;
-#ifdef CONFIG_FDT
-    void *fdt;
-    int r;
-
-    /* Try the local "mb.dtb" override.  */
-    fdt = load_device_tree("mb.dtb", &fdt_size);
-    if (!fdt) {
-        path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
-        if (path) {
-            fdt = load_device_tree(path, &fdt_size);
-            g_free(path);
-        }
-        if (!fdt)
-            return 0;
-    }
-
-    r = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline);
-    if (r < 0)
-        fprintf(stderr, "couldn't set /chosen/bootargs\n");
-    cpu_physical_memory_write (addr, (void *)fdt, fdt_size);
-#else
-    /* We lack libfdt so we cannot manipulate the fdt. Just pass on the blob
-       to the kernel.  */
-    fdt_size = load_image_targphys("mb.dtb", addr, 0x10000);
-    if (fdt_size < 0) {
-        path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
-        if (path) {
-            fdt_size = load_image_targphys(path, addr, 0x10000);
-	    g_free(path);
-        }
-    }
-
-    if (kernel_cmdline) {
-        fprintf(stderr,
-                "Warning: missing libfdt, cannot pass cmdline to kernel!\n");
-    }
-#endif
-    return fdt_size;
-}
-
-static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
-{
-    return addr - 0x30000000LL;
-}
 
 static void
 petalogix_s3adsp1800_init(ram_addr_t ram_size,
@@ -122,7 +51,6 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
 {
     DeviceState *dev;
     CPUState *env;
-    int kernel_size;
     DriveInfo *dinfo;
     int i;
     target_phys_addr_t ddr_base = 0x90000000;
@@ -137,8 +65,8 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
     }
     env = cpu_init(cpu_model);
 
+    /* FIXME: move to machine specfic cpu reset */
     env->pvr.regs[10] = 0x0c000000; /* spartan 3a dsp family.  */
-    qemu_register_reset(main_cpu_reset, env);
 
     /* Attach emulated BRAM through the LMB.  */
     memory_region_init_ram(phys_lmb_bram,
@@ -168,55 +96,8 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
     xilinx_timer_create(0x83c00000, irq[0], 2, 62 * 1000000);
     xilinx_ethlite_create(&nd_table[0], 0x81000000, irq[1], 0, 0);
 
-    if (kernel_filename) {
-        uint64_t entry, low, high;
-        uint32_t base32;
-        int big_endian = 0;
-
-#ifdef TARGET_WORDS_BIGENDIAN
-        big_endian = 1;
-#endif
-
-        /* Boots a kernel elf binary.  */
-        kernel_size = load_elf(kernel_filename, NULL, NULL,
-                               &entry, &low, &high,
-                               big_endian, ELF_MACHINE, 0);
-        base32 = entry;
-        if (base32 == 0xc0000000) {
-            kernel_size = load_elf(kernel_filename, translate_kernel_address,
-                                   NULL, &entry, NULL, NULL,
-                                   big_endian, ELF_MACHINE, 0);
-        }
-        /* Always boot into physical ram.  */
-        boot_info.bootstrap_pc = ddr_base + (entry & 0x0fffffff);
-
-        /* If it wasn't an ELF image, try an u-boot image.  */
-        if (kernel_size < 0) {
-            target_phys_addr_t uentry, loadaddr;
-
-            kernel_size = load_uimage(kernel_filename, &uentry, &loadaddr, 0);
-            boot_info.bootstrap_pc = uentry;
-            high = (loadaddr + kernel_size + 3) & ~3;
-        }
-
-        /* Not an ELF image nor an u-boot image, try a RAW image.  */
-        if (kernel_size < 0) {
-            kernel_size = load_image_targphys(kernel_filename, ddr_base,
-                                              ram_size);
-            boot_info.bootstrap_pc = ddr_base;
-            high = (ddr_base + kernel_size + 3) & ~3;
-        }
-
-        boot_info.cmdline = high + 4096;
-        if (kernel_cmdline && strlen(kernel_cmdline)) {
-            pstrcpy_targphys("cmdline", boot_info.cmdline, 256, kernel_cmdline);
-        }
-        /* Provide a device-tree.  */
-        boot_info.fdt = boot_info.cmdline + 4096; 
-        petalogix_load_device_tree(boot_info.fdt, ram_size,
-                                   0, 0,
-                                   kernel_cmdline);
-    }
+    microblaze_load_kernel(env, ddr_base, ram_size,
+                    BINARY_DEVICE_TREE_FILE, NULL);
 }
 
 static QEMUMachine petalogix_s3adsp1800_machine = {
commit 27a9476cf75c4e147cb7d8c10c415928b3791b91
Merge: a2d3352... 3208afb...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Mon Mar 5 18:55:11 2012 +0000

    Merge branch 's390-for-upstream' of git://repo.or.cz/qemu/agraf
    
    * 's390-for-upstream' of git://repo.or.cz/qemu/agraf:
      Move helpers.h to helper.h
      s390: Rework kernel loading: supports elf and newer kernels

commit 3208afbe04ad976e038fdb55d11f9f90629a5217
Author: Lluís Vilanova <vilanova at ac.upc.edu>
Date:   Mon Feb 13 05:33:45 2012 +0000

    Move helpers.h to helper.h
    
    Provides a file naming scheme consistent with other targets.
    
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
new file mode 100644
index 0000000..01c8d0e
--- /dev/null
+++ b/target-s390x/helper.h
@@ -0,0 +1,152 @@
+#include "def-helper.h"
+
+DEF_HELPER_1(exception, void, i32)
+DEF_HELPER_3(nc, i32, i32, i64, i64)
+DEF_HELPER_3(oc, i32, i32, i64, i64)
+DEF_HELPER_3(xc, i32, i32, i64, i64)
+DEF_HELPER_3(mvc, void, i32, i64, i64)
+DEF_HELPER_3(clc, i32, i32, i64, i64)
+DEF_HELPER_2(mvcl, i32, i32, i32)
+DEF_HELPER_FLAGS_1(set_cc_comp_s32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32)
+DEF_HELPER_FLAGS_1(set_cc_comp_s64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64)
+DEF_HELPER_FLAGS_2(set_cc_icm, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32)
+DEF_HELPER_3(clm, i32, i32, i32, i64)
+DEF_HELPER_3(stcm, void, i32, i32, i64)
+DEF_HELPER_2(mlg, void, i32, i64)
+DEF_HELPER_2(dlg, void, i32, i64)
+DEF_HELPER_FLAGS_3(set_cc_add64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64, s64, s64)
+DEF_HELPER_FLAGS_3(set_cc_addu64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64)
+DEF_HELPER_FLAGS_3(set_cc_add32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32, s32, s32)
+DEF_HELPER_FLAGS_3(set_cc_addu32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32)
+DEF_HELPER_FLAGS_3(set_cc_sub64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64, s64, s64)
+DEF_HELPER_FLAGS_3(set_cc_subu64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64)
+DEF_HELPER_FLAGS_3(set_cc_sub32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32, s32, s32)
+DEF_HELPER_FLAGS_3(set_cc_subu32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32)
+DEF_HELPER_3(srst, i32, i32, i32, i32)
+DEF_HELPER_3(clst, i32, i32, i32, i32)
+DEF_HELPER_3(mvpg, void, i64, i64, i64)
+DEF_HELPER_3(mvst, void, i32, i32, i32)
+DEF_HELPER_3(csg, i32, i32, i64, i32)
+DEF_HELPER_3(cdsg, i32, i32, i64, i32)
+DEF_HELPER_3(cs, i32, i32, i64, i32)
+DEF_HELPER_4(ex, i32, i32, i64, i64, i64)
+DEF_HELPER_FLAGS_1(abs_i32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32)
+DEF_HELPER_FLAGS_1(nabs_i32, TCG_CALL_PURE|TCG_CALL_CONST, s32, s32)
+DEF_HELPER_FLAGS_1(abs_i64, TCG_CALL_PURE|TCG_CALL_CONST, i64, s64)
+DEF_HELPER_FLAGS_1(nabs_i64, TCG_CALL_PURE|TCG_CALL_CONST, s64, s64)
+DEF_HELPER_3(stcmh, void, i32, i64, i32)
+DEF_HELPER_3(icmh, i32, i32, i64, i32)
+DEF_HELPER_2(ipm, void, i32, i32)
+DEF_HELPER_FLAGS_3(addc_u32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32)
+DEF_HELPER_FLAGS_3(set_cc_addc_u64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64)
+DEF_HELPER_3(stam, void, i32, i64, i32)
+DEF_HELPER_3(lam, void, i32, i64, i32)
+DEF_HELPER_3(mvcle, i32, i32, i64, i32)
+DEF_HELPER_3(clcle, i32, i32, i64, i32)
+DEF_HELPER_3(slb, i32, i32, i32, i32)
+DEF_HELPER_4(slbg, i32, i32, i32, i64, i64)
+DEF_HELPER_2(cefbr, void, i32, s32)
+DEF_HELPER_2(cdfbr, void, i32, s32)
+DEF_HELPER_2(cxfbr, void, i32, s32)
+DEF_HELPER_2(cegbr, void, i32, s64)
+DEF_HELPER_2(cdgbr, void, i32, s64)
+DEF_HELPER_2(cxgbr, void, i32, s64)
+DEF_HELPER_2(adbr, i32, i32, i32)
+DEF_HELPER_2(aebr, i32, i32, i32)
+DEF_HELPER_2(sebr, i32, i32, i32)
+DEF_HELPER_2(sdbr, i32, i32, i32)
+DEF_HELPER_2(debr, void, i32, i32)
+DEF_HELPER_2(dxbr, void, i32, i32)
+DEF_HELPER_2(mdbr, void, i32, i32)
+DEF_HELPER_2(mxbr, void, i32, i32)
+DEF_HELPER_2(ldebr, void, i32, i32)
+DEF_HELPER_2(ldxbr, void, i32, i32)
+DEF_HELPER_2(lxdbr, void, i32, i32)
+DEF_HELPER_2(ledbr, void, i32, i32)
+DEF_HELPER_2(lexbr, void, i32, i32)
+DEF_HELPER_2(lpebr, i32, i32, i32)
+DEF_HELPER_2(lpdbr, i32, i32, i32)
+DEF_HELPER_2(lpxbr, i32, i32, i32)
+DEF_HELPER_2(ltebr, i32, i32, i32)
+DEF_HELPER_2(ltdbr, i32, i32, i32)
+DEF_HELPER_2(ltxbr, i32, i32, i32)
+DEF_HELPER_2(lcebr, i32, i32, i32)
+DEF_HELPER_2(lcdbr, i32, i32, i32)
+DEF_HELPER_2(lcxbr, i32, i32, i32)
+DEF_HELPER_2(aeb, void, i32, i32)
+DEF_HELPER_2(deb, void, i32, i32)
+DEF_HELPER_2(meeb, void, i32, i32)
+DEF_HELPER_2(cdb, i32, i32, i64)
+DEF_HELPER_2(adb, i32, i32, i64)
+DEF_HELPER_2(seb, void, i32, i32)
+DEF_HELPER_2(sdb, i32, i32, i64)
+DEF_HELPER_2(mdb, void, i32, i64)
+DEF_HELPER_2(ddb, void, i32, i64)
+DEF_HELPER_FLAGS_2(cebr, TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(cdbr, TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(cxbr, TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_3(cgebr, i32, i32, i32, i32)
+DEF_HELPER_3(cgdbr, i32, i32, i32, i32)
+DEF_HELPER_3(cgxbr, i32, i32, i32, i32)
+DEF_HELPER_1(lzer, void, i32)
+DEF_HELPER_1(lzdr, void, i32)
+DEF_HELPER_1(lzxr, void, i32)
+DEF_HELPER_3(cfebr, i32, i32, i32, i32)
+DEF_HELPER_3(cfdbr, i32, i32, i32, i32)
+DEF_HELPER_3(cfxbr, i32, i32, i32, i32)
+DEF_HELPER_2(axbr, i32, i32, i32)
+DEF_HELPER_2(sxbr, i32, i32, i32)
+DEF_HELPER_2(meebr, void, i32, i32)
+DEF_HELPER_2(ddbr, void, i32, i32)
+DEF_HELPER_3(madb, void, i32, i64, i32)
+DEF_HELPER_3(maebr, void, i32, i32, i32)
+DEF_HELPER_3(madbr, void, i32, i32, i32)
+DEF_HELPER_3(msdbr, void, i32, i32, i32)
+DEF_HELPER_2(ldeb, void, i32, i64)
+DEF_HELPER_2(lxdb, void, i32, i64)
+DEF_HELPER_FLAGS_2(tceb, TCG_CALL_PURE, i32, i32, i64)
+DEF_HELPER_FLAGS_2(tcdb, TCG_CALL_PURE, i32, i32, i64)
+DEF_HELPER_FLAGS_2(tcxb, TCG_CALL_PURE, i32, i32, i64)
+DEF_HELPER_2(flogr, i32, i32, i64)
+DEF_HELPER_2(sqdbr, void, i32, i32)
+DEF_HELPER_FLAGS_1(cvd, TCG_CALL_PURE|TCG_CALL_CONST, i64, s32)
+DEF_HELPER_3(unpk, void, i32, i64, i64)
+DEF_HELPER_3(tr, void, i32, i64, i64)
+
+DEF_HELPER_2(servc, i32, i32, i64)
+DEF_HELPER_3(diag, i64, i32, i64, i64)
+DEF_HELPER_2(load_psw, void, i64, i64)
+DEF_HELPER_1(program_interrupt, void, i32)
+DEF_HELPER_FLAGS_1(stidp, TCG_CALL_CONST, void, i64)
+DEF_HELPER_FLAGS_1(spx, TCG_CALL_CONST, void, i64)
+DEF_HELPER_FLAGS_1(sck, TCG_CALL_CONST, i32, i64)
+DEF_HELPER_1(stck, i32, i64)
+DEF_HELPER_1(stcke, i32, i64)
+DEF_HELPER_FLAGS_1(sckc, TCG_CALL_CONST, void, i64)
+DEF_HELPER_FLAGS_1(stckc, TCG_CALL_CONST, void, i64)
+DEF_HELPER_FLAGS_1(spt, TCG_CALL_CONST, void, i64)
+DEF_HELPER_FLAGS_1(stpt, TCG_CALL_CONST, void, i64)
+DEF_HELPER_3(stsi, i32, i64, i32, i32)
+DEF_HELPER_3(lctl, void, i32, i64, i32)
+DEF_HELPER_3(lctlg, void, i32, i64, i32)
+DEF_HELPER_3(stctl, void, i32, i64, i32)
+DEF_HELPER_3(stctg, void, i32, i64, i32)
+DEF_HELPER_FLAGS_2(tprot, TCG_CALL_CONST, i32, i64, i64)
+DEF_HELPER_FLAGS_1(iske, TCG_CALL_PURE|TCG_CALL_CONST, i64, i64)
+DEF_HELPER_FLAGS_2(sske, TCG_CALL_CONST, void, i32, i64)
+DEF_HELPER_FLAGS_2(rrbe, TCG_CALL_CONST, i32, i32, i64)
+DEF_HELPER_2(csp, i32, i32, i32)
+DEF_HELPER_3(mvcs, i32, i64, i64, i64)
+DEF_HELPER_3(mvcp, i32, i64, i64, i64)
+DEF_HELPER_3(sigp, i32, i64, i32, i64)
+DEF_HELPER_1(sacf, void, i64)
+DEF_HELPER_FLAGS_2(ipte, TCG_CALL_CONST, void, i64, i64)
+DEF_HELPER_FLAGS_0(ptlb, TCG_CALL_CONST, void)
+DEF_HELPER_2(lra, i32, i64, i32)
+DEF_HELPER_2(stura, void, i64, i32)
+DEF_HELPER_2(cksm, void, i32, i32)
+
+DEF_HELPER_FLAGS_4(calc_cc, TCG_CALL_PURE|TCG_CALL_CONST,
+                   i32, i32, i64, i64, i64)
+
+#include "def-helper.h"
diff --git a/target-s390x/helpers.h b/target-s390x/helpers.h
deleted file mode 100644
index 01c8d0e..0000000
--- a/target-s390x/helpers.h
+++ /dev/null
@@ -1,152 +0,0 @@
-#include "def-helper.h"
-
-DEF_HELPER_1(exception, void, i32)
-DEF_HELPER_3(nc, i32, i32, i64, i64)
-DEF_HELPER_3(oc, i32, i32, i64, i64)
-DEF_HELPER_3(xc, i32, i32, i64, i64)
-DEF_HELPER_3(mvc, void, i32, i64, i64)
-DEF_HELPER_3(clc, i32, i32, i64, i64)
-DEF_HELPER_2(mvcl, i32, i32, i32)
-DEF_HELPER_FLAGS_1(set_cc_comp_s32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32)
-DEF_HELPER_FLAGS_1(set_cc_comp_s64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64)
-DEF_HELPER_FLAGS_2(set_cc_icm, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32)
-DEF_HELPER_3(clm, i32, i32, i32, i64)
-DEF_HELPER_3(stcm, void, i32, i32, i64)
-DEF_HELPER_2(mlg, void, i32, i64)
-DEF_HELPER_2(dlg, void, i32, i64)
-DEF_HELPER_FLAGS_3(set_cc_add64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64, s64, s64)
-DEF_HELPER_FLAGS_3(set_cc_addu64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64)
-DEF_HELPER_FLAGS_3(set_cc_add32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32, s32, s32)
-DEF_HELPER_FLAGS_3(set_cc_addu32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32)
-DEF_HELPER_FLAGS_3(set_cc_sub64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64, s64, s64)
-DEF_HELPER_FLAGS_3(set_cc_subu64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64)
-DEF_HELPER_FLAGS_3(set_cc_sub32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32, s32, s32)
-DEF_HELPER_FLAGS_3(set_cc_subu32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32)
-DEF_HELPER_3(srst, i32, i32, i32, i32)
-DEF_HELPER_3(clst, i32, i32, i32, i32)
-DEF_HELPER_3(mvpg, void, i64, i64, i64)
-DEF_HELPER_3(mvst, void, i32, i32, i32)
-DEF_HELPER_3(csg, i32, i32, i64, i32)
-DEF_HELPER_3(cdsg, i32, i32, i64, i32)
-DEF_HELPER_3(cs, i32, i32, i64, i32)
-DEF_HELPER_4(ex, i32, i32, i64, i64, i64)
-DEF_HELPER_FLAGS_1(abs_i32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32)
-DEF_HELPER_FLAGS_1(nabs_i32, TCG_CALL_PURE|TCG_CALL_CONST, s32, s32)
-DEF_HELPER_FLAGS_1(abs_i64, TCG_CALL_PURE|TCG_CALL_CONST, i64, s64)
-DEF_HELPER_FLAGS_1(nabs_i64, TCG_CALL_PURE|TCG_CALL_CONST, s64, s64)
-DEF_HELPER_3(stcmh, void, i32, i64, i32)
-DEF_HELPER_3(icmh, i32, i32, i64, i32)
-DEF_HELPER_2(ipm, void, i32, i32)
-DEF_HELPER_FLAGS_3(addc_u32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32)
-DEF_HELPER_FLAGS_3(set_cc_addc_u64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64)
-DEF_HELPER_3(stam, void, i32, i64, i32)
-DEF_HELPER_3(lam, void, i32, i64, i32)
-DEF_HELPER_3(mvcle, i32, i32, i64, i32)
-DEF_HELPER_3(clcle, i32, i32, i64, i32)
-DEF_HELPER_3(slb, i32, i32, i32, i32)
-DEF_HELPER_4(slbg, i32, i32, i32, i64, i64)
-DEF_HELPER_2(cefbr, void, i32, s32)
-DEF_HELPER_2(cdfbr, void, i32, s32)
-DEF_HELPER_2(cxfbr, void, i32, s32)
-DEF_HELPER_2(cegbr, void, i32, s64)
-DEF_HELPER_2(cdgbr, void, i32, s64)
-DEF_HELPER_2(cxgbr, void, i32, s64)
-DEF_HELPER_2(adbr, i32, i32, i32)
-DEF_HELPER_2(aebr, i32, i32, i32)
-DEF_HELPER_2(sebr, i32, i32, i32)
-DEF_HELPER_2(sdbr, i32, i32, i32)
-DEF_HELPER_2(debr, void, i32, i32)
-DEF_HELPER_2(dxbr, void, i32, i32)
-DEF_HELPER_2(mdbr, void, i32, i32)
-DEF_HELPER_2(mxbr, void, i32, i32)
-DEF_HELPER_2(ldebr, void, i32, i32)
-DEF_HELPER_2(ldxbr, void, i32, i32)
-DEF_HELPER_2(lxdbr, void, i32, i32)
-DEF_HELPER_2(ledbr, void, i32, i32)
-DEF_HELPER_2(lexbr, void, i32, i32)
-DEF_HELPER_2(lpebr, i32, i32, i32)
-DEF_HELPER_2(lpdbr, i32, i32, i32)
-DEF_HELPER_2(lpxbr, i32, i32, i32)
-DEF_HELPER_2(ltebr, i32, i32, i32)
-DEF_HELPER_2(ltdbr, i32, i32, i32)
-DEF_HELPER_2(ltxbr, i32, i32, i32)
-DEF_HELPER_2(lcebr, i32, i32, i32)
-DEF_HELPER_2(lcdbr, i32, i32, i32)
-DEF_HELPER_2(lcxbr, i32, i32, i32)
-DEF_HELPER_2(aeb, void, i32, i32)
-DEF_HELPER_2(deb, void, i32, i32)
-DEF_HELPER_2(meeb, void, i32, i32)
-DEF_HELPER_2(cdb, i32, i32, i64)
-DEF_HELPER_2(adb, i32, i32, i64)
-DEF_HELPER_2(seb, void, i32, i32)
-DEF_HELPER_2(sdb, i32, i32, i64)
-DEF_HELPER_2(mdb, void, i32, i64)
-DEF_HELPER_2(ddb, void, i32, i64)
-DEF_HELPER_FLAGS_2(cebr, TCG_CALL_PURE, i32, i32, i32)
-DEF_HELPER_FLAGS_2(cdbr, TCG_CALL_PURE, i32, i32, i32)
-DEF_HELPER_FLAGS_2(cxbr, TCG_CALL_PURE, i32, i32, i32)
-DEF_HELPER_3(cgebr, i32, i32, i32, i32)
-DEF_HELPER_3(cgdbr, i32, i32, i32, i32)
-DEF_HELPER_3(cgxbr, i32, i32, i32, i32)
-DEF_HELPER_1(lzer, void, i32)
-DEF_HELPER_1(lzdr, void, i32)
-DEF_HELPER_1(lzxr, void, i32)
-DEF_HELPER_3(cfebr, i32, i32, i32, i32)
-DEF_HELPER_3(cfdbr, i32, i32, i32, i32)
-DEF_HELPER_3(cfxbr, i32, i32, i32, i32)
-DEF_HELPER_2(axbr, i32, i32, i32)
-DEF_HELPER_2(sxbr, i32, i32, i32)
-DEF_HELPER_2(meebr, void, i32, i32)
-DEF_HELPER_2(ddbr, void, i32, i32)
-DEF_HELPER_3(madb, void, i32, i64, i32)
-DEF_HELPER_3(maebr, void, i32, i32, i32)
-DEF_HELPER_3(madbr, void, i32, i32, i32)
-DEF_HELPER_3(msdbr, void, i32, i32, i32)
-DEF_HELPER_2(ldeb, void, i32, i64)
-DEF_HELPER_2(lxdb, void, i32, i64)
-DEF_HELPER_FLAGS_2(tceb, TCG_CALL_PURE, i32, i32, i64)
-DEF_HELPER_FLAGS_2(tcdb, TCG_CALL_PURE, i32, i32, i64)
-DEF_HELPER_FLAGS_2(tcxb, TCG_CALL_PURE, i32, i32, i64)
-DEF_HELPER_2(flogr, i32, i32, i64)
-DEF_HELPER_2(sqdbr, void, i32, i32)
-DEF_HELPER_FLAGS_1(cvd, TCG_CALL_PURE|TCG_CALL_CONST, i64, s32)
-DEF_HELPER_3(unpk, void, i32, i64, i64)
-DEF_HELPER_3(tr, void, i32, i64, i64)
-
-DEF_HELPER_2(servc, i32, i32, i64)
-DEF_HELPER_3(diag, i64, i32, i64, i64)
-DEF_HELPER_2(load_psw, void, i64, i64)
-DEF_HELPER_1(program_interrupt, void, i32)
-DEF_HELPER_FLAGS_1(stidp, TCG_CALL_CONST, void, i64)
-DEF_HELPER_FLAGS_1(spx, TCG_CALL_CONST, void, i64)
-DEF_HELPER_FLAGS_1(sck, TCG_CALL_CONST, i32, i64)
-DEF_HELPER_1(stck, i32, i64)
-DEF_HELPER_1(stcke, i32, i64)
-DEF_HELPER_FLAGS_1(sckc, TCG_CALL_CONST, void, i64)
-DEF_HELPER_FLAGS_1(stckc, TCG_CALL_CONST, void, i64)
-DEF_HELPER_FLAGS_1(spt, TCG_CALL_CONST, void, i64)
-DEF_HELPER_FLAGS_1(stpt, TCG_CALL_CONST, void, i64)
-DEF_HELPER_3(stsi, i32, i64, i32, i32)
-DEF_HELPER_3(lctl, void, i32, i64, i32)
-DEF_HELPER_3(lctlg, void, i32, i64, i32)
-DEF_HELPER_3(stctl, void, i32, i64, i32)
-DEF_HELPER_3(stctg, void, i32, i64, i32)
-DEF_HELPER_FLAGS_2(tprot, TCG_CALL_CONST, i32, i64, i64)
-DEF_HELPER_FLAGS_1(iske, TCG_CALL_PURE|TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_2(sske, TCG_CALL_CONST, void, i32, i64)
-DEF_HELPER_FLAGS_2(rrbe, TCG_CALL_CONST, i32, i32, i64)
-DEF_HELPER_2(csp, i32, i32, i32)
-DEF_HELPER_3(mvcs, i32, i64, i64, i64)
-DEF_HELPER_3(mvcp, i32, i64, i64, i64)
-DEF_HELPER_3(sigp, i32, i64, i32, i64)
-DEF_HELPER_1(sacf, void, i64)
-DEF_HELPER_FLAGS_2(ipte, TCG_CALL_CONST, void, i64, i64)
-DEF_HELPER_FLAGS_0(ptlb, TCG_CALL_CONST, void)
-DEF_HELPER_2(lra, i32, i64, i32)
-DEF_HELPER_2(stura, void, i64, i32)
-DEF_HELPER_2(cksm, void, i32, i32)
-
-DEF_HELPER_FLAGS_4(calc_cc, TCG_CALL_PURE|TCG_CALL_CONST,
-                   i32, i32, i64, i64, i64)
-
-#include "def-helper.h"
diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index cf26b29..70d98a8 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -21,7 +21,7 @@
 #include "cpu.h"
 #include "dyngen-exec.h"
 #include "host-utils.h"
-#include "helpers.h"
+#include "helper.h"
 #include <string.h>
 #include "kvm.h"
 #include "qemu-timer.h"
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 71f9dcd..8fab38c 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -38,9 +38,9 @@
 static TCGv_ptr cpu_env;
 
 #include "gen-icount.h"
-#include "helpers.h"
+#include "helper.h"
 #define GEN_HELPER 1
-#include "helpers.h"
+#include "helper.h"
 
 typedef struct DisasContext DisasContext;
 struct DisasContext {
commit 1edb493490c5cb1eb5ddd55ba498dfb5f008050c
Author: Christian Borntraeger <borntraeger at de.ibm.com>
Date:   Thu Dec 29 23:10:26 2011 +0000

    s390: Rework kernel loading: supports elf and newer kernels
    
    This reworks the image loading on s390.
    
    Newer kernels will not always have a 0dd0 (basr 13,0) at address 0x10000.
    We must not rely on specific code at certain  addresses. This check was
    introduced to warn users that tried to load vmlinux, since ELF loading
    was not supported. Lets wire that up. If elf loading fails, we assume
    that this is a standard kernel image and load that via load_image_targphys.
    This patch also changes all other users of load_image to
    load_image_targphys to be consistent. (the elf loader registers the kernel
    as rom).
    
    Signed-off-by: Christian Borntraeger <borntraeger at de.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index 51123a7..15e3ef3 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -224,13 +224,17 @@ static void s390_init(ram_addr_t my_ram_size,
     s390_add_running_cpu(env);
 
     if (kernel_filename) {
-        kernel_size = load_image(kernel_filename, qemu_get_ram_ptr(0));
 
-        if (lduw_be_phys(KERN_IMAGE_START) != 0x0dd0) {
-            fprintf(stderr, "Specified image is not an s390 boot image\n");
-            exit(1);
+        kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, NULL,
+                               NULL, 1, ELF_MACHINE, 0);
+        if (kernel_size == -1UL) {
+            kernel_size = load_image_targphys(kernel_filename, 0, ram_size);
         }
-
+        /*
+         * we can not rely on the ELF entry point, since up to 3.2 this
+         * value was 0x800 (the SALIPL loader) and it wont work. For
+         * all (Linux) cases 0x10000 (KERN_IMAGE_START) should be fine.
+         */
         env->psw.addr = KERN_IMAGE_START;
         env->psw.mask = 0x0000000180000000ULL;
     } else {
@@ -243,7 +247,7 @@ static void s390_init(ram_addr_t my_ram_size,
         }
 
         bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-        bios_size = load_image(bios_filename, qemu_get_ram_ptr(ZIPL_LOAD_ADDR));
+        bios_size = load_image_targphys(bios_filename, ZIPL_LOAD_ADDR, 4096);
         g_free(bios_filename);
 
         if ((long)bios_size < 0) {
@@ -263,15 +267,17 @@ static void s390_init(ram_addr_t my_ram_size,
         while (kernel_size + 0x100000 > initrd_offset) {
             initrd_offset += 0x100000;
         }
-        initrd_size = load_image(initrd_filename, qemu_get_ram_ptr(initrd_offset));
-
-        stq_be_phys(INITRD_PARM_START, initrd_offset);
-        stq_be_phys(INITRD_PARM_SIZE, initrd_size);
+        initrd_size = load_image_targphys(initrd_filename, initrd_offset,
+                                          ram_size - initrd_offset);
+        /* we have to overwrite values in the kernel image, which are "rom" */
+        memcpy(rom_ptr(INITRD_PARM_START), &initrd_offset, 8);
+        memcpy(rom_ptr(INITRD_PARM_SIZE), &initrd_size, 8);
     }
 
     if (kernel_cmdline) {
-        cpu_physical_memory_write(KERN_PARM_AREA, kernel_cmdline,
-                                  strlen(kernel_cmdline) + 1);
+        /* we have to overwrite values in the kernel image, which are "rom" */
+        memcpy(rom_ptr(KERN_PARM_AREA), kernel_cmdline,
+               strlen(kernel_cmdline) + 1);
     }
 
     /* Create VirtIO network adapters */
commit a2d335214a53b0cc6f7a4a2009d842bea1958085
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Mar 5 17:40:12 2012 +0200

    memory: fix I/O port aliases
    
    Commit e58ac72b6a0 ("ioport: change portio_list not to use
    memory_region_set_offset()") started using aliases of I/O memory
    regions.  Since the IORange used for the I/O was contained in the
    target region, the alias information (specifically, the offset
    into the region) was lost.  This broke -vga std.
    
    Fix by allocating an independent object to hold the IORange and
    also the new offset.
    
    Note that I/O memory regions were conceptually broken wrt aliases
    in a different way: an alias can cause the same region to appear
    twice in an address space, but we had just one IORange to service it.
    This patch fixes that problem as well, since we can now have multiple
    IORange/MemoryRegion associations.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index 3ce3539..1e5bbd6 100644
--- a/exec.c
+++ b/exec.c
@@ -3668,9 +3668,13 @@ static void io_commit(MemoryListener *listener)
 static void io_region_add(MemoryListener *listener,
                           MemoryRegionSection *section)
 {
-    iorange_init(&section->mr->iorange, &memory_region_iorange_ops,
+    MemoryRegionIORange *mrio = g_new(MemoryRegionIORange, 1);
+
+    mrio->mr = section->mr;
+    mrio->offset = section->offset_within_region;
+    iorange_init(&mrio->iorange, &memory_region_iorange_ops,
                  section->offset_within_address_space, section->size);
-    ioport_register(&section->mr->iorange);
+    ioport_register(&mrio->iorange);
 }
 
 static void io_region_del(MemoryListener *listener,
diff --git a/memory.c b/memory.c
index 6565e2e..4c3dc49 100644
--- a/memory.c
+++ b/memory.c
@@ -382,16 +382,20 @@ static void memory_region_iorange_read(IORange *iorange,
                                        unsigned width,
                                        uint64_t *data)
 {
-    MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
+    MemoryRegionIORange *mrio
+        = container_of(iorange, MemoryRegionIORange, iorange);
+    MemoryRegion *mr = mrio->mr;
 
+    offset += mrio->offset;
     if (mr->ops->old_portio) {
-        const MemoryRegionPortio *mrp = find_portio(mr, offset, width, false);
+        const MemoryRegionPortio *mrp = find_portio(mr, offset - mrio->offset,
+                                                    width, false);
 
         *data = ((uint64_t)1 << (width * 8)) - 1;
         if (mrp) {
             *data = mrp->read(mr->opaque, offset);
         } else if (width == 2) {
-            mrp = find_portio(mr, offset, 1, false);
+            mrp = find_portio(mr, offset - mrio->offset, 1, false);
             assert(mrp);
             *data = mrp->read(mr->opaque, offset) |
                     (mrp->read(mr->opaque, offset + 1) << 8);
@@ -410,15 +414,19 @@ static void memory_region_iorange_write(IORange *iorange,
                                         unsigned width,
                                         uint64_t data)
 {
-    MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
+    MemoryRegionIORange *mrio
+        = container_of(iorange, MemoryRegionIORange, iorange);
+    MemoryRegion *mr = mrio->mr;
 
+    offset += mrio->offset;
     if (mr->ops->old_portio) {
-        const MemoryRegionPortio *mrp = find_portio(mr, offset, width, true);
+        const MemoryRegionPortio *mrp = find_portio(mr, offset - mrio->offset,
+                                                    width, true);
 
         if (mrp) {
             mrp->write(mr->opaque, offset, data);
         } else if (width == 2) {
-            mrp = find_portio(mr, offset, 1, false);
+            mrp = find_portio(mr, offset - mrio->offset, 1, false);
             assert(mrp);
             mrp->write(mr->opaque, offset, data & 0xff);
             mrp->write(mr->opaque, offset + 1, data >> 8);
@@ -431,9 +439,15 @@ static void memory_region_iorange_write(IORange *iorange,
                               memory_region_write_accessor, mr);
 }
 
+static void memory_region_iorange_destructor(IORange *iorange)
+{
+    g_free(container_of(iorange, MemoryRegionIORange, iorange));
+}
+
 const IORangeOps memory_region_iorange_ops = {
     .read = memory_region_iorange_read,
     .write = memory_region_iorange_write,
+    .destructor = memory_region_iorange_destructor,
 };
 
 static AddressSpace address_space_io;
diff --git a/memory.h b/memory.h
index b7bccd1..53ff62b 100644
--- a/memory.h
+++ b/memory.h
@@ -43,6 +43,14 @@ struct MemoryRegionMmio {
     CPUWriteMemoryFunc *write[3];
 };
 
+/* Internal use; thunks between old-style IORange and MemoryRegions. */
+typedef struct MemoryRegionIORange MemoryRegionIORange;
+struct MemoryRegionIORange {
+    IORange iorange;
+    MemoryRegion *mr;
+    target_phys_addr_t offset;
+};
+
 /*
  * Memory region callbacks
  */
@@ -117,7 +125,6 @@ struct MemoryRegion {
     target_phys_addr_t addr;
     void (*destructor)(MemoryRegion *mr);
     ram_addr_t ram_addr;
-    IORange iorange;
     bool subpage;
     bool terminates;
     bool readable;
commit c5b703ac2073de8b968ef058793db0294f6a2979
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Mar 5 17:36:19 2012 +0200

    ioport: add destructor method to IORange
    
    Previously all callers had a containing object with a destructor that
    could be used to trigger cleanup of the IORange objects (typically
    just freeing the containing object), but a forthcoming memory API
    change doesn't fit this pattern.  Rather than setting up a new global
    table, extend the ioport system to support destructors.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/ioport.c b/ioport.c
index 8a474d3..78a3b89 100644
--- a/ioport.c
+++ b/ioport.c
@@ -52,6 +52,7 @@
 static void *ioport_opaque[MAX_IOPORTS];
 static IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
 static IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
+static IOPortDestructor *ioport_destructor_table[MAX_IOPORTS];
 
 static IOPortReadFunc default_ioport_readb, default_ioport_readw, default_ioport_readl;
 static IOPortWriteFunc default_ioport_writeb, default_ioport_writew, default_ioport_writel;
@@ -225,6 +226,15 @@ static void ioport_writel_thunk(void *opaque, uint32_t addr, uint32_t data)
     ioport->ops->write(ioport, addr - ioport->base, 4, data);
 }
 
+static void iorange_destructor_thunk(void *opaque)
+{
+    IORange *iorange = opaque;
+
+    if (iorange->ops->destructor) {
+        iorange->ops->destructor(iorange);
+    }
+}
+
 void ioport_register(IORange *ioport)
 {
     register_ioport_read(ioport->base, ioport->len, 1,
@@ -239,12 +249,17 @@ void ioport_register(IORange *ioport)
                           ioport_writew_thunk, ioport);
     register_ioport_write(ioport->base, ioport->len, 4,
                           ioport_writel_thunk, ioport);
+    ioport_destructor_table[ioport->base] = iorange_destructor_thunk;
 }
 
 void isa_unassign_ioport(pio_addr_t start, int length)
 {
     int i;
 
+    if (ioport_destructor_table[start]) {
+        ioport_destructor_table[start](ioport_opaque[start]);
+        ioport_destructor_table[start] = NULL;
+    }
     for(i = start; i < start + length; i++) {
         ioport_read_table[0][i] = NULL;
         ioport_read_table[1][i] = NULL;
diff --git a/ioport.h b/ioport.h
index ab29c89..23441cb 100644
--- a/ioport.h
+++ b/ioport.h
@@ -36,6 +36,7 @@ typedef uint32_t pio_addr_t;
 /* These should really be in isa.h, but are here to make pc.h happy.  */
 typedef void (IOPortWriteFunc)(void *opaque, uint32_t address, uint32_t data);
 typedef uint32_t (IOPortReadFunc)(void *opaque, uint32_t address);
+typedef void (IOPortDestructor)(void *opaque);
 
 void ioport_register(IORange *iorange);
 int register_ioport_read(pio_addr_t start, int length, int size,
diff --git a/iorange.h b/iorange.h
index 9783168..cd980a8 100644
--- a/iorange.h
+++ b/iorange.h
@@ -11,6 +11,7 @@ struct IORangeOps {
                  uint64_t *data);
     void (*write)(IORange *iorange, uint64_t offset, unsigned width,
                   uint64_t data);
+    void (*destructor)(IORange *iorange);
 };
 
 struct IORange {
commit 2aeabc08179553e1a7eed6cf26286c3efc06ee0b
Author: Stefan Weil <sw at weilnetz.de>
Date:   Fri Mar 2 23:30:07 2012 +0100

    w64: fix type casts when calling flush_icache_range
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 351a0a3..cd2db3c 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -253,8 +253,8 @@ void tcg_prologue_init(TCGContext *s)
     s->code_buf = code_gen_prologue;
     s->code_ptr = s->code_buf;
     tcg_target_qemu_prologue(s);
-    flush_icache_range((unsigned long)s->code_buf, 
-                       (unsigned long)s->code_ptr);
+    flush_icache_range((tcg_target_ulong)s->code_buf,
+                       (tcg_target_ulong)s->code_ptr);
 }
 
 void tcg_set_frame(TCGContext *s, int reg,
@@ -2176,8 +2176,9 @@ int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
     tcg_gen_code_common(s, gen_code_buf, -1);
 
     /* flush instruction cache */
-    flush_icache_range((unsigned long)gen_code_buf, 
-                       (unsigned long)s->code_ptr);
+    flush_icache_range((tcg_target_ulong)gen_code_buf,
+                       (tcg_target_ulong)s->code_ptr);
+
     return s->code_ptr -  gen_code_buf;
 }
 
commit 021ecd8b9db37927059f5d3234b51ed766706437
Author: Stefan Weil <sw at weilnetz.de>
Date:   Fri Mar 2 23:30:06 2012 +0100

    cache-utils: Change data type of parameters for flush_icache_range
    
    The TCG targets i386 and tci needed a change of the function
    prototype for w64.
    
    This change is currently not needed here, but it can be applied
    to avoid code differences.
    
    Cc: Alexander Graf <agraf at suse.de>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cache-utils.h b/cache-utils.h
index 0b65907..04a6e2e 100644
--- a/cache-utils.h
+++ b/cache-utils.h
@@ -12,7 +12,7 @@ extern struct qemu_cache_conf qemu_cache_conf;
 void qemu_cache_utils_init(char **envp);
 
 /* mildly adjusted code from tcg-dyngen.c */
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
+static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
 {
     unsigned long p, start1, stop1;
     unsigned long dsize = qemu_cache_conf.dcache_bsize;
commit dba4f1bcc3d45384238864d006b0a83788b56a65
Author: Stefan Weil <sw at weilnetz.de>
Date:   Fri Mar 2 23:30:05 2012 +0100

    w64: Change data type of parameters for flush_icache_range
    
    The TCG targets i386 and tci needed a change of the function
    prototype for w64.
    
    This change is currently not needed for the other TCG targets,
    but it can be applied to avoid code differences.
    
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Cc: Andrzej Zaborowski <balrogg at gmail.com>
    Cc: Richard Henderson <rth at twiddle.net>
    Cc: Aurelien Jarno <aurelien at aurel32.net>
    Cc: Alexander Graf <agraf at suse.de>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index 0035b47..f90b834 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -81,7 +81,8 @@ enum {
     TCG_AREG0 = TCG_REG_R6,
 };
 
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
+static inline void flush_icache_range(tcg_target_ulong start,
+                                      tcg_target_ulong stop)
 {
 #if QEMU_GNUC_PREREQ(4, 1)
     __builtin___clear_cache((char *) start, (char *) stop);
diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h
index 7f3c4cc..d4bf6fe 100644
--- a/tcg/hppa/tcg-target.h
+++ b/tcg/hppa/tcg-target.h
@@ -107,7 +107,9 @@ typedef enum {
 /* Note: must be synced with dyngen-exec.h */
 #define TCG_AREG0 TCG_REG_R17
 
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
+
+static inline void flush_icache_range(tcg_target_ulong start,
+                                      tcg_target_ulong stop)
 {
     start &= ~31;
     while (start <= stop) {
diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h
index c388089..0631b9f 100644
--- a/tcg/ia64/tcg-target.h
+++ b/tcg/ia64/tcg-target.h
@@ -146,7 +146,8 @@ typedef enum {
 /* Guest base is supported */
 #define TCG_TARGET_HAS_GUEST_BASE
 
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
+static inline void flush_icache_range(tcg_target_ulong start,
+                                      tcg_target_ulong stop)
 {
     start = start & ~(32UL - 1UL);
     stop = (stop + (32UL - 1UL)) & ~(32UL - 1UL);
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index 477bc38..d3c804d 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -108,7 +108,8 @@ typedef enum {
 #include <sys/cachectl.h>
 #endif
 
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
+static inline void flush_icache_range(tcg_target_ulong start,
+                                      tcg_target_ulong stop)
 {
     cacheflush ((void *)start, stop-start, ICACHE);
 }
diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h
index e4cd641..d12f90b 100644
--- a/tcg/s390/tcg-target.h
+++ b/tcg/s390/tcg-target.h
@@ -100,6 +100,7 @@ enum {
     TCG_AREG0 = TCG_REG_R10,
 };
 
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
+static inline void flush_icache_range(tcg_target_ulong start,
+                                      tcg_target_ulong stop)
 {
 }
diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h
index c3fe131..ee2274d 100644
--- a/tcg/sparc/tcg-target.h
+++ b/tcg/sparc/tcg-target.h
@@ -134,7 +134,8 @@ typedef enum {
 #define TCG_AREG0 TCG_REG_G6
 #endif
 
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
+static inline void flush_icache_range(tcg_target_ulong start,
+                                      tcg_target_ulong stop)
 {
     unsigned long p;
 
commit f57a51603987a600952113103bbd777333a2737a
Author: Stefan Weil <sw at weilnetz.de>
Date:   Fri Mar 2 23:30:04 2012 +0100

    w64: Fix data type of parameters for flush_icache_range
    
    flush_icache_range takes two address parameters which must be large
    enough to address any address of the host.
    
    For hosts with sizeof(unsigned long) == sizeof(void *), this patch
    changes nothing. All currently supported hosts fall into this category.
    
    For w64 hosts, sizeof(unsigned long) is 4 while sizeof(void *) is 8,
    so the use of tcg_target_ulong is needed for i386 and tci (the tcg
    targets which work with w64).
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
index adbb036..c3cfe05 100644
--- a/tcg/i386/tcg-target.h
+++ b/tcg/i386/tcg-target.h
@@ -123,6 +123,7 @@ typedef enum {
 # define TCG_AREG0 TCG_REG_EBP
 #endif
 
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
+static inline void flush_icache_range(tcg_target_ulong start,
+                                      tcg_target_ulong stop)
 {
 }
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
index 03e0fd1..81fcc0f 100644
--- a/tcg/tci/tcg-target.h
+++ b/tcg/tci/tcg-target.h
@@ -157,7 +157,8 @@ void tci_disas(uint8_t opc);
 unsigned long tcg_qemu_tb_exec(CPUState *env, uint8_t *tb_ptr);
 #define tcg_qemu_tb_exec tcg_qemu_tb_exec
 
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
+static inline void flush_icache_range(tcg_target_ulong start,
+                                      tcg_target_ulong stop)
 {
 }
 
commit c38bb94a995fd4b7f92ff933c19c1a1ffbe9df5b
Author: Stefan Weil <sw at weilnetz.de>
Date:   Fri Mar 2 23:30:03 2012 +0100

    tcg: Rearrange definitions and include statements
    
    This change makes tcg_target_ulong available in tcg-target.h.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/tcg.h b/tcg/tcg.h
index 5c28239..cc223ea 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -32,9 +32,6 @@
 # error Unknown pointer size for tcg target
 #endif
 
-#include "tcg-target.h"
-#include "tcg-runtime.h"
-
 #if TCG_TARGET_REG_BITS == 32
 typedef int32_t tcg_target_long;
 typedef uint32_t tcg_target_ulong;
@@ -49,6 +46,9 @@ typedef uint64_t tcg_target_ulong;
 #error unsupported
 #endif
 
+#include "tcg-target.h"
+#include "tcg-runtime.h"
+
 #if TCG_TARGET_NB_REGS <= 32
 typedef uint32_t TCGRegSet;
 #elif TCG_TARGET_NB_REGS <= 64
commit 53576999a6905d76a59ce47006a2a0c0b03f942e
Author: Stefan Weil <sw at weilnetz.de>
Date:   Fri Mar 2 23:30:02 2012 +0100

    w64: Fix size of ram_addr_t
    
    ram_addr_t must be large enough to address any address of the host.
    
    For hosts with sizeof(unsigned long) == sizeof(void *), this patch
    changes nothing. All currently supported hosts fall into this category.
    
    For w64 hosts, sizeof(unsigned long) is 4 while sizeof(void *) is 8,
    so the use of uintptr_t is needed.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpu-common.h b/cpu-common.h
index a40c57d..dca5175 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -28,9 +28,9 @@ typedef uint64_t ram_addr_t;
 #  define RAM_ADDR_MAX UINT64_MAX
 #  define RAM_ADDR_FMT "%" PRIx64
 #else
-typedef unsigned long ram_addr_t;
-#  define RAM_ADDR_MAX ULONG_MAX
-#  define RAM_ADDR_FMT "%lx"
+typedef uintptr_t ram_addr_t;
+#  define RAM_ADDR_MAX UINTPTR_MAX
+#  define RAM_ADDR_FMT "%" PRIxPTR
 #endif
 
 /* memory API */
commit 5a30d3f19d9c6d135bf7a395a24dc455698d5cf9
Merge: 41e37c3... c0fd260...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Mar 3 17:59:06 2012 +0000

    Merge branch 'upstream' of git://qemu.weilnetz.de/qemu
    
    * 'upstream' of git://qemu.weilnetz.de/qemu:
      Move definition of HOST_LONG_BITS to qemu-common.h
      target-xtensa: Clean includes
      target-unicore32: Clean includes
      target-sh4: Clean includes
      target-s390x: Clean includes
      target-ppc: Clean includes
      target-mips: Clean includes
      target-microblaze: Clean includes
      target-m68k: Clean includes
      target-lm32: Clean includes
      target-i386: Clean includes
      target-cris: Clean includes
      target-arm: Clean includes
      target-alpha: Clean includes
      Remove macro HOST_LONG_SIZE

commit 41e37c33fc5897ff8015af8e0e3f5eb13c394b51
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Thu Mar 1 10:43:50 2012 +0100

    usb: Fix signature of stub usb_host_device_open
    
    This was a breakage of 3741715cf2.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/usb-stub.c b/usb-stub.c
index 9c3fcea..b4e10c1 100644
--- a/usb-stub.c
+++ b/usb-stub.c
@@ -41,7 +41,7 @@ void usb_host_info(Monitor *mon)
 }
 
 /* XXX: modify configure to compile the right host driver */
-USBDevice *usb_host_device_open(const char *devname)
+USBDevice *usb_host_device_open(USBBus *bus, const char *devname)
 {
     return NULL;
 }
commit d9bafcd1db602b199dfffc8bcfef08f42f447d38
Merge: b3e54c6... 0f58a18...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Mar 3 17:53:56 2012 +0000

    Merge branch 'arm-devs.for-upstream' of git://git.linaro.org/people/pmaydell/qemu-arm
    
    * 'arm-devs.for-upstream' of git://git.linaro.org/people/pmaydell/qemu-arm:
      hw/arm11mpcore: Fix broken realview_mpcore/arm11mpcore_priv properties
      arm: add device tree support
      arm: make sure that number of irqs can be represented in GICD_TYPER.
      arm: clean up GIC constants

commit b3e54c689c0630e9a79f33a8b03c71296334fd36
Merge: 88e6c60... e7dfa64...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Mar 3 17:53:41 2012 +0000

    Merge branch 'xtensa' of git://jcmvbkbc.spb.ru/dumb/qemu-xtensa
    
    * 'xtensa' of git://jcmvbkbc.spb.ru/dumb/qemu-xtensa:
      target-xtensa: add breakpoint tests
      target-xtensa: add DEBUG_SECTION to overlay tool
      target-xtensa: add DBREAK data breakpoints
      exec: let cpu_watchpoint_insert accept larger watchpoints
      exec: fix check_watchpoint exiting cpu_loop
      exec: add missing breaks to the watch_mem_write
      target-xtensa: add ICOUNT SR and debug exception
      target-xtensa: implement instruction breakpoints
      target-xtensa: add DEBUGCAUSE SR and configuration
      target-xtensa: fetch 3rd opcode byte only when needed
      target-xtensa: implement info tlb monitor command
      target-xtensa: define TLB_TEMPLATE for MMU-less cores

commit 0f58a1882bae42d7c76bdb66792c204a810ec01f
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 2 11:56:39 2012 +0000

    hw/arm11mpcore: Fix broken realview_mpcore/arm11mpcore_priv properties
    
    Fix confusion in the Property arrays for the "arm11mpcore_priv"
    (per-CPU devices for the ARM11MPcore CPU) and "realview_mpcore"
    (realview-eb board specific device encapsulating CPU and some
    extra interrupt controllers) -- the num-irq property was defined
    on the wrong device and the mpcore_rirq_properties were defined
    as offsets in the wrong structure. The effect was that the
    realview-eb-mpcore machine would abort on startup trying to
    allocate an insane amount of memory. (This bug was introduced in
    the QOM conversion in commit 999e12bb.)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index 102348b..c67b70f 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -202,16 +202,7 @@ static int realview_mpcore_init(SysBusDevice *dev)
 }
 
 static Property mpcore_rirq_properties[] = {
-    DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
-    /* The ARM11 MPCORE TRM says the on-chip controller may have
-     * anything from 0 to 224 external interrupt IRQ lines (with another
-     * 32 internal). We default to 32+32, which is the number provided by
-     * the ARM11 MPCore test chip in the Realview Versatile Express
-     * coretile. Other boards may differ and should set this property
-     * appropriately. Some Linux kernels may not boot if the hardware
-     * has more IRQ lines than the kernel expects.
-     */
-    DEFINE_PROP_UINT32("num-irq", mpcore_priv_state, num_irq, 64),
+    DEFINE_PROP_UINT32("num-cpu", mpcore_rirq_state, num_cpu, 1),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -233,6 +224,15 @@ static TypeInfo mpcore_rirq_info = {
 
 static Property mpcore_priv_properties[] = {
     DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
+    /* The ARM11 MPCORE TRM says the on-chip controller may have
+     * anything from 0 to 224 external interrupt IRQ lines (with another
+     * 32 internal). We default to 32+32, which is the number provided by
+     * the ARM11 MPCore test chip in the Realview Versatile Express
+     * coretile. Other boards may differ and should set this property
+     * appropriately. Some Linux kernels may not boot if the hardware
+     * has more IRQ lines than the kernel expects.
+     */
+    DEFINE_PROP_UINT32("num-irq", mpcore_priv_state, num_irq, 64),
     DEFINE_PROP_END_OF_LIST(),
 };
 
commit 412beee6a0349ce430920e2b2faa8009ced4a672
Author: Grant Likely <grant.likely at secretlab.ca>
Date:   Fri Mar 2 11:56:38 2012 +0000

    arm: add device tree support
    
    If compiled with CONFIG_FDT, allow user to specify a device tree file using
    the -dtb argument.  If the machine supports it then the dtb will be loaded
    into memory and passed to the kernel on boot.
    
    Signed-off-by: Jeremy Kerr <jeremy.kerr at canonical.com>
    Signed-off-by: Grant Likely <grant.likely at secretlab.ca>
    [Peter Maydell: Use machine opt rather than global to pass dtb filename]
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/Makefile.target b/Makefile.target
index 68a5641..6a56b3e 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -373,6 +373,7 @@ 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
diff --git a/configure b/configure
index fb0e18e..7e69ea8 100755
--- a/configure
+++ b/configure
@@ -3485,6 +3485,7 @@ case "$target_arch2" in
     gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
     target_phys_bits=32
     target_llong_alignment=4
+    target_libs_softmmu="$fdt_libs"
   ;;
   cris)
     target_nptl="yes"
diff --git a/hw/arm-misc.h b/hw/arm-misc.h
index 306013a..734bd82 100644
--- a/hw/arm-misc.h
+++ b/hw/arm-misc.h
@@ -29,6 +29,7 @@ struct arm_boot_info {
     const char *kernel_filename;
     const char *kernel_cmdline;
     const char *initrd_filename;
+    const char *dtb_filename;
     target_phys_addr_t loader_start;
     /* multicore boards that use the default secondary core boot functions
      * need to put the address of the secondary boot code, the boot reg,
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index 2ef25ca..fc66910 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -7,11 +7,14 @@
  * This code is licensed under the GPL.
  */
 
+#include "config.h"
 #include "hw.h"
 #include "arm-misc.h"
 #include "sysemu.h"
+#include "boards.h"
 #include "loader.h"
 #include "elf.h"
+#include "device_tree.h"
 
 #define KERNEL_ARGS_ADDR 0x100
 #define KERNEL_LOAD_ADDR 0x00010000
@@ -208,6 +211,67 @@ static void set_kernel_args_old(const struct arm_boot_info *info)
     }
 }
 
+static int load_dtb(target_phys_addr_t addr, const struct arm_boot_info *binfo)
+{
+#ifdef CONFIG_FDT
+    uint32_t mem_reg_property[] = { cpu_to_be32(binfo->loader_start),
+                                    cpu_to_be32(binfo->ram_size) };
+    void *fdt = NULL;
+    char *filename;
+    int size, rc;
+
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, binfo->dtb_filename);
+    if (!filename) {
+        fprintf(stderr, "Couldn't open dtb file %s\n", binfo->dtb_filename);
+        return -1;
+    }
+
+    fdt = load_device_tree(filename, &size);
+    if (!fdt) {
+        fprintf(stderr, "Couldn't open dtb file %s\n", filename);
+        g_free(filename);
+        return -1;
+    }
+    g_free(filename);
+
+    rc = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
+                               sizeof(mem_reg_property));
+    if (rc < 0) {
+        fprintf(stderr, "couldn't set /memory/reg\n");
+    }
+
+    rc = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
+                                      binfo->kernel_cmdline);
+    if (rc < 0) {
+        fprintf(stderr, "couldn't set /chosen/bootargs\n");
+    }
+
+    if (binfo->initrd_size) {
+        rc = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
+                binfo->loader_start + INITRD_LOAD_ADDR);
+        if (rc < 0) {
+            fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
+        }
+
+        rc = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
+                    binfo->loader_start + INITRD_LOAD_ADDR +
+                    binfo->initrd_size);
+        if (rc < 0) {
+            fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
+        }
+    }
+
+    cpu_physical_memory_write(addr, fdt, size);
+
+    return 0;
+
+#else
+    fprintf(stderr, "Device tree requested, "
+                "but qemu was compiled without fdt support\n");
+    return -1;
+#endif
+}
+
 static void do_cpu_reset(void *opaque)
 {
     CPUState *env = opaque;
@@ -222,10 +286,12 @@ static void do_cpu_reset(void *opaque)
         } else {
             if (env == first_cpu) {
                 env->regs[15] = info->loader_start;
-                if (old_param) {
-                    set_kernel_args_old(info);
-                } else {
-                    set_kernel_args(info);
+                if (!info->dtb_filename) {
+                    if (old_param) {
+                        set_kernel_args_old(info);
+                    } else {
+                        set_kernel_args(info);
+                    }
                 }
             } else {
                 info->secondary_cpu_reset_hook(env, info);
@@ -243,6 +309,7 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
     uint64_t elf_entry;
     target_phys_addr_t entry;
     int big_endian;
+    QemuOpts *machine_opts;
 
     /* Load the kernel.  */
     if (!info->kernel_filename) {
@@ -250,6 +317,13 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
         exit(1);
     }
 
+    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
+    if (machine_opts) {
+        info->dtb_filename = qemu_opt_get(machine_opts, "dtb");
+    } else {
+        info->dtb_filename = NULL;
+    }
+
     if (!info->secondary_cpu_reset_hook) {
         info->secondary_cpu_reset_hook = default_reset_secondary;
     }
@@ -300,8 +374,25 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
         } else {
             initrd_size = 0;
         }
+        info->initrd_size = initrd_size;
+
         bootloader[4] = info->board_id;
-        bootloader[5] = info->loader_start + KERNEL_ARGS_ADDR;
+
+        /* for device tree boot, we pass the DTB directly in r2. Otherwise
+         * we point to the kernel args.
+         */
+        if (info->dtb_filename) {
+            /* Place the DTB after the initrd in memory */
+            target_phys_addr_t dtb_start = TARGET_PAGE_ALIGN(info->loader_start
+                                                             + INITRD_LOAD_ADDR
+                                                             + initrd_size);
+            if (load_dtb(dtb_start, info)) {
+                exit(1);
+            }
+            bootloader[5] = dtb_start;
+        } else {
+            bootloader[5] = info->loader_start + KERNEL_ARGS_ADDR;
+        }
         bootloader[6] = entry;
         for (n = 0; n < sizeof(bootloader) / 4; n++) {
             bootloader[n] = tswap32(bootloader[n]);
@@ -311,7 +402,6 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
         if (info->nb_cpus > 1) {
             info->write_secondary_boot(env, info);
         }
-        info->initrd_size = initrd_size;
     }
     info->is_linux = is_linux;
 
diff --git a/qemu-config.c b/qemu-config.c
index 7d9da78..be84a03 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -578,6 +578,10 @@ static QemuOptsList qemu_machine_opts = {
             .name = "append",
             .type = QEMU_OPT_STRING,
             .help = "Linux kernel command line",
+        }, {
+            .name = "dtb",
+            .type = QEMU_OPT_STRING,
+            .help = "Linux kernel device tree file",
         },
         { /* End of list */ }
     },
diff --git a/qemu-options.hx b/qemu-options.hx
index b129996..e38799c 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2037,6 +2037,15 @@ Use @var{file1} and @var{file2} as modules and pass arg=foo as parameter to the
 first module.
 ETEXI
 
+DEF("dtb", HAS_ARG, QEMU_OPTION_dtb, \
+    "-dtb    file    use 'file' as device tree image\n", QEMU_ARCH_ARM)
+STEXI
+ at item -dtb @var{file}
+ at findex -dtb
+Use @var{file} as a device tree binary (dtb) image and pass it to the kernel
+on boot.
+ETEXI
+
 STEXI
 @end table
 ETEXI
diff --git a/vl.c b/vl.c
index 4a77696..97ab2b9 100644
--- a/vl.c
+++ b/vl.c
@@ -2527,6 +2527,9 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_append:
                 qemu_opts_set(qemu_find_opts("machine"), 0, "append", optarg);
                 break;
+            case QEMU_OPTION_dtb:
+                qemu_opts_set(qemu_find_opts("machine"), 0, "dtb", optarg);
+                break;
             case QEMU_OPTION_cdrom:
                 drive_add(IF_DEFAULT, 2, optarg, CDROM_OPTS);
                 break;
@@ -3346,6 +3349,11 @@ int main(int argc, char **argv, char **envp)
         exit(1);
     }
 
+    if (!linux_boot && machine_opts && qemu_opt_get(machine_opts, "dtb")) {
+        fprintf(stderr, "-dtb only allowed with -kernel option\n");
+        exit(1);
+    }
+
     os_set_line_buffering();
 
     if (init_timer_alarm() < 0) {
commit 41c1e2f54e6fc76dbc7047f1a95693f4d37b4623
Author: Rusty Russell <rusty at rustcorp.com.au>
Date:   Fri Mar 2 11:56:38 2012 +0000

    arm: make sure that number of irqs can be represented in GICD_TYPER.
    
    We currently assume that the number of interrupts (ITLinesNumber in
    the architecture reference manual) is divisible by 32, since we
    present it to the guest when it reads GICD_TYPER (in gic_dist_readb())
    as (N / 32) - 1.
    
    Signed-off-by: Rusty Russell <rusty at rustcorp.com.au>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 59eabcc..d8a7a19 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -819,6 +819,15 @@ static void gic_init(gic_state *s, int num_irq)
         hw_error("requested %u interrupt lines exceeds GIC maximum %d\n",
                  num_irq, GIC_MAXIRQ);
     }
+    /* ITLinesNumber is represented as (N / 32) - 1 (see
+     * gic_dist_readb) so this is an implementation imposed
+     * restriction, not an architectural one:
+     */
+    if (s->num_irq < 32 || (s->num_irq % 32)) {
+        hw_error("%d interrupt lines unsupported: not divisible by 32\n",
+                 num_irq);
+    }
+
     qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - GIC_INTERNAL);
     for (i = 0; i < NUM_CPU(s); i++) {
         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
commit 6925380062263df34dcf7ba8e139e426a077f04f
Author: Rusty Russell <rusty at rustcorp.com.au>
Date:   Fri Mar 2 11:56:38 2012 +0000

    arm: clean up GIC constants
    
    Interrupts numbers 0-31 are private to the processor interface, 32-1019 are
    general interrupts.  Add GIC_INTERNAL and substitute everywhere.
    
    Signed-off-by: Rusty Russell <rusty at rustcorp.com.au>
    [Peter Maydell: converted some tabs to spaces]
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index cf582a5..59eabcc 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -13,6 +13,8 @@
 
 /* Maximum number of possible interrupts, determined by the GIC architecture */
 #define GIC_MAXIRQ 1020
+/* First 32 are private to each CPU (SGIs and PPIs). */
+#define GIC_INTERNAL 32
 //#define DEBUG_GIC
 
 #ifdef DEBUG_GIC
@@ -73,8 +75,9 @@ typedef struct gic_irq_state
 #define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = 1
 #define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = 0
 #define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger
-#define GIC_GET_PRIORITY(irq, cpu) \
-  (((irq) < 32) ? s->priority1[irq][cpu] : s->priority2[(irq) - 32])
+#define GIC_GET_PRIORITY(irq, cpu) (((irq) < GIC_INTERNAL) ?            \
+                                    s->priority1[irq][cpu] :            \
+                                    s->priority2[(irq) - GIC_INTERNAL])
 #ifdef NVIC
 #define GIC_TARGET(irq) 1
 #else
@@ -92,8 +95,8 @@ typedef struct gic_state
 #ifndef NVIC
     int irq_target[GIC_MAXIRQ];
 #endif
-    int priority1[32][NCPU];
-    int priority2[GIC_MAXIRQ - 32];
+    int priority1[GIC_INTERNAL][NCPU];
+    int priority2[GIC_MAXIRQ - GIC_INTERNAL];
     int last_active[GIC_MAXIRQ][NCPU];
 
     int priority_mask[NCPU];
@@ -174,7 +177,7 @@ static void gic_set_irq(void *opaque, int irq, int level)
 {
     gic_state *s = (gic_state *)opaque;
     /* The first external input line is internal interrupt 32.  */
-    irq += 32;
+    irq += GIC_INTERNAL;
     if (level == GIC_TEST_LEVEL(irq, ALL_CPU_MASK))
         return;
 
@@ -316,7 +319,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
-        mask = (irq < 32) ?  cm : ALL_CPU_MASK;
+        mask = (irq < GIC_INTERNAL) ?  cm : ALL_CPU_MASK;
         for (i = 0; i < 8; i++) {
             if (GIC_TEST_PENDING(irq + i, mask)) {
                 res |= (1 << i);
@@ -328,7 +331,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
-        mask = (irq < 32) ?  cm : ALL_CPU_MASK;
+        mask = (irq < GIC_INTERNAL) ?  cm : ALL_CPU_MASK;
         for (i = 0; i < 8; i++) {
             if (GIC_TEST_ACTIVE(irq + i, mask)) {
                 res |= (1 << i);
@@ -435,8 +438,8 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
           value = 0xff;
         for (i = 0; i < 8; i++) {
             if (value & (1 << i)) {
-                int mask = (irq < 32) ? (1 << cpu) : GIC_TARGET(irq);
-                int cm = (irq < 32) ? (1 << cpu) : ALL_CPU_MASK;
+                int mask = (irq < GIC_INTERNAL) ? (1 << cpu) : GIC_TARGET(irq);
+                int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
 
                 if (!GIC_TEST_ENABLED(irq + i, cm)) {
                     DPRINTF("Enabled IRQ %d\n", irq + i);
@@ -460,7 +463,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
           value = 0;
         for (i = 0; i < 8; i++) {
             if (value & (1 << i)) {
-                int cm = (irq < 32) ? (1 << cpu) : ALL_CPU_MASK;
+                int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
 
                 if (GIC_TEST_ENABLED(irq + i, cm)) {
                     DPRINTF("Disabled IRQ %d\n", irq + i);
@@ -502,10 +505,10 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
         irq = (offset - 0x400) + GIC_BASE_IRQ;
         if (irq >= s->num_irq)
             goto bad_reg;
-        if (irq < 32) {
+        if (irq < GIC_INTERNAL) {
             s->priority1[irq][cpu] = value;
         } else {
-            s->priority2[irq - 32] = value;
+            s->priority2[irq - GIC_INTERNAL] = value;
         }
 #ifndef NVIC
     } else if (offset < 0xc00) {
@@ -515,7 +518,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
             goto bad_reg;
         if (irq < 29)
             value = 0;
-        else if (irq < 32)
+        else if (irq < GIC_INTERNAL)
             value = ALL_CPU_MASK;
         s->irq_target[irq] = value & ALL_CPU_MASK;
     } else if (offset < 0xf00) {
@@ -523,7 +526,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
         irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
         if (irq >= s->num_irq)
             goto bad_reg;
-        if (irq < 32)
+        if (irq < GIC_INTERNAL)
             value |= 0xaa;
         for (i = 0; i < 4; i++) {
             if (value & (1 << (i * 2))) {
@@ -736,7 +739,7 @@ static void gic_save(QEMUFile *f, void *opaque)
     qemu_put_be32(f, s->enabled);
     for (i = 0; i < NUM_CPU(s); i++) {
         qemu_put_be32(f, s->cpu_enabled[i]);
-        for (j = 0; j < 32; j++)
+        for (j = 0; j < GIC_INTERNAL; j++)
             qemu_put_be32(f, s->priority1[j][i]);
         for (j = 0; j < s->num_irq; j++)
             qemu_put_be32(f, s->last_active[j][i]);
@@ -745,7 +748,7 @@ static void gic_save(QEMUFile *f, void *opaque)
         qemu_put_be32(f, s->running_priority[i]);
         qemu_put_be32(f, s->current_pending[i]);
     }
-    for (i = 0; i < s->num_irq - 32; i++) {
+    for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
         qemu_put_be32(f, s->priority2[i]);
     }
     for (i = 0; i < s->num_irq; i++) {
@@ -773,7 +776,7 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
     s->enabled = qemu_get_be32(f);
     for (i = 0; i < NUM_CPU(s); i++) {
         s->cpu_enabled[i] = qemu_get_be32(f);
-        for (j = 0; j < 32; j++)
+        for (j = 0; j < GIC_INTERNAL; j++)
             s->priority1[j][i] = qemu_get_be32(f);
         for (j = 0; j < s->num_irq; j++)
             s->last_active[j][i] = qemu_get_be32(f);
@@ -782,7 +785,7 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
         s->running_priority[i] = qemu_get_be32(f);
         s->current_pending[i] = qemu_get_be32(f);
     }
-    for (i = 0; i < s->num_irq - 32; i++) {
+    for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
         s->priority2[i] = qemu_get_be32(f);
     }
     for (i = 0; i < s->num_irq; i++) {
@@ -816,7 +819,7 @@ static void gic_init(gic_state *s, int num_irq)
         hw_error("requested %u interrupt lines exceeds GIC maximum %d\n",
                  num_irq, GIC_MAXIRQ);
     }
-    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - 32);
+    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - GIC_INTERNAL);
     for (i = 0; i < NUM_CPU(s); i++) {
         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
     }
commit 88e6c60671df4c8b1b6c1eb8f76950ab1bea0ec2
Merge: 14655e4... 8f6f962...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Mar 1 15:26:55 2012 -0600

    Merge remote-tracking branch 'qemu-kvm/memory/urgent' into staging
    
    * qemu-kvm/memory/urgent:
      kvm: fix unaligned slots

commit 14655e482bc9ef44b841bdca55d79ab0891058e9
Merge: 5918ff6... 07f07b3...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Mar 1 15:26:25 2012 -0600

    Merge remote-tracking branch 'qemu-kvm/memory/core' into staging
    
    * qemu-kvm/memory/core: (30 commits)
      memory: allow phys_map tree paths to terminate early
      memory: unify PhysPageEntry::node and ::leaf
      memory: change phys_page_set() to set multiple pages
      memory: switch phys_page_set() to a recursive implementation
      memory: replace phys_page_find_alloc() with phys_page_set()
      memory: simplify multipage/subpage registration
      memory: give phys_page_find() its own tree search loop
      memory: make phys_page_find() return a MemoryRegionSection
      memory: move tlb flush to MemoryListener commit callback
      memory: unify the two branches of cpu_register_physical_memory_log()
      memory: fix RAM subpages in newly initialized pages
      memory: compress phys_map node pointers to 16 bits
      memory: store MemoryRegionSection pointers in phys_map
      memory: unify phys_map last level with intermediate levels
      memory: remove first level of l1_phys_map
      memory: change memory registration to rebuild the memory map on each change
      memory: support stateless memory listeners
      memory: split memory listener for the two address spaces
      xen: ignore I/O memory regions
      memory: allow MemoryListeners to observe a specific address space
      ...

commit 5918ff68ff3ffe61ae8ebff5b031d6bdcc63c6bc
Merge: 7c51c1a... 5b6fb06...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Mar 1 15:26:01 2012 -0600

    Merge remote-tracking branch 'qemu-kvm/uq/master' into staging
    
    * qemu-kvm/uq/master:
      pc-bios: update kvmvapic.bin
      kvmvapic: Use optionrom helpers
      optionsrom: Reserve space for checksum
      kvmvapic: Simplify mp/up_set_tpr
      kvmvapic: Introduce TPR access optimization for Windows guests
      kvmvapic: Add option ROM
      target-i386: Add infrastructure for reporting TPR MMIO accesses
      Allow to use pause_all_vcpus from VCPU context
      Process pending work while waiting for initial kick-off in TCG mode
      Remove useless casts from cpu iterators
      kvm: Set cpu_single_env only once
      kvm: Synchronize cpu state in kvm_arch_stop_on_emulation_error()

commit 8f6f962b994e1402935055ac7093ac977ccc9a5c
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Feb 29 13:22:12 2012 +0200

    kvm: fix unaligned slots
    
    kvm_set_phys_mem() may be passed sections that are not aligned to a page
    boundary.  The current code simply brute-forces the alignment which leads
    to an inconsistency and an abort().
    
    Fix by aligning the start and the end of the section correctly, discarding
    and unaligned head or tail.
    
    This was triggered by a guest sizing a 64-bit BAR that is smaller than a page
    with PCI_COMMAND_MEMORY enabled and the upper dword clear.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index c4babda..4b7a4ae 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -541,17 +541,26 @@ static void kvm_set_phys_mem(MemoryRegionSection *section, bool add)
     target_phys_addr_t start_addr = section->offset_within_address_space;
     ram_addr_t size = section->size;
     void *ram = NULL;
+    unsigned delta;
 
     /* kvm works in page size chunks, but the function may be called
        with sub-page size and unaligned start address. */
-    size = TARGET_PAGE_ALIGN(size);
-    start_addr = TARGET_PAGE_ALIGN(start_addr);
+    delta = TARGET_PAGE_ALIGN(size) - size;
+    if (delta > size) {
+        return;
+    }
+    start_addr += delta;
+    size -= delta;
+    size &= TARGET_PAGE_MASK;
+    if (!size || (start_addr & ~TARGET_PAGE_MASK)) {
+        return;
+    }
 
     if (!memory_region_is_ram(mr)) {
         return;
     }
 
-    ram = memory_region_get_ram_ptr(mr) + section->offset_within_region;
+    ram = memory_region_get_ram_ptr(mr) + section->offset_within_region + delta;
 
     while (1) {
         mem = kvm_lookup_overlapping_slot(s, start_addr, start_addr + size);
commit 5b6fb069378e61c45c577bbec3d7ef60367f7e4c
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Mar 1 12:58:46 2012 +0200

    pc-bios: update kvmvapic.bin
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/pc-bios/kvmvapic.bin b/pc-bios/kvmvapic.bin
new file mode 100755
index 0000000..045f5c2
Binary files /dev/null and b/pc-bios/kvmvapic.bin differ
commit 7c51c1aa03a52b9fd75ed1ade2e65d079ae4d50e
Merge: f06d0f0... 67d384e...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Feb 29 12:57:28 2012 -0600

    Merge remote-tracking branch 'kwolf/for-anthony' into staging
    
    * kwolf/for-anthony: (27 commits)
      qemu-img: fix segment fault when the image format is qed
      qemu-io: fix segment fault when the image format is qed
      qemu-tool: revert cpu_get_clock() abort(3)
      qemu-iotests: Test rebase with short backing file
      qemu-iotests: 026: Reduce output changes for cache=none qcow2
      qemu-iotests: Filter out DOS line endings
      test: add image streaming tests
      qemu-iotests: add iotests Python module
      qemu-iotests: export TEST_DIR for non-bash tests
      QMP: Add qmp command for blockdev-group-snapshot-sync
      qapi: Introduce blockdev-group-snapshot-sync command
      qcow2: Reject too large header extensions
      qcow2: Fix offset in qcow2_read_extensions
      block: drop aio_multiwrite in BlockDriver
      block: remove unused fields in BlockDriverState
      qcow2: Fix build with DEBUG_EXT enabled
      ide: fail I/O to empty disk
      fdc: DIR (Digital Input Register) should return status of current drive...
      fdc: fix seek command, which shouldn't check tracks
      fdc: check if media rate is correct before doing any transfer
      ...

commit f06d0f0755dbd9fee2fd3f21eefd2b19105fa346
Merge: 5ca2358... e2efc0a...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Feb 29 12:54:08 2012 -0600

    Merge remote-tracking branch 'spice/spice.v49' into staging
    
    * spice/spice.v49:
      qxl: properly handle upright and non-shared surfaces
      Error out when tls-channel option is used without TLS
      spice: use error_report to report errors
      qxl: add optinal 64bit vram bar
      qxl: make qxl_render_update async
      qxl: introduce QXLCookie
      qxl: remove flipped
      qxl: require spice >= 0.8.2
      qxl: drop qxl_spice_update_area_async definition
      sdl: remove NULL check, g_malloc0 can't fail
      qxl: fix spice+sdl no cursor regression

commit 5ca2358ac895139e624881c5b3bf3095d3cc4515
Merge: b55c952... 3741715...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Feb 29 09:11:00 2012 -0600

    Merge remote-tracking branch 'kraxel/usb.39' into staging
    
    * kraxel/usb.39: (21 commits)
      usb: Resolve warnings about unassigned bus on usb device creation
      usb-redir: Return USB_RET_NAK when we've no data for an interrupt endpoint
      usb-redir: Limit return values returned by iso packets
      usb-redir: Let the usb-host know about our device filtering
      usb-redir: Always clear device state on filter reject
      usb-redir: Fix printing of device version
      ehci: drop old stuff
      usb-ehci: Handle ISO packets failing with an error other then NAK
      libcacard: fix reported ATR length
      usb-ccid: advertise SELF_POWERED
      libcacard: link with glib for g_strndup
      usb-desc: fix user trigerrable segfaults (!config)
      usb-ehci: sanity-check iso xfers
      usb: add tracepoint for usb packet state changes.
      usb-xhci: enable packet queuing
      usb-uhci: implement packet queuing
      usb-uhci: process uhci_handle_td return code via switch.
      usb-uhci: add UHCIQueue
      usb-uhci: cleanup UHCIAsync allocation & initialization.
      usb-ehci: fix reset
      ...

commit 67d384e80471e91aa490d4573cac5a46f92f685f
Author: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com>
Date:   Sun Feb 19 22:24:35 2012 +0800

    qemu-img: fix segment fault when the image format is qed
    
    [root at f15 qemu]# qemu-img info /home/zwu/work/misc/rh6.img
    image: /home/zwu/work/misc/rh6.img
    file format: qed
    virtual size: 4.0G (4294967296 bytes)
    disk size: 1.2G
    cluster_size: 65536
    Segmentation fault (core dumped)
    
    Today when i were fixing another issue, i found this issue; After simple
    investigation, i found that the required clock vm_clock is not created
    for qemu tool.
    
    Signed-off-by: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-img.c b/qemu-img.c
index c4bcf41..8df3564 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1655,6 +1655,8 @@ int main(int argc, char **argv)
     cmdname = argv[1];
     argc--; argv++;
 
+    qemu_init_main_loop();
+
     /* find the command */
     for(cmd = img_cmds; cmd->name != NULL; cmd++) {
         if (!strcmp(cmdname, cmd->name)) {
commit a57d114389bdf8ce493456f85f2ec2229f7d0c00
Author: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com>
Date:   Sun Feb 19 22:24:59 2012 +0800

    qemu-io: fix segment fault when the image format is qed
    
    [root at f15 qemu]# qemu-io -c info /home/zwu/work/misc/rh6.img
    format name: qed
    cluster size: 64 KiB
    vm state offset: 0.000000 bytes
    Segmentation fault (core dumped)
    
    This reason is same as the former patch
    
    Signed-off-by: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-io.c b/qemu-io.c
index 0249be4..3189530 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -1856,6 +1856,8 @@ int main(int argc, char **argv)
 
     bdrv_init();
 
+    qemu_init_main_loop();
+
     /* initialize commands */
     quit_init();
     help_init();
commit 4889978e94bd16c5374f473d57f5e757fbe72485
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Wed Feb 29 14:41:32 2012 +0000

    qemu-tool: revert cpu_get_clock() abort(3)
    
    Despite the fact that the qemu-tool environment has no guest running and
    vm_clock therefore does not make sense, there is code that gets the
    vm_clock time even in qemu-tool.  Therefore, revert the abort(3) call
    and just return 0 like we used to.  This unbreaks qemu-img/qemu-io with
    QED and Kevin has also expressed interest in this for qcow2.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-tool.c b/qemu-tool.c
index 183a583..edb84f5 100644
--- a/qemu-tool.c
+++ b/qemu-tool.c
@@ -61,7 +61,7 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
 
 int64_t cpu_get_clock(void)
 {
-    abort();
+    return 0;
 }
 
 int64_t cpu_get_icount(void)
commit 6ce2d77abeb7dece24612e884a74d149cdf52376
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Feb 15 15:03:25 2012 +0100

    qemu-iotests: Test rebase with short backing file
    
    This tests that qemu-img rebase doesn't assume that the backing file has
    the same size as the image, but considers that it can be smaller.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/tests/qemu-iotests/028 b/tests/qemu-iotests/028
index 07c5bb6..b091ba9 100755
--- a/tests/qemu-iotests/028
+++ b/tests/qemu-iotests/028
@@ -96,6 +96,11 @@ io_zero readv $(( offset + 32 * 1024 )) 512 1024 32
 
 _check_test_img
 
+# Rebase it on top of its base image
+$QEMU_IMG rebase -b $TEST_IMG.base $TEST_IMG
+
+_check_test_img
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/028.out b/tests/qemu-iotests/028.out
index f429029..fe00788 100644
--- a/tests/qemu-iotests/028.out
+++ b/tests/qemu-iotests/028.out
@@ -465,4 +465,5 @@ qemu-io> read 512/512 bytes at offset 3221257728
 qemu-io> read 512/512 bytes at offset 3221258752
 512.000000 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 qemu-io> No errors were found on the image.
+No errors were found on the image.
 *** done
commit 92ab69b61fe04d811378ae4eda9799a5ad6ddb14
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Apr 29 15:32:55 2011 +0200

    qemu-iotests: 026: Reduce output changes for cache=none qcow2
    
    qemu-iotests supports the -nocache option which makes the tests run with
    cache=none. For blkdebug tests with qcow2 this means that we may see
    test results that differ from cache=writethrough. This patch makes the
    diff a bit smaller and therefore easier to review.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/tests/qemu-iotests/026 b/tests/qemu-iotests/026
index 33e7da6..1602ccd 100755
--- a/tests/qemu-iotests/026
+++ b/tests/qemu-iotests/026
@@ -87,6 +87,12 @@ _make_test_img 1G
 
 echo
 echo "Event: $event; errno: $errno; imm: $imm; once: $once; write $vmstate"
+
+# We want to catch a simple L2 update, not the allocation of the first L2 table
+if [ "$event" == "l2_update" ]; then
+    $QEMU_IO -c "write $vmstate 0 512" $TEST_IMG > /dev/null 2>&1
+fi
+
 $QEMU_IO -c "write $vmstate 0 128k " $BLKDBG_TEST_IMG | _filter_qemu_io
 
 # l2_load is not called on allocation, so issue a second write
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
index 8499a04..aae1378 100755
--- a/tests/qemu-iotests/check
+++ b/tests/qemu-iotests/check
@@ -243,7 +243,7 @@ do
 		echo " - no qualified output"
 		err=true
 	    else
-		if diff $seq.out $tmp.out >/dev/null 2>&1
+		if diff -w $seq.out $tmp.out >/dev/null 2>&1
 		then
 		    echo ""
 		    if $err
@@ -255,7 +255,7 @@ do
 		else
 		    echo " - output mismatch (see $seq.out.bad)"
 		    mv $tmp.out $seq.out.bad
-		    $diff $seq.out $seq.out.bad
+		    $diff -w $seq.out $seq.out.bad
 		    err=true
 		fi
 	    fi
commit a06d5cc20b574e24630d9e59bf2a707728bc3101
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Apr 29 15:30:25 2011 +0200

    qemu-iotests: Filter out DOS line endings
    
    This one makes it possible to run qemu-iotests on a Windows build using Wine
    and get somewhat meaningful results.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
index da77ede..fa26b62 100644
--- a/tests/qemu-iotests/common.filter
+++ b/tests/qemu-iotests/common.filter
@@ -140,10 +140,16 @@ _filter_imgfmt()
     sed -e "s#$IMGFMT#IMGFMT#g"
 }
 
+# Removes \r from messages
+_filter_win32()
+{
+    sed -e 's/\r//g'
+}
+
 # sanitize qemu-io output
 _filter_qemu_io()
 {
-    sed -e "s/[0-9]* ops\; [0-9/:. sec]* ([0-9/.inf]* [EPTGMKiBbytes]*\/sec and [0-9/.inf]* ops\/sec)/X ops\; XX:XX:XX.X (XXX YYY\/sec and XXX ops\/sec)/"
+    _filter_win32 | sed -e "s/[0-9]* ops\; [0-9/:. sec]* ([0-9/.inf]* [EPTGMKiBbytes]*\/sec and [0-9/.inf]* ops\/sec)/X ops\; XX:XX:XX.X (XXX YYY\/sec and XXX ops\/sec)/"
 }
 
 # make sure this script returns success
commit 37ce63eb23ad092e88891cf458bd3491af65d0a3
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Wed Feb 29 13:25:22 2012 +0000

    test: add image streaming tests
    
    This patch adds a test suite for the image streaming feature.  It
    exercises the 'block_stream', 'block_job_cancel', 'block_job_set_speed',
    and 'query-block-jobs' QMP commands.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
new file mode 100755
index 0000000..1faf984
--- /dev/null
+++ b/tests/qemu-iotests/030
@@ -0,0 +1,151 @@
+#!/usr/bin/env python
+#
+# Tests for image streaming.
+#
+# Copyright (C) 2012 IBM Corp.
+#
+# 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/>.
+#
+
+import os
+import iotests
+from iotests import qemu_img, qemu_io
+
+backing_img = os.path.join(iotests.test_dir, 'backing.img')
+test_img = os.path.join(iotests.test_dir, 'test.img')
+
+class ImageStreamingTestCase(iotests.QMPTestCase):
+    '''Abstract base class for image streaming test cases'''
+
+    def assert_no_active_streams(self):
+        result = self.vm.qmp('query-block-jobs')
+        self.assert_qmp(result, 'return', [])
+
+class TestSingleDrive(ImageStreamingTestCase):
+    image_len = 1 * 1024 * 1024 # MB
+
+    def setUp(self):
+        qemu_img('create', backing_img, str(TestSingleDrive.image_len))
+        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
+        self.vm = iotests.VM().add_drive(test_img)
+        self.vm.launch()
+
+    def tearDown(self):
+        self.vm.shutdown()
+        os.remove(test_img)
+        os.remove(backing_img)
+
+    def test_stream(self):
+        self.assert_no_active_streams()
+
+        result = self.vm.qmp('block_stream', device='drive0')
+        self.assert_qmp(result, 'return', {})
+
+        completed = False
+        while not completed:
+            for event in self.vm.get_qmp_events(wait=True):
+                if event['event'] == 'BLOCK_JOB_COMPLETED':
+                    self.assert_qmp(event, 'data/type', 'stream')
+                    self.assert_qmp(event, 'data/device', 'drive0')
+                    self.assert_qmp(event, 'data/offset', self.image_len)
+                    self.assert_qmp(event, 'data/len', self.image_len)
+                    completed = True
+
+        self.assert_no_active_streams()
+
+        self.assertFalse('sectors not allocated' in qemu_io('-c', 'map', test_img),
+                         'image file not fully populated after streaming')
+
+    def test_device_not_found(self):
+        result = self.vm.qmp('block_stream', device='nonexistent')
+        self.assert_qmp(result, 'error/class', 'DeviceNotFound')
+
+class TestStreamStop(ImageStreamingTestCase):
+    image_len = 8 * 1024 * 1024 * 1024 # GB
+
+    def setUp(self):
+        qemu_img('create', backing_img, str(TestStreamStop.image_len))
+        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
+        self.vm = iotests.VM().add_drive(test_img)
+        self.vm.launch()
+
+    def tearDown(self):
+        self.vm.shutdown()
+        os.remove(test_img)
+        os.remove(backing_img)
+
+    def test_stream_stop(self):
+        import time
+
+        self.assert_no_active_streams()
+
+        result = self.vm.qmp('block_stream', device='drive0')
+        self.assert_qmp(result, 'return', {})
+
+        time.sleep(1)
+        events = self.vm.get_qmp_events(wait=False)
+        self.assertEqual(events, [], 'unexpected QMP event: %s' % events)
+
+        self.vm.qmp('block_job_cancel', device='drive0')
+        self.assert_qmp(result, 'return', {})
+
+        cancelled = False
+        while not cancelled:
+            for event in self.vm.get_qmp_events(wait=True):
+                if event['event'] == 'BLOCK_JOB_CANCELLED':
+                    self.assert_qmp(event, 'data/type', 'stream')
+                    self.assert_qmp(event, 'data/device', 'drive0')
+                    cancelled = True
+
+        self.assert_no_active_streams()
+
+# This is a short performance test which is not run by default.
+# Invoke "IMGFMT=qed ./030 TestSetSpeed.perf_test_set_speed"
+class TestSetSpeed(ImageStreamingTestCase):
+    image_len = 80 * 1024 * 1024 # MB
+
+    def setUp(self):
+        qemu_img('create', backing_img, str(TestSetSpeed.image_len))
+        qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
+        self.vm = iotests.VM().add_drive(test_img)
+        self.vm.launch()
+
+    def tearDown(self):
+        self.vm.shutdown()
+        os.remove(test_img)
+        os.remove(backing_img)
+
+    def perf_test_set_speed(self):
+        self.assert_no_active_streams()
+
+        result = self.vm.qmp('block_stream', device='drive0')
+        self.assert_qmp(result, 'return', {})
+
+        result = self.vm.qmp('block_job_set_speed', device='drive0', value=8 * 1024 * 1024)
+        self.assert_qmp(result, 'return', {})
+
+        completed = False
+        while not completed:
+            for event in self.vm.get_qmp_events(wait=True):
+                if event['event'] == 'BLOCK_JOB_COMPLETED':
+                    self.assert_qmp(event, 'data/type', 'stream')
+                    self.assert_qmp(event, 'data/device', 'drive0')
+                    self.assert_qmp(event, 'data/offset', self.image_len)
+                    self.assert_qmp(event, 'data/len', self.image_len)
+                    completed = True
+
+        self.assert_no_active_streams()
+
+if __name__ == '__main__':
+    iotests.main(supported_fmts=['qcow2', 'qed'])
diff --git a/tests/qemu-iotests/030.out b/tests/qemu-iotests/030.out
new file mode 100644
index 0000000..8d7e996
--- /dev/null
+++ b/tests/qemu-iotests/030.out
@@ -0,0 +1,5 @@
+...
+----------------------------------------------------------------------
+Ran 3 tests
+
+OK
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index 0a5c866..fcf869d 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -36,3 +36,4 @@
 027 rw auto
 028 rw backing auto
 029 rw auto
+030 rw auto
commit f345cfd01935c6d7ab19f841a2eee2901ca3221e
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Wed Feb 29 13:25:21 2012 +0000

    qemu-iotests: add iotests Python module
    
    Block layer tests that involve QMP commands rather than qemu-img or
    qemu-io are not well-suited for shell scripting.  This patch adds a
    Python module which allows tests to be written in Python instead.
    
    The basic API is:
    
      VM          - class for launching and interacting with a VM
      QMPTestCase - abstract base class for tests that use QMP
      qemu_img()  - wrapper function for invoking qemu-img
      qemu_io()   - wrapper function for invoking qemu-io
      imgfmt      - the image format under test (e.g. qcow2, qed)
      test_dir    - scratch directory path for temporary files
      main()      - entry point for running tests
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
new file mode 100644
index 0000000..ec1a86a
--- /dev/null
+++ b/tests/qemu-iotests/iotests.py
@@ -0,0 +1,164 @@
+# Common utilities and Python wrappers for qemu-iotests
+#
+# Copyright (C) 2012 IBM Corp.
+#
+# 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/>.
+#
+
+import os
+import re
+import subprocess
+import unittest
+import sys; sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'QMP'))
+import qmp
+
+__all__ = ['imgfmt', 'imgproto', 'test_dir' 'qemu_img', 'qemu_io',
+           'VM', 'QMPTestCase', 'notrun', 'main']
+
+# This will not work if arguments or path contain spaces but is necessary if we
+# want to support the override options that ./check supports.
+qemu_img_args = os.environ.get('QEMU_IMG', 'qemu-img').split(' ')
+qemu_io_args = os.environ.get('QEMU_IO', 'qemu-io').split(' ')
+qemu_args = os.environ.get('QEMU', 'qemu').split(' ')
+
+imgfmt = os.environ.get('IMGFMT', 'raw')
+imgproto = os.environ.get('IMGPROTO', 'file')
+test_dir = os.environ.get('TEST_DIR', '/var/tmp')
+
+def qemu_img(*args):
+    '''Run qemu-img and return the exit code'''
+    devnull = open('/dev/null', 'r+')
+    return subprocess.call(qemu_img_args + list(args), stdin=devnull, stdout=devnull)
+
+def qemu_io(*args):
+    '''Run qemu-io and return the stdout data'''
+    args = qemu_io_args + list(args)
+    return subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0]
+
+class VM(object):
+    '''A QEMU VM'''
+
+    def __init__(self):
+        self._monitor_path = os.path.join(test_dir, 'qemu-mon.%d' % os.getpid())
+        self._qemu_log_path = os.path.join(test_dir, 'qemu-log.%d' % os.getpid())
+        self._args = qemu_args + ['-chardev',
+                     'socket,id=mon,path=' + self._monitor_path,
+                     '-mon', 'chardev=mon,mode=control', '-nographic']
+        self._num_drives = 0
+
+    def add_drive(self, path, opts=''):
+        '''Add a virtio-blk drive to the VM'''
+        options = ['if=virtio',
+                   'format=%s' % imgfmt,
+                   'cache=none',
+                   'file=%s' % path,
+                   'id=drive%d' % self._num_drives]
+        if opts:
+            options.append(opts)
+
+        self._args.append('-drive')
+        self._args.append(','.join(options))
+        self._num_drives += 1
+        return self
+
+    def launch(self):
+        '''Launch the VM and establish a QMP connection'''
+        devnull = open('/dev/null', 'rb')
+        qemulog = open(self._qemu_log_path, 'wb')
+        try:
+            self._qmp = qmp.QEMUMonitorProtocol(self._monitor_path, server=True)
+            self._popen = subprocess.Popen(self._args, stdin=devnull, stdout=qemulog,
+                                           stderr=subprocess.STDOUT)
+            self._qmp.accept()
+        except:
+            os.remove(self._monitor_path)
+            raise
+
+    def shutdown(self):
+        '''Terminate the VM and clean up'''
+        self._qmp.cmd('quit')
+        self._popen.wait()
+        os.remove(self._monitor_path)
+        os.remove(self._qemu_log_path)
+
+    def qmp(self, cmd, **args):
+        '''Invoke a QMP command and return the result dict'''
+        return self._qmp.cmd(cmd, args=args)
+
+    def get_qmp_events(self, wait=False):
+        '''Poll for queued QMP events and return a list of dicts'''
+        events = self._qmp.get_events(wait=wait)
+        self._qmp.clear_events()
+        return events
+
+index_re = re.compile(r'([^\[]+)\[([^\]]+)\]')
+
+class QMPTestCase(unittest.TestCase):
+    '''Abstract base class for QMP test cases'''
+
+    def dictpath(self, d, path):
+        '''Traverse a path in a nested dict'''
+        for component in path.split('/'):
+            m = index_re.match(component)
+            if m:
+                component, idx = m.groups()
+                idx = int(idx)
+
+            if not isinstance(d, dict) or component not in d:
+                self.fail('failed path traversal for "%s" in "%s"' % (path, str(d)))
+            d = d[component]
+
+            if m:
+                if not isinstance(d, list):
+                    self.fail('path component "%s" in "%s" is not a list in "%s"' % (component, path, str(d)))
+                try:
+                    d = d[idx]
+                except IndexError:
+                    self.fail('invalid index "%s" in path "%s" in "%s"' % (idx, path, str(d)))
+        return d
+
+    def assert_qmp(self, d, path, value):
+        '''Assert that the value for a specific path in a QMP dict matches'''
+        result = self.dictpath(d, path)
+        self.assertEqual(result, value, 'values not equal "%s" and "%s"' % (str(result), str(value)))
+
+def notrun(reason):
+    '''Skip this test suite'''
+    # Each test in qemu-iotests has a number ("seq")
+    seq = os.path.basename(sys.argv[0])
+
+    open('%s.notrun' % seq, 'wb').write(reason + '\n')
+    print '%s not run: %s' % (seq, reason)
+    sys.exit(0)
+
+def main(supported_fmts=[]):
+    '''Run tests'''
+
+    if supported_fmts and (imgfmt not in supported_fmts):
+        notrun('not suitable for this image format: %s' % imgfmt)
+
+    # We need to filter out the time taken from the output so that qemu-iotest
+    # can reliably diff the results against master output.
+    import StringIO
+    output = StringIO.StringIO()
+
+    class MyTestRunner(unittest.TextTestRunner):
+        def __init__(self, stream=output, descriptions=True, verbosity=1):
+            unittest.TextTestRunner.__init__(self, stream, descriptions, verbosity)
+
+    # unittest.main() will use sys.exit() so expect a SystemExit exception
+    try:
+        unittest.main(testRunner=MyTestRunner)
+    finally:
+        sys.stderr.write(re.sub(r'Ran (\d+) test[s] in [\d.]+s', r'Ran \1 tests', output.getvalue()))
commit 049255b60c2bd95df09e3da9de0d9658b2ec4a98
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Wed Feb 29 13:25:20 2012 +0000

    qemu-iotests: export TEST_DIR for non-bash tests
    
    Since qemu-iotests may need to create large image files it is possible
    to specify the test directory.  The TEST_DIR variable needs to be
    exported so non-bash tests can make use of it.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/tests/qemu-iotests/common.config b/tests/qemu-iotests/common.config
index d07f435..a220684 100644
--- a/tests/qemu-iotests/common.config
+++ b/tests/qemu-iotests/common.config
@@ -121,6 +121,8 @@ if [ ! -d "$TEST_DIR" ]; then
     exit 1
 fi
 
+export TEST_DIR
+
 _readlink()
 {
     if [ $# -ne 1 ]; then
commit c186402c444a9598a71da6aef1360f4171e57ad3
Author: Jeff Cody <jcody at redhat.com>
Date:   Tue Feb 28 15:54:07 2012 -0500

    QMP: Add qmp command for blockdev-group-snapshot-sync
    
    This adds the QMP command for blockdev-group-snapshot-sync. It
    takes an array in as the input, for the argument devlist.  The
    array consists of the following elements:
    
        + device:        device to snapshot. e.g. "ide-hd0", "virtio0"
        + snapshot-file: path & file for the snapshot image. e.g. "/tmp/file.img"
        + format:        snapshot format. e.g., "qcow2". Optional
    
    There is no HMP equivalent for the command.
    
    Signed-off-by: Jeff Cody <jcody at redhat.com>
    Acked-by: Luiz Capitulino <lcapitulino at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qmp-commands.hx b/qmp-commands.hx
index 705f704..0c9bfac 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -686,6 +686,45 @@ EQMP
         .args_type  = "device:B",
         .mhandler.cmd_new = qmp_marshal_input_block_job_cancel,
     },
+    {
+        .name       = "blockdev-group-snapshot-sync",
+        .args_type  = "devlist:O",
+        .params  = "device:B,snapshot-file:s,format:s?",
+        .mhandler.cmd_new = qmp_marshal_input_blockdev_group_snapshot_sync,
+    },
+
+SQMP
+blockdev-group-snapshot-sync
+----------------------
+
+Synchronous snapshot of one or more block devices.  A list array input
+is accepted, that contains the device and snapshot file information for
+each device in group. The default format, if not specified, is qcow2.
+
+If there is any failure creating or opening a new snapshot, all snapshots
+for the group are abandoned, and the original disks pre-snapshot attempt
+are used.
+
+
+Arguments:
+
+devlist array:
+    - "device": device name to snapshot (json-string)
+    - "snapshot-file": name of new image file (json-string)
+    - "format": format of new image (json-string, optional)
+
+Example:
+
+-> { "execute": "blockdev-group-snapshot-sync", "arguments":
+                      { "devlist": [{ "device": "ide-hd0",
+                                      "snapshot-file": "/some/place/my-image",
+                                      "format": "qcow2" },
+                                    { "device": "ide-hd1",
+                                      "snapshot-file": "/some/place/my-image2",
+                                      "format": "qcow2" }] } }
+<- { "return": {} }
+
+EQMP
 
     {
         .name       = "blockdev-snapshot-sync",
commit 8802d1fdd4b73e02ce13fb3a233c64c1913634ab
Author: Jeff Cody <jcody at redhat.com>
Date:   Tue Feb 28 15:54:06 2012 -0500

    qapi: Introduce blockdev-group-snapshot-sync command
    
    This is a QAPI/QMP only command to take a snapshot of a group of
    devices. This is similar to the blockdev-snapshot-sync command, except
    blockdev-group-snapshot-sync accepts a list devices, filenames, and
    formats.
    
    It is attempted to keep the snapshot of the group atomic; if the
    creation or open of any of the new snapshots fails, then all of
    the new snapshots are abandoned, and the name of the snapshot image
    that failed is returned.  The failure case should not interrupt
    any operations.
    
    Rather than use bdrv_close() along with a subsequent bdrv_open() to
    perform the pivot, the original image is never closed and the new
    image is placed 'in front' of the original image via manipulation
    of the BlockDriverState fields.  Thus, once the new snapshot image
    has been successfully created, there are no more failure points
    before pivoting to the new snapshot.
    
    This allows the group of disks to remain consistent with each other,
    even across snapshot failures.
    
    Signed-off-by: Jeff Cody <jcody at redhat.com>
    Acked-by: Luiz Capitulino <lcapitulino at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index f23eccc..52ffe14 100644
--- a/block.c
+++ b/block.c
@@ -882,6 +882,87 @@ void bdrv_make_anon(BlockDriverState *bs)
     bs->device_name[0] = '\0';
 }
 
+/*
+ * Add new bs contents at the top of an image chain while the chain is
+ * live, while keeping required fields on the top layer.
+ *
+ * This will modify the BlockDriverState fields, and swap contents
+ * between bs_new and bs_top. Both bs_new and bs_top are modified.
+ *
+ * This function does not create any image files.
+ */
+void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top)
+{
+    BlockDriverState tmp;
+
+    /* the new bs must not be in bdrv_states */
+    bdrv_make_anon(bs_new);
+
+    tmp = *bs_new;
+
+    /* there are some fields that need to stay on the top layer: */
+
+    /* dev info */
+    tmp.dev_ops           = bs_top->dev_ops;
+    tmp.dev_opaque        = bs_top->dev_opaque;
+    tmp.dev               = bs_top->dev;
+    tmp.buffer_alignment  = bs_top->buffer_alignment;
+    tmp.copy_on_read      = bs_top->copy_on_read;
+
+    /* i/o timing parameters */
+    tmp.slice_time        = bs_top->slice_time;
+    tmp.slice_start       = bs_top->slice_start;
+    tmp.slice_end         = bs_top->slice_end;
+    tmp.io_limits         = bs_top->io_limits;
+    tmp.io_base           = bs_top->io_base;
+    tmp.throttled_reqs    = bs_top->throttled_reqs;
+    tmp.block_timer       = bs_top->block_timer;
+    tmp.io_limits_enabled = bs_top->io_limits_enabled;
+
+    /* geometry */
+    tmp.cyls              = bs_top->cyls;
+    tmp.heads             = bs_top->heads;
+    tmp.secs              = bs_top->secs;
+    tmp.translation       = bs_top->translation;
+
+    /* r/w error */
+    tmp.on_read_error     = bs_top->on_read_error;
+    tmp.on_write_error    = bs_top->on_write_error;
+
+    /* i/o status */
+    tmp.iostatus_enabled  = bs_top->iostatus_enabled;
+    tmp.iostatus          = bs_top->iostatus;
+
+    /* keep the same entry in bdrv_states */
+    pstrcpy(tmp.device_name, sizeof(tmp.device_name), bs_top->device_name);
+    tmp.list = bs_top->list;
+
+    /* The contents of 'tmp' will become bs_top, as we are
+     * swapping bs_new and bs_top contents. */
+    tmp.backing_hd = bs_new;
+    pstrcpy(tmp.backing_file, sizeof(tmp.backing_file), bs_top->filename);
+
+    /* swap contents of the fixed new bs and the current top */
+    *bs_new = *bs_top;
+    *bs_top = tmp;
+
+    /* clear the copied fields in the new backing file */
+    bdrv_detach_dev(bs_new, bs_new->dev);
+
+    qemu_co_queue_init(&bs_new->throttled_reqs);
+    memset(&bs_new->io_base,   0, sizeof(bs_new->io_base));
+    memset(&bs_new->io_limits, 0, sizeof(bs_new->io_limits));
+    bdrv_iostatus_disable(bs_new);
+
+    /* we don't use bdrv_io_limits_disable() for this, because we don't want
+     * to affect or delete the block_timer, as it has been moved to bs_top */
+    bs_new->io_limits_enabled = false;
+    bs_new->block_timer       = NULL;
+    bs_new->slice_time        = 0;
+    bs_new->slice_start       = 0;
+    bs_new->slice_end         = 0;
+}
+
 void bdrv_delete(BlockDriverState *bs)
 {
     assert(!bs->dev);
diff --git a/block.h b/block.h
index bbc3830..48d0bf3 100644
--- a/block.h
+++ b/block.h
@@ -114,6 +114,7 @@ int bdrv_create(BlockDriver *drv, const char* filename,
 int bdrv_create_file(const char* filename, QEMUOptionParameter *options);
 BlockDriverState *bdrv_new(const char *device_name);
 void bdrv_make_anon(BlockDriverState *bs);
+void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top);
 void bdrv_delete(BlockDriverState *bs);
 int bdrv_parse_cache_flags(const char *mode, int *flags);
 int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags);
diff --git a/block_int.h b/block_int.h
index bd86af0..b460c36 100644
--- a/block_int.h
+++ b/block_int.h
@@ -221,6 +221,12 @@ struct BlockDriver {
     QLIST_ENTRY(BlockDriver) list;
 };
 
+/*
+ * Note: the function bdrv_append() copies and swaps contents of
+ * BlockDriverStates, so if you add new fields to this struct, please
+ * inspect bdrv_append() to determine if the new fields need to be
+ * copied as well.
+ */
 struct BlockDriverState {
     int64_t total_sectors; /* if we are reading a disk image, give its
                               size in sectors */
diff --git a/blockdev.c b/blockdev.c
index 2c132a3..d78aa51 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -714,6 +714,137 @@ void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file,
     }
 }
 
+
+/* New and old BlockDriverState structs for group snapshots */
+typedef struct BlkGroupSnapshotStates {
+    BlockDriverState *old_bs;
+    BlockDriverState *new_bs;
+    QSIMPLEQ_ENTRY(BlkGroupSnapshotStates) entry;
+} BlkGroupSnapshotStates;
+
+/*
+ * 'Atomic' group snapshots.  The snapshots are taken as a set, and if any fail
+ *  then we do not pivot any of the devices in the group, and abandon the
+ *  snapshots
+ */
+void qmp_blockdev_group_snapshot_sync(SnapshotDevList *dev_list,
+                                      Error **errp)
+{
+    int ret = 0;
+    SnapshotDevList *dev_entry = dev_list;
+    SnapshotDev *dev_info = NULL;
+    BlkGroupSnapshotStates *states;
+    BlockDriver *proto_drv;
+    BlockDriver *drv;
+    int flags;
+    const char *format;
+    const char *snapshot_file;
+
+    QSIMPLEQ_HEAD(snap_bdrv_states, BlkGroupSnapshotStates) snap_bdrv_states;
+    QSIMPLEQ_INIT(&snap_bdrv_states);
+
+    /* drain all i/o before any snapshots */
+    bdrv_drain_all();
+
+    /* We don't do anything in this loop that commits us to the snapshot */
+    while (NULL != dev_entry) {
+        dev_info = dev_entry->value;
+        dev_entry = dev_entry->next;
+
+        states = g_malloc0(sizeof(BlkGroupSnapshotStates));
+        QSIMPLEQ_INSERT_TAIL(&snap_bdrv_states, states, entry);
+
+        states->old_bs = bdrv_find(dev_info->device);
+
+        if (!states->old_bs) {
+            error_set(errp, QERR_DEVICE_NOT_FOUND, dev_info->device);
+            goto delete_and_fail;
+        }
+
+        if (bdrv_in_use(states->old_bs)) {
+            error_set(errp, QERR_DEVICE_IN_USE, dev_info->device);
+            goto delete_and_fail;
+        }
+
+        if (!bdrv_is_read_only(states->old_bs) &&
+             bdrv_is_inserted(states->old_bs)) {
+
+            if (bdrv_flush(states->old_bs)) {
+                error_set(errp, QERR_IO_ERROR);
+                goto delete_and_fail;
+            }
+        }
+
+        snapshot_file = dev_info->snapshot_file;
+
+        flags = states->old_bs->open_flags;
+
+        if (!dev_info->has_format) {
+            format = "qcow2";
+        } else {
+            format = dev_info->format;
+        }
+
+        drv = bdrv_find_format(format);
+        if (!drv) {
+            error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
+            goto delete_and_fail;
+        }
+
+        proto_drv = bdrv_find_protocol(snapshot_file);
+        if (!proto_drv) {
+            error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
+            goto delete_and_fail;
+        }
+
+        /* create new image w/backing file */
+        ret = bdrv_img_create(snapshot_file, format,
+                              states->old_bs->filename,
+                              drv->format_name, NULL, -1, flags);
+        if (ret) {
+            error_set(errp, QERR_OPEN_FILE_FAILED, snapshot_file);
+            goto delete_and_fail;
+        }
+
+        /* We will manually add the backing_hd field to the bs later */
+        states->new_bs = bdrv_new("");
+        ret = bdrv_open(states->new_bs, snapshot_file,
+                        flags | BDRV_O_NO_BACKING, drv);
+        if (ret != 0) {
+            error_set(errp, QERR_OPEN_FILE_FAILED, snapshot_file);
+            goto delete_and_fail;
+        }
+    }
+
+
+    /* Now we are going to do the actual pivot.  Everything up to this point
+     * is reversible, but we are committed at this point */
+    QSIMPLEQ_FOREACH(states, &snap_bdrv_states, entry) {
+        /* This removes our old bs from the bdrv_states, and adds the new bs */
+        bdrv_append(states->new_bs, states->old_bs);
+    }
+
+    /* success */
+    goto exit;
+
+delete_and_fail:
+    /*
+    * failure, and it is all-or-none; abandon each new bs, and keep using
+    * the original bs for all images
+    */
+    QSIMPLEQ_FOREACH(states, &snap_bdrv_states, entry) {
+        if (states->new_bs) {
+             bdrv_delete(states->new_bs);
+        }
+    }
+exit:
+    QSIMPLEQ_FOREACH(states, &snap_bdrv_states, entry) {
+        g_free(states);
+    }
+    return;
+}
+
+
 static void eject_device(BlockDriverState *bs, int force, Error **errp)
 {
     if (bdrv_in_use(bs)) {
diff --git a/qapi-schema.json b/qapi-schema.json
index d0b6792..5f293c4 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1118,6 +1118,44 @@
 { 'command': 'block_resize', 'data': { 'device': 'str', 'size': 'int' }}
 
 ##
+# @SnapshotDev
+#
+# @device:  the name of the device to generate the snapshot from.
+#
+# @snapshot-file: the target of the new image. A new file will be created.
+#
+# @format: #optional the format of the snapshot image, default is 'qcow2'.
+##
+{ 'type': 'SnapshotDev',
+  'data': {'device': 'str', 'snapshot-file': 'str', '*format': 'str' } }
+
+##
+# @blockdev-group-snapshot-sync
+#
+# Generates a synchronous snapshot of a group of one or more block devices,
+# as atomically as possible.  If the snapshot of any device in the group
+# fails, then the entire group snapshot will be abandoned and the
+# appropriate error returned.
+#
+#  List of:
+#  @SnapshotDev: information needed for the device snapshot
+#
+# Returns: nothing on success
+#          If @device is not a valid block device, DeviceNotFound
+#          If @device is busy, DeviceInUse will be returned
+#          If @snapshot-file can't be created, OpenFileFailed
+#          If @snapshot-file can't be opened, OpenFileFailed
+#          If @format is invalid, InvalidBlockFormat
+#
+# Note: The group snapshot attempt returns failure on the first snapshot
+# device failure.  Therefore, there will be only one device or snapshot file
+# returned in an error condition, and subsequent devices will not have been
+# attempted.
+##
+{ 'command': 'blockdev-group-snapshot-sync',
+  'data': { 'devlist': [ 'SnapshotDev' ] } }
+
+##
 # @blockdev-snapshot-sync
 #
 # Generates a synchronous snapshot of a block device.
commit 64ca6aee4f06a3af869e5e09f0afeb6721966875
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Feb 22 12:37:13 2012 +0100

    qcow2: Reject too large header extensions
    
    Image files that make qemu-img info read several gigabytes into the
    unknown header extensions list are bad. Just fail opening the image
    if an extension claims to be larger than the header extension area.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index f68f0e1..eb5ea48 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -108,6 +108,11 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
 #ifdef DEBUG_EXT
         printf("ext.magic = 0x%x\n", ext.magic);
 #endif
+        if (ext.len > end_offset - offset) {
+            error_report("Header extension too large");
+            return -EINVAL;
+        }
+
         switch (ext.magic) {
         case QCOW2_EXT_MAGIC_END:
             return 0;
commit fd29b4bbef9f75bba64ad7c4db38babc397a4814
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Feb 22 12:31:47 2012 +0100

    qcow2: Fix offset in qcow2_read_extensions
    
    The spec says that the length of extensions is padded to 8 bytes, not
    the offset. Currently this is the same because the header size is a
    multiple of 8, so this is only about compatibility with future changes
    to the header size.
    
    While touching it, move the calculation to a common place instead of
    duplicating it for each header extension type.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index dea12c1..f68f0e1 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -126,7 +126,6 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
 #ifdef DEBUG_EXT
             printf("Qcow2: Got format extension %s\n", bs->backing_format);
 #endif
-            offset = ((offset + ext.len + 7) & ~7);
             break;
 
         default:
@@ -143,11 +142,11 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
                 if (ret < 0) {
                     return ret;
                 }
-
-                offset = ((offset + ext.len + 7) & ~7);
             }
             break;
         }
+
+        offset += ((ext.len + 7) & ~7);
     }
 
     return 0;
commit b6a127a156d5c26ea714493731db35a9491919da
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Feb 21 16:43:52 2012 +0100

    block: drop aio_multiwrite in BlockDriver
    
    These were never used.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 1150437..f23eccc 100644
--- a/block.c
+++ b/block.c
@@ -2791,7 +2791,6 @@ typedef struct MultiwriteCB {
         BlockDriverCompletionFunc *cb;
         void *opaque;
         QEMUIOVector *free_qiov;
-        void *free_buf;
     } callbacks[];
 } MultiwriteCB;
 
@@ -2805,7 +2804,6 @@ static void multiwrite_user_cb(MultiwriteCB *mcb)
             qemu_iovec_destroy(mcb->callbacks[i].free_qiov);
         }
         g_free(mcb->callbacks[i].free_qiov);
-        qemu_vfree(mcb->callbacks[i].free_buf);
     }
 }
 
@@ -2862,20 +2860,11 @@ static int multiwrite_merge(BlockDriverState *bs, BlockRequest *reqs,
         int merge = 0;
         int64_t oldreq_last = reqs[outidx].sector + reqs[outidx].nb_sectors;
 
-        // This handles the cases that are valid for all block drivers, namely
-        // exactly sequential writes and overlapping writes.
+        // Handle exactly sequential writes and overlapping writes.
         if (reqs[i].sector <= oldreq_last) {
             merge = 1;
         }
 
-        // The block driver may decide that it makes sense to combine requests
-        // even if there is a gap of some sectors between them. In this case,
-        // the gap is filled with zeros (therefore only applicable for yet
-        // unused space in format like qcow2).
-        if (!merge && bs->drv->bdrv_merge_requests) {
-            merge = bs->drv->bdrv_merge_requests(bs, &reqs[outidx], &reqs[i]);
-        }
-
         if (reqs[outidx].qiov->niov + reqs[i].qiov->niov + 1 > IOV_MAX) {
             merge = 0;
         }
@@ -2891,14 +2880,8 @@ static int multiwrite_merge(BlockDriverState *bs, BlockRequest *reqs,
             size = (reqs[i].sector - reqs[outidx].sector) << 9;
             qemu_iovec_concat(qiov, reqs[outidx].qiov, size);
 
-            // We might need to add some zeros between the two requests
-            if (reqs[i].sector > oldreq_last) {
-                size_t zero_bytes = (reqs[i].sector - oldreq_last) << 9;
-                uint8_t *buf = qemu_blockalign(bs, zero_bytes);
-                memset(buf, 0, zero_bytes);
-                qemu_iovec_add(qiov, buf, zero_bytes);
-                mcb->callbacks[i].free_buf = buf;
-            }
+            // We should need to add any zeros between the two requests
+            assert (reqs[i].sector <= oldreq_last);
 
             // Add the second request
             qemu_iovec_concat(qiov, reqs[i].qiov, reqs[i].qiov->size);
diff --git a/block_int.h b/block_int.h
index 25aff80..bd86af0 100644
--- a/block_int.h
+++ b/block_int.h
@@ -162,12 +162,6 @@ struct BlockDriver {
      */
     int coroutine_fn (*bdrv_co_flush_to_os)(BlockDriverState *bs);
 
-    int (*bdrv_aio_multiwrite)(BlockDriverState *bs, BlockRequest *reqs,
-        int num_reqs);
-    int (*bdrv_merge_requests)(BlockDriverState *bs, BlockRequest* a,
-        BlockRequest *b);
-
-
     const char *protocol_name;
     int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset);
     int64_t (*bdrv_getlength)(BlockDriverState *bs);
commit 56116a14699b9d898a8d6581a58ec81e4abae6e6
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Feb 20 17:58:34 2012 +0100

    block: remove unused fields in BlockDriverState
    
    sync_aiocb is unused since commit ce1a14d (Dynamically allocate AIO
    Completion Blocks., 2006-08-07).
    
    private is unused since commit 56a1493 (drive cleanup fixes., 2009-09-25).
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block_int.h b/block_int.h
index 04f4b83..25aff80 100644
--- a/block_int.h
+++ b/block_int.h
@@ -259,10 +259,6 @@ struct BlockDriverState {
     /* number of in-flight copy-on-read requests */
     unsigned int copy_on_read_in_flight;
 
-    /* async read/write emulation */
-
-    void *sync_aiocb;
-
     /* the time for latest disk I/O */
     int64_t slice_time;
     int64_t slice_start;
@@ -299,7 +295,6 @@ struct BlockDriverState {
     int64_t dirty_count;
     int in_use; /* users other than guest access, eg. block migration */
     QTAILQ_ENTRY(BlockDriverState) list;
-    void *private;
 
     QLIST_HEAD(, BdrvTrackedRequest) tracked_requests;
 
commit 423477e5568c75e5b6e468c561e75417d8ae9585
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Feb 17 18:45:33 2012 +0100

    qcow2: Fix build with DEBUG_EXT enabled
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index 3692b45..dea12c1 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -89,7 +89,6 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
     while (offset < end_offset) {
 
 #ifdef DEBUG_EXT
-        BDRVQcowState *s = bs->opaque;
         /* Sanity check */
         if (offset > s->cluster_size)
             printf("qcow2_read_extension: suspicious offset %lu\n", offset);
commit d53cdb307a6f6d7a5136898902659f2ded8f6582
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Feb 15 11:46:11 2012 +0100

    ide: fail I/O to empty disk
    
    Requesting a read or a write operation on an empty disk can lead
    to QEMU dumping core.
    
    Also fix a few braces here and there.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index ce570a7..4d568ac 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1068,6 +1068,9 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
             ide_set_signature(s); /* odd, but ATA4 8.27.5.2 requires it */
             goto abort_cmd;
         }
+        if (!s->bs) {
+            goto abort_cmd;
+        }
 	ide_cmd_lba48_transform(s, lba48);
         s->req_nb_sectors = 1;
         ide_sector_read(s);
@@ -1078,6 +1081,9 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
     case WIN_WRITE_ONCE:
     case CFA_WRITE_SECT_WO_ERASE:
     case WIN_WRITE_VERIFY:
+        if (!s->bs) {
+            goto abort_cmd;
+        }
 	ide_cmd_lba48_transform(s, lba48);
         s->error = 0;
         s->status = SEEK_STAT | READY_STAT;
@@ -1088,8 +1094,12 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
     case WIN_MULTREAD_EXT:
 	lba48 = 1;
     case WIN_MULTREAD:
-        if (!s->mult_sectors)
+        if (!s->bs) {
             goto abort_cmd;
+        }
+        if (!s->mult_sectors) {
+            goto abort_cmd;
+        }
 	ide_cmd_lba48_transform(s, lba48);
         s->req_nb_sectors = s->mult_sectors;
         ide_sector_read(s);
@@ -1098,8 +1108,12 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
 	lba48 = 1;
     case WIN_MULTWRITE:
     case CFA_WRITE_MULTI_WO_ERASE:
-        if (!s->mult_sectors)
+        if (!s->bs) {
             goto abort_cmd;
+        }
+        if (!s->mult_sectors) {
+            goto abort_cmd;
+        }
 	ide_cmd_lba48_transform(s, lba48);
         s->error = 0;
         s->status = SEEK_STAT | READY_STAT;
@@ -1114,8 +1128,9 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
 	lba48 = 1;
     case WIN_READDMA:
     case WIN_READDMA_ONCE:
-        if (!s->bs)
+        if (!s->bs) {
             goto abort_cmd;
+        }
 	ide_cmd_lba48_transform(s, lba48);
         ide_sector_start_dma(s, IDE_DMA_READ);
         break;
@@ -1123,8 +1138,9 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
 	lba48 = 1;
     case WIN_WRITEDMA:
     case WIN_WRITEDMA_ONCE:
-        if (!s->bs)
+        if (!s->bs) {
             goto abort_cmd;
+        }
 	ide_cmd_lba48_transform(s, lba48);
         ide_sector_start_dma(s, IDE_DMA_WRITE);
         s->media_changed = 1;
commit a2df5fa324cd09a31225701e5b2f9fb067c237cd
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Mon Feb 6 22:29:12 2012 +0100

    fdc: DIR (Digital Input Register) should return status of current drive...
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/fdc.c b/hw/fdc.c
index 7879b70..a0236b7 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -216,6 +216,7 @@ static void fdctrl_reset_fifo(FDCtrl *fdctrl);
 static int fdctrl_transfer_handler (void *opaque, int nchan,
                                     int dma_pos, int dma_len);
 static void fdctrl_raise_irq(FDCtrl *fdctrl, uint8_t status0);
+static FDrive *get_cur_drv(FDCtrl *fdctrl);
 
 static uint32_t fdctrl_read_statusA(FDCtrl *fdctrl);
 static uint32_t fdctrl_read_statusB(FDCtrl *fdctrl);
@@ -956,14 +957,9 @@ static uint32_t fdctrl_read_dir(FDCtrl *fdctrl)
 {
     uint32_t retval = 0;
 
-    if (fdctrl_media_changed(drv0(fdctrl))
-     || fdctrl_media_changed(drv1(fdctrl))
-#if MAX_FD == 4
-     || fdctrl_media_changed(drv2(fdctrl))
-     || fdctrl_media_changed(drv3(fdctrl))
-#endif
-        )
+    if (fdctrl_media_changed(get_cur_drv(fdctrl))) {
         retval |= FD_DIR_DSKCHG;
+    }
     if (retval != 0) {
         FLOPPY_DPRINTF("Floppy digital input register: 0x%02x\n", retval);
     }
commit b072a3c85da1391d86aaea60451738131034c7c3
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Mon Feb 6 22:29:11 2012 +0100

    fdc: fix seek command, which shouldn't check tracks
    
    The seek command just sends step pulses to the drive and doesn't care if
    there is a medium inserted of if it is banging the head against the drive.
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/fdc.c b/hw/fdc.c
index cc03326..7879b70 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -1622,13 +1622,16 @@ static void fdctrl_handle_seek(FDCtrl *fdctrl, int direction)
     SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
     cur_drv = get_cur_drv(fdctrl);
     fdctrl_reset_fifo(fdctrl);
+    /* The seek command just sends step pulses to the drive and doesn't care if
+     * there is a medium inserted of if it's banging the head against the drive.
+     */
     if (fdctrl->fifo[2] > cur_drv->max_track) {
-        fdctrl_raise_irq(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK);
+        cur_drv->track = cur_drv->max_track;
     } else {
         cur_drv->track = fdctrl->fifo[2];
-        /* Raise Interrupt */
-        fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
     }
+    /* Raise Interrupt */
+    fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
 }
 
 static void fdctrl_handle_perpendicular_mode(FDCtrl *fdctrl, int direction)
commit 844f65d661fa6d7e5460cc76ccabfe1398849fe7
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Mon Feb 6 22:29:10 2012 +0100

    fdc: check if media rate is correct before doing any transfer
    
    The programmed rate has to be the same as the required rate for the
    floppy format ; if that's not the case, the transfer should abort.
    This check can be disabled by using the 'check_media_rate' property.
    
    Save media rate value only if media rate check is enabled.
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/fdc.c b/hw/fdc.c
index 1c7e775..cc03326 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -62,12 +62,15 @@
 #define FD_SECTOR_SC           2   /* Sector size code */
 #define FD_RESET_SENSEI_COUNT  4   /* Number of sense interrupts on RESET */
 
+typedef struct FDCtrl FDCtrl;
+
 /* Floppy disk drive emulation */
 typedef enum FDiskFlags {
     FDISK_DBL_SIDES  = 0x01,
 } FDiskFlags;
 
 typedef struct FDrive {
+    FDCtrl *fdctrl;
     BlockDriverState *bs;
     /* Drive status */
     FDriveType drive;
@@ -83,6 +86,7 @@ typedef struct FDrive {
     uint16_t bps;             /* Bytes per sector       */
     uint8_t ro;               /* Is read-only           */
     uint8_t media_changed;    /* Is media changed       */
+    uint8_t media_rate;       /* Data rate of medium    */
 } FDrive;
 
 static void fd_init(FDrive *drv)
@@ -195,6 +199,7 @@ static void fd_revalidate(FDrive *drv)
         drv->last_sect = last_sect;
         drv->ro = ro;
         drv->drive = drive;
+        drv->media_rate = rate;
     } else {
         FLOPPY_DPRINTF("No disk in drive\n");
         drv->last_sect = 0;
@@ -206,8 +211,6 @@ static void fd_revalidate(FDrive *drv)
 /********************************************************/
 /* Intel 82078 floppy disk controller emulation          */
 
-typedef struct FDCtrl FDCtrl;
-
 static void fdctrl_reset(FDCtrl *fdctrl, int do_irq);
 static void fdctrl_reset_fifo(FDCtrl *fdctrl);
 static int fdctrl_transfer_handler (void *opaque, int nchan,
@@ -303,6 +306,7 @@ enum {
 };
 
 enum {
+    FD_SR1_MA       = 0x01, /* Missing address mark */
     FD_SR1_NW       = 0x02, /* Not writable */
     FD_SR1_EC       = 0x80, /* End of cylinder */
 };
@@ -549,6 +553,24 @@ static const VMStateDescription vmstate_fdrive_media_changed = {
     }
 };
 
+static bool fdrive_media_rate_needed(void *opaque)
+{
+    FDrive *drive = opaque;
+
+    return drive->fdctrl->check_media_rate;
+}
+
+static const VMStateDescription vmstate_fdrive_media_rate = {
+    .name = "fdrive/media_rate",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT8(media_rate, FDrive),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static const VMStateDescription vmstate_fdrive = {
     .name = "fdrive",
     .version_id = 1,
@@ -565,6 +587,9 @@ static const VMStateDescription vmstate_fdrive = {
             .vmsd = &vmstate_fdrive_media_changed,
             .needed = &fdrive_media_changed_needed,
         } , {
+            .vmsd = &vmstate_fdrive_media_rate,
+            .needed = &fdrive_media_rate_needed,
+        } , {
             /* empty */
         }
     }
@@ -1078,6 +1103,19 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction)
         break;
     }
 
+    /* Check the data rate. If the programmed data rate does not match
+     * the currently inserted medium, the operation has to fail. */
+    if (fdctrl->check_media_rate &&
+        (fdctrl->dsr & FD_DSR_DRATEMASK) != cur_drv->media_rate) {
+        FLOPPY_DPRINTF("data rate mismatch (fdc=%d, media=%d)\n",
+                       fdctrl->dsr & FD_DSR_DRATEMASK, cur_drv->media_rate);
+        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA, 0x00);
+        fdctrl->fifo[3] = kt;
+        fdctrl->fifo[4] = kh;
+        fdctrl->fifo[5] = ks;
+        return;
+    }
+
     /* Set the FIFO state */
     fdctrl->data_dir = direction;
     fdctrl->data_pos = 0;
@@ -1800,7 +1838,15 @@ static void fdctrl_result_timer(void *opaque)
     if (cur_drv->last_sect != 0) {
         cur_drv->sect = (cur_drv->sect % cur_drv->last_sect) + 1;
     }
-    fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
+    /* READ_ID can't automatically succeed! */
+    if (fdctrl->check_media_rate &&
+        (fdctrl->dsr & FD_DSR_DRATEMASK) != cur_drv->media_rate) {
+        FLOPPY_DPRINTF("read id rate mismatch (fdc=%d, media=%d)\n",
+                       fdctrl->dsr & FD_DSR_DRATEMASK, cur_drv->media_rate);
+        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA, 0x00);
+    } else {
+        fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
+    }
 }
 
 static void fdctrl_change_cb(void *opaque, bool load)
@@ -1822,6 +1868,7 @@ static int fdctrl_connect_drives(FDCtrl *fdctrl)
 
     for (i = 0; i < MAX_FD; i++) {
         drive = &fdctrl->drives[i];
+        drive->fdctrl = fdctrl;
 
         if (drive->bs) {
             if (bdrv_get_on_error(drive->bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
commit 09c6d5850fbd2b8abeba927fffff036585a755e0
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Mon Feb 6 22:29:09 2012 +0100

    fdc: add a 'check media rate' property. Not used yet
    
    Set it to true for current Qemu versions, and false for previous ones
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/fdc.c b/hw/fdc.c
index 08012f9..1c7e775 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -420,6 +420,7 @@ struct FDCtrl {
     int sun4m;
     FDrive drives[MAX_FD];
     int reset_sensei;
+    uint32_t check_media_rate;
     /* Timers state */
     uint8_t timer0;
     uint8_t timer1;
@@ -2003,6 +2004,8 @@ static Property isa_fdc_properties[] = {
     DEFINE_PROP_DRIVE("driveB", FDCtrlISABus, state.drives[1].bs),
     DEFINE_PROP_INT32("bootindexA", FDCtrlISABus, bootindexA, -1),
     DEFINE_PROP_INT32("bootindexB", FDCtrlISABus, bootindexB, -1),
+    DEFINE_PROP_BIT("check_media_rate", FDCtrlISABus, state.check_media_rate,
+                    0, true),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 5e11d15..6c5c40f 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -384,6 +384,10 @@ static QEMUMachine pc_machine_v1_0 = {
             .driver   = "pc-sysfw",
             .property = "rom_only",
             .value    = stringify(1),
+        }, {
+            .driver   = "isa-fdc",
+            .property = "check_media_rate",
+            .value    = "off",
         },
         { /* end of list */ }
     },
@@ -399,6 +403,10 @@ static QEMUMachine pc_machine_v0_15 = {
             .driver   = "pc-sysfw",
             .property = "rom_only",
             .value    = stringify(1),
+        }, {
+            .driver   = "isa-fdc",
+            .property = "check_media_rate",
+            .value    = "off",
         },
         { /* end of list */ }
     },
@@ -434,6 +442,10 @@ static QEMUMachine pc_machine_v0_14 = {
             .driver   = "virtio-balloon-pci",
             .property = "event_idx",
             .value    = "off",
+        },{
+            .driver   = "isa-fdc",
+            .property = "check_media_rate",
+            .value    = "off",
         },
         {
             .driver   = "pc-sysfw",
@@ -486,6 +498,10 @@ static QEMUMachine pc_machine_v0_13 = {
             .driver   = "AC97",
             .property = "use_broken_id",
             .value    = stringify(1),
+        },{
+            .driver   = "isa-fdc",
+            .property = "check_media_rate",
+            .value    = "off",
         },
         {
             .driver   = "pc-sysfw",
@@ -542,6 +558,10 @@ static QEMUMachine pc_machine_v0_12 = {
             .driver   = "AC97",
             .property = "use_broken_id",
             .value    = stringify(1),
+        },{
+            .driver   = "isa-fdc",
+            .property = "check_media_rate",
+            .value    = "off",
         },
         {
             .driver   = "pc-sysfw",
@@ -606,6 +626,10 @@ static QEMUMachine pc_machine_v0_11 = {
             .driver   = "AC97",
             .property = "use_broken_id",
             .value    = stringify(1),
+        },{
+            .driver   = "isa-fdc",
+            .property = "check_media_rate",
+            .value    = "off",
         },
         {
             .driver   = "pc-sysfw",
@@ -682,6 +706,10 @@ static QEMUMachine pc_machine_v0_10 = {
             .driver   = "AC97",
             .property = "use_broken_id",
             .value    = stringify(1),
+        },{
+            .driver   = "isa-fdc",
+            .property = "check_media_rate",
+            .value    = "off",
         },
         {
             .driver   = "pc-sysfw",
commit f8d3d128576d2b492c4267083f67671b19edb63a
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Mon Feb 6 22:29:07 2012 +0100

    block: add a transfer rate for floppy types
    
    Floppies must be read at a specific transfer rate, depending of its own format.
    Update floppy description table to include required transfer rate.
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index e27d528..1150437 100644
--- a/block.c
+++ b/block.c
@@ -2013,58 +2013,60 @@ typedef struct FDFormat {
     uint8_t last_sect;
     uint8_t max_track;
     uint8_t max_head;
+    FDriveRate rate;
 } FDFormat;
 
 static const FDFormat fd_formats[] = {
     /* First entry is default format */
     /* 1.44 MB 3"1/2 floppy disks */
-    { FDRIVE_DRV_144, 18, 80, 1, },
-    { FDRIVE_DRV_144, 20, 80, 1, },
-    { FDRIVE_DRV_144, 21, 80, 1, },
-    { FDRIVE_DRV_144, 21, 82, 1, },
-    { FDRIVE_DRV_144, 21, 83, 1, },
-    { FDRIVE_DRV_144, 22, 80, 1, },
-    { FDRIVE_DRV_144, 23, 80, 1, },
-    { FDRIVE_DRV_144, 24, 80, 1, },
+    { FDRIVE_DRV_144, 18, 80, 1, FDRIVE_RATE_500K, },
+    { FDRIVE_DRV_144, 20, 80, 1, FDRIVE_RATE_500K, },
+    { FDRIVE_DRV_144, 21, 80, 1, FDRIVE_RATE_500K, },
+    { FDRIVE_DRV_144, 21, 82, 1, FDRIVE_RATE_500K, },
+    { FDRIVE_DRV_144, 21, 83, 1, FDRIVE_RATE_500K, },
+    { FDRIVE_DRV_144, 22, 80, 1, FDRIVE_RATE_500K, },
+    { FDRIVE_DRV_144, 23, 80, 1, FDRIVE_RATE_500K, },
+    { FDRIVE_DRV_144, 24, 80, 1, FDRIVE_RATE_500K, },
     /* 2.88 MB 3"1/2 floppy disks */
-    { FDRIVE_DRV_288, 36, 80, 1, },
-    { FDRIVE_DRV_288, 39, 80, 1, },
-    { FDRIVE_DRV_288, 40, 80, 1, },
-    { FDRIVE_DRV_288, 44, 80, 1, },
-    { FDRIVE_DRV_288, 48, 80, 1, },
+    { FDRIVE_DRV_288, 36, 80, 1, FDRIVE_RATE_1M, },
+    { FDRIVE_DRV_288, 39, 80, 1, FDRIVE_RATE_1M, },
+    { FDRIVE_DRV_288, 40, 80, 1, FDRIVE_RATE_1M, },
+    { FDRIVE_DRV_288, 44, 80, 1, FDRIVE_RATE_1M, },
+    { FDRIVE_DRV_288, 48, 80, 1, FDRIVE_RATE_1M, },
     /* 720 kB 3"1/2 floppy disks */
-    { FDRIVE_DRV_144,  9, 80, 1, },
-    { FDRIVE_DRV_144, 10, 80, 1, },
-    { FDRIVE_DRV_144, 10, 82, 1, },
-    { FDRIVE_DRV_144, 10, 83, 1, },
-    { FDRIVE_DRV_144, 13, 80, 1, },
-    { FDRIVE_DRV_144, 14, 80, 1, },
+    { FDRIVE_DRV_144,  9, 80, 1, FDRIVE_RATE_250K, },
+    { FDRIVE_DRV_144, 10, 80, 1, FDRIVE_RATE_250K, },
+    { FDRIVE_DRV_144, 10, 82, 1, FDRIVE_RATE_250K, },
+    { FDRIVE_DRV_144, 10, 83, 1, FDRIVE_RATE_250K, },
+    { FDRIVE_DRV_144, 13, 80, 1, FDRIVE_RATE_250K, },
+    { FDRIVE_DRV_144, 14, 80, 1, FDRIVE_RATE_250K, },
     /* 1.2 MB 5"1/4 floppy disks */
-    { FDRIVE_DRV_120, 15, 80, 1, },
-    { FDRIVE_DRV_120, 18, 80, 1, },
-    { FDRIVE_DRV_120, 18, 82, 1, },
-    { FDRIVE_DRV_120, 18, 83, 1, },
-    { FDRIVE_DRV_120, 20, 80, 1, },
+    { FDRIVE_DRV_120, 15, 80, 1, FDRIVE_RATE_500K, },
+    { FDRIVE_DRV_120, 18, 80, 1, FDRIVE_RATE_500K, },
+    { FDRIVE_DRV_120, 18, 82, 1, FDRIVE_RATE_500K, },
+    { FDRIVE_DRV_120, 18, 83, 1, FDRIVE_RATE_500K, },
+    { FDRIVE_DRV_120, 20, 80, 1, FDRIVE_RATE_500K, },
     /* 720 kB 5"1/4 floppy disks */
-    { FDRIVE_DRV_120,  9, 80, 1, },
-    { FDRIVE_DRV_120, 11, 80, 1, },
+    { FDRIVE_DRV_120,  9, 80, 1, FDRIVE_RATE_250K, },
+    { FDRIVE_DRV_120, 11, 80, 1, FDRIVE_RATE_250K, },
     /* 360 kB 5"1/4 floppy disks */
-    { FDRIVE_DRV_120,  9, 40, 1, },
-    { FDRIVE_DRV_120,  9, 40, 0, },
-    { FDRIVE_DRV_120, 10, 41, 1, },
-    { FDRIVE_DRV_120, 10, 42, 1, },
+    { FDRIVE_DRV_120,  9, 40, 1, FDRIVE_RATE_300K, },
+    { FDRIVE_DRV_120,  9, 40, 0, FDRIVE_RATE_300K, },
+    { FDRIVE_DRV_120, 10, 41, 1, FDRIVE_RATE_300K, },
+    { FDRIVE_DRV_120, 10, 42, 1, FDRIVE_RATE_300K, },
     /* 320 kB 5"1/4 floppy disks */
-    { FDRIVE_DRV_120,  8, 40, 1, },
-    { FDRIVE_DRV_120,  8, 40, 0, },
+    { FDRIVE_DRV_120,  8, 40, 1, FDRIVE_RATE_250K, },
+    { FDRIVE_DRV_120,  8, 40, 0, FDRIVE_RATE_250K, },
     /* 360 kB must match 5"1/4 better than 3"1/2... */
-    { FDRIVE_DRV_144,  9, 80, 0, },
+    { FDRIVE_DRV_144,  9, 80, 0, FDRIVE_RATE_250K, },
     /* end */
-    { FDRIVE_DRV_NONE, -1, -1, 0, },
+    { FDRIVE_DRV_NONE, -1, -1, 0, 0, },
 };
 
 void bdrv_get_floppy_geometry_hint(BlockDriverState *bs, int *nb_heads,
                                    int *max_track, int *last_sect,
-                                   FDriveType drive_in, FDriveType *drive)
+                                   FDriveType drive_in, FDriveType *drive,
+                                   FDriveRate *rate)
 {
     const FDFormat *parse;
     uint64_t nb_sectors, size;
@@ -2073,6 +2075,7 @@ void bdrv_get_floppy_geometry_hint(BlockDriverState *bs, int *nb_heads,
     bdrv_get_geometry_hint(bs, nb_heads, max_track, last_sect);
     if (*nb_heads != 0 && *max_track != 0 && *last_sect != 0) {
         /* User defined disk */
+        *rate = FDRIVE_RATE_500K;
     } else {
         bdrv_get_geometry(bs, &nb_sectors);
         match = -1;
@@ -2107,6 +2110,7 @@ void bdrv_get_floppy_geometry_hint(BlockDriverState *bs, int *nb_heads,
         *max_track = parse->max_track;
         *last_sect = parse->last_sect;
         *drive = parse->drive;
+        *rate = parse->rate;
     }
 }
 
diff --git a/block.h b/block.h
index 49bca5a..bbc3830 100644
--- a/block.h
+++ b/block.h
@@ -252,9 +252,17 @@ typedef enum FDriveType {
     FDRIVE_DRV_NONE = 0x03,   /* No drive connected     */
 } FDriveType;
 
+typedef enum FDriveRate {
+    FDRIVE_RATE_500K = 0x00,  /* 500 Kbps */
+    FDRIVE_RATE_300K = 0x01,  /* 300 Kbps */
+    FDRIVE_RATE_250K = 0x02,  /* 250 Kbps */
+    FDRIVE_RATE_1M   = 0x03,  /*   1 Mbps */
+} FDriveRate;
+
 void bdrv_get_floppy_geometry_hint(BlockDriverState *bs, int *nb_heads,
                                    int *max_track, int *last_sect,
-                                   FDriveType drive_in, FDriveType *drive);
+                                   FDriveType drive_in, FDriveType *drive,
+                                   FDriveRate *rate);
 int bdrv_get_translation_hint(BlockDriverState *bs);
 void bdrv_set_on_error(BlockDriverState *bs, BlockErrorAction on_read_error,
                        BlockErrorAction on_write_error);
diff --git a/hw/fdc.c b/hw/fdc.c
index 02ced22..08012f9 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -172,12 +172,13 @@ static void fd_revalidate(FDrive *drv)
 {
     int nb_heads, max_track, last_sect, ro;
     FDriveType drive;
+    FDriveRate rate;
 
     FLOPPY_DPRINTF("revalidate\n");
     if (drv->bs != NULL && bdrv_is_inserted(drv->bs)) {
         ro = bdrv_is_read_only(drv->bs);
         bdrv_get_floppy_geometry_hint(drv->bs, &nb_heads, &max_track,
-                                      &last_sect, drv->drive, &drive);
+                                      &last_sect, drv->drive, &drive, &rate);
         if (nb_heads != 0 && max_track != 0 && last_sect != 0) {
             FLOPPY_DPRINTF("User defined disk (%d %d %d)",
                            nb_heads - 1, max_track, last_sect);
diff --git a/hw/pc.c b/hw/pc.c
index 59a7f39..12c02f2 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -335,6 +335,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
 {
     int val, nb, nb_heads, max_track, last_sect, i;
     FDriveType fd_type[2] = { FDRIVE_DRV_NONE, FDRIVE_DRV_NONE };
+    FDriveRate rate;
     BlockDriverState *fd[MAX_FD];
     static pc_cmos_init_late_arg arg;
 
@@ -383,7 +384,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
             if (fd[i] && bdrv_is_inserted(fd[i])) {
                 bdrv_get_floppy_geometry_hint(fd[i], &nb_heads, &max_track,
                                               &last_sect, FDRIVE_DRV_NONE,
-                                              &fd_type[i]);
+                                              &fd_type[i], &rate);
             }
         }
     }
commit a758f8f415985abc85be1da6d22f0590a74ca23d
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Mon Feb 6 22:29:06 2012 +0100

    fdc: add CCR (Configuration Control Register) write register
    
    DIR and CCR registers share the same address ; DIR is read-only
    while CCR is write-only
    
    CCR register is used to change media transfer rate, which will be
    checked in following changes.
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/fdc.c b/hw/fdc.c
index 3d4bb11..02ced22 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -224,6 +224,7 @@ static void fdctrl_write_rate(FDCtrl *fdctrl, uint32_t value);
 static uint32_t fdctrl_read_data(FDCtrl *fdctrl);
 static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value);
 static uint32_t fdctrl_read_dir(FDCtrl *fdctrl);
+static void fdctrl_write_ccr(FDCtrl *fdctrl, uint32_t value);
 
 enum {
     FD_DIR_WRITE   = 0,
@@ -248,6 +249,7 @@ enum {
     FD_REG_DSR = 0x04,
     FD_REG_FIFO = 0x05,
     FD_REG_DIR = 0x07,
+    FD_REG_CCR = 0x07,
 };
 
 enum {
@@ -491,6 +493,9 @@ static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value)
     case FD_REG_FIFO:
         fdctrl_write_data(fdctrl, value);
         break;
+    case FD_REG_CCR:
+        fdctrl_write_ccr(fdctrl, value);
+        break;
     default:
         break;
     }
@@ -881,6 +886,23 @@ static void fdctrl_write_rate(FDCtrl *fdctrl, uint32_t value)
     fdctrl->dsr = value;
 }
 
+/* Configuration control register: 0x07 (write) */
+static void fdctrl_write_ccr(FDCtrl *fdctrl, uint32_t value)
+{
+    /* Reset mode */
+    if (!(fdctrl->dor & FD_DOR_nRESET)) {
+        FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
+        return;
+    }
+    FLOPPY_DPRINTF("configuration control register set to 0x%02x\n", value);
+
+    /* Only the rate selection bits used in AT mode, and we
+     * store those in the DSR.
+     */
+    fdctrl->dsr = (fdctrl->dsr & ~FD_DSR_DRATEMASK) |
+                  (value & FD_DSR_DRATEMASK);
+}
+
 static int fdctrl_media_changed(FDrive *drv)
 {
     int ret;
commit 8510854ee7dc04f70b53aea4d2518a0585fe5d09
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Mon Feb 6 22:29:05 2012 +0100

    fdc: handle read-only floppies (abort early on write commands)
    
    A real floppy doesn't attempt to write to read-only media either.
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/fdc.c b/hw/fdc.c
index 9d1f5b3..3d4bb11 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -300,6 +300,7 @@ enum {
 };
 
 enum {
+    FD_SR1_NW       = 0x02, /* Not writable */
     FD_SR1_EC       = 0x80, /* End of cylinder */
 };
 
@@ -1179,6 +1180,16 @@ static int fdctrl_transfer_handler (void *opaque, int nchan,
             break;
         case FD_DIR_WRITE:
             /* WRITE commands */
+            if (cur_drv->ro) {
+                /* Handle readonly medium early, no need to do DMA, touch the
+                 * LED or attempt any writes. A real floppy doesn't attempt
+                 * to write to readonly media either. */
+                fdctrl_stop_transfer(fdctrl,
+                                     FD_SR0_ABNTERM | FD_SR0_SEEK, FD_SR1_NW,
+                                     0x00);
+                goto transfer_error;
+            }
+
             DMA_read_memory (nchan, fdctrl->fifo + rel_pos,
                              fdctrl->data_pos, len);
             if (bdrv_write(cur_drv->bs, fd_sector(cur_drv),
commit a005186c176e0e630dd146cd3b973384d5e62f34
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Mon Feb 6 22:29:04 2012 +0100

    fdc: most control commands do not generate interrupts
    
    In fact, only three control commands generate an interrupt:
    read_id, recalibrate and seek
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/fdc.c b/hw/fdc.c
index 05edc3a..9d1f5b3 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -1348,7 +1348,7 @@ static void fdctrl_handle_lock(FDCtrl *fdctrl, int direction)
 {
     fdctrl->lock = (fdctrl->fifo[0] & 0x80) ? 1 : 0;
     fdctrl->fifo[0] = fdctrl->lock << 4;
-    fdctrl_set_fifo(fdctrl, 1, fdctrl->lock);
+    fdctrl_set_fifo(fdctrl, 1, 0);
 }
 
 static void fdctrl_handle_dumpreg(FDCtrl *fdctrl, int direction)
@@ -1380,7 +1380,7 @@ static void fdctrl_handle_version(FDCtrl *fdctrl, int direction)
 {
     /* Controller's version */
     fdctrl->fifo[0] = fdctrl->version;
-    fdctrl_set_fifo(fdctrl, 1, 1);
+    fdctrl_set_fifo(fdctrl, 1, 0);
 }
 
 static void fdctrl_handle_partid(FDCtrl *fdctrl, int direction)
@@ -1439,7 +1439,7 @@ static void fdctrl_handle_save(FDCtrl *fdctrl, int direction)
     fdctrl->fifo[12] = fdctrl->pwrd;
     fdctrl->fifo[13] = 0;
     fdctrl->fifo[14] = 0;
-    fdctrl_set_fifo(fdctrl, 15, 1);
+    fdctrl_set_fifo(fdctrl, 15, 0);
 }
 
 static void fdctrl_handle_readid(FDCtrl *fdctrl, int direction)
@@ -1580,7 +1580,7 @@ static void fdctrl_handle_powerdown_mode(FDCtrl *fdctrl, int direction)
 {
     fdctrl->pwrd = fdctrl->fifo[1];
     fdctrl->fifo[0] = fdctrl->fifo[1];
-    fdctrl_set_fifo(fdctrl, 1, 1);
+    fdctrl_set_fifo(fdctrl, 1, 0);
 }
 
 static void fdctrl_handle_option(FDCtrl *fdctrl, int direction)
@@ -1599,7 +1599,7 @@ static void fdctrl_handle_drive_specification_command(FDCtrl *fdctrl, int direct
             fdctrl->fifo[0] = fdctrl->fifo[1];
             fdctrl->fifo[2] = 0;
             fdctrl->fifo[3] = 0;
-            fdctrl_set_fifo(fdctrl, 4, 1);
+            fdctrl_set_fifo(fdctrl, 4, 0);
         } else {
             fdctrl_reset_fifo(fdctrl);
         }
@@ -1607,7 +1607,7 @@ static void fdctrl_handle_drive_specification_command(FDCtrl *fdctrl, int direct
         /* ERROR */
         fdctrl->fifo[0] = 0x80 |
             (cur_drv->head << 2) | GET_CUR_DRV(fdctrl);
-        fdctrl_set_fifo(fdctrl, 1, 1);
+        fdctrl_set_fifo(fdctrl, 1, 0);
     }
 }
 
commit 1457a75843740b0433edfc88666c793858f4423a
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Mon Feb 6 22:29:03 2012 +0100

    fdc: set busy bit when starting a command
    
    This bit must be active while a command is currently executed.
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/fdc.c b/hw/fdc.c
index 64e635a..05edc3a 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -1446,7 +1446,6 @@ static void fdctrl_handle_readid(FDCtrl *fdctrl, int direction)
 {
     FDrive *cur_drv = get_cur_drv(fdctrl);
 
-    /* XXX: should set main status register to busy */
     cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
     qemu_mod_timer(fdctrl->result_timer,
                    qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() / 50));
@@ -1734,6 +1733,7 @@ static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value)
         pos = command_to_handler[value & 0xff];
         FLOPPY_DPRINTF("%s command\n", handlers[pos].name);
         fdctrl->data_len = handlers[pos].parameters + 1;
+        fdctrl->msr |= FD_MSR_CMDBUSY;
     }
 
     FLOPPY_DPRINTF("%s: %02x\n", __func__, value);
commit 08388273a3c4e895bf7e10f356f66c2363cfe90b
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Mon Feb 6 22:29:02 2012 +0100

    fdc: take side count into account
    
    Floppies can be simple or double-sided. However, current code
    was only taking the common case into account (ie 2 sides).
    
    This repairs single-sided floppies, which where totally broken
    before this patch : for track > 0, wrong sector number was
    calculated, and data was read/written at wrong place on
    underlying device.
    
    Fortunately, only some 360 kB floppies are single-sided, so
    this bug was probably not seen much.
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/fdc.c b/hw/fdc.c
index 38fad58..64e635a 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -95,16 +95,19 @@ static void fd_init(FDrive *drv)
     drv->max_track = 0;
 }
 
+#define NUM_SIDES(drv) ((drv)->flags & FDISK_DBL_SIDES ? 2 : 1)
+
 static int fd_sector_calc(uint8_t head, uint8_t track, uint8_t sect,
-                          uint8_t last_sect)
+                          uint8_t last_sect, uint8_t num_sides)
 {
-    return (((track * 2) + head) * last_sect) + sect - 1;
+    return (((track * num_sides) + head) * last_sect) + sect - 1;
 }
 
 /* Returns current position, in sectors, for given drive */
 static int fd_sector(FDrive *drv)
 {
-    return fd_sector_calc(drv->head, drv->track, drv->sect, drv->last_sect);
+    return fd_sector_calc(drv->head, drv->track, drv->sect, drv->last_sect,
+                          NUM_SIDES(drv));
 }
 
 /* Seek to a new position:
@@ -135,7 +138,7 @@ static int fd_seek(FDrive *drv, uint8_t head, uint8_t track, uint8_t sect,
                        drv->max_track, drv->last_sect);
         return 3;
     }
-    sector = fd_sector_calc(head, track, sect, drv->last_sect);
+    sector = fd_sector_calc(head, track, sect, drv->last_sect, NUM_SIDES(drv));
     ret = 0;
     if (sector != fd_sector(drv)) {
 #if 0
@@ -1019,7 +1022,8 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction)
     ks = fdctrl->fifo[4];
     FLOPPY_DPRINTF("Start transfer at %d %d %02x %02x (%d)\n",
                    GET_CUR_DRV(fdctrl), kh, kt, ks,
-                   fd_sector_calc(kh, kt, ks, cur_drv->last_sect));
+                   fd_sector_calc(kh, kt, ks, cur_drv->last_sect,
+                                  NUM_SIDES(cur_drv)));
     switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & FD_CONFIG_EIS)) {
     case 2:
         /* sect too big */
@@ -1289,7 +1293,8 @@ static void fdctrl_format_sector(FDCtrl *fdctrl)
     ks = fdctrl->fifo[8];
     FLOPPY_DPRINTF("format sector at %d %d %02x %02x (%d)\n",
                    GET_CUR_DRV(fdctrl), kh, kt, ks,
-                   fd_sector_calc(kh, kt, ks, cur_drv->last_sect));
+                   fd_sector_calc(kh, kt, ks, cur_drv->last_sect,
+                                  NUM_SIDES(cur_drv)));
     switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & FD_CONFIG_EIS)) {
     case 2:
         /* sect too big */
commit 07f07b31e57efa6e4f563802136ffa1694a2692b
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Feb 13 20:45:32 2012 +0200

    memory: allow phys_map tree paths to terminate early
    
    When storing large contiguous ranges in phys_map, all values tend to
    be the same pointers to a single MemoryRegionSection.  Collapse them
    by marking nodes with level > 0 as leaves.  This reduces tree memory
    usage dramatically.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index a2015f7..0c93b26 100644
--- a/exec.c
+++ b/exec.c
@@ -193,19 +193,20 @@ static unsigned phys_sections_nb, phys_sections_nb_alloc;
 static uint16_t phys_section_unassigned;
 
 struct PhysPageEntry {
-     /* index into phys_sections (last level) or phys_map_nodes (others) */
-    uint16_t ptr;
+    uint16_t is_leaf : 1;
+     /* index into phys_sections (is_leaf) or phys_map_nodes (!is_leaf) */
+    uint16_t ptr : 15;
 };
 
 /* Simple allocator for PhysPageEntry nodes */
 static PhysPageEntry (*phys_map_nodes)[L2_SIZE];
 static unsigned phys_map_nodes_nb, phys_map_nodes_nb_alloc;
 
-#define PHYS_MAP_NODE_NIL ((uint16_t)~0)
+#define PHYS_MAP_NODE_NIL (((uint16_t)~0) >> 1)
 
 /* This is a multi-level map on the physical address space.
    The bottom level has pointers to MemoryRegionSections.  */
-static PhysPageEntry phys_map = { .ptr = PHYS_MAP_NODE_NIL };
+static PhysPageEntry phys_map = { .ptr = PHYS_MAP_NODE_NIL, .is_leaf = 0 };
 
 static void io_mem_init(void);
 static void memory_map_init(void);
@@ -423,6 +424,7 @@ static uint16_t phys_map_node_alloc(void)
     assert(ret != PHYS_MAP_NODE_NIL);
     assert(ret != phys_map_nodes_nb_alloc);
     for (i = 0; i < L2_SIZE; ++i) {
+        phys_map_nodes[ret][i].is_leaf = 0;
         phys_map_nodes[ret][i].ptr = PHYS_MAP_NODE_NIL;
     }
     return ret;
@@ -440,12 +442,14 @@ static void phys_page_set_level(PhysPageEntry *lp, target_phys_addr_t *index,
 {
     PhysPageEntry *p;
     int i;
+    target_phys_addr_t step = (target_phys_addr_t)1 << (level * L2_BITS);
 
-    if (lp->ptr == PHYS_MAP_NODE_NIL) {
+    if (!lp->is_leaf && lp->ptr == PHYS_MAP_NODE_NIL) {
         lp->ptr = phys_map_node_alloc();
         p = phys_map_nodes[lp->ptr];
         if (level == 0) {
             for (i = 0; i < L2_SIZE; i++) {
+                p[i].is_leaf = 1;
                 p[i].ptr = phys_section_unassigned;
             }
         }
@@ -455,10 +459,11 @@ static void phys_page_set_level(PhysPageEntry *lp, target_phys_addr_t *index,
     lp = &p[(*index >> (level * L2_BITS)) & (L2_SIZE - 1)];
 
     while (*nb && lp < &p[L2_SIZE]) {
-        if (level == 0) {
+        if ((*index & (step - 1)) == 0 && *nb >= step) {
+            lp->is_leaf = true;
             lp->ptr = leaf;
-            ++*index;
-            --*nb;
+            *index += step;
+            *nb -= step;
         } else {
             phys_page_set_level(lp, index, nb, leaf, level - 1);
         }
@@ -470,7 +475,7 @@ static void phys_page_set(target_phys_addr_t index, target_phys_addr_t nb,
                           uint16_t leaf)
 {
     /* Wildly overreserve - it doesn't matter much. */
-    phys_map_node_reserve((nb + L2_SIZE - 1) / L2_SIZE * P_L2_LEVELS);
+    phys_map_node_reserve(3 * P_L2_LEVELS);
 
     phys_page_set_level(&phys_map, &index, &nb, leaf, P_L2_LEVELS - 1);
 }
@@ -484,7 +489,7 @@ static MemoryRegionSection phys_page_find(target_phys_addr_t index)
     target_phys_addr_t delta;
     uint16_t s_index = phys_section_unassigned;
 
-    for (i = P_L2_LEVELS - 1; i >= 0; i--) {
+    for (i = P_L2_LEVELS - 1; i >= 0 && !lp.is_leaf; i--) {
         if (lp.ptr == PHYS_MAP_NODE_NIL) {
             goto not_found;
         }
@@ -2580,12 +2585,13 @@ static void destroy_l2_mapping(PhysPageEntry *lp, unsigned level)
 
     p = phys_map_nodes[lp->ptr];
     for (i = 0; i < L2_SIZE; ++i) {
-        if (level > 0) {
+        if (!p[i].is_leaf) {
             destroy_l2_mapping(&p[i], level - 1);
         } else {
             destroy_page_desc(p[i].ptr);
         }
     }
+    lp->is_leaf = 0;
     lp->ptr = PHYS_MAP_NODE_NIL;
 }
 
commit c19e8800d4a9c019299cc9232b4e628469a81d2d
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Feb 13 20:25:31 2012 +0200

    memory: unify PhysPageEntry::node and ::leaf
    
    They have the same type, unify them.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index 98c0056..a2015f7 100644
--- a/exec.c
+++ b/exec.c
@@ -193,10 +193,8 @@ static unsigned phys_sections_nb, phys_sections_nb_alloc;
 static uint16_t phys_section_unassigned;
 
 struct PhysPageEntry {
-    union {
-        uint16_t leaf; /* index into phys_sections */
-        uint16_t node; /* index into phys_map_nodes */
-    } u;
+     /* index into phys_sections (last level) or phys_map_nodes (others) */
+    uint16_t ptr;
 };
 
 /* Simple allocator for PhysPageEntry nodes */
@@ -207,7 +205,7 @@ static unsigned phys_map_nodes_nb, phys_map_nodes_nb_alloc;
 
 /* This is a multi-level map on the physical address space.
    The bottom level has pointers to MemoryRegionSections.  */
-static PhysPageEntry phys_map = { .u.node = PHYS_MAP_NODE_NIL };
+static PhysPageEntry phys_map = { .ptr = PHYS_MAP_NODE_NIL };
 
 static void io_mem_init(void);
 static void memory_map_init(void);
@@ -425,7 +423,7 @@ static uint16_t phys_map_node_alloc(void)
     assert(ret != PHYS_MAP_NODE_NIL);
     assert(ret != phys_map_nodes_nb_alloc);
     for (i = 0; i < L2_SIZE; ++i) {
-        phys_map_nodes[ret][i].u.node = PHYS_MAP_NODE_NIL;
+        phys_map_nodes[ret][i].ptr = PHYS_MAP_NODE_NIL;
     }
     return ret;
 }
@@ -443,22 +441,22 @@ static void phys_page_set_level(PhysPageEntry *lp, target_phys_addr_t *index,
     PhysPageEntry *p;
     int i;
 
-    if (lp->u.node == PHYS_MAP_NODE_NIL) {
-        lp->u.node = phys_map_node_alloc();
-        p = phys_map_nodes[lp->u.node];
+    if (lp->ptr == PHYS_MAP_NODE_NIL) {
+        lp->ptr = phys_map_node_alloc();
+        p = phys_map_nodes[lp->ptr];
         if (level == 0) {
             for (i = 0; i < L2_SIZE; i++) {
-                p[i].u.leaf = phys_section_unassigned;
+                p[i].ptr = phys_section_unassigned;
             }
         }
     } else {
-        p = phys_map_nodes[lp->u.node];
+        p = phys_map_nodes[lp->ptr];
     }
     lp = &p[(*index >> (level * L2_BITS)) & (L2_SIZE - 1)];
 
     while (*nb && lp < &p[L2_SIZE]) {
         if (level == 0) {
-            lp->u.leaf = leaf;
+            lp->ptr = leaf;
             ++*index;
             --*nb;
         } else {
@@ -487,14 +485,14 @@ static MemoryRegionSection phys_page_find(target_phys_addr_t index)
     uint16_t s_index = phys_section_unassigned;
 
     for (i = P_L2_LEVELS - 1; i >= 0; i--) {
-        if (lp.u.node == PHYS_MAP_NODE_NIL) {
+        if (lp.ptr == PHYS_MAP_NODE_NIL) {
             goto not_found;
         }
-        p = phys_map_nodes[lp.u.node];
+        p = phys_map_nodes[lp.ptr];
         lp = p[(index >> (i * L2_BITS)) & (L2_SIZE - 1)];
     }
 
-    s_index = lp.u.leaf;
+    s_index = lp.ptr;
 not_found:
     section = phys_sections[s_index];
     index <<= TARGET_PAGE_BITS;
@@ -2576,19 +2574,19 @@ static void destroy_l2_mapping(PhysPageEntry *lp, unsigned level)
     unsigned i;
     PhysPageEntry *p;
 
-    if (lp->u.node == PHYS_MAP_NODE_NIL) {
+    if (lp->ptr == PHYS_MAP_NODE_NIL) {
         return;
     }
 
-    p = phys_map_nodes[lp->u.node];
+    p = phys_map_nodes[lp->ptr];
     for (i = 0; i < L2_SIZE; ++i) {
         if (level > 0) {
             destroy_l2_mapping(&p[i], level - 1);
         } else {
-            destroy_page_desc(p[i].u.leaf);
+            destroy_page_desc(p[i].ptr);
         }
     }
-    lp->u.node = PHYS_MAP_NODE_NIL;
+    lp->ptr = PHYS_MAP_NODE_NIL;
 }
 
 static void destroy_all_mappings(void)
@@ -3575,7 +3573,7 @@ static void core_begin(MemoryListener *listener)
 {
     destroy_all_mappings();
     phys_sections_clear();
-    phys_map.u.node = PHYS_MAP_NODE_NIL;
+    phys_map.ptr = PHYS_MAP_NODE_NIL;
     phys_section_unassigned = dummy_section(&io_mem_unassigned);
 }
 
commit 2999097bf178536188b0f4caf937c4d347e96627
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Feb 13 20:21:20 2012 +0200

    memory: change phys_page_set() to set multiple pages
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index f4cd867..98c0056 100644
--- a/exec.c
+++ b/exec.c
@@ -436,8 +436,9 @@ static void phys_map_nodes_reset(void)
 }
 
 
-static void phys_page_set_level(PhysPageEntry *lp, target_phys_addr_t index,
-                                uint16_t leaf, int level)
+static void phys_page_set_level(PhysPageEntry *lp, target_phys_addr_t *index,
+                                target_phys_addr_t *nb, uint16_t leaf,
+                                int level)
 {
     PhysPageEntry *p;
     int i;
@@ -453,20 +454,27 @@ static void phys_page_set_level(PhysPageEntry *lp, target_phys_addr_t index,
     } else {
         p = phys_map_nodes[lp->u.node];
     }
-    lp = &p[(index >> (level * L2_BITS)) & (L2_SIZE - 1)];
+    lp = &p[(*index >> (level * L2_BITS)) & (L2_SIZE - 1)];
 
-    if (level == 0) {
-        lp->u.leaf = leaf;
-    } else {
-        phys_page_set_level(lp, index, leaf, level - 1);
+    while (*nb && lp < &p[L2_SIZE]) {
+        if (level == 0) {
+            lp->u.leaf = leaf;
+            ++*index;
+            --*nb;
+        } else {
+            phys_page_set_level(lp, index, nb, leaf, level - 1);
+        }
+        ++lp;
     }
 }
 
-static void phys_page_set(target_phys_addr_t index, uint16_t leaf)
+static void phys_page_set(target_phys_addr_t index, target_phys_addr_t nb,
+                          uint16_t leaf)
 {
-    phys_map_node_reserve(P_L2_LEVELS);
+    /* Wildly overreserve - it doesn't matter much. */
+    phys_map_node_reserve((nb + L2_SIZE - 1) / L2_SIZE * P_L2_LEVELS);
 
-    phys_page_set_level(&phys_map, index, leaf, P_L2_LEVELS - 1);
+    phys_page_set_level(&phys_map, &index, &nb, leaf, P_L2_LEVELS - 1);
 }
 
 static MemoryRegionSection phys_page_find(target_phys_addr_t index)
@@ -2630,7 +2638,8 @@ static void register_subpage(MemoryRegionSection *section)
     if (!(existing.mr->subpage)) {
         subpage = subpage_init(base);
         subsection.mr = &subpage->iomem;
-        phys_page_set(base >> TARGET_PAGE_BITS, phys_section_add(&subsection));
+        phys_page_set(base >> TARGET_PAGE_BITS, 1,
+                      phys_section_add(&subsection));
     } else {
         subpage = container_of(existing.mr, subpage_t, iomem);
     }
@@ -2644,18 +2653,14 @@ static void register_multipage(MemoryRegionSection *section)
 {
     target_phys_addr_t start_addr = section->offset_within_address_space;
     ram_addr_t size = section->size;
-    target_phys_addr_t addr, end_addr;
+    target_phys_addr_t addr;
     uint16_t section_index = phys_section_add(section);
 
     assert(size);
 
-    end_addr = start_addr + (target_phys_addr_t)size;
-
     addr = start_addr;
-    do {
-        phys_page_set(addr >> TARGET_PAGE_BITS, section_index);
-        addr += TARGET_PAGE_SIZE;
-    } while (addr != end_addr);
+    phys_page_set(addr >> TARGET_PAGE_BITS, size >> TARGET_PAGE_BITS,
+                  section_index);
 }
 
 void cpu_register_physical_memory_log(MemoryRegionSection *section,
commit f7bf546118837a64d4b04dd650e3f64eaa25e623
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Feb 13 20:12:05 2012 +0200

    memory: switch phys_page_set() to a recursive implementation
    
    Setting multiple pages at once requires backtracking to previous
    nodes; easiest to achieve via recursion.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index 26e70c3..f4cd867 100644
--- a/exec.c
+++ b/exec.c
@@ -404,24 +404,30 @@ static inline PageDesc *page_find(tb_page_addr_t index)
 
 #if !defined(CONFIG_USER_ONLY)
 
-static PhysPageEntry *phys_map_node_alloc(uint16_t *ptr)
+static void phys_map_node_reserve(unsigned nodes)
 {
-    unsigned i;
-    uint16_t ret;
-
-    /* Assign early to avoid the pointer being invalidated by g_renew() */
-    *ptr = ret = phys_map_nodes_nb++;
-    assert(ret != PHYS_MAP_NODE_NIL);
-    if (ret == phys_map_nodes_nb_alloc) {
+    if (phys_map_nodes_nb + nodes > phys_map_nodes_nb_alloc) {
         typedef PhysPageEntry Node[L2_SIZE];
         phys_map_nodes_nb_alloc = MAX(phys_map_nodes_nb_alloc * 2, 16);
+        phys_map_nodes_nb_alloc = MAX(phys_map_nodes_nb_alloc,
+                                      phys_map_nodes_nb + nodes);
         phys_map_nodes = g_renew(Node, phys_map_nodes,
                                  phys_map_nodes_nb_alloc);
     }
+}
+
+static uint16_t phys_map_node_alloc(void)
+{
+    unsigned i;
+    uint16_t ret;
+
+    ret = phys_map_nodes_nb++;
+    assert(ret != PHYS_MAP_NODE_NIL);
+    assert(ret != phys_map_nodes_nb_alloc);
     for (i = 0; i < L2_SIZE; ++i) {
         phys_map_nodes[ret][i].u.node = PHYS_MAP_NODE_NIL;
     }
-    return phys_map_nodes[ret];
+    return ret;
 }
 
 static void phys_map_nodes_reset(void)
@@ -429,29 +435,38 @@ static void phys_map_nodes_reset(void)
     phys_map_nodes_nb = 0;
 }
 
-static void phys_page_set(target_phys_addr_t index, uint16_t leaf)
-{
-    PhysPageEntry *lp, *p;
-    int i, j;
 
-    lp = &phys_map;
+static void phys_page_set_level(PhysPageEntry *lp, target_phys_addr_t index,
+                                uint16_t leaf, int level)
+{
+    PhysPageEntry *p;
+    int i;
 
-    /* Level 1..N.  */
-    for (i = P_L2_LEVELS - 1; i >= 0; i--) {
-        if (lp->u.node == PHYS_MAP_NODE_NIL) {
-            p = phys_map_node_alloc(&lp->u.node);
-            if (i == 0) {
-                for (j = 0; j < L2_SIZE; j++) {
-                    p[j].u.leaf = phys_section_unassigned;
-                }
+    if (lp->u.node == PHYS_MAP_NODE_NIL) {
+        lp->u.node = phys_map_node_alloc();
+        p = phys_map_nodes[lp->u.node];
+        if (level == 0) {
+            for (i = 0; i < L2_SIZE; i++) {
+                p[i].u.leaf = phys_section_unassigned;
             }
-        } else {
-            p = phys_map_nodes[lp->u.node];
         }
-        lp = &p[(index >> (i * L2_BITS)) & (L2_SIZE - 1)];
+    } else {
+        p = phys_map_nodes[lp->u.node];
     }
+    lp = &p[(index >> (level * L2_BITS)) & (L2_SIZE - 1)];
+
+    if (level == 0) {
+        lp->u.leaf = leaf;
+    } else {
+        phys_page_set_level(lp, index, leaf, level - 1);
+    }
+}
+
+static void phys_page_set(target_phys_addr_t index, uint16_t leaf)
+{
+    phys_map_node_reserve(P_L2_LEVELS);
 
-    lp->u.leaf = leaf;
+    phys_page_set_level(&phys_map, index, leaf, P_L2_LEVELS - 1);
 }
 
 static MemoryRegionSection phys_page_find(target_phys_addr_t index)
commit a39184328611abfeb384f99d13d48b1c46d53bae
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Feb 13 17:19:30 2012 +0200

    memory: replace phys_page_find_alloc() with phys_page_set()
    
    By giving the function the value we want to set, we make it
    more flexible for the next patch.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index e382858..26e70c3 100644
--- a/exec.c
+++ b/exec.c
@@ -429,7 +429,7 @@ static void phys_map_nodes_reset(void)
     phys_map_nodes_nb = 0;
 }
 
-static uint16_t *phys_page_find_alloc(target_phys_addr_t index, int alloc)
+static void phys_page_set(target_phys_addr_t index, uint16_t leaf)
 {
     PhysPageEntry *lp, *p;
     int i, j;
@@ -439,9 +439,6 @@ static uint16_t *phys_page_find_alloc(target_phys_addr_t index, int alloc)
     /* Level 1..N.  */
     for (i = P_L2_LEVELS - 1; i >= 0; i--) {
         if (lp->u.node == PHYS_MAP_NODE_NIL) {
-            if (!alloc) {
-                return NULL;
-            }
             p = phys_map_node_alloc(&lp->u.node);
             if (i == 0) {
                 for (j = 0; j < L2_SIZE; j++) {
@@ -454,7 +451,7 @@ static uint16_t *phys_page_find_alloc(target_phys_addr_t index, int alloc)
         lp = &p[(index >> (i * L2_BITS)) & (L2_SIZE - 1)];
     }
 
-    return &lp->u.leaf;
+    lp->u.leaf = leaf;
 }
 
 static MemoryRegionSection phys_page_find(target_phys_addr_t index)
@@ -2611,7 +2608,6 @@ static void register_subpage(MemoryRegionSection *section)
         .offset_within_address_space = base,
         .size = TARGET_PAGE_SIZE,
     };
-    uint16_t *ptr;
     target_phys_addr_t start, end;
 
     assert(existing.mr->subpage || existing.mr == &io_mem_unassigned);
@@ -2619,8 +2615,7 @@ static void register_subpage(MemoryRegionSection *section)
     if (!(existing.mr->subpage)) {
         subpage = subpage_init(base);
         subsection.mr = &subpage->iomem;
-        ptr = phys_page_find_alloc(base >> TARGET_PAGE_BITS, 1);
-        *ptr = phys_section_add(&subsection);
+        phys_page_set(base >> TARGET_PAGE_BITS, phys_section_add(&subsection));
     } else {
         subpage = container_of(existing.mr, subpage_t, iomem);
     }
@@ -2643,9 +2638,7 @@ static void register_multipage(MemoryRegionSection *section)
 
     addr = start_addr;
     do {
-        uint16_t *p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
-        assert(*p == phys_section_unassigned);
-        *p = section_index;
+        phys_page_set(addr >> TARGET_PAGE_BITS, section_index);
         addr += TARGET_PAGE_SIZE;
     } while (addr != end_addr);
 }
commit 0f0cb164cc6d75fa3be079b8fc41c75c5fabe402
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Feb 13 17:14:32 2012 +0200

    memory: simplify multipage/subpage registration
    
    Instead of considering subpage on a per-page basis, split each section
    into a subpage head, multipage body, and subpage tail, and register
    each separately.  This simplifies the registration functions.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index 24423d5..e382858 100644
--- a/exec.c
+++ b/exec.c
@@ -2538,28 +2538,7 @@ typedef struct subpage_t {
 
 static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
                              uint16_t section);
-static subpage_t *subpage_init (target_phys_addr_t base, uint16_t *section,
-                                uint16_t orig_section);
-#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
-                      need_subpage)                                     \
-    do {                                                                \
-        if (addr > start_addr)                                          \
-            start_addr2 = 0;                                            \
-        else {                                                          \
-            start_addr2 = start_addr & ~TARGET_PAGE_MASK;               \
-            if (start_addr2 > 0)                                        \
-                need_subpage = 1;                                       \
-        }                                                               \
-                                                                        \
-        if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE)        \
-            end_addr2 = TARGET_PAGE_SIZE - 1;                           \
-        else {                                                          \
-            end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
-            if (end_addr2 < TARGET_PAGE_SIZE - 1)                       \
-                need_subpage = 1;                                       \
-        }                                                               \
-    } while (0)
-
+static subpage_t *subpage_init(target_phys_addr_t base);
 static void destroy_page_desc(uint16_t section_index)
 {
     MemoryRegionSection *section = &phys_sections[section_index];
@@ -2622,47 +2601,85 @@ static void phys_sections_clear(void)
    start_addr and region_offset are rounded down to a page boundary
    before calculating this offset.  This should not be a problem unless
    the low bits of start_addr and region_offset differ.  */
-void cpu_register_physical_memory_log(MemoryRegionSection *section,
-                                      bool readonly)
+static void register_subpage(MemoryRegionSection *section)
+{
+    subpage_t *subpage;
+    target_phys_addr_t base = section->offset_within_address_space
+        & TARGET_PAGE_MASK;
+    MemoryRegionSection existing = phys_page_find(base >> TARGET_PAGE_BITS);
+    MemoryRegionSection subsection = {
+        .offset_within_address_space = base,
+        .size = TARGET_PAGE_SIZE,
+    };
+    uint16_t *ptr;
+    target_phys_addr_t start, end;
+
+    assert(existing.mr->subpage || existing.mr == &io_mem_unassigned);
+
+    if (!(existing.mr->subpage)) {
+        subpage = subpage_init(base);
+        subsection.mr = &subpage->iomem;
+        ptr = phys_page_find_alloc(base >> TARGET_PAGE_BITS, 1);
+        *ptr = phys_section_add(&subsection);
+    } else {
+        subpage = container_of(existing.mr, subpage_t, iomem);
+    }
+    start = section->offset_within_address_space & ~TARGET_PAGE_MASK;
+    end = start + section->size;
+    subpage_register(subpage, start, end, phys_section_add(section));
+}
+
+
+static void register_multipage(MemoryRegionSection *section)
 {
     target_phys_addr_t start_addr = section->offset_within_address_space;
     ram_addr_t size = section->size;
     target_phys_addr_t addr, end_addr;
-    ram_addr_t orig_size = size;
-    subpage_t *subpage;
     uint16_t section_index = phys_section_add(section);
 
     assert(size);
 
-    size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
     end_addr = start_addr + (target_phys_addr_t)size;
 
     addr = start_addr;
     do {
         uint16_t *p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
-        uint16_t orig_memory = *p;
-        target_phys_addr_t start_addr2, end_addr2;
-        int need_subpage = 0;
-        MemoryRegion *mr = phys_sections[orig_memory].mr;
-
-        CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
-                      need_subpage);
-        if (need_subpage) {
-            if (!(mr->subpage)) {
-                subpage = subpage_init((addr & TARGET_PAGE_MASK),
-                                       p, orig_memory);
-            } else {
-                subpage = container_of(mr, subpage_t, iomem);
-            }
-            subpage_register(subpage, start_addr2, end_addr2,
-                             section_index);
-        } else {
-            *p = section_index;
-        }
+        assert(*p == phys_section_unassigned);
+        *p = section_index;
         addr += TARGET_PAGE_SIZE;
     } while (addr != end_addr);
 }
 
+void cpu_register_physical_memory_log(MemoryRegionSection *section,
+                                      bool readonly)
+{
+    MemoryRegionSection now = *section, remain = *section;
+
+    if ((now.offset_within_address_space & ~TARGET_PAGE_MASK)
+        || (now.size < TARGET_PAGE_SIZE)) {
+        now.size = MIN(TARGET_PAGE_ALIGN(now.offset_within_address_space)
+                       - now.offset_within_address_space,
+                       now.size);
+        register_subpage(&now);
+        remain.size -= now.size;
+        remain.offset_within_address_space += now.size;
+        remain.offset_within_region += now.size;
+    }
+    now = remain;
+    now.size &= TARGET_PAGE_MASK;
+    if (now.size) {
+        register_multipage(&now);
+        remain.size -= now.size;
+        remain.offset_within_address_space += now.size;
+        remain.offset_within_region += now.size;
+    }
+    now = remain;
+    if (now.size) {
+        register_subpage(&now);
+    }
+}
+
+
 void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
 {
     if (kvm_enabled())
@@ -3442,14 +3459,9 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
     return 0;
 }
 
-static subpage_t *subpage_init (target_phys_addr_t base, uint16_t *section_ind,
-                                uint16_t orig_section)
+static subpage_t *subpage_init(target_phys_addr_t base)
 {
     subpage_t *mmio;
-    MemoryRegionSection section = {
-        .offset_within_address_space = base,
-        .size = TARGET_PAGE_SIZE,
-    };
 
     mmio = g_malloc0(sizeof(subpage_t));
 
@@ -3457,13 +3469,11 @@ static subpage_t *subpage_init (target_phys_addr_t base, uint16_t *section_ind,
     memory_region_init_io(&mmio->iomem, &subpage_ops, mmio,
                           "subpage", TARGET_PAGE_SIZE);
     mmio->iomem.subpage = true;
-    section.mr = &mmio->iomem;
 #if defined(DEBUG_SUBPAGE)
     printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
            mmio, base, TARGET_PAGE_SIZE, subpage_memory);
 #endif
-    *section_ind = phys_section_add(&section);
-    subpage_register(mmio, 0, TARGET_PAGE_SIZE-1, orig_section);
+    subpage_register(mmio, 0, TARGET_PAGE_SIZE-1, phys_section_unassigned);
 
     return mmio;
 }
commit 31ab2b4a46eb9761feae9457387eb5ee523f5afd
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Feb 13 16:44:19 2012 +0200

    memory: give phys_page_find() its own tree search loop
    
    We'll change phys_page_find_alloc() soon, but phys_page_find()
    doesn't need to bear the consequences.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index bf34dc9..24423d5 100644
--- a/exec.c
+++ b/exec.c
@@ -459,14 +459,23 @@ static uint16_t *phys_page_find_alloc(target_phys_addr_t index, int alloc)
 
 static MemoryRegionSection phys_page_find(target_phys_addr_t index)
 {
-    uint16_t *p = phys_page_find_alloc(index, 0);
-    uint16_t s_index = phys_section_unassigned;
+    PhysPageEntry lp = phys_map;
+    PhysPageEntry *p;
+    int i;
     MemoryRegionSection section;
     target_phys_addr_t delta;
+    uint16_t s_index = phys_section_unassigned;
 
-    if (p) {
-        s_index = *p;
+    for (i = P_L2_LEVELS - 1; i >= 0; i--) {
+        if (lp.u.node == PHYS_MAP_NODE_NIL) {
+            goto not_found;
+        }
+        p = phys_map_nodes[lp.u.node];
+        lp = p[(index >> (i * L2_BITS)) & (L2_SIZE - 1)];
     }
+
+    s_index = lp.u.leaf;
+not_found:
     section = phys_sections[s_index];
     index <<= TARGET_PAGE_BITS;
     assert(section.offset_within_address_space <= index
commit 06ef3525e1f271b6a842781a05eace5cf63b95c2
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Feb 13 16:11:22 2012 +0200

    memory: make phys_page_find() return a MemoryRegionSection
    
    We no longer describe memory in terms of individual pages; use sections
    throughout instead.
    
    PhysPageDesc no longer used - remove.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index 2171eba..bf34dc9 100644
--- a/exec.c
+++ b/exec.c
@@ -186,12 +186,6 @@ unsigned long qemu_host_page_mask;
 static void *l1_map[V_L1_SIZE];
 
 #if !defined(CONFIG_USER_ONLY)
-typedef struct PhysPageDesc {
-    /* offset in host memory of the page + io_index in the low bits */
-    ram_addr_t phys_offset;
-    ram_addr_t region_offset;
-} PhysPageDesc;
-
 typedef struct PhysPageEntry PhysPageEntry;
 
 static MemoryRegionSection *phys_sections;
@@ -212,7 +206,7 @@ static unsigned phys_map_nodes_nb, phys_map_nodes_nb_alloc;
 #define PHYS_MAP_NODE_NIL ((uint16_t)~0)
 
 /* This is a multi-level map on the physical address space.
-   The bottom level has pointers to PhysPageDesc.  */
+   The bottom level has pointers to MemoryRegionSections.  */
 static PhysPageEntry phys_map = { .u.node = PHYS_MAP_NODE_NIL };
 
 static void io_mem_init(void);
@@ -463,33 +457,25 @@ static uint16_t *phys_page_find_alloc(target_phys_addr_t index, int alloc)
     return &lp->u.leaf;
 }
 
-static inline PhysPageDesc phys_page_find(target_phys_addr_t index)
+static MemoryRegionSection phys_page_find(target_phys_addr_t index)
 {
     uint16_t *p = phys_page_find_alloc(index, 0);
     uint16_t s_index = phys_section_unassigned;
-    MemoryRegionSection *section;
-    PhysPageDesc pd;
+    MemoryRegionSection section;
+    target_phys_addr_t delta;
 
     if (p) {
         s_index = *p;
     }
-    section = &phys_sections[s_index];
+    section = phys_sections[s_index];
     index <<= TARGET_PAGE_BITS;
-    assert(section->offset_within_address_space <= index
-           && index <= section->offset_within_address_space + section->size-1);
-    pd.phys_offset = section->mr->ram_addr;
-    pd.region_offset = (index - section->offset_within_address_space)
-        + section->offset_within_region;
-    if (memory_region_is_ram(section->mr)) {
-        pd.phys_offset += pd.region_offset;
-        pd.region_offset = 0;
-    } else if (section->mr->rom_device) {
-        pd.phys_offset += pd.region_offset;
-    }
-    if (section->readonly) {
-        pd.phys_offset |= io_mem_rom.ram_addr;
-    }
-    return pd;
+    assert(section.offset_within_address_space <= index
+           && index <= section.offset_within_address_space + section.size-1);
+    delta = index - section.offset_within_address_space;
+    section.offset_within_address_space += delta;
+    section.offset_within_region += delta;
+    section.size -= delta;
+    return section;
 }
 
 static void tlb_protect_code(ram_addr_t ram_addr);
@@ -1449,14 +1435,18 @@ static void breakpoint_invalidate(CPUState *env, target_ulong pc)
 static void breakpoint_invalidate(CPUState *env, target_ulong pc)
 {
     target_phys_addr_t addr;
-    target_ulong pd;
     ram_addr_t ram_addr;
-    PhysPageDesc p;
+    MemoryRegionSection section;
 
     addr = cpu_get_phys_page_debug(env, pc);
-    p = phys_page_find(addr >> TARGET_PAGE_BITS);
-    pd = p.phys_offset;
-    ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
+    section = phys_page_find(addr >> TARGET_PAGE_BITS);
+    if (!(memory_region_is_ram(section.mr)
+          || (section.mr->rom_device && section.mr->readable))) {
+        return;
+    }
+    ram_addr = (memory_region_get_ram_addr(section.mr)
+                + section.offset_within_region) & TARGET_PAGE_MASK;
+    ram_addr |= (pc & ~TARGET_PAGE_MASK);
     tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
 }
 #endif
@@ -2134,24 +2124,21 @@ static void tlb_add_large_page(CPUState *env, target_ulong vaddr,
     env->tlb_flush_mask = mask;
 }
 
-static bool is_ram_rom(ram_addr_t pd)
+static bool is_ram_rom(MemoryRegionSection *s)
 {
-    pd &= ~TARGET_PAGE_MASK;
-    return pd == io_mem_ram.ram_addr || pd == io_mem_rom.ram_addr;
+    return memory_region_is_ram(s->mr);
 }
 
-static bool is_romd(ram_addr_t pd)
+static bool is_romd(MemoryRegionSection *s)
 {
-    MemoryRegion *mr;
+    MemoryRegion *mr = s->mr;
 
-    pd &= ~TARGET_PAGE_MASK;
-    mr = io_mem_region[pd];
     return mr->rom_device && mr->readable;
 }
 
-static bool is_ram_rom_romd(ram_addr_t pd)
+static bool is_ram_rom_romd(MemoryRegionSection *s)
 {
-    return is_ram_rom(pd) || is_romd(pd);
+    return is_ram_rom(s) || is_romd(s);
 }
 
 /* Add a new TLB entry. At most one entry for a given virtual address
@@ -2161,8 +2148,7 @@ void tlb_set_page(CPUState *env, target_ulong vaddr,
                   target_phys_addr_t paddr, int prot,
                   int mmu_idx, target_ulong size)
 {
-    PhysPageDesc p;
-    unsigned long pd;
+    MemoryRegionSection section;
     unsigned int index;
     target_ulong address;
     target_ulong code_address;
@@ -2175,8 +2161,7 @@ void tlb_set_page(CPUState *env, target_ulong vaddr,
     if (size != TARGET_PAGE_SIZE) {
         tlb_add_large_page(env, vaddr, size);
     }
-    p = phys_page_find(paddr >> TARGET_PAGE_BITS);
-    pd = p.phys_offset;
+    section = phys_page_find(paddr >> TARGET_PAGE_BITS);
 #if defined(DEBUG_TLB)
     printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x" TARGET_FMT_plx
            " prot=%x idx=%d pd=0x%08lx\n",
@@ -2184,15 +2169,21 @@ void tlb_set_page(CPUState *env, target_ulong vaddr,
 #endif
 
     address = vaddr;
-    if (!is_ram_rom_romd(pd)) {
+    if (!is_ram_rom_romd(&section)) {
         /* IO memory case (romd handled later) */
         address |= TLB_MMIO;
     }
-    addend = (unsigned long)qemu_get_ram_ptr(pd & TARGET_PAGE_MASK);
-    if (is_ram_rom(pd)) {
+    if (is_ram_rom_romd(&section)) {
+        addend = (unsigned long)(memory_region_get_ram_ptr(section.mr)
+                                 + section.offset_within_region);
+    } else {
+        addend = 0;
+    }
+    if (is_ram_rom(&section)) {
         /* Normal RAM.  */
-        iotlb = pd & TARGET_PAGE_MASK;
-        if ((pd & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr)
+        iotlb = (memory_region_get_ram_addr(section.mr)
+                 + section.offset_within_region) & TARGET_PAGE_MASK;
+        if (!section.readonly)
             iotlb |= io_mem_notdirty.ram_addr;
         else
             iotlb |= io_mem_rom.ram_addr;
@@ -2203,8 +2194,8 @@ void tlb_set_page(CPUState *env, target_ulong vaddr,
            and avoid full address decoding in every device.
            We can't use the high bits of pd for this because
            IO_MEM_ROMD uses these as a ram address.  */
-        iotlb = (pd & ~TARGET_PAGE_MASK);
-        iotlb += p.region_offset;
+        iotlb = memory_region_get_ram_addr(section.mr) & ~TARGET_PAGE_MASK;
+        iotlb += section.offset_within_region;
     }
 
     code_address = address;
@@ -2237,11 +2228,14 @@ void tlb_set_page(CPUState *env, target_ulong vaddr,
         te->addr_code = -1;
     }
     if (prot & PAGE_WRITE) {
-        if ((pd & ~TARGET_PAGE_MASK) == io_mem_rom.ram_addr || is_romd(pd)) {
+        if ((memory_region_is_ram(section.mr) && section.readonly)
+            || is_romd(&section)) {
             /* Write access calls the I/O callback.  */
             te->addr_write = address | TLB_MMIO;
-        } else if ((pd & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr &&
-                   !cpu_physical_memory_is_dirty(pd)) {
+        } else if (memory_region_is_ram(section.mr)
+                   && !cpu_physical_memory_is_dirty(
+                           section.mr->ram_addr
+                           + section.offset_within_region)) {
             te->addr_write = address | TLB_NOTDIRTY;
         } else {
             te->addr_write = address;
@@ -3788,22 +3782,22 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
     uint8_t *ptr;
     uint32_t val;
     target_phys_addr_t page;
-    ram_addr_t pd;
-    PhysPageDesc p;
+    MemoryRegionSection section;
 
     while (len > 0) {
         page = addr & TARGET_PAGE_MASK;
         l = (page + TARGET_PAGE_SIZE) - addr;
         if (l > len)
             l = len;
-        p = phys_page_find(page >> TARGET_PAGE_BITS);
-        pd = p.phys_offset;
+        section = phys_page_find(page >> TARGET_PAGE_BITS);
 
         if (is_write) {
-            if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) {
+            if (!memory_region_is_ram(section.mr)) {
                 target_phys_addr_t addr1;
-                io_index = pd & (IO_MEM_NB_ENTRIES - 1);
-                addr1 = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
+                io_index = memory_region_get_ram_addr(section.mr)
+                    & (IO_MEM_NB_ENTRIES - 1);
+                addr1 = (addr & ~TARGET_PAGE_MASK)
+                    + section.offset_within_region;
                 /* XXX: could force cpu_single_env to NULL to avoid
                    potential bugs */
                 if (l >= 4 && ((addr1 & 3) == 0)) {
@@ -3822,9 +3816,11 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
                     io_mem_write(io_index, addr1, val, 1);
                     l = 1;
                 }
-            } else {
+            } else if (!section.readonly) {
                 ram_addr_t addr1;
-                addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
+                addr1 = (memory_region_get_ram_addr(section.mr)
+                         + section.offset_within_region)
+                    | (addr & ~TARGET_PAGE_MASK);
                 /* RAM case */
                 ptr = qemu_get_ram_ptr(addr1);
                 memcpy(ptr, buf, l);
@@ -3838,11 +3834,13 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
                 qemu_put_ram_ptr(ptr);
             }
         } else {
-            if (!is_ram_rom_romd(pd)) {
+            if (!is_ram_rom_romd(&section)) {
                 target_phys_addr_t addr1;
                 /* I/O case */
-                io_index = pd & (IO_MEM_NB_ENTRIES - 1);
-                addr1 = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
+                io_index = memory_region_get_ram_addr(section.mr)
+                    & (IO_MEM_NB_ENTRIES - 1);
+                addr1 = (addr & ~TARGET_PAGE_MASK)
+                    + section.offset_within_region;
                 if (l >= 4 && ((addr1 & 3) == 0)) {
                     /* 32 bit read access */
                     val = io_mem_read(io_index, addr1, 4);
@@ -3861,7 +3859,8 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
                 }
             } else {
                 /* RAM case */
-                ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK);
+                ptr = qemu_get_ram_ptr(section.mr->ram_addr
+                                       + section.offset_within_region);
                 memcpy(buf, ptr + (addr & ~TARGET_PAGE_MASK), l);
                 qemu_put_ram_ptr(ptr);
             }
@@ -3879,22 +3878,22 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr,
     int l;
     uint8_t *ptr;
     target_phys_addr_t page;
-    unsigned long pd;
-    PhysPageDesc p;
+    MemoryRegionSection section;
 
     while (len > 0) {
         page = addr & TARGET_PAGE_MASK;
         l = (page + TARGET_PAGE_SIZE) - addr;
         if (l > len)
             l = len;
-        p = phys_page_find(page >> TARGET_PAGE_BITS);
-        pd = p.phys_offset;
+        section = phys_page_find(page >> TARGET_PAGE_BITS);
 
-        if (!is_ram_rom_romd(pd)) {
+        if (!is_ram_rom_romd(&section)) {
             /* do nothing */
         } else {
             unsigned long addr1;
-            addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
+            addr1 = (memory_region_get_ram_addr(section.mr)
+                     + section.offset_within_region)
+                + (addr & ~TARGET_PAGE_MASK);
             /* ROM/RAM case */
             ptr = qemu_get_ram_ptr(addr1);
             memcpy(ptr, buf, l);
@@ -3967,8 +3966,7 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
     target_phys_addr_t todo = 0;
     int l;
     target_phys_addr_t page;
-    unsigned long pd;
-    PhysPageDesc p;
+    MemoryRegionSection section;
     ram_addr_t raddr = RAM_ADDR_MAX;
     ram_addr_t rlen;
     void *ret;
@@ -3978,10 +3976,9 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
         l = (page + TARGET_PAGE_SIZE) - addr;
         if (l > len)
             l = len;
-        p = phys_page_find(page >> TARGET_PAGE_BITS);
-        pd = p.phys_offset;
+        section = phys_page_find(page >> TARGET_PAGE_BITS);
 
-        if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) {
+        if (!(memory_region_is_ram(section.mr) && !section.readonly)) {
             if (todo || bounce.buffer) {
                 break;
             }
@@ -3996,7 +3993,9 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
             return bounce.buffer;
         }
         if (!todo) {
-            raddr = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
+            raddr = memory_region_get_ram_addr(section.mr)
+                + section.offset_within_region
+                + (addr & ~TARGET_PAGE_MASK);
         }
 
         len -= l;
@@ -4055,16 +4054,15 @@ static inline uint32_t ldl_phys_internal(target_phys_addr_t addr,
     int io_index;
     uint8_t *ptr;
     uint32_t val;
-    unsigned long pd;
-    PhysPageDesc p;
+    MemoryRegionSection section;
 
-    p = phys_page_find(addr >> TARGET_PAGE_BITS);
-    pd = p.phys_offset;
+    section = phys_page_find(addr >> TARGET_PAGE_BITS);
 
-    if (!is_ram_rom_romd(pd)) {
+    if (!is_ram_rom_romd(&section)) {
         /* I/O case */
-        io_index = pd & (IO_MEM_NB_ENTRIES - 1);
-        addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
+        io_index = memory_region_get_ram_addr(section.mr)
+            & (IO_MEM_NB_ENTRIES - 1);
+        addr = (addr & ~TARGET_PAGE_MASK) + section.offset_within_region;
         val = io_mem_read(io_index, addr, 4);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
@@ -4077,7 +4075,9 @@ static inline uint32_t ldl_phys_internal(target_phys_addr_t addr,
 #endif
     } else {
         /* RAM case */
-        ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
+        ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section.mr)
+                                & TARGET_PAGE_MASK)
+                               + section.offset_within_region) +
             (addr & ~TARGET_PAGE_MASK);
         switch (endian) {
         case DEVICE_LITTLE_ENDIAN:
@@ -4116,16 +4116,15 @@ static inline uint64_t ldq_phys_internal(target_phys_addr_t addr,
     int io_index;
     uint8_t *ptr;
     uint64_t val;
-    unsigned long pd;
-    PhysPageDesc p;
+    MemoryRegionSection section;
 
-    p = phys_page_find(addr >> TARGET_PAGE_BITS);
-    pd = p.phys_offset;
+    section = phys_page_find(addr >> TARGET_PAGE_BITS);
 
-    if (!is_ram_rom_romd(pd)) {
+    if (!is_ram_rom_romd(&section)) {
         /* I/O case */
-        io_index = pd & (IO_MEM_NB_ENTRIES - 1);
-        addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
+        io_index = memory_region_get_ram_addr(section.mr)
+            & (IO_MEM_NB_ENTRIES - 1);
+        addr = (addr & ~TARGET_PAGE_MASK) + section.offset_within_region;
 
         /* XXX This is broken when device endian != cpu endian.
                Fix and add "endian" variable check */
@@ -4138,8 +4137,10 @@ static inline uint64_t ldq_phys_internal(target_phys_addr_t addr,
 #endif
     } else {
         /* RAM case */
-        ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
-            (addr & ~TARGET_PAGE_MASK);
+        ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section.mr)
+                                & TARGET_PAGE_MASK)
+                               + section.offset_within_region)
+            + (addr & ~TARGET_PAGE_MASK);
         switch (endian) {
         case DEVICE_LITTLE_ENDIAN:
             val = ldq_le_p(ptr);
@@ -4185,16 +4186,15 @@ static inline uint32_t lduw_phys_internal(target_phys_addr_t addr,
     int io_index;
     uint8_t *ptr;
     uint64_t val;
-    unsigned long pd;
-    PhysPageDesc p;
+    MemoryRegionSection section;
 
-    p = phys_page_find(addr >> TARGET_PAGE_BITS);
-    pd = p.phys_offset;
+    section = phys_page_find(addr >> TARGET_PAGE_BITS);
 
-    if (!is_ram_rom_romd(pd)) {
+    if (!is_ram_rom_romd(&section)) {
         /* I/O case */
-        io_index = pd & (IO_MEM_NB_ENTRIES - 1);
-        addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
+        io_index = memory_region_get_ram_addr(section.mr)
+            & (IO_MEM_NB_ENTRIES - 1);
+        addr = (addr & ~TARGET_PAGE_MASK) + section.offset_within_region;
         val = io_mem_read(io_index, addr, 2);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
@@ -4207,8 +4207,10 @@ static inline uint32_t lduw_phys_internal(target_phys_addr_t addr,
 #endif
     } else {
         /* RAM case */
-        ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
-            (addr & ~TARGET_PAGE_MASK);
+        ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section.mr)
+                                & TARGET_PAGE_MASK)
+                               + section.offset_within_region)
+            + (addr & ~TARGET_PAGE_MASK);
         switch (endian) {
         case DEVICE_LITTLE_ENDIAN:
             val = lduw_le_p(ptr);
@@ -4246,18 +4248,23 @@ void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
 {
     int io_index;
     uint8_t *ptr;
-    unsigned long pd;
-    PhysPageDesc p;
+    MemoryRegionSection section;
 
-    p = phys_page_find(addr >> TARGET_PAGE_BITS);
-    pd = p.phys_offset;
+    section = phys_page_find(addr >> TARGET_PAGE_BITS);
 
-    if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) {
-        io_index = pd & (IO_MEM_NB_ENTRIES - 1);
-        addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
+    if (!memory_region_is_ram(section.mr) || section.readonly) {
+        if (memory_region_is_ram(section.mr)) {
+            io_index = io_mem_rom.ram_addr;
+        } else {
+            io_index = memory_region_get_ram_addr(section.mr);
+        }
+        addr = (addr & ~TARGET_PAGE_MASK) + section.offset_within_region;
         io_mem_write(io_index, addr, val, 4);
     } else {
-        unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
+        unsigned long addr1 = (memory_region_get_ram_addr(section.mr)
+                               & TARGET_PAGE_MASK)
+            + section.offset_within_region
+            + (addr & ~TARGET_PAGE_MASK);
         ptr = qemu_get_ram_ptr(addr1);
         stl_p(ptr, val);
 
@@ -4277,15 +4284,18 @@ void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
 {
     int io_index;
     uint8_t *ptr;
-    unsigned long pd;
-    PhysPageDesc p;
+    MemoryRegionSection section;
 
-    p = phys_page_find(addr >> TARGET_PAGE_BITS);
-    pd = p.phys_offset;
+    section = phys_page_find(addr >> TARGET_PAGE_BITS);
 
-    if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) {
-        io_index = pd & (IO_MEM_NB_ENTRIES - 1);
-        addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
+    if (!memory_region_is_ram(section.mr) || section.readonly) {
+        if (memory_region_is_ram(section.mr)) {
+                io_index = io_mem_rom.ram_addr;
+        } else {
+            io_index = memory_region_get_ram_addr(section.mr)
+                & (IO_MEM_NB_ENTRIES - 1);
+        }
+        addr = (addr & ~TARGET_PAGE_MASK) + section.offset_within_region;
 #ifdef TARGET_WORDS_BIGENDIAN
         io_mem_write(io_index, addr, val >> 32, 4);
         io_mem_write(io_index, addr + 4, (uint32_t)val, 4);
@@ -4294,8 +4304,10 @@ void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
         io_mem_write(io_index, addr + 4, val >> 32, 4);
 #endif
     } else {
-        ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
-            (addr & ~TARGET_PAGE_MASK);
+        ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section.mr)
+                                & TARGET_PAGE_MASK)
+                               + section.offset_within_region)
+            + (addr & ~TARGET_PAGE_MASK);
         stq_p(ptr, val);
     }
 }
@@ -4306,15 +4318,18 @@ static inline void stl_phys_internal(target_phys_addr_t addr, uint32_t val,
 {
     int io_index;
     uint8_t *ptr;
-    unsigned long pd;
-    PhysPageDesc p;
+    MemoryRegionSection section;
 
-    p = phys_page_find(addr >> TARGET_PAGE_BITS);
-    pd = p.phys_offset;
+    section = phys_page_find(addr >> TARGET_PAGE_BITS);
 
-    if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) {
-        io_index = pd & (IO_MEM_NB_ENTRIES - 1);
-        addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
+    if (!memory_region_is_ram(section.mr) || section.readonly) {
+        if (memory_region_is_ram(section.mr)) {
+            io_index = io_mem_rom.ram_addr;
+        } else {
+            io_index = memory_region_get_ram_addr(section.mr)
+                & (IO_MEM_NB_ENTRIES - 1);
+        }
+        addr = (addr & ~TARGET_PAGE_MASK) + section.offset_within_region;
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
             val = bswap32(val);
@@ -4327,7 +4342,9 @@ static inline void stl_phys_internal(target_phys_addr_t addr, uint32_t val,
         io_mem_write(io_index, addr, val, 4);
     } else {
         unsigned long addr1;
-        addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
+        addr1 = (memory_region_get_ram_addr(section.mr) & TARGET_PAGE_MASK)
+            + section.offset_within_region
+            + (addr & ~TARGET_PAGE_MASK);
         /* RAM case */
         ptr = qemu_get_ram_ptr(addr1);
         switch (endian) {
@@ -4379,15 +4396,18 @@ static inline void stw_phys_internal(target_phys_addr_t addr, uint32_t val,
 {
     int io_index;
     uint8_t *ptr;
-    unsigned long pd;
-    PhysPageDesc p;
+    MemoryRegionSection section;
 
-    p = phys_page_find(addr >> TARGET_PAGE_BITS);
-    pd = p.phys_offset;
+    section = phys_page_find(addr >> TARGET_PAGE_BITS);
 
-    if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) {
-        io_index = pd & (IO_MEM_NB_ENTRIES - 1);
-        addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
+    if (!memory_region_is_ram(section.mr) || section.readonly) {
+        if (memory_region_is_ram(section.mr)) {
+            io_index = io_mem_rom.ram_addr;
+        } else {
+            io_index = memory_region_get_ram_addr(section.mr)
+                & (IO_MEM_NB_ENTRIES - 1);
+        }
+        addr = (addr & ~TARGET_PAGE_MASK) + section.offset_within_region;
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
             val = bswap16(val);
@@ -4400,7 +4420,8 @@ static inline void stw_phys_internal(target_phys_addr_t addr, uint32_t val,
         io_mem_write(io_index, addr, val, 2);
     } else {
         unsigned long addr1;
-        addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
+        addr1 = (memory_region_get_ram_addr(section.mr) & TARGET_PAGE_MASK)
+            + section.offset_within_region + (addr & ~TARGET_PAGE_MASK);
         /* RAM case */
         ptr = qemu_get_ram_ptr(addr1);
         switch (endian) {
@@ -4617,7 +4638,7 @@ tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong addr)
     }
     pd = env1->tlb_table[mmu_idx][page_index].addr_code & ~TARGET_PAGE_MASK;
     if (pd != io_mem_ram.ram_addr && pd != io_mem_rom.ram_addr
-        && !is_romd(pd)) {
+        && !io_mem_region[pd]->rom_device) {
 #if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC)
         cpu_unassigned_access(env1, addr, 0, 1, 0, 4);
 #else
commit 117712c3e48e64c763d981b0d72603ef703031fe
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Feb 12 21:23:17 2012 +0200

    memory: move tlb flush to MemoryListener commit callback
    
    This way, if we have several changes in a single transaction, we flush just
    once.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index 6232a39..2171eba 100644
--- a/exec.c
+++ b/exec.c
@@ -2625,7 +2625,6 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section,
     target_phys_addr_t start_addr = section->offset_within_address_space;
     ram_addr_t size = section->size;
     target_phys_addr_t addr, end_addr;
-    CPUState *env;
     ram_addr_t orig_size = size;
     subpage_t *subpage;
     uint16_t section_index = phys_section_add(section);
@@ -2659,13 +2658,6 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section,
         }
         addr += TARGET_PAGE_SIZE;
     } while (addr != end_addr);
-
-    /* since each CPU stores ram addresses in its TLB cache, we must
-       reset the modified entries */
-    /* XXX: slow ! */
-    for(env = first_cpu; env != NULL; env = env->next_cpu) {
-        tlb_flush(env, 1);
-    }
 }
 
 void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
@@ -3563,6 +3555,14 @@ static void core_begin(MemoryListener *listener)
 
 static void core_commit(MemoryListener *listener)
 {
+    CPUState *env;
+
+    /* since each CPU stores ram addresses in its TLB cache, we must
+       reset the modified entries */
+    /* XXX: slow ! */
+    for(env = first_cpu; env != NULL; env = env->next_cpu) {
+        tlb_flush(env, 1);
+    }
 }
 
 static void core_region_add(MemoryListener *listener,
commit 717cb7b259d7258063f8c4a812098a8d3adfa4b3
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Feb 12 21:21:21 2012 +0200

    memory: unify the two branches of cpu_register_physical_memory_log()
    
    Identical except that the second branch knows its not modifying an existing
    subpage.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index 5d0afdb..6232a39 100644
--- a/exec.c
+++ b/exec.c
@@ -2625,7 +2625,6 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section,
     target_phys_addr_t start_addr = section->offset_within_address_space;
     ram_addr_t size = section->size;
     target_phys_addr_t addr, end_addr;
-    uint16_t *p;
     CPUState *env;
     ram_addr_t orig_size = size;
     subpage_t *subpage;
@@ -2638,43 +2637,25 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section,
 
     addr = start_addr;
     do {
-        p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 0);
-        if (p && *p != phys_section_unassigned) {
-            uint16_t orig_memory= *p;
-            target_phys_addr_t start_addr2, end_addr2;
-            int need_subpage = 0;
-            MemoryRegion *mr = phys_sections[orig_memory].mr;
-
-            CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
-                          need_subpage);
-            if (need_subpage) {
-                if (!(mr->subpage)) {
-                    subpage = subpage_init((addr & TARGET_PAGE_MASK),
-                                           p, orig_memory);
-                } else {
-                    subpage = container_of(mr, subpage_t, iomem);
-                }
-                subpage_register(subpage, start_addr2, end_addr2,
-                                 section_index);
+        uint16_t *p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
+        uint16_t orig_memory = *p;
+        target_phys_addr_t start_addr2, end_addr2;
+        int need_subpage = 0;
+        MemoryRegion *mr = phys_sections[orig_memory].mr;
+
+        CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
+                      need_subpage);
+        if (need_subpage) {
+            if (!(mr->subpage)) {
+                subpage = subpage_init((addr & TARGET_PAGE_MASK),
+                                       p, orig_memory);
             } else {
-                *p = section_index;
+                subpage = container_of(mr, subpage_t, iomem);
             }
+            subpage_register(subpage, start_addr2, end_addr2,
+                             section_index);
         } else {
-            target_phys_addr_t start_addr2, end_addr2;
-            int need_subpage = 0;
-
-            p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
             *p = section_index;
-
-            CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
-                          end_addr2, need_subpage);
-
-            if (need_subpage) {
-                subpage = subpage_init((addr & TARGET_PAGE_MASK),
-                                       p, phys_section_unassigned);
-                subpage_register(subpage, start_addr2, end_addr2,
-                                 section_index);
-            }
         }
         addr += TARGET_PAGE_SIZE;
     } while (addr != end_addr);
commit 8636b9295be46307a1de86942accabea50fa59ae
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Feb 12 21:10:50 2012 +0200

    memory: fix RAM subpages in newly initialized pages
    
    If the first subpage installed in a page is RAM, then we install it as
    a full page, instead of a subpage.  Fix by not special casing RAM.
    
    The issue dates to commit db7b5426a4b4242, which introduced subpages.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index 0756919..5d0afdb 100644
--- a/exec.c
+++ b/exec.c
@@ -2660,22 +2660,20 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section,
                 *p = section_index;
             }
         } else {
-            MemoryRegion *mr = section->mr;
+            target_phys_addr_t start_addr2, end_addr2;
+            int need_subpage = 0;
+
             p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
             *p = section_index;
-            if (!(memory_region_is_ram(mr) || mr->rom_device)) {
-                target_phys_addr_t start_addr2, end_addr2;
-                int need_subpage = 0;
 
-                CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
-                              end_addr2, need_subpage);
+            CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
+                          end_addr2, need_subpage);
 
-                if (need_subpage) {
-                    subpage = subpage_init((addr & TARGET_PAGE_MASK),
-                                           p, phys_section_unassigned);
-                    subpage_register(subpage, start_addr2, end_addr2,
-                                     section_index);
-                }
+            if (need_subpage) {
+                subpage = subpage_init((addr & TARGET_PAGE_MASK),
+                                       p, phys_section_unassigned);
+                subpage_register(subpage, start_addr2, end_addr2,
+                                 section_index);
             }
         }
         addr += TARGET_PAGE_SIZE;
commit d6f2ea22a05b429ba83248b80a625b6fe1d927f3
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Feb 12 20:12:49 2012 +0200

    memory: compress phys_map node pointers to 16 bits
    
    Use an expanding vector to store nodes.  Allocation is baroque to g_renew()
    potentially invalidating pointers; this will be addressed later.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index 957bc6d..0756919 100644
--- a/exec.c
+++ b/exec.c
@@ -201,13 +201,19 @@ static uint16_t phys_section_unassigned;
 struct PhysPageEntry {
     union {
         uint16_t leaf; /* index into phys_sections */
-        PhysPageEntry *node;
+        uint16_t node; /* index into phys_map_nodes */
     } u;
 };
 
+/* Simple allocator for PhysPageEntry nodes */
+static PhysPageEntry (*phys_map_nodes)[L2_SIZE];
+static unsigned phys_map_nodes_nb, phys_map_nodes_nb_alloc;
+
+#define PHYS_MAP_NODE_NIL ((uint16_t)~0)
+
 /* This is a multi-level map on the physical address space.
    The bottom level has pointers to PhysPageDesc.  */
-static PhysPageEntry phys_map;
+static PhysPageEntry phys_map = { .u.node = PHYS_MAP_NODE_NIL };
 
 static void io_mem_init(void);
 static void memory_map_init(void);
@@ -403,6 +409,32 @@ static inline PageDesc *page_find(tb_page_addr_t index)
 }
 
 #if !defined(CONFIG_USER_ONLY)
+
+static PhysPageEntry *phys_map_node_alloc(uint16_t *ptr)
+{
+    unsigned i;
+    uint16_t ret;
+
+    /* Assign early to avoid the pointer being invalidated by g_renew() */
+    *ptr = ret = phys_map_nodes_nb++;
+    assert(ret != PHYS_MAP_NODE_NIL);
+    if (ret == phys_map_nodes_nb_alloc) {
+        typedef PhysPageEntry Node[L2_SIZE];
+        phys_map_nodes_nb_alloc = MAX(phys_map_nodes_nb_alloc * 2, 16);
+        phys_map_nodes = g_renew(Node, phys_map_nodes,
+                                 phys_map_nodes_nb_alloc);
+    }
+    for (i = 0; i < L2_SIZE; ++i) {
+        phys_map_nodes[ret][i].u.node = PHYS_MAP_NODE_NIL;
+    }
+    return phys_map_nodes[ret];
+}
+
+static void phys_map_nodes_reset(void)
+{
+    phys_map_nodes_nb = 0;
+}
+
 static uint16_t *phys_page_find_alloc(target_phys_addr_t index, int alloc)
 {
     PhysPageEntry *lp, *p;
@@ -412,18 +444,20 @@ static uint16_t *phys_page_find_alloc(target_phys_addr_t index, int alloc)
 
     /* Level 1..N.  */
     for (i = P_L2_LEVELS - 1; i >= 0; i--) {
-        if (lp->u.node == NULL) {
+        if (lp->u.node == PHYS_MAP_NODE_NIL) {
             if (!alloc) {
                 return NULL;
             }
-            lp->u.node = p = g_malloc0(sizeof(PhysPageEntry) * L2_SIZE);
+            p = phys_map_node_alloc(&lp->u.node);
             if (i == 0) {
                 for (j = 0; j < L2_SIZE; j++) {
                     p[j].u.leaf = phys_section_unassigned;
                 }
             }
+        } else {
+            p = phys_map_nodes[lp->u.node];
         }
-        lp = &lp->u.node[(index >> (i * L2_BITS)) & (L2_SIZE - 1)];
+        lp = &p[(index >> (i * L2_BITS)) & (L2_SIZE - 1)];
     }
 
     return &lp->u.leaf;
@@ -2538,12 +2572,13 @@ static void destroy_page_desc(uint16_t section_index)
 static void destroy_l2_mapping(PhysPageEntry *lp, unsigned level)
 {
     unsigned i;
-    PhysPageEntry *p = lp->u.node;
+    PhysPageEntry *p;
 
-    if (!p) {
+    if (lp->u.node == PHYS_MAP_NODE_NIL) {
         return;
     }
 
+    p = phys_map_nodes[lp->u.node];
     for (i = 0; i < L2_SIZE; ++i) {
         if (level > 0) {
             destroy_l2_mapping(&p[i], level - 1);
@@ -2551,13 +2586,13 @@ static void destroy_l2_mapping(PhysPageEntry *lp, unsigned level)
             destroy_page_desc(p[i].u.leaf);
         }
     }
-    g_free(p);
-    lp->u.node = NULL;
+    lp->u.node = PHYS_MAP_NODE_NIL;
 }
 
 static void destroy_all_mappings(void)
 {
     destroy_l2_mapping(&phys_map, P_L2_LEVELS - 1);
+    phys_map_nodes_reset();
 }
 
 static uint16_t phys_section_add(MemoryRegionSection *section)
@@ -3543,6 +3578,7 @@ static void core_begin(MemoryListener *listener)
 {
     destroy_all_mappings();
     phys_sections_clear();
+    phys_map.u.node = PHYS_MAP_NODE_NIL;
     phys_section_unassigned = dummy_section(&io_mem_unassigned);
 }
 
commit 5312bd8b3152f8d4fcf9389ba54e32b09f4b4093
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Feb 12 18:32:55 2012 +0200

    memory: store MemoryRegionSection pointers in phys_map
    
    Instead of storing PhysPageDesc, store pointers to MemoryRegionSections.
    The various offsets (phys_offset & ~TARGET_PAGE_MASK,
    PHYS_OFFSET & TARGET_PAGE_MASK, region_offset) can all be synthesized
    from the information in a MemoryRegionSection.  Adjust phys_page_find()
    to synthesize a PhysPageDesc.
    
    The upshot is that phys_map now contains uniform values, so it's easier
    to generate and compress.
    
    The end result is somewhat clumsy but this will be improved as we we
    propagate MemoryRegionSections throughout the code instead of transforming
    them to PhysPageDesc.
    
    The MemoryRegionSection pointers are stored as uint16_t offsets in an
    array.  This saves space (when we also compress node pointers) and is
    more cache friendly.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index 536e70f..957bc6d 100644
--- a/exec.c
+++ b/exec.c
@@ -194,9 +194,13 @@ typedef struct PhysPageDesc {
 
 typedef struct PhysPageEntry PhysPageEntry;
 
+static MemoryRegionSection *phys_sections;
+static unsigned phys_sections_nb, phys_sections_nb_alloc;
+static uint16_t phys_section_unassigned;
+
 struct PhysPageEntry {
     union {
-        PhysPageDesc leaf;
+        uint16_t leaf; /* index into phys_sections */
         PhysPageEntry *node;
     } u;
 };
@@ -399,7 +403,7 @@ static inline PageDesc *page_find(tb_page_addr_t index)
 }
 
 #if !defined(CONFIG_USER_ONLY)
-static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
+static uint16_t *phys_page_find_alloc(target_phys_addr_t index, int alloc)
 {
     PhysPageEntry *lp, *p;
     int i, j;
@@ -414,11 +418,8 @@ static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
             }
             lp->u.node = p = g_malloc0(sizeof(PhysPageEntry) * L2_SIZE);
             if (i == 0) {
-                int first_index = index & ~(L2_SIZE - 1);
                 for (j = 0; j < L2_SIZE; j++) {
-                    p[j].u.leaf.phys_offset = io_mem_unassigned.ram_addr;
-                    p[j].u.leaf.region_offset
-                        = (first_index + j) << TARGET_PAGE_BITS;
+                    p[j].u.leaf = phys_section_unassigned;
                 }
             }
         }
@@ -430,16 +431,31 @@ static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
 
 static inline PhysPageDesc phys_page_find(target_phys_addr_t index)
 {
-    PhysPageDesc *p = phys_page_find_alloc(index, 0);
+    uint16_t *p = phys_page_find_alloc(index, 0);
+    uint16_t s_index = phys_section_unassigned;
+    MemoryRegionSection *section;
+    PhysPageDesc pd;
 
     if (p) {
-        return *p;
-    } else {
-        return (PhysPageDesc) {
-            .phys_offset = io_mem_unassigned.ram_addr,
-            .region_offset = index << TARGET_PAGE_BITS,
-        };
+        s_index = *p;
+    }
+    section = &phys_sections[s_index];
+    index <<= TARGET_PAGE_BITS;
+    assert(section->offset_within_address_space <= index
+           && index <= section->offset_within_address_space + section->size-1);
+    pd.phys_offset = section->mr->ram_addr;
+    pd.region_offset = (index - section->offset_within_address_space)
+        + section->offset_within_region;
+    if (memory_region_is_ram(section->mr)) {
+        pd.phys_offset += pd.region_offset;
+        pd.region_offset = 0;
+    } else if (section->mr->rom_device) {
+        pd.phys_offset += pd.region_offset;
     }
+    if (section->readonly) {
+        pd.phys_offset |= io_mem_rom.ram_addr;
+    }
+    return pd;
 }
 
 static void tlb_protect_code(ram_addr_t ram_addr);
@@ -2480,15 +2496,13 @@ static inline void tlb_set_dirty(CPUState *env,
 typedef struct subpage_t {
     MemoryRegion iomem;
     target_phys_addr_t base;
-    ram_addr_t sub_io_index[TARGET_PAGE_SIZE];
-    ram_addr_t region_offset[TARGET_PAGE_SIZE];
+    uint16_t sub_section[TARGET_PAGE_SIZE];
 } subpage_t;
 
 static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
-                             ram_addr_t memory, ram_addr_t region_offset);
-static subpage_t *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
-                                ram_addr_t orig_memory,
-                                ram_addr_t region_offset);
+                             uint16_t section);
+static subpage_t *subpage_init (target_phys_addr_t base, uint16_t *section,
+                                uint16_t orig_section);
 #define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
                       need_subpage)                                     \
     do {                                                                \
@@ -2509,10 +2523,10 @@ static subpage_t *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
         }                                                               \
     } while (0)
 
-static void destroy_page_desc(PhysPageDesc pd)
+static void destroy_page_desc(uint16_t section_index)
 {
-    unsigned io_index = pd.phys_offset & ~TARGET_PAGE_MASK;
-    MemoryRegion *mr = io_mem_region[io_index];
+    MemoryRegionSection *section = &phys_sections[section_index];
+    MemoryRegion *mr = section->mr;
 
     if (mr->subpage) {
         subpage_t *subpage = container_of(mr, subpage_t, iomem);
@@ -2546,6 +2560,22 @@ static void destroy_all_mappings(void)
     destroy_l2_mapping(&phys_map, P_L2_LEVELS - 1);
 }
 
+static uint16_t phys_section_add(MemoryRegionSection *section)
+{
+    if (phys_sections_nb == phys_sections_nb_alloc) {
+        phys_sections_nb_alloc = MAX(phys_sections_nb_alloc * 2, 16);
+        phys_sections = g_renew(MemoryRegionSection, phys_sections,
+                                phys_sections_nb_alloc);
+    }
+    phys_sections[phys_sections_nb] = *section;
+    return phys_sections_nb++;
+}
+
+static void phys_sections_clear(void)
+{
+    phys_sections_nb = 0;
+}
+
 /* register physical memory.
    For RAM, 'size' must be a multiple of the target page size.
    If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
@@ -2559,67 +2589,46 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section,
 {
     target_phys_addr_t start_addr = section->offset_within_address_space;
     ram_addr_t size = section->size;
-    ram_addr_t phys_offset = section->mr->ram_addr;
-    ram_addr_t region_offset = section->offset_within_region;
     target_phys_addr_t addr, end_addr;
-    PhysPageDesc *p;
+    uint16_t *p;
     CPUState *env;
     ram_addr_t orig_size = size;
     subpage_t *subpage;
-
-    if (memory_region_is_ram(section->mr)) {
-        phys_offset += region_offset;
-        region_offset = 0;
-    }
-
-    if (readonly) {
-        phys_offset |= io_mem_rom.ram_addr;
-    }
+    uint16_t section_index = phys_section_add(section);
 
     assert(size);
 
-    if (phys_offset == io_mem_unassigned.ram_addr) {
-        region_offset = start_addr;
-    }
-    region_offset &= TARGET_PAGE_MASK;
     size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
     end_addr = start_addr + (target_phys_addr_t)size;
 
     addr = start_addr;
     do {
         p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 0);
-        if (p && p->phys_offset != io_mem_unassigned.ram_addr) {
-            ram_addr_t orig_memory = p->phys_offset;
+        if (p && *p != phys_section_unassigned) {
+            uint16_t orig_memory= *p;
             target_phys_addr_t start_addr2, end_addr2;
             int need_subpage = 0;
-            MemoryRegion *mr = io_mem_region[orig_memory & ~TARGET_PAGE_MASK];
+            MemoryRegion *mr = phys_sections[orig_memory].mr;
 
             CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
                           need_subpage);
             if (need_subpage) {
                 if (!(mr->subpage)) {
                     subpage = subpage_init((addr & TARGET_PAGE_MASK),
-                                           &p->phys_offset, orig_memory,
-                                           p->region_offset);
+                                           p, orig_memory);
                 } else {
                     subpage = container_of(mr, subpage_t, iomem);
                 }
-                subpage_register(subpage, start_addr2, end_addr2, phys_offset,
-                                 region_offset);
-                p->region_offset = 0;
+                subpage_register(subpage, start_addr2, end_addr2,
+                                 section_index);
             } else {
-                p->phys_offset = phys_offset;
-                p->region_offset = region_offset;
-                if (is_ram_rom_romd(phys_offset))
-                    phys_offset += TARGET_PAGE_SIZE;
+                *p = section_index;
             }
         } else {
+            MemoryRegion *mr = section->mr;
             p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
-            p->phys_offset = phys_offset;
-            p->region_offset = region_offset;
-            if (is_ram_rom_romd(phys_offset)) {
-                phys_offset += TARGET_PAGE_SIZE;
-            } else {
+            *p = section_index;
+            if (!(memory_region_is_ram(mr) || mr->rom_device)) {
                 target_phys_addr_t start_addr2, end_addr2;
                 int need_subpage = 0;
 
@@ -2628,16 +2637,12 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section,
 
                 if (need_subpage) {
                     subpage = subpage_init((addr & TARGET_PAGE_MASK),
-                                           &p->phys_offset,
-                                           io_mem_unassigned.ram_addr,
-                                           addr & TARGET_PAGE_MASK);
+                                           p, phys_section_unassigned);
                     subpage_register(subpage, start_addr2, end_addr2,
-                                     phys_offset, region_offset);
-                    p->region_offset = 0;
+                                     section_index);
                 }
             }
         }
-        region_offset += TARGET_PAGE_SIZE;
         addr += TARGET_PAGE_SIZE;
     } while (addr != end_addr);
 
@@ -3333,14 +3338,17 @@ static uint64_t subpage_read(void *opaque, target_phys_addr_t addr,
 {
     subpage_t *mmio = opaque;
     unsigned int idx = SUBPAGE_IDX(addr);
+    MemoryRegionSection *section;
 #if defined(DEBUG_SUBPAGE)
     printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
            mmio, len, addr, idx);
 #endif
 
-    addr += mmio->region_offset[idx];
-    idx = mmio->sub_io_index[idx];
-    return io_mem_read(idx, addr, len);
+    section = &phys_sections[mmio->sub_section[idx]];
+    addr += mmio->base;
+    addr -= section->offset_within_address_space;
+    addr += section->offset_within_region;
+    return io_mem_read(section->mr->ram_addr, addr, len);
 }
 
 static void subpage_write(void *opaque, target_phys_addr_t addr,
@@ -3348,15 +3356,18 @@ static void subpage_write(void *opaque, target_phys_addr_t addr,
 {
     subpage_t *mmio = opaque;
     unsigned int idx = SUBPAGE_IDX(addr);
+    MemoryRegionSection *section;
 #if defined(DEBUG_SUBPAGE)
     printf("%s: subpage %p len %d addr " TARGET_FMT_plx
            " idx %d value %"PRIx64"\n",
            __func__, mmio, len, addr, idx, value);
 #endif
 
-    addr += mmio->region_offset[idx];
-    idx = mmio->sub_io_index[idx];
-    io_mem_write(idx, addr, value, len);
+    section = &phys_sections[mmio->sub_section[idx]];
+    addr += mmio->base;
+    addr -= section->offset_within_address_space;
+    addr += section->offset_within_region;
+    io_mem_write(section->mr->ram_addr, addr, value, len);
 }
 
 static const MemoryRegionOps subpage_ops = {
@@ -3398,7 +3409,7 @@ static const MemoryRegionOps subpage_ram_ops = {
 };
 
 static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
-                             ram_addr_t memory, ram_addr_t region_offset)
+                             uint16_t section)
 {
     int idx, eidx;
 
@@ -3410,24 +3421,26 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
     printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %ld\n", __func__,
            mmio, start, end, idx, eidx, memory);
 #endif
-    if ((memory & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr) {
-        memory = io_mem_subpage_ram.ram_addr;
+    if (memory_region_is_ram(phys_sections[section].mr)) {
+        MemoryRegionSection new_section = phys_sections[section];
+        new_section.mr = &io_mem_subpage_ram;
+        section = phys_section_add(&new_section);
     }
-    memory &= IO_MEM_NB_ENTRIES - 1;
     for (; idx <= eidx; idx++) {
-        mmio->sub_io_index[idx] = memory;
-        mmio->region_offset[idx] = region_offset;
+        mmio->sub_section[idx] = section;
     }
 
     return 0;
 }
 
-static subpage_t *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
-                                ram_addr_t orig_memory,
-                                ram_addr_t region_offset)
+static subpage_t *subpage_init (target_phys_addr_t base, uint16_t *section_ind,
+                                uint16_t orig_section)
 {
     subpage_t *mmio;
-    int subpage_memory;
+    MemoryRegionSection section = {
+        .offset_within_address_space = base,
+        .size = TARGET_PAGE_SIZE,
+    };
 
     mmio = g_malloc0(sizeof(subpage_t));
 
@@ -3435,13 +3448,13 @@ static subpage_t *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
     memory_region_init_io(&mmio->iomem, &subpage_ops, mmio,
                           "subpage", TARGET_PAGE_SIZE);
     mmio->iomem.subpage = true;
-    subpage_memory = mmio->iomem.ram_addr;
+    section.mr = &mmio->iomem;
 #if defined(DEBUG_SUBPAGE)
     printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
            mmio, base, TARGET_PAGE_SIZE, subpage_memory);
 #endif
-    *phys = subpage_memory;
-    subpage_register(mmio, 0, TARGET_PAGE_SIZE-1, orig_memory, region_offset);
+    *section_ind = phys_section_add(&section);
+    subpage_register(mmio, 0, TARGET_PAGE_SIZE-1, orig_section);
 
     return mmio;
 }
@@ -3493,6 +3506,18 @@ void cpu_unregister_io_memory(int io_index)
     io_mem_used[io_index] = 0;
 }
 
+static uint16_t dummy_section(MemoryRegion *mr)
+{
+    MemoryRegionSection section = {
+        .mr = mr,
+        .offset_within_address_space = 0,
+        .offset_within_region = 0,
+        .size = UINT64_MAX,
+    };
+
+    return phys_section_add(&section);
+}
+
 static void io_mem_init(void)
 {
     int i;
@@ -3517,6 +3542,8 @@ static void io_mem_init(void)
 static void core_begin(MemoryListener *listener)
 {
     destroy_all_mappings();
+    phys_sections_clear();
+    phys_section_unassigned = dummy_section(&io_mem_unassigned);
 }
 
 static void core_commit(MemoryListener *listener)
commit 4346ae3e28fc19e01b3070de169ea9fcef5f54aa
Author: Avi Kivity <avi at redhat.com>
Date:   Fri Feb 10 17:00:01 2012 +0200

    memory: unify phys_map last level with intermediate levels
    
    This lays the groundwork for storing leaf data in intermediate levels,
    saving space.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index c541ee7..536e70f 100644
--- a/exec.c
+++ b/exec.c
@@ -192,9 +192,18 @@ typedef struct PhysPageDesc {
     ram_addr_t region_offset;
 } PhysPageDesc;
 
+typedef struct PhysPageEntry PhysPageEntry;
+
+struct PhysPageEntry {
+    union {
+        PhysPageDesc leaf;
+        PhysPageEntry *node;
+    } u;
+};
+
 /* This is a multi-level map on the physical address space.
    The bottom level has pointers to PhysPageDesc.  */
-static void *phys_map;
+static PhysPageEntry phys_map;
 
 static void io_mem_init(void);
 static void memory_map_init(void);
@@ -392,42 +401,31 @@ static inline PageDesc *page_find(tb_page_addr_t index)
 #if !defined(CONFIG_USER_ONLY)
 static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
 {
-    PhysPageDesc *pd;
-    void **lp;
-    int i;
+    PhysPageEntry *lp, *p;
+    int i, j;
 
     lp = &phys_map;
 
-    /* Level 1..N-1.  */
-    for (i = P_L2_LEVELS - 1; i > 0; i--) {
-        void **p = *lp;
-        if (p == NULL) {
+    /* Level 1..N.  */
+    for (i = P_L2_LEVELS - 1; i >= 0; i--) {
+        if (lp->u.node == NULL) {
             if (!alloc) {
                 return NULL;
             }
-            *lp = p = g_malloc0(sizeof(void *) * L2_SIZE);
-        }
-        lp = p + ((index >> (i * L2_BITS)) & (L2_SIZE - 1));
-    }
-
-    pd = *lp;
-    if (pd == NULL) {
-        int i;
-        int first_index = index & ~(L2_SIZE - 1);
-
-        if (!alloc) {
-            return NULL;
-        }
-
-        *lp = pd = g_malloc(sizeof(PhysPageDesc) * L2_SIZE);
-
-        for (i = 0; i < L2_SIZE; i++) {
-            pd[i].phys_offset = io_mem_unassigned.ram_addr;
-            pd[i].region_offset = (first_index + i) << TARGET_PAGE_BITS;
+            lp->u.node = p = g_malloc0(sizeof(PhysPageEntry) * L2_SIZE);
+            if (i == 0) {
+                int first_index = index & ~(L2_SIZE - 1);
+                for (j = 0; j < L2_SIZE; j++) {
+                    p[j].u.leaf.phys_offset = io_mem_unassigned.ram_addr;
+                    p[j].u.leaf.region_offset
+                        = (first_index + j) << TARGET_PAGE_BITS;
+                }
+            }
         }
+        lp = &lp->u.node[(index >> (i * L2_BITS)) & (L2_SIZE - 1)];
     }
 
-    return pd + (index & (L2_SIZE - 1));
+    return &lp->u.leaf;
 }
 
 static inline PhysPageDesc phys_page_find(target_phys_addr_t index)
@@ -2523,30 +2521,24 @@ static void destroy_page_desc(PhysPageDesc pd)
     }
 }
 
-static void destroy_l2_mapping(void **lp, unsigned level)
+static void destroy_l2_mapping(PhysPageEntry *lp, unsigned level)
 {
     unsigned i;
-    void **p;
-    PhysPageDesc *pd;
+    PhysPageEntry *p = lp->u.node;
 
-    if (!*lp) {
+    if (!p) {
         return;
     }
 
-    if (level > 0) {
-        p = *lp;
-        for (i = 0; i < L2_SIZE; ++i) {
+    for (i = 0; i < L2_SIZE; ++i) {
+        if (level > 0) {
             destroy_l2_mapping(&p[i], level - 1);
+        } else {
+            destroy_page_desc(p[i].u.leaf);
         }
-        g_free(p);
-    } else {
-        pd = *lp;
-        for (i = 0; i < L2_SIZE; ++i) {
-            destroy_page_desc(pd[i]);
-        }
-        g_free(pd);
     }
-    *lp = NULL;
+    g_free(p);
+    lp->u.node = NULL;
 }
 
 static void destroy_all_mappings(void)
commit 3eef53df6b0240547bd5a80261091266c6ab1e3c
Author: Avi Kivity <avi at redhat.com>
Date:   Fri Feb 10 14:57:31 2012 +0200

    memory: remove first level of l1_phys_map
    
    L1 and the lower levels in l1_phys_map are equivalent, except that L1 has
    a different size, and is always allocated.  Simplify the code by removing
    L1.  This leaves us with a tree composed solely of L2 tables, but that
    problem can be renamed away later.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index b36c301..c541ee7 100644
--- a/exec.c
+++ b/exec.c
@@ -160,29 +160,21 @@ typedef struct PageDesc {
 #define L2_BITS 10
 #define L2_SIZE (1 << L2_BITS)
 
+#define P_L2_LEVELS \
+    (((TARGET_PHYS_ADDR_SPACE_BITS - TARGET_PAGE_BITS - 1) / L2_BITS) + 1)
+
 /* The bits remaining after N lower levels of page tables.  */
-#define P_L1_BITS_REM \
-    ((TARGET_PHYS_ADDR_SPACE_BITS - TARGET_PAGE_BITS) % L2_BITS)
 #define V_L1_BITS_REM \
     ((L1_MAP_ADDR_SPACE_BITS - TARGET_PAGE_BITS) % L2_BITS)
 
-/* Size of the L1 page table.  Avoid silly small sizes.  */
-#if P_L1_BITS_REM < 4
-#define P_L1_BITS  (P_L1_BITS_REM + L2_BITS)
-#else
-#define P_L1_BITS  P_L1_BITS_REM
-#endif
-
 #if V_L1_BITS_REM < 4
 #define V_L1_BITS  (V_L1_BITS_REM + L2_BITS)
 #else
 #define V_L1_BITS  V_L1_BITS_REM
 #endif
 
-#define P_L1_SIZE  ((target_phys_addr_t)1 << P_L1_BITS)
 #define V_L1_SIZE  ((target_ulong)1 << V_L1_BITS)
 
-#define P_L1_SHIFT (TARGET_PHYS_ADDR_SPACE_BITS - TARGET_PAGE_BITS - P_L1_BITS)
 #define V_L1_SHIFT (L1_MAP_ADDR_SPACE_BITS - TARGET_PAGE_BITS - V_L1_BITS)
 
 unsigned long qemu_real_host_page_size;
@@ -202,7 +194,7 @@ typedef struct PhysPageDesc {
 
 /* This is a multi-level map on the physical address space.
    The bottom level has pointers to PhysPageDesc.  */
-static void *l1_phys_map[P_L1_SIZE];
+static void *phys_map;
 
 static void io_mem_init(void);
 static void memory_map_init(void);
@@ -404,11 +396,10 @@ static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
     void **lp;
     int i;
 
-    /* Level 1.  Always allocated.  */
-    lp = l1_phys_map + ((index >> P_L1_SHIFT) & (P_L1_SIZE - 1));
+    lp = &phys_map;
 
-    /* Level 2..N-1.  */
-    for (i = P_L1_SHIFT / L2_BITS - 1; i > 0; i--) {
+    /* Level 1..N-1.  */
+    for (i = P_L2_LEVELS - 1; i > 0; i--) {
         void **p = *lp;
         if (p == NULL) {
             if (!alloc) {
@@ -2560,11 +2551,7 @@ static void destroy_l2_mapping(void **lp, unsigned level)
 
 static void destroy_all_mappings(void)
 {
-    unsigned i;
-
-    for (i = 0; i < P_L1_SIZE; ++i) {
-        destroy_l2_mapping(&l1_phys_map[i], P_L1_SHIFT / L2_BITS - 1);
-    }
+    destroy_l2_mapping(&phys_map, P_L2_LEVELS - 1);
 }
 
 /* register physical memory.
commit 54688b1ec1f468c7272b837ff57298068aaedf5f
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Feb 9 17:34:32 2012 +0200

    memory: change memory registration to rebuild the memory map on each change
    
    Instead of incrementally building the memory map, rebuild it every time.
    This allows later simplification, since the code need not consider overlaying
    a previous mapping.  It is also RCU friendly.
    
    With large memory guests this can get expensive, since the operation is
    O(mem size), but this will be optimized later.
    
    As a side effect subpage and L2 leaks are fixed here.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index 6726afd..b36c301 100644
--- a/exec.c
+++ b/exec.c
@@ -2520,6 +2520,53 @@ static subpage_t *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
         }                                                               \
     } while (0)
 
+static void destroy_page_desc(PhysPageDesc pd)
+{
+    unsigned io_index = pd.phys_offset & ~TARGET_PAGE_MASK;
+    MemoryRegion *mr = io_mem_region[io_index];
+
+    if (mr->subpage) {
+        subpage_t *subpage = container_of(mr, subpage_t, iomem);
+        memory_region_destroy(&subpage->iomem);
+        g_free(subpage);
+    }
+}
+
+static void destroy_l2_mapping(void **lp, unsigned level)
+{
+    unsigned i;
+    void **p;
+    PhysPageDesc *pd;
+
+    if (!*lp) {
+        return;
+    }
+
+    if (level > 0) {
+        p = *lp;
+        for (i = 0; i < L2_SIZE; ++i) {
+            destroy_l2_mapping(&p[i], level - 1);
+        }
+        g_free(p);
+    } else {
+        pd = *lp;
+        for (i = 0; i < L2_SIZE; ++i) {
+            destroy_page_desc(pd[i]);
+        }
+        g_free(pd);
+    }
+    *lp = NULL;
+}
+
+static void destroy_all_mappings(void)
+{
+    unsigned i;
+
+    for (i = 0; i < P_L1_SIZE; ++i) {
+        destroy_l2_mapping(&l1_phys_map[i], P_L1_SHIFT / L2_BITS - 1);
+    }
+}
+
 /* register physical memory.
    For RAM, 'size' must be a multiple of the target page size.
    If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
@@ -3490,6 +3537,7 @@ static void io_mem_init(void)
 
 static void core_begin(MemoryListener *listener)
 {
+    destroy_all_mappings();
 }
 
 static void core_commit(MemoryListener *listener)
@@ -3505,12 +3553,12 @@ static void core_region_add(MemoryListener *listener,
 static void core_region_del(MemoryListener *listener,
                             MemoryRegionSection *section)
 {
-    cpu_register_physical_memory_log(section, false);
 }
 
 static void core_region_nop(MemoryListener *listener,
                             MemoryRegionSection *section)
 {
+    cpu_register_physical_memory_log(section, section->readonly);
 }
 
 static void core_log_start(MemoryListener *listener,
commit 50c1e1491e1981ecba14a477897681d8d0602500
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Feb 8 21:36:02 2012 +0200

    memory: support stateless memory listeners
    
    Current memory listeners are incremental; that is, they are expected to
    maintain their own state, and receive callbacks for changes to that state.
    
    This patch adds support for stateless listeners; these work by receiving
    a ->begin() callback (which tells them that new state is coming), a
    sequence of ->region_add() and ->region_nop() callbacks, and then a
    ->commit() callback which signifies the end of the new state.  They should
    ignore ->region_del() callbacks.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index 16973a6..6726afd 100644
--- a/exec.c
+++ b/exec.c
@@ -3488,6 +3488,14 @@ static void io_mem_init(void)
                           "watch", UINT64_MAX);
 }
 
+static void core_begin(MemoryListener *listener)
+{
+}
+
+static void core_commit(MemoryListener *listener)
+{
+}
+
 static void core_region_add(MemoryListener *listener,
                             MemoryRegionSection *section)
 {
@@ -3500,6 +3508,11 @@ static void core_region_del(MemoryListener *listener,
     cpu_register_physical_memory_log(section, false);
 }
 
+static void core_region_nop(MemoryListener *listener,
+                            MemoryRegionSection *section)
+{
+}
+
 static void core_log_start(MemoryListener *listener,
                            MemoryRegionSection *section)
 {
@@ -3537,6 +3550,14 @@ static void core_eventfd_del(MemoryListener *listener,
 {
 }
 
+static void io_begin(MemoryListener *listener)
+{
+}
+
+static void io_commit(MemoryListener *listener)
+{
+}
+
 static void io_region_add(MemoryListener *listener,
                           MemoryRegionSection *section)
 {
@@ -3551,6 +3572,11 @@ static void io_region_del(MemoryListener *listener,
     isa_unassign_ioport(section->offset_within_address_space, section->size);
 }
 
+static void io_region_nop(MemoryListener *listener,
+                          MemoryRegionSection *section)
+{
+}
+
 static void io_log_start(MemoryListener *listener,
                          MemoryRegionSection *section)
 {
@@ -3587,8 +3613,11 @@ static void io_eventfd_del(MemoryListener *listener,
 }
 
 static MemoryListener core_memory_listener = {
+    .begin = core_begin,
+    .commit = core_commit,
     .region_add = core_region_add,
     .region_del = core_region_del,
+    .region_nop = core_region_nop,
     .log_start = core_log_start,
     .log_stop = core_log_stop,
     .log_sync = core_log_sync,
@@ -3600,8 +3629,11 @@ static MemoryListener core_memory_listener = {
 };
 
 static MemoryListener io_memory_listener = {
+    .begin = io_begin,
+    .commit = io_commit,
     .region_add = io_region_add,
     .region_del = io_region_del,
+    .region_nop = io_region_nop,
     .log_start = io_log_start,
     .log_stop = io_log_stop,
     .log_sync = io_log_sync,
diff --git a/hw/vhost.c b/hw/vhost.c
index 01f676a..8d3ba5b 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -436,6 +436,14 @@ static bool vhost_section(MemoryRegionSection *section)
         && memory_region_is_ram(section->mr);
 }
 
+static void vhost_begin(MemoryListener *listener)
+{
+}
+
+static void vhost_commit(MemoryListener *listener)
+{
+}
+
 static void vhost_region_add(MemoryListener *listener,
                              MemoryRegionSection *section)
 {
@@ -476,6 +484,11 @@ static void vhost_region_del(MemoryListener *listener,
     }
 }
 
+static void vhost_region_nop(MemoryListener *listener,
+                             MemoryRegionSection *section)
+{
+}
+
 static int vhost_virtqueue_set_addr(struct vhost_dev *dev,
                                     struct vhost_virtqueue *vq,
                                     unsigned idx, bool enable_log)
@@ -756,8 +769,11 @@ int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force)
     hdev->features = features;
 
     hdev->memory_listener = (MemoryListener) {
+        .begin = vhost_begin,
+        .commit = vhost_commit,
         .region_add = vhost_region_add,
         .region_del = vhost_region_del,
+        .region_nop = vhost_region_nop,
         .log_start = vhost_log_start,
         .log_stop = vhost_log_stop,
         .log_sync = vhost_log_sync,
diff --git a/kvm-all.c b/kvm-all.c
index 15bc42f..c07823d 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -680,6 +680,14 @@ static void kvm_set_phys_mem(MemoryRegionSection *section, bool add)
     }
 }
 
+static void kvm_begin(MemoryListener *listener)
+{
+}
+
+static void kvm_commit(MemoryListener *listener)
+{
+}
+
 static void kvm_region_add(MemoryListener *listener,
                            MemoryRegionSection *section)
 {
@@ -692,6 +700,11 @@ static void kvm_region_del(MemoryListener *listener,
     kvm_set_phys_mem(section, false);
 }
 
+static void kvm_region_nop(MemoryListener *listener,
+                           MemoryRegionSection *section)
+{
+}
+
 static void kvm_log_sync(MemoryListener *listener,
                          MemoryRegionSection *section)
 {
@@ -795,8 +808,11 @@ static void kvm_eventfd_del(MemoryListener *listener,
 }
 
 static MemoryListener kvm_memory_listener = {
+    .begin = kvm_begin,
+    .commit = kvm_commit,
     .region_add = kvm_region_add,
     .region_del = kvm_region_del,
+    .region_nop = kvm_region_nop,
     .log_start = kvm_log_start,
     .log_stop = kvm_log_stop,
     .log_sync = kvm_log_sync,
diff --git a/memory.c b/memory.c
index 35e1483..6565e2e 100644
--- a/memory.c
+++ b/memory.c
@@ -676,6 +676,7 @@ static void address_space_update_topology_pass(AddressSpace *as,
             /* In both (logging may have changed) */
 
             if (adding) {
+                MEMORY_LISTENER_UPDATE_REGION(frnew, as, Forward, region_nop);
                 if (frold->dirty_log_mask && !frnew->dirty_log_mask) {
                     MEMORY_LISTENER_UPDATE_REGION(frnew, as, Reverse, log_stop);
                 } else if (frnew->dirty_log_mask && !frold->dirty_log_mask) {
@@ -722,6 +723,8 @@ static void memory_region_update_topology(MemoryRegion *mr)
         return;
     }
 
+    MEMORY_LISTENER_CALL_GLOBAL(begin, Forward);
+
     if (address_space_memory.root) {
         address_space_update_topology(&address_space_memory);
     }
@@ -729,6 +732,8 @@ static void memory_region_update_topology(MemoryRegion *mr)
         address_space_update_topology(&address_space_io);
     }
 
+    MEMORY_LISTENER_CALL_GLOBAL(commit, Forward);
+
     memory_region_update_pending = false;
 }
 
diff --git a/memory.h b/memory.h
index bc9600b..b7bccd1 100644
--- a/memory.h
+++ b/memory.h
@@ -180,8 +180,11 @@ typedef struct MemoryListener MemoryListener;
  * Use with memory_listener_register() and memory_listener_unregister().
  */
 struct MemoryListener {
+    void (*begin)(MemoryListener *listener);
+    void (*commit)(MemoryListener *listener);
     void (*region_add)(MemoryListener *listener, MemoryRegionSection *section);
     void (*region_del)(MemoryListener *listener, MemoryRegionSection *section);
+    void (*region_nop)(MemoryListener *listener, MemoryRegionSection *section);
     void (*log_start)(MemoryListener *listener, MemoryRegionSection *section);
     void (*log_stop)(MemoryListener *listener, MemoryRegionSection *section);
     void (*log_sync)(MemoryListener *listener, MemoryRegionSection *section);
diff --git a/xen-all.c b/xen-all.c
index a58a397..6a11342 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -394,6 +394,14 @@ static void xen_set_memory(struct MemoryListener *listener,
     }
 }
 
+static void xen_begin(MemoryListener *listener)
+{
+}
+
+static void xen_commit(MemoryListener *listener)
+{
+}
+
 static void xen_region_add(MemoryListener *listener,
                            MemoryRegionSection *section)
 {
@@ -406,6 +414,11 @@ static void xen_region_del(MemoryListener *listener,
     xen_set_memory(listener, section, false);
 }
 
+static void xen_region_nop(MemoryListener *listener,
+                           MemoryRegionSection *section)
+{
+}
+
 static void xen_sync_dirty_bitmap(XenIOState *state,
                                   target_phys_addr_t start_addr,
                                   ram_addr_t size)
@@ -500,8 +513,11 @@ static void xen_eventfd_del(MemoryListener *listener,
 }
 
 static MemoryListener xen_memory_listener = {
+    .begin = xen_begin,
+    .commit = xen_commit,
     .region_add = xen_region_add,
     .region_del = xen_region_del,
+    .region_nop = xen_region_nop,
     .log_start = xen_log_start,
     .log_stop = xen_log_stop,
     .log_sync = xen_log_sync,
commit 4855d41a61301a04e54c074f1139040e4cb4dd00
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Feb 8 21:16:05 2012 +0200

    memory: split memory listener for the two address spaces
    
    The memory and I/O address spaces do different things, so split them into
    two memory listeners.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index aa54eb1..16973a6 100644
--- a/exec.c
+++ b/exec.c
@@ -3491,24 +3491,13 @@ static void io_mem_init(void)
 static void core_region_add(MemoryListener *listener,
                             MemoryRegionSection *section)
 {
-    if (section->address_space == get_system_memory()) {
-        cpu_register_physical_memory_log(section, section->readonly);
-    } else {
-        iorange_init(&section->mr->iorange, &memory_region_iorange_ops,
-                     section->offset_within_address_space, section->size);
-        ioport_register(&section->mr->iorange);
-    }
+    cpu_register_physical_memory_log(section, section->readonly);
 }
 
 static void core_region_del(MemoryListener *listener,
                             MemoryRegionSection *section)
 {
-    if (section->address_space == get_system_memory()) {
-        cpu_register_physical_memory_log(section, false);
-    } else {
-        isa_unassign_ioport(section->offset_within_address_space,
-                            section->size);
-    }
+    cpu_register_physical_memory_log(section, false);
 }
 
 static void core_log_start(MemoryListener *listener,
@@ -3548,6 +3537,55 @@ static void core_eventfd_del(MemoryListener *listener,
 {
 }
 
+static void io_region_add(MemoryListener *listener,
+                          MemoryRegionSection *section)
+{
+    iorange_init(&section->mr->iorange, &memory_region_iorange_ops,
+                 section->offset_within_address_space, section->size);
+    ioport_register(&section->mr->iorange);
+}
+
+static void io_region_del(MemoryListener *listener,
+                          MemoryRegionSection *section)
+{
+    isa_unassign_ioport(section->offset_within_address_space, section->size);
+}
+
+static void io_log_start(MemoryListener *listener,
+                         MemoryRegionSection *section)
+{
+}
+
+static void io_log_stop(MemoryListener *listener,
+                        MemoryRegionSection *section)
+{
+}
+
+static void io_log_sync(MemoryListener *listener,
+                        MemoryRegionSection *section)
+{
+}
+
+static void io_log_global_start(MemoryListener *listener)
+{
+}
+
+static void io_log_global_stop(MemoryListener *listener)
+{
+}
+
+static void io_eventfd_add(MemoryListener *listener,
+                           MemoryRegionSection *section,
+                           bool match_data, uint64_t data, int fd)
+{
+}
+
+static void io_eventfd_del(MemoryListener *listener,
+                           MemoryRegionSection *section,
+                           bool match_data, uint64_t data, int fd)
+{
+}
+
 static MemoryListener core_memory_listener = {
     .region_add = core_region_add,
     .region_del = core_region_del,
@@ -3561,6 +3599,19 @@ static MemoryListener core_memory_listener = {
     .priority = 0,
 };
 
+static MemoryListener io_memory_listener = {
+    .region_add = io_region_add,
+    .region_del = io_region_del,
+    .log_start = io_log_start,
+    .log_stop = io_log_stop,
+    .log_sync = io_log_sync,
+    .log_global_start = io_log_global_start,
+    .log_global_stop = io_log_global_stop,
+    .eventfd_add = io_eventfd_add,
+    .eventfd_del = io_eventfd_del,
+    .priority = 0,
+};
+
 static void memory_map_init(void)
 {
     system_memory = g_malloc(sizeof(*system_memory));
@@ -3571,7 +3622,8 @@ static void memory_map_init(void)
     memory_region_init(system_io, "io", 65536);
     set_system_io_map(system_io);
 
-    memory_listener_register(&core_memory_listener, NULL);
+    memory_listener_register(&core_memory_listener, system_memory);
+    memory_listener_register(&io_memory_listener, system_io);
 }
 
 MemoryRegion *get_system_memory(void)
commit 947f562c989d034c6a82920e11f4641f1681583d
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Feb 8 21:10:42 2012 +0200

    xen: ignore I/O memory regions
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/xen-all.c b/xen-all.c
index dd52f02..a58a397 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -989,7 +989,7 @@ int xen_hvm_init(void)
 
     state->memory_listener = xen_memory_listener;
     QLIST_INIT(&state->physmap);
-    memory_listener_register(&state->memory_listener, NULL);
+    memory_listener_register(&state->memory_listener, get_system_memory());
     state->log_for_dirtybit = NULL;
 
     /* Initialize backend core & drivers */
commit 7376e5827a898d8ddf10f929047cc84bf65d9f52
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Feb 8 21:05:17 2012 +0200

    memory: allow MemoryListeners to observe a specific address space
    
    Ignore any regions not belonging to a specified address space.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index 7fb5d4e..aa54eb1 100644
--- a/exec.c
+++ b/exec.c
@@ -3571,7 +3571,7 @@ static void memory_map_init(void)
     memory_region_init(system_io, "io", 65536);
     set_system_io_map(system_io);
 
-    memory_listener_register(&core_memory_listener);
+    memory_listener_register(&core_memory_listener, NULL);
 }
 
 MemoryRegion *get_system_memory(void)
diff --git a/hw/vhost.c b/hw/vhost.c
index e1e7e01..01f676a 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -774,7 +774,7 @@ int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force)
     hdev->log_size = 0;
     hdev->log_enabled = false;
     hdev->started = false;
-    memory_listener_register(&hdev->memory_listener);
+    memory_listener_register(&hdev->memory_listener, NULL);
     hdev->force = force;
     return 0;
 fail:
diff --git a/kvm-all.c b/kvm-all.c
index a05e591..15bc42f 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1049,7 +1049,7 @@ int kvm_init(void)
     }
 
     kvm_state = s;
-    memory_listener_register(&kvm_memory_listener);
+    memory_listener_register(&kvm_memory_listener, NULL);
 
     s->many_ioeventfds = kvm_check_many_ioeventfds();
 
diff --git a/memory.c b/memory.c
index 12ba60f..35e1483 100644
--- a/memory.c
+++ b/memory.c
@@ -84,7 +84,14 @@ static AddrRange addrrange_intersection(AddrRange r1, AddrRange r2)
 
 enum ListenerDirection { Forward, Reverse };
 
-#define MEMORY_LISTENER_CALL(_callback, _direction, _args...)           \
+static bool memory_listener_match(MemoryListener *listener,
+                                  MemoryRegionSection *section)
+{
+    return !listener->address_space_filter
+        || listener->address_space_filter == section->address_space;
+}
+
+#define MEMORY_LISTENER_CALL_GLOBAL(_callback, _direction, _args...)    \
     do {                                                                \
         MemoryListener *_listener;                                      \
                                                                         \
@@ -105,15 +112,40 @@ enum ListenerDirection { Forward, Reverse };
         }                                                               \
     } while (0)
 
+#define MEMORY_LISTENER_CALL(_callback, _direction, _section, _args...) \
+    do {                                                                \
+        MemoryListener *_listener;                                      \
+                                                                        \
+        switch (_direction) {                                           \
+        case Forward:                                                   \
+            QTAILQ_FOREACH(_listener, &memory_listeners, link) {        \
+                if (memory_listener_match(_listener, _section)) {       \
+                    _listener->_callback(_listener, _section, ##_args); \
+                }                                                       \
+            }                                                           \
+            break;                                                      \
+        case Reverse:                                                   \
+            QTAILQ_FOREACH_REVERSE(_listener, &memory_listeners,        \
+                                   memory_listeners, link) {            \
+                if (memory_listener_match(_listener, _section)) {       \
+                    _listener->_callback(_listener, _section, ##_args); \
+                }                                                       \
+            }                                                           \
+            break;                                                      \
+        default:                                                        \
+            abort();                                                    \
+        }                                                               \
+    } while (0)
+
 #define MEMORY_LISTENER_UPDATE_REGION(fr, as, dir, callback)            \
-    MEMORY_LISTENER_CALL(callback, dir, &(MemoryRegionSection) {        \
+    MEMORY_LISTENER_CALL(callback, dir, (&(MemoryRegionSection) {       \
         .mr = (fr)->mr,                                                 \
         .address_space = (as)->root,                                    \
         .offset_within_region = (fr)->offset_in_region,                 \
         .size = int128_get64((fr)->addr.size),                          \
         .offset_within_address_space = int128_get64((fr)->addr.start),  \
         .readonly = (fr)->readonly,                                     \
-                })
+              }))
 
 struct CoalescedMemoryRange {
     AddrRange addr;
@@ -1382,13 +1414,13 @@ void memory_global_sync_dirty_bitmap(MemoryRegion *address_space)
 void memory_global_dirty_log_start(void)
 {
     global_dirty_log = true;
-    MEMORY_LISTENER_CALL(log_global_start, Forward);
+    MEMORY_LISTENER_CALL_GLOBAL(log_global_start, Forward);
 }
 
 void memory_global_dirty_log_stop(void)
 {
     global_dirty_log = false;
-    MEMORY_LISTENER_CALL(log_global_stop, Reverse);
+    MEMORY_LISTENER_CALL_GLOBAL(log_global_stop, Reverse);
 }
 
 static void listener_add_address_space(MemoryListener *listener,
@@ -1412,10 +1444,11 @@ static void listener_add_address_space(MemoryListener *listener,
     }
 }
 
-void memory_listener_register(MemoryListener *listener)
+void memory_listener_register(MemoryListener *listener, MemoryRegion *filter)
 {
     MemoryListener *other = NULL;
 
+    listener->address_space_filter = filter;
     if (QTAILQ_EMPTY(&memory_listeners)
         || listener->priority >= QTAILQ_LAST(&memory_listeners,
                                              memory_listeners)->priority) {
diff --git a/memory.h b/memory.h
index 1d99cee..bc9600b 100644
--- a/memory.h
+++ b/memory.h
@@ -193,6 +193,7 @@ struct MemoryListener {
                         bool match_data, uint64_t data, int fd);
     /* Lower = earlier (during add), later (during del) */
     unsigned priority;
+    MemoryRegion *address_space_filter;
     QTAILQ_ENTRY(MemoryListener) link;
 };
 
@@ -685,8 +686,9 @@ void memory_region_transaction_commit(void);
  *                           space
  *
  * @listener: an object containing the callbacks to be called
+ * @filter: if non-%NULL, only regions in this address space will be observed
  */
-void memory_listener_register(MemoryListener *listener);
+void memory_listener_register(MemoryListener *listener, MemoryRegion *filter);
 
 /**
  * memory_listener_unregister: undo the effect of memory_listener_register()
diff --git a/xen-all.c b/xen-all.c
index e005b63..dd52f02 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -989,7 +989,7 @@ int xen_hvm_init(void)
 
     state->memory_listener = xen_memory_listener;
     QLIST_INIT(&state->physmap);
-    memory_listener_register(&state->memory_listener);
+    memory_listener_register(&state->memory_listener, NULL);
     state->log_for_dirtybit = NULL;
 
     /* Initialize backend core & drivers */
commit 8df8a8436fa22442a58b366fbb7e471b4a8d88ce
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Feb 8 17:19:46 2012 +0200

    memory: drop AddressSpaceOps
    
    All functionality has been moved to various MemoryListeners.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/memory.c b/memory.c
index d5591f8..12ba60f 100644
--- a/memory.c
+++ b/memory.c
@@ -191,20 +191,12 @@ typedef struct AddressSpaceOps AddressSpaceOps;
 
 /* A system address space - I/O, memory, etc. */
 struct AddressSpace {
-    const AddressSpaceOps *ops;
     MemoryRegion *root;
     FlatView current_map;
     int ioeventfd_nb;
     MemoryRegionIoeventfd *ioeventfds;
 };
 
-struct AddressSpaceOps {
-    void (*range_add)(AddressSpace *as, FlatRange *fr);
-    void (*range_del)(AddressSpace *as, FlatRange *fr);
-    void (*log_start)(AddressSpace *as, FlatRange *fr);
-    void (*log_stop)(AddressSpace *as, FlatRange *fr);
-};
-
 #define FOR_EACH_FLAT_RANGE(var, view)          \
     for (var = (view)->ranges; var < (view)->ranges + (view)->nr; ++var)
 
@@ -336,32 +328,7 @@ static void access_with_adjusted_size(target_phys_addr_t addr,
     }
 }
 
-static void as_memory_range_add(AddressSpace *as, FlatRange *fr)
-{
-}
-
-static void as_memory_range_del(AddressSpace *as, FlatRange *fr)
-{
-}
-
-static void as_memory_log_start(AddressSpace *as, FlatRange *fr)
-{
-}
-
-static void as_memory_log_stop(AddressSpace *as, FlatRange *fr)
-{
-}
-
-static const AddressSpaceOps address_space_ops_memory = {
-    .range_add = as_memory_range_add,
-    .range_del = as_memory_range_del,
-    .log_start = as_memory_log_start,
-    .log_stop = as_memory_log_stop,
-};
-
-static AddressSpace address_space_memory = {
-    .ops = &address_space_ops_memory,
-};
+static AddressSpace address_space_memory;
 
 static const MemoryRegionPortio *find_portio(MemoryRegion *mr, uint64_t offset,
                                              unsigned width, bool write)
@@ -437,22 +404,7 @@ const IORangeOps memory_region_iorange_ops = {
     .write = memory_region_iorange_write,
 };
 
-static void as_io_range_add(AddressSpace *as, FlatRange *fr)
-{
-}
-
-static void as_io_range_del(AddressSpace *as, FlatRange *fr)
-{
-}
-
-static const AddressSpaceOps address_space_ops_io = {
-    .range_add = as_io_range_add,
-    .range_del = as_io_range_del,
-};
-
-static AddressSpace address_space_io = {
-    .ops = &address_space_ops_io,
-};
+static AddressSpace address_space_io;
 
 static AddressSpace *memory_region_to_address_space(MemoryRegion *mr)
 {
@@ -685,7 +637,6 @@ static void address_space_update_topology_pass(AddressSpace *as,
 
             if (!adding) {
                 MEMORY_LISTENER_UPDATE_REGION(frold, as, Reverse, region_del);
-                as->ops->range_del(as, frold);
             }
 
             ++iold;
@@ -695,9 +646,7 @@ static void address_space_update_topology_pass(AddressSpace *as,
             if (adding) {
                 if (frold->dirty_log_mask && !frnew->dirty_log_mask) {
                     MEMORY_LISTENER_UPDATE_REGION(frnew, as, Reverse, log_stop);
-                    as->ops->log_stop(as, frnew);
                 } else if (frnew->dirty_log_mask && !frold->dirty_log_mask) {
-                    as->ops->log_start(as, frnew);
                     MEMORY_LISTENER_UPDATE_REGION(frnew, as, Forward, log_start);
                 }
             }
@@ -708,7 +657,6 @@ static void address_space_update_topology_pass(AddressSpace *as,
             /* In new */
 
             if (adding) {
-                as->ops->range_add(as, frnew);
                 MEMORY_LISTENER_UPDATE_REGION(frnew, as, Forward, region_add);
             }
 
commit 9363274709af23c499b6db3eb402b6f9aa46c40b
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Feb 8 16:54:16 2012 +0200

    memory: use a MemoryListener for core memory map updates too
    
    This transforms memory.c into a library which can then be unit tested
    easily, by feeding it inputs and listening to its outputs.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/exec-obsolete.h b/exec-obsolete.h
index 23ffbaa..4dbe476 100644
--- a/exec-obsolete.h
+++ b/exec-obsolete.h
@@ -121,6 +121,9 @@ static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start,
 
 void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
                                      int dirty_flags);
+
+extern const IORangeOps memory_region_iorange_ops;
+
 #endif
 
 #endif
diff --git a/exec.c b/exec.c
index d3020ab..7fb5d4e 100644
--- a/exec.c
+++ b/exec.c
@@ -3488,6 +3488,79 @@ static void io_mem_init(void)
                           "watch", UINT64_MAX);
 }
 
+static void core_region_add(MemoryListener *listener,
+                            MemoryRegionSection *section)
+{
+    if (section->address_space == get_system_memory()) {
+        cpu_register_physical_memory_log(section, section->readonly);
+    } else {
+        iorange_init(&section->mr->iorange, &memory_region_iorange_ops,
+                     section->offset_within_address_space, section->size);
+        ioport_register(&section->mr->iorange);
+    }
+}
+
+static void core_region_del(MemoryListener *listener,
+                            MemoryRegionSection *section)
+{
+    if (section->address_space == get_system_memory()) {
+        cpu_register_physical_memory_log(section, false);
+    } else {
+        isa_unassign_ioport(section->offset_within_address_space,
+                            section->size);
+    }
+}
+
+static void core_log_start(MemoryListener *listener,
+                           MemoryRegionSection *section)
+{
+}
+
+static void core_log_stop(MemoryListener *listener,
+                          MemoryRegionSection *section)
+{
+}
+
+static void core_log_sync(MemoryListener *listener,
+                          MemoryRegionSection *section)
+{
+}
+
+static void core_log_global_start(MemoryListener *listener)
+{
+    cpu_physical_memory_set_dirty_tracking(1);
+}
+
+static void core_log_global_stop(MemoryListener *listener)
+{
+    cpu_physical_memory_set_dirty_tracking(0);
+}
+
+static void core_eventfd_add(MemoryListener *listener,
+                             MemoryRegionSection *section,
+                             bool match_data, uint64_t data, int fd)
+{
+}
+
+static void core_eventfd_del(MemoryListener *listener,
+                             MemoryRegionSection *section,
+                             bool match_data, uint64_t data, int fd)
+{
+}
+
+static MemoryListener core_memory_listener = {
+    .region_add = core_region_add,
+    .region_del = core_region_del,
+    .log_start = core_log_start,
+    .log_stop = core_log_stop,
+    .log_sync = core_log_sync,
+    .log_global_start = core_log_global_start,
+    .log_global_stop = core_log_global_stop,
+    .eventfd_add = core_eventfd_add,
+    .eventfd_del = core_eventfd_del,
+    .priority = 0,
+};
+
 static void memory_map_init(void)
 {
     system_memory = g_malloc(sizeof(*system_memory));
@@ -3497,6 +3570,8 @@ static void memory_map_init(void)
     system_io = g_malloc(sizeof(*system_io));
     memory_region_init(system_io, "io", 65536);
     set_system_io_map(system_io);
+
+    memory_listener_register(&core_memory_listener);
 }
 
 MemoryRegion *get_system_memory(void)
diff --git a/memory.c b/memory.c
index 85959ee..d5591f8 100644
--- a/memory.c
+++ b/memory.c
@@ -338,28 +338,10 @@ static void access_with_adjusted_size(target_phys_addr_t addr,
 
 static void as_memory_range_add(AddressSpace *as, FlatRange *fr)
 {
-    MemoryRegionSection section = {
-        .mr = fr->mr,
-        .offset_within_address_space = int128_get64(fr->addr.start),
-        .offset_within_region = fr->offset_in_region,
-        .size = int128_get64(fr->addr.size),
-        .readonly = fr->readonly,
-    };
-
-    cpu_register_physical_memory_log(&section, fr->readonly);
 }
 
 static void as_memory_range_del(AddressSpace *as, FlatRange *fr)
 {
-    MemoryRegionSection section = {
-        .mr = &io_mem_unassigned,
-        .offset_within_address_space = int128_get64(fr->addr.start),
-        .offset_within_region = int128_get64(fr->addr.start),
-        .size = int128_get64(fr->addr.size),
-        .readonly = fr->readonly,
-    };
-
-    cpu_register_physical_memory_log(&section, false);
 }
 
 static void as_memory_log_start(AddressSpace *as, FlatRange *fr)
@@ -450,22 +432,17 @@ static void memory_region_iorange_write(IORange *iorange,
                               memory_region_write_accessor, mr);
 }
 
-static const IORangeOps memory_region_iorange_ops = {
+const IORangeOps memory_region_iorange_ops = {
     .read = memory_region_iorange_read,
     .write = memory_region_iorange_write,
 };
 
 static void as_io_range_add(AddressSpace *as, FlatRange *fr)
 {
-    iorange_init(&fr->mr->iorange, &memory_region_iorange_ops,
-                 int128_get64(fr->addr.start), int128_get64(fr->addr.size));
-    ioport_register(&fr->mr->iorange);
 }
 
 static void as_io_range_del(AddressSpace *as, FlatRange *fr)
 {
-    isa_unassign_ioport(int128_get64(fr->addr.start),
-                        int128_get64(fr->addr.size));
 }
 
 static const AddressSpaceOps address_space_ops_io = {
@@ -1456,7 +1433,6 @@ void memory_global_sync_dirty_bitmap(MemoryRegion *address_space)
 
 void memory_global_dirty_log_start(void)
 {
-    cpu_physical_memory_set_dirty_tracking(1);
     global_dirty_log = true;
     MEMORY_LISTENER_CALL(log_global_start, Forward);
 }
@@ -1465,7 +1441,6 @@ void memory_global_dirty_log_stop(void)
 {
     global_dirty_log = false;
     MEMORY_LISTENER_CALL(log_global_stop, Reverse);
-    cpu_physical_memory_set_dirty_tracking(0);
 }
 
 static void listener_add_address_space(MemoryListener *listener,
commit d7ec83e6b57f48cf07f663e232e4aa2b32bc33c7
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Feb 8 17:07:26 2012 +0200

    memory: don't pass ->readable attribute to cpu_register_physical_memory_log
    
    It can be derived from the MemoryRegion itself (which is why it is not
    used there).
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/exec-obsolete.h b/exec-obsolete.h
index 94c23d0..23ffbaa 100644
--- a/exec-obsolete.h
+++ b/exec-obsolete.h
@@ -37,7 +37,7 @@ void cpu_unregister_io_memory(int table_address);
 
 struct MemoryRegionSection;
 void cpu_register_physical_memory_log(struct MemoryRegionSection *section,
-                                      bool readable, bool readonly);
+                                      bool readonly);
 
 void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size);
 void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size);
diff --git a/exec.c b/exec.c
index b81677a..d3020ab 100644
--- a/exec.c
+++ b/exec.c
@@ -2529,7 +2529,7 @@ static subpage_t *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
    before calculating this offset.  This should not be a problem unless
    the low bits of start_addr and region_offset differ.  */
 void cpu_register_physical_memory_log(MemoryRegionSection *section,
-                                      bool readable, bool readonly)
+                                      bool readonly)
 {
     target_phys_addr_t start_addr = section->offset_within_address_space;
     ram_addr_t size = section->size;
diff --git a/memory.c b/memory.c
index ccc3efb..85959ee 100644
--- a/memory.c
+++ b/memory.c
@@ -346,7 +346,7 @@ static void as_memory_range_add(AddressSpace *as, FlatRange *fr)
         .readonly = fr->readonly,
     };
 
-    cpu_register_physical_memory_log(&section, fr->readable, fr->readonly);
+    cpu_register_physical_memory_log(&section, fr->readonly);
 }
 
 static void as_memory_range_del(AddressSpace *as, FlatRange *fr)
@@ -359,7 +359,7 @@ static void as_memory_range_del(AddressSpace *as, FlatRange *fr)
         .readonly = fr->readonly,
     };
 
-    cpu_register_physical_memory_log(&section, true, false);
+    cpu_register_physical_memory_log(&section, false);
 }
 
 static void as_memory_log_start(AddressSpace *as, FlatRange *fr)
commit 7a8499e88bffff66d90300d4f2018c938543b1cf
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Feb 8 17:01:23 2012 +0200

    memory: add a readonly attribute to MemoryRegionSection
    
    .readonly cannot be obtained from the MemoryRegion, since it is
    inherited from aliases (so you can have a MemoryRegion mapped RW
    at one address and RO at another).  Record it in a MemoryRegionSection
    for listeners.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/memory.c b/memory.c
index a73c5a7..ccc3efb 100644
--- a/memory.c
+++ b/memory.c
@@ -112,6 +112,7 @@ enum ListenerDirection { Forward, Reverse };
         .offset_within_region = (fr)->offset_in_region,                 \
         .size = int128_get64((fr)->addr.size),                          \
         .offset_within_address_space = int128_get64((fr)->addr.start),  \
+        .readonly = (fr)->readonly,                                     \
                 })
 
 struct CoalescedMemoryRange {
@@ -342,6 +343,7 @@ static void as_memory_range_add(AddressSpace *as, FlatRange *fr)
         .offset_within_address_space = int128_get64(fr->addr.start),
         .offset_within_region = fr->offset_in_region,
         .size = int128_get64(fr->addr.size),
+        .readonly = fr->readonly,
     };
 
     cpu_register_physical_memory_log(&section, fr->readable, fr->readonly);
@@ -354,6 +356,7 @@ static void as_memory_range_del(AddressSpace *as, FlatRange *fr)
         .offset_within_address_space = int128_get64(fr->addr.start),
         .offset_within_region = int128_get64(fr->addr.start),
         .size = int128_get64(fr->addr.size),
+        .readonly = fr->readonly,
     };
 
     cpu_register_physical_memory_log(&section, true, false);
@@ -1437,6 +1440,7 @@ MemoryRegionSection memory_region_find(MemoryRegion *address_space,
                                                         fr->addr.start));
     ret.size = int128_get64(range.size);
     ret.offset_within_address_space = int128_get64(range.start);
+    ret.readonly = fr->readonly;
     return ret;
 }
 
@@ -1479,6 +1483,7 @@ static void listener_add_address_space(MemoryListener *listener,
             .offset_within_region = fr->offset_in_region,
             .size = int128_get64(fr->addr.size),
             .offset_within_address_space = int128_get64(fr->addr.start),
+            .readonly = fr->readonly,
         };
         listener->region_add(listener, &section);
     }
diff --git a/memory.h b/memory.h
index 84bb67c..1d99cee 100644
--- a/memory.h
+++ b/memory.h
@@ -160,6 +160,7 @@ typedef struct MemoryRegionSection MemoryRegionSection;
  * @size: the size of the section; will not exceed @mr's boundaries
  * @offset_within_address_space: the address of the first byte of the section
  *     relative to the region's address space
+ * @readonly: writes to this section are ignored
  */
 struct MemoryRegionSection {
     MemoryRegion *mr;
@@ -167,6 +168,7 @@ struct MemoryRegionSection {
     target_phys_addr_t offset_within_region;
     uint64_t size;
     target_phys_addr_t offset_within_address_space;
+    bool readonly;
 };
 
 typedef struct MemoryListener MemoryListener;
commit 80a1ea3748203b840d8bad488ada4d6f5bb66c9d
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Feb 8 16:39:06 2012 +0200

    memory: move ioeventfd ops to MemoryListener
    
    This way the accelerator (kvm) can handle them directly.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/hw/vhost.c b/hw/vhost.c
index 4737145..e1e7e01 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -720,6 +720,18 @@ static void vhost_virtqueue_cleanup(struct vhost_dev *dev,
                               0, virtio_queue_get_desc_size(vdev, idx));
 }
 
+static void vhost_eventfd_add(MemoryListener *listener,
+                              MemoryRegionSection *section,
+                              bool match_data, uint64_t data, int fd)
+{
+}
+
+static void vhost_eventfd_del(MemoryListener *listener,
+                              MemoryRegionSection *section,
+                              bool match_data, uint64_t data, int fd)
+{
+}
+
 int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force)
 {
     uint64_t features;
@@ -751,6 +763,8 @@ int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force)
         .log_sync = vhost_log_sync,
         .log_global_start = vhost_log_global_start,
         .log_global_stop = vhost_log_global_stop,
+        .eventfd_add = vhost_eventfd_add,
+        .eventfd_del = vhost_eventfd_del,
         .priority = 10
     };
     hdev->mem = g_malloc0(offsetof(struct vhost_memory, regions));
diff --git a/kvm-all.c b/kvm-all.c
index 6835fd4..a05e591 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -28,6 +28,7 @@
 #include "kvm.h"
 #include "bswap.h"
 #include "memory.h"
+#include "exec-memory.h"
 
 /* This check must be after config-host.h is included */
 #ifdef CONFIG_EVENTFD
@@ -718,6 +719,81 @@ static void kvm_log_global_stop(struct MemoryListener *listener)
     assert(r >= 0);
 }
 
+static void kvm_mem_ioeventfd_add(MemoryRegionSection *section,
+                                  bool match_data, uint64_t data, int fd)
+{
+    int r;
+
+    assert(match_data && section->size == 4);
+
+    r = kvm_set_ioeventfd_mmio_long(fd, section->offset_within_address_space,
+                                    data, true);
+    if (r < 0) {
+        abort();
+    }
+}
+
+static void kvm_mem_ioeventfd_del(MemoryRegionSection *section,
+                                  bool match_data, uint64_t data, int fd)
+{
+    int r;
+
+    r = kvm_set_ioeventfd_mmio_long(fd, section->offset_within_address_space,
+                                    data, false);
+    if (r < 0) {
+        abort();
+    }
+}
+
+static void kvm_io_ioeventfd_add(MemoryRegionSection *section,
+                                 bool match_data, uint64_t data, int fd)
+{
+    int r;
+
+    assert(match_data && section->size == 2);
+
+    r = kvm_set_ioeventfd_pio_word(fd, section->offset_within_address_space,
+                                   data, true);
+    if (r < 0) {
+        abort();
+    }
+}
+
+static void kvm_io_ioeventfd_del(MemoryRegionSection *section,
+                                 bool match_data, uint64_t data, int fd)
+
+{
+    int r;
+
+    r = kvm_set_ioeventfd_pio_word(fd, section->offset_within_address_space,
+                                   data, false);
+    if (r < 0) {
+        abort();
+    }
+}
+
+static void kvm_eventfd_add(MemoryListener *listener,
+                            MemoryRegionSection *section,
+                            bool match_data, uint64_t data, int fd)
+{
+    if (section->address_space == get_system_memory()) {
+        kvm_mem_ioeventfd_add(section, match_data, data, fd);
+    } else {
+        kvm_io_ioeventfd_add(section, match_data, data, fd);
+    }
+}
+
+static void kvm_eventfd_del(MemoryListener *listener,
+                            MemoryRegionSection *section,
+                            bool match_data, uint64_t data, int fd)
+{
+    if (section->address_space == get_system_memory()) {
+        kvm_mem_ioeventfd_del(section, match_data, data, fd);
+    } else {
+        kvm_io_ioeventfd_del(section, match_data, data, fd);
+    }
+}
+
 static MemoryListener kvm_memory_listener = {
     .region_add = kvm_region_add,
     .region_del = kvm_region_del,
@@ -726,6 +802,8 @@ static MemoryListener kvm_memory_listener = {
     .log_sync = kvm_log_sync,
     .log_global_start = kvm_log_global_start,
     .log_global_stop = kvm_log_global_stop,
+    .eventfd_add = kvm_eventfd_add,
+    .eventfd_del = kvm_eventfd_del,
     .priority = 10,
 };
 
diff --git a/memory.c b/memory.c
index 90f5973..a73c5a7 100644
--- a/memory.c
+++ b/memory.c
@@ -202,8 +202,6 @@ struct AddressSpaceOps {
     void (*range_del)(AddressSpace *as, FlatRange *fr);
     void (*log_start)(AddressSpace *as, FlatRange *fr);
     void (*log_stop)(AddressSpace *as, FlatRange *fr);
-    void (*ioeventfd_add)(AddressSpace *as, MemoryRegionIoeventfd *fd);
-    void (*ioeventfd_del)(AddressSpace *as, MemoryRegionIoeventfd *fd);
 };
 
 #define FOR_EACH_FLAT_RANGE(var, view)          \
@@ -369,37 +367,11 @@ static void as_memory_log_stop(AddressSpace *as, FlatRange *fr)
 {
 }
 
-static void as_memory_ioeventfd_add(AddressSpace *as, MemoryRegionIoeventfd *fd)
-{
-    int r;
-
-    assert(fd->match_data && int128_get64(fd->addr.size) == 4);
-
-    r = kvm_set_ioeventfd_mmio_long(fd->fd, int128_get64(fd->addr.start),
-                                    fd->data, true);
-    if (r < 0) {
-        abort();
-    }
-}
-
-static void as_memory_ioeventfd_del(AddressSpace *as, MemoryRegionIoeventfd *fd)
-{
-    int r;
-
-    r = kvm_set_ioeventfd_mmio_long(fd->fd, int128_get64(fd->addr.start),
-                                    fd->data, false);
-    if (r < 0) {
-        abort();
-    }
-}
-
 static const AddressSpaceOps address_space_ops_memory = {
     .range_add = as_memory_range_add,
     .range_del = as_memory_range_del,
     .log_start = as_memory_log_start,
     .log_stop = as_memory_log_stop,
-    .ioeventfd_add = as_memory_ioeventfd_add,
-    .ioeventfd_del = as_memory_ioeventfd_del,
 };
 
 static AddressSpace address_space_memory = {
@@ -493,35 +465,9 @@ static void as_io_range_del(AddressSpace *as, FlatRange *fr)
                         int128_get64(fr->addr.size));
 }
 
-static void as_io_ioeventfd_add(AddressSpace *as, MemoryRegionIoeventfd *fd)
-{
-    int r;
-
-    assert(fd->match_data && int128_get64(fd->addr.size) == 2);
-
-    r = kvm_set_ioeventfd_pio_word(fd->fd, int128_get64(fd->addr.start),
-                                   fd->data, true);
-    if (r < 0) {
-        abort();
-    }
-}
-
-static void as_io_ioeventfd_del(AddressSpace *as, MemoryRegionIoeventfd *fd)
-{
-    int r;
-
-    r = kvm_set_ioeventfd_pio_word(fd->fd, int128_get64(fd->addr.start),
-                                   fd->data, false);
-    if (r < 0) {
-        abort();
-    }
-}
-
 static const AddressSpaceOps address_space_ops_io = {
     .range_add = as_io_range_add,
     .range_del = as_io_range_del,
-    .ioeventfd_add = as_io_ioeventfd_add,
-    .ioeventfd_del = as_io_ioeventfd_del,
 };
 
 static AddressSpace address_space_io = {
@@ -653,6 +599,8 @@ static void address_space_add_del_ioeventfds(AddressSpace *as,
                                              unsigned fds_old_nb)
 {
     unsigned iold, inew;
+    MemoryRegionIoeventfd *fd;
+    MemoryRegionSection section;
 
     /* Generate a symmetric difference of the old and new fd sets, adding
      * and deleting as necessary.
@@ -664,13 +612,27 @@ static void address_space_add_del_ioeventfds(AddressSpace *as,
             && (inew == fds_new_nb
                 || memory_region_ioeventfd_before(fds_old[iold],
                                                   fds_new[inew]))) {
-            as->ops->ioeventfd_del(as, &fds_old[iold]);
+            fd = &fds_old[iold];
+            section = (MemoryRegionSection) {
+                .address_space = as->root,
+                .offset_within_address_space = int128_get64(fd->addr.start),
+                .size = int128_get64(fd->addr.size),
+            };
+            MEMORY_LISTENER_CALL(eventfd_del, Forward, &section,
+                                 fd->match_data, fd->data, fd->fd);
             ++iold;
         } else if (inew < fds_new_nb
                    && (iold == fds_old_nb
                        || memory_region_ioeventfd_before(fds_new[inew],
                                                          fds_old[iold]))) {
-            as->ops->ioeventfd_add(as, &fds_new[inew]);
+            fd = &fds_new[inew];
+            section = (MemoryRegionSection) {
+                .address_space = as->root,
+                .offset_within_address_space = int128_get64(fd->addr.start),
+                .size = int128_get64(fd->addr.size),
+            };
+            MEMORY_LISTENER_CALL(eventfd_add, Reverse, &section,
+                                 fd->match_data, fd->data, fd->fd);
             ++inew;
         } else {
             ++iold;
diff --git a/memory.h b/memory.h
index 954dc86..84bb67c 100644
--- a/memory.h
+++ b/memory.h
@@ -185,6 +185,10 @@ struct MemoryListener {
     void (*log_sync)(MemoryListener *listener, MemoryRegionSection *section);
     void (*log_global_start)(MemoryListener *listener);
     void (*log_global_stop)(MemoryListener *listener);
+    void (*eventfd_add)(MemoryListener *listener, MemoryRegionSection *section,
+                        bool match_data, uint64_t data, int fd);
+    void (*eventfd_del)(MemoryListener *listener, MemoryRegionSection *section,
+                        bool match_data, uint64_t data, int fd);
     /* Lower = earlier (during add), later (during del) */
     unsigned priority;
     QTAILQ_ENTRY(MemoryListener) link;
diff --git a/xen-all.c b/xen-all.c
index 8cb84ef..e005b63 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -487,6 +487,18 @@ static void xen_log_global_stop(MemoryListener *listener)
 {
 }
 
+static void xen_eventfd_add(MemoryListener *listener,
+                            MemoryRegionSection *section,
+                            bool match_data, uint64_t data, int fd)
+{
+}
+
+static void xen_eventfd_del(MemoryListener *listener,
+                            MemoryRegionSection *section,
+                            bool match_data, uint64_t data, int fd)
+{
+}
+
 static MemoryListener xen_memory_listener = {
     .region_add = xen_region_add,
     .region_del = xen_region_del,
@@ -495,6 +507,8 @@ static MemoryListener xen_memory_listener = {
     .log_sync = xen_log_sync,
     .log_global_start = xen_log_global_start,
     .log_global_stop = xen_log_global_stop,
+    .eventfd_add = xen_eventfd_add,
+    .eventfd_del = xen_eventfd_del,
     .priority = 10,
 };
 
commit 0e0d36b446bbe913edcf5a7af24590360845f824
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Feb 8 16:39:45 2012 +0200

    memory: code motion: move MEMORY_LISTENER_CALL()
    
    So it can be used in earlier code.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/memory.c b/memory.c
index a8fb39e..90f5973 100644
--- a/memory.c
+++ b/memory.c
@@ -82,6 +82,38 @@ static AddrRange addrrange_intersection(AddrRange r1, AddrRange r2)
     return addrrange_make(start, int128_sub(end, start));
 }
 
+enum ListenerDirection { Forward, Reverse };
+
+#define MEMORY_LISTENER_CALL(_callback, _direction, _args...)           \
+    do {                                                                \
+        MemoryListener *_listener;                                      \
+                                                                        \
+        switch (_direction) {                                           \
+        case Forward:                                                   \
+            QTAILQ_FOREACH(_listener, &memory_listeners, link) {        \
+                _listener->_callback(_listener, ##_args);               \
+            }                                                           \
+            break;                                                      \
+        case Reverse:                                                   \
+            QTAILQ_FOREACH_REVERSE(_listener, &memory_listeners,        \
+                                   memory_listeners, link) {            \
+                _listener->_callback(_listener, ##_args);               \
+            }                                                           \
+            break;                                                      \
+        default:                                                        \
+            abort();                                                    \
+        }                                                               \
+    } while (0)
+
+#define MEMORY_LISTENER_UPDATE_REGION(fr, as, dir, callback)            \
+    MEMORY_LISTENER_CALL(callback, dir, &(MemoryRegionSection) {        \
+        .mr = (fr)->mr,                                                 \
+        .address_space = (as)->root,                                    \
+        .offset_within_region = (fr)->offset_in_region,                 \
+        .size = int128_get64((fr)->addr.size),                          \
+        .offset_within_address_space = int128_get64((fr)->addr.start),  \
+                })
+
 struct CoalescedMemoryRange {
     AddrRange addr;
     QTAILQ_ENTRY(CoalescedMemoryRange) link;
@@ -678,38 +710,6 @@ static void address_space_update_ioeventfds(AddressSpace *as)
     as->ioeventfd_nb = ioeventfd_nb;
 }
 
-enum ListenerDirection { Forward, Reverse };
-
-#define MEMORY_LISTENER_CALL(_callback, _direction, _args...)           \
-    do {                                                                \
-        MemoryListener *_listener;                                      \
-                                                                        \
-        switch (_direction) {                                           \
-        case Forward:                                                   \
-            QTAILQ_FOREACH(_listener, &memory_listeners, link) {        \
-                _listener->_callback(_listener, ##_args);               \
-            }                                                           \
-            break;                                                      \
-        case Reverse:                                                   \
-            QTAILQ_FOREACH_REVERSE(_listener, &memory_listeners,        \
-                                   memory_listeners, link) {            \
-                _listener->_callback(_listener, ##_args);               \
-            }                                                           \
-            break;                                                      \
-        default:                                                        \
-            abort();                                                    \
-        }                                                               \
-    } while (0)
-
-#define MEMORY_LISTENER_UPDATE_REGION(fr, as, dir, callback)            \
-    MEMORY_LISTENER_CALL(callback, dir, &(MemoryRegionSection) {        \
-        .mr = (fr)->mr,                                                 \
-        .address_space = (as)->root,                                    \
-        .offset_within_region = (fr)->offset_in_region,                 \
-        .size = int128_get64((fr)->addr.size),                          \
-        .offset_within_address_space = int128_get64((fr)->addr.start),  \
-                })
-
 static void address_space_update_topology_pass(AddressSpace *as,
                                                FlatView old_view,
                                                FlatView new_view,
commit 72e22d2fe17b85e56b4f0c437c61c6e2de97b308
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Feb 8 15:05:50 2012 +0200

    memory: switch memory listeners to a QTAILQ
    
    This allows reverse iteration, which in turns allows consistent ordering
    among multiple listeners:
    
      l1->add
      l2->add
      l2->del
      l1->del
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/hw/vhost.c b/hw/vhost.c
index 5ece659..4737145 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -751,6 +751,7 @@ int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force)
         .log_sync = vhost_log_sync,
         .log_global_start = vhost_log_global_start,
         .log_global_stop = vhost_log_global_stop,
+        .priority = 10
     };
     hdev->mem = g_malloc0(offsetof(struct vhost_memory, regions));
     hdev->n_mem_sections = 0;
diff --git a/kvm-all.c b/kvm-all.c
index 0b87658..6835fd4 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -726,6 +726,7 @@ static MemoryListener kvm_memory_listener = {
     .log_sync = kvm_log_sync,
     .log_global_start = kvm_log_global_start,
     .log_global_stop = kvm_log_global_stop,
+    .priority = 10,
 };
 
 static void kvm_handle_interrupt(CPUState *env, int mask)
diff --git a/memory.c b/memory.c
index 570125c..a8fb39e 100644
--- a/memory.c
+++ b/memory.c
@@ -27,8 +27,8 @@ unsigned memory_region_transaction_depth = 0;
 static bool memory_region_update_pending = false;
 static bool global_dirty_log = false;
 
-static QLIST_HEAD(, MemoryListener) memory_listeners
-    = QLIST_HEAD_INITIALIZER(memory_listeners);
+static QTAILQ_HEAD(memory_listeners, MemoryListener) memory_listeners
+    = QTAILQ_HEAD_INITIALIZER(memory_listeners);
 
 typedef struct AddrRange AddrRange;
 
@@ -678,17 +678,31 @@ static void address_space_update_ioeventfds(AddressSpace *as)
     as->ioeventfd_nb = ioeventfd_nb;
 }
 
-#define MEMORY_LISTENER_CALL(_callback, _args...)               \
-    do {                                                        \
-        MemoryListener *_listener;                              \
-                                                                \
-        QLIST_FOREACH(_listener, &memory_listeners, link) {     \
-            _listener->_callback(_listener, ##_args);           \
-        }                                                       \
+enum ListenerDirection { Forward, Reverse };
+
+#define MEMORY_LISTENER_CALL(_callback, _direction, _args...)           \
+    do {                                                                \
+        MemoryListener *_listener;                                      \
+                                                                        \
+        switch (_direction) {                                           \
+        case Forward:                                                   \
+            QTAILQ_FOREACH(_listener, &memory_listeners, link) {        \
+                _listener->_callback(_listener, ##_args);               \
+            }                                                           \
+            break;                                                      \
+        case Reverse:                                                   \
+            QTAILQ_FOREACH_REVERSE(_listener, &memory_listeners,        \
+                                   memory_listeners, link) {            \
+                _listener->_callback(_listener, ##_args);               \
+            }                                                           \
+            break;                                                      \
+        default:                                                        \
+            abort();                                                    \
+        }                                                               \
     } while (0)
 
-#define MEMORY_LISTENER_UPDATE_REGION(fr, as, callback)                 \
-    MEMORY_LISTENER_CALL(callback, &(MemoryRegionSection) {             \
+#define MEMORY_LISTENER_UPDATE_REGION(fr, as, dir, callback)            \
+    MEMORY_LISTENER_CALL(callback, dir, &(MemoryRegionSection) {        \
         .mr = (fr)->mr,                                                 \
         .address_space = (as)->root,                                    \
         .offset_within_region = (fr)->offset_in_region,                 \
@@ -728,7 +742,7 @@ static void address_space_update_topology_pass(AddressSpace *as,
             /* In old, but (not in new, or in new but attributes changed). */
 
             if (!adding) {
-                MEMORY_LISTENER_UPDATE_REGION(frold, as, region_del);
+                MEMORY_LISTENER_UPDATE_REGION(frold, as, Reverse, region_del);
                 as->ops->range_del(as, frold);
             }
 
@@ -738,11 +752,11 @@ static void address_space_update_topology_pass(AddressSpace *as,
 
             if (adding) {
                 if (frold->dirty_log_mask && !frnew->dirty_log_mask) {
-                    MEMORY_LISTENER_UPDATE_REGION(frnew, as, log_stop);
+                    MEMORY_LISTENER_UPDATE_REGION(frnew, as, Reverse, log_stop);
                     as->ops->log_stop(as, frnew);
                 } else if (frnew->dirty_log_mask && !frold->dirty_log_mask) {
                     as->ops->log_start(as, frnew);
-                    MEMORY_LISTENER_UPDATE_REGION(frnew, as, log_start);
+                    MEMORY_LISTENER_UPDATE_REGION(frnew, as, Forward, log_start);
                 }
             }
 
@@ -753,7 +767,7 @@ static void address_space_update_topology_pass(AddressSpace *as,
 
             if (adding) {
                 as->ops->range_add(as, frnew);
-                MEMORY_LISTENER_UPDATE_REGION(frnew, as, region_add);
+                MEMORY_LISTENER_UPDATE_REGION(frnew, as, Forward, region_add);
             }
 
             ++inew;
@@ -1142,7 +1156,8 @@ void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
 
     FOR_EACH_FLAT_RANGE(fr, &address_space_memory.current_map) {
         if (fr->mr == mr) {
-            MEMORY_LISTENER_UPDATE_REGION(fr, &address_space_memory, log_sync);
+            MEMORY_LISTENER_UPDATE_REGION(fr, &address_space_memory,
+                                          Forward, log_sync);
         }
     }
 }
@@ -1469,7 +1484,7 @@ void memory_global_sync_dirty_bitmap(MemoryRegion *address_space)
     FlatRange *fr;
 
     FOR_EACH_FLAT_RANGE(fr, &as->current_map) {
-        MEMORY_LISTENER_UPDATE_REGION(fr, as, log_sync);
+        MEMORY_LISTENER_UPDATE_REGION(fr, as, Forward, log_sync);
     }
 }
 
@@ -1477,13 +1492,13 @@ void memory_global_dirty_log_start(void)
 {
     cpu_physical_memory_set_dirty_tracking(1);
     global_dirty_log = true;
-    MEMORY_LISTENER_CALL(log_global_start);
+    MEMORY_LISTENER_CALL(log_global_start, Forward);
 }
 
 void memory_global_dirty_log_stop(void)
 {
     global_dirty_log = false;
-    MEMORY_LISTENER_CALL(log_global_stop);
+    MEMORY_LISTENER_CALL(log_global_stop, Reverse);
     cpu_physical_memory_set_dirty_tracking(0);
 }
 
@@ -1509,14 +1524,27 @@ static void listener_add_address_space(MemoryListener *listener,
 
 void memory_listener_register(MemoryListener *listener)
 {
-    QLIST_INSERT_HEAD(&memory_listeners, listener, link);
+    MemoryListener *other = NULL;
+
+    if (QTAILQ_EMPTY(&memory_listeners)
+        || listener->priority >= QTAILQ_LAST(&memory_listeners,
+                                             memory_listeners)->priority) {
+        QTAILQ_INSERT_TAIL(&memory_listeners, listener, link);
+    } else {
+        QTAILQ_FOREACH(other, &memory_listeners, link) {
+            if (listener->priority < other->priority) {
+                break;
+            }
+        }
+        QTAILQ_INSERT_BEFORE(other, listener, link);
+    }
     listener_add_address_space(listener, &address_space_memory);
     listener_add_address_space(listener, &address_space_io);
 }
 
 void memory_listener_unregister(MemoryListener *listener)
 {
-    QLIST_REMOVE(listener, link);
+    QTAILQ_REMOVE(&memory_listeners, listener, link);
 }
 
 void set_system_memory_map(MemoryRegion *mr)
diff --git a/memory.h b/memory.h
index 4763286..954dc86 100644
--- a/memory.h
+++ b/memory.h
@@ -185,7 +185,9 @@ struct MemoryListener {
     void (*log_sync)(MemoryListener *listener, MemoryRegionSection *section);
     void (*log_global_start)(MemoryListener *listener);
     void (*log_global_stop)(MemoryListener *listener);
-    QLIST_ENTRY(MemoryListener) link;
+    /* Lower = earlier (during add), later (during del) */
+    unsigned priority;
+    QTAILQ_ENTRY(MemoryListener) link;
 };
 
 /**
diff --git a/xen-all.c b/xen-all.c
index fd39168..8cb84ef 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -495,6 +495,7 @@ static MemoryListener xen_memory_listener = {
     .log_sync = xen_log_sync,
     .log_global_start = xen_log_global_start,
     .log_global_stop = xen_log_global_stop,
+    .priority = 10,
 };
 
 /* VCPU Operations, MMIO, IO ring ... */
commit 946996e9c1b0b7b4a6dc56b253e947ea90d24ec4
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Feb 8 13:58:44 2012 +0200

    memory: add shorthand for invoking a callback on all listeners
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/memory.c b/memory.c
index e3a66de..570125c 100644
--- a/memory.c
+++ b/memory.c
@@ -678,31 +678,23 @@ static void address_space_update_ioeventfds(AddressSpace *as)
     as->ioeventfd_nb = ioeventfd_nb;
 }
 
-typedef void ListenerCallback(MemoryListener *listener,
-                              MemoryRegionSection *mrs);
-
-/* Want "void (&MemoryListener::*callback)(const MemoryRegionSection& s)" */
-static void memory_listener_update_region(FlatRange *fr, AddressSpace *as,
-                                          size_t callback_offset)
-{
-    MemoryRegionSection section = {
-        .mr = fr->mr,
-        .address_space = as->root,
-        .offset_within_region = fr->offset_in_region,
-        .size = int128_get64(fr->addr.size),
-        .offset_within_address_space = int128_get64(fr->addr.start),
-    };
-    MemoryListener *listener;
-
-    QLIST_FOREACH(listener, &memory_listeners, link) {
-        ListenerCallback *callback
-            = *(ListenerCallback **)((void *)listener + callback_offset);
-        callback(listener, &section);
-    }
-}
-
-#define MEMORY_LISTENER_UPDATE_REGION(fr, as, callback) \
-    memory_listener_update_region(fr, as, offsetof(MemoryListener, callback))
+#define MEMORY_LISTENER_CALL(_callback, _args...)               \
+    do {                                                        \
+        MemoryListener *_listener;                              \
+                                                                \
+        QLIST_FOREACH(_listener, &memory_listeners, link) {     \
+            _listener->_callback(_listener, ##_args);           \
+        }                                                       \
+    } while (0)
+
+#define MEMORY_LISTENER_UPDATE_REGION(fr, as, callback)                 \
+    MEMORY_LISTENER_CALL(callback, &(MemoryRegionSection) {             \
+        .mr = (fr)->mr,                                                 \
+        .address_space = (as)->root,                                    \
+        .offset_within_region = (fr)->offset_in_region,                 \
+        .size = int128_get64((fr)->addr.size),                          \
+        .offset_within_address_space = int128_get64((fr)->addr.start),  \
+                })
 
 static void address_space_update_topology_pass(AddressSpace *as,
                                                FlatView old_view,
@@ -1483,23 +1475,15 @@ void memory_global_sync_dirty_bitmap(MemoryRegion *address_space)
 
 void memory_global_dirty_log_start(void)
 {
-    MemoryListener *listener;
-
     cpu_physical_memory_set_dirty_tracking(1);
     global_dirty_log = true;
-    QLIST_FOREACH(listener, &memory_listeners, link) {
-        listener->log_global_start(listener);
-    }
+    MEMORY_LISTENER_CALL(log_global_start);
 }
 
 void memory_global_dirty_log_stop(void)
 {
-    MemoryListener *listener;
-
     global_dirty_log = false;
-    QLIST_FOREACH(listener, &memory_listeners, link) {
-        listener->log_global_stop(listener);
-    }
+    MEMORY_LISTENER_CALL(log_global_stop);
     cpu_physical_memory_set_dirty_tracking(0);
 }
 
commit 2b50aa1f14d8e0a40f905ad0c022443c15646914
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Jan 8 19:51:35 2012 +0200

    memory: remove memory_region_set_offset()
    
    memory_region_set_offset() complicates the API, and has been deprecated
    since its introduction.  Now that it is no longer used, remove it.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/memory.c b/memory.c
index 22816e2..e3a66de 100644
--- a/memory.c
+++ b/memory.c
@@ -401,17 +401,17 @@ static void memory_region_iorange_read(IORange *iorange,
 
         *data = ((uint64_t)1 << (width * 8)) - 1;
         if (mrp) {
-            *data = mrp->read(mr->opaque, offset + mr->offset);
+            *data = mrp->read(mr->opaque, offset);
         } else if (width == 2) {
             mrp = find_portio(mr, offset, 1, false);
             assert(mrp);
-            *data = mrp->read(mr->opaque, offset + mr->offset) |
-                    (mrp->read(mr->opaque, offset + mr->offset + 1) << 8);
+            *data = mrp->read(mr->opaque, offset) |
+                    (mrp->read(mr->opaque, offset + 1) << 8);
         }
         return;
     }
     *data = 0;
-    access_with_adjusted_size(offset + mr->offset, data, width,
+    access_with_adjusted_size(offset, data, width,
                               mr->ops->impl.min_access_size,
                               mr->ops->impl.max_access_size,
                               memory_region_read_accessor, mr);
@@ -428,16 +428,16 @@ static void memory_region_iorange_write(IORange *iorange,
         const MemoryRegionPortio *mrp = find_portio(mr, offset, width, true);
 
         if (mrp) {
-            mrp->write(mr->opaque, offset + mr->offset, data);
+            mrp->write(mr->opaque, offset, data);
         } else if (width == 2) {
             mrp = find_portio(mr, offset, 1, false);
             assert(mrp);
-            mrp->write(mr->opaque, offset + mr->offset, data & 0xff);
-            mrp->write(mr->opaque, offset + mr->offset + 1, data >> 8);
+            mrp->write(mr->opaque, offset, data & 0xff);
+            mrp->write(mr->opaque, offset + 1, data >> 8);
         }
         return;
     }
-    access_with_adjusted_size(offset + mr->offset, &data, width,
+    access_with_adjusted_size(offset, &data, width,
                               mr->ops->impl.min_access_size,
                               mr->ops->impl.max_access_size,
                               memory_region_write_accessor, mr);
@@ -863,7 +863,6 @@ void memory_region_init(MemoryRegion *mr,
         mr->size = int128_2_64();
     }
     mr->addr = 0;
-    mr->offset = 0;
     mr->subpage = false;
     mr->enabled = true;
     mr->terminates = false;
@@ -925,7 +924,7 @@ static uint64_t memory_region_dispatch_read1(MemoryRegion *mr,
     }
 
     /* FIXME: support unaligned access */
-    access_with_adjusted_size(addr + mr->offset, &data, size,
+    access_with_adjusted_size(addr, &data, size,
                               mr->ops->impl.min_access_size,
                               mr->ops->impl.max_access_size,
                               memory_region_read_accessor, mr);
@@ -979,7 +978,7 @@ static void memory_region_dispatch_write(MemoryRegion *mr,
     }
 
     /* FIXME: support unaligned access */
-    access_with_adjusted_size(addr + mr->offset, &data, size,
+    access_with_adjusted_size(addr, &data, size,
                               mr->ops->impl.min_access_size,
                               mr->ops->impl.max_access_size,
                               memory_region_write_accessor, mr);
@@ -1122,11 +1121,6 @@ bool memory_region_is_rom(MemoryRegion *mr)
     return mr->ram && mr->readonly;
 }
 
-void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset)
-{
-    mr->offset = offset;
-}
-
 void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
 {
     uint8_t mask = 1 << client;
diff --git a/memory.h b/memory.h
index 4cf8d2f..4763286 100644
--- a/memory.h
+++ b/memory.h
@@ -115,7 +115,6 @@ struct MemoryRegion {
     MemoryRegion *parent;
     Int128 size;
     target_phys_addr_t addr;
-    target_phys_addr_t offset;
     void (*destructor)(MemoryRegion *mr);
     ram_addr_t ram_addr;
     IORange iorange;
@@ -359,14 +358,6 @@ bool memory_region_is_rom(MemoryRegion *mr);
 void *memory_region_get_ram_ptr(MemoryRegion *mr);
 
 /**
- * memory_region_set_offset: Sets an offset to be added to MemoryRegionOps
- *                           callbacks.
- *
- * This function is deprecated and should not be used in new code.
- */
-void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset);
-
-/**
  * memory_region_set_log: Turn dirty logging on or off for a region.
  *
  * Turns dirty logging on or off for a specified client (display, migration).
commit de58ac72b6a062d1a61478284c0c0f8a0428613e
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Jan 8 19:46:17 2012 +0200

    ioport: change portio_list not to use memory_region_set_offset()
    
    memory_region_set_offset() will be going away soon, so don't use it.
    Use an alias instead.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/ioport.c b/ioport.c
index 36fa3a4..8a474d3 100644
--- a/ioport.c
+++ b/ioport.c
@@ -328,6 +328,7 @@ void portio_list_init(PortioList *piolist,
     piolist->ports = callbacks;
     piolist->nr = 0;
     piolist->regions = g_new0(MemoryRegion *, n);
+    piolist->aliases = g_new0(MemoryRegion *, n);
     piolist->address_space = NULL;
     piolist->opaque = opaque;
     piolist->name = name;
@@ -336,6 +337,7 @@ void portio_list_init(PortioList *piolist,
 void portio_list_destroy(PortioList *piolist)
 {
     g_free(piolist->regions);
+    g_free(piolist->aliases);
 }
 
 static void portio_list_add_1(PortioList *piolist,
@@ -345,7 +347,7 @@ static void portio_list_add_1(PortioList *piolist,
 {
     MemoryRegionPortio *pio;
     MemoryRegionOps *ops;
-    MemoryRegion *region;
+    MemoryRegion *region, *alias;
     unsigned i;
 
     /* Copy the sub-list and null-terminate it.  */
@@ -362,12 +364,20 @@ static void portio_list_add_1(PortioList *piolist,
     ops->old_portio = pio;
 
     region = g_new(MemoryRegion, 1);
+    alias = g_new(MemoryRegion, 1);
+    /*
+     * Use an alias so that the callback is called with an absolute address,
+     * rather than an offset relative to to start + off_low.
+     */
     memory_region_init_io(region, ops, piolist->opaque, piolist->name,
-                          off_high - off_low);
-    memory_region_set_offset(region, start + off_low);
+                          UINT64_MAX);
+    memory_region_init_alias(alias, piolist->name,
+                             region, start + off_low, off_high - off_low);
     memory_region_add_subregion(piolist->address_space,
-                                start + off_low, region);
-    piolist->regions[piolist->nr++] = region;
+                                start + off_low, alias);
+    piolist->regions[piolist->nr] = region;
+    piolist->aliases[piolist->nr] = alias;
+    ++piolist->nr;
 }
 
 void portio_list_add(PortioList *piolist,
@@ -409,15 +419,19 @@ void portio_list_add(PortioList *piolist,
 
 void portio_list_del(PortioList *piolist)
 {
-    MemoryRegion *mr;
+    MemoryRegion *mr, *alias;
     unsigned i;
 
     for (i = 0; i < piolist->nr; ++i) {
         mr = piolist->regions[i];
-        memory_region_del_subregion(piolist->address_space, mr);
+        alias = piolist->aliases[i];
+        memory_region_del_subregion(piolist->address_space, alias);
+        memory_region_destroy(alias);
         memory_region_destroy(mr);
         g_free((MemoryRegionOps *)mr->ops);
         g_free(mr);
+        g_free(alias);
         piolist->regions[i] = NULL;
+        piolist->aliases[i] = NULL;
     }
 }
diff --git a/ioport.h b/ioport.h
index ae3e9da..ab29c89 100644
--- a/ioport.h
+++ b/ioport.h
@@ -60,6 +60,7 @@ typedef struct PortioList {
     struct MemoryRegion *address_space;
     unsigned nr;
     struct MemoryRegion **regions;
+    struct MemoryRegion **aliases;
     void *opaque;
     const char *name;
 } PortioList;
commit c0fd260e9da7e6e60ea6bf1b0198a804f147073f
Author: Stefan Weil <sw at weilnetz.de>
Date:   Wed Feb 1 21:04:13 2012 +0100

    Move definition of HOST_LONG_BITS to qemu-common.h
    
    Like the related macro TCG_TARGET_LONG, HOST_LONG_BITS can be determined
    by the C preprocessor. It is also not used in Makefiles.
    
    So there is no need to calculate it in configure, and it can be defined
    in qemu-common.h.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/configure b/configure
index d9dde96..9ae85be 100755
--- a/configure
+++ b/configure
@@ -1291,17 +1291,6 @@ esac
 
 fi
 
-# host long bits test, actually a pointer size test
-cat > $TMPC << EOF
-int sizeof_pointer_is_8[sizeof(void *) == 8 ? 1 : -1];
-EOF
-if compile_object; then
-hostlongbits=64
-else
-hostlongbits=32
-fi
-
-
 ##########################################
 # NPTL probe
 
@@ -2988,7 +2977,6 @@ fi
 if test "$bigendian" = "yes" ; then
   echo "HOST_WORDS_BIGENDIAN=y" >> $config_host_mak
 fi
-echo "HOST_LONG_BITS=$hostlongbits" >> $config_host_mak
 if test "$mingw32" = "yes" ; then
   echo "CONFIG_WIN32=y" >> $config_host_mak
   rc_version=`cat $source_path/VERSION`
diff --git a/qemu-common.h b/qemu-common.h
index c5e9cad..dbfce6f 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -65,6 +65,15 @@ typedef struct Monitor Monitor;
 #define TIME_MAX LONG_MAX
 #endif
 
+/* HOST_LONG_BITS is the size of a native pointer in bits. */
+#if UINTPTR_MAX == UINT32_MAX
+# define HOST_LONG_BITS 32
+#elif UINTPTR_MAX == UINT64_MAX
+# define HOST_LONG_BITS 64
+#else
+# error Unknown pointer size
+#endif
+
 #ifndef CONFIG_IOVEC
 #define CONFIG_IOVEC
 struct iovec {
commit 2ad5201c1e3d53fef14af1e9eb629c180b318d89
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Feb 2 21:48:08 2012 +0100

    target-xtensa: Clean includes
    
    Remove some include statements which are not needed.
    
    Acked-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/target-xtensa/core-dc232b.c b/target-xtensa/core-dc232b.c
index 4d9bd55..21b287d 100644
--- a/target-xtensa/core-dc232b.c
+++ b/target-xtensa/core-dc232b.c
@@ -1,7 +1,6 @@
 #include "cpu.h"
 #include "exec-all.h"
 #include "gdbstub.h"
-#include "qemu-common.h"
 #include "host-utils.h"
 
 #include "core-dc232b/core-isa.h"
diff --git a/target-xtensa/core-fsf.c b/target-xtensa/core-fsf.c
index 7650462..763b8e5 100644
--- a/target-xtensa/core-fsf.c
+++ b/target-xtensa/core-fsf.c
@@ -1,7 +1,6 @@
 #include "cpu.h"
 #include "exec-all.h"
 #include "gdbstub.h"
-#include "qemu-common.h"
 #include "host-utils.h"
 
 #include "core-fsf/core-isa.h"
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index 2a0cb1a..1264c83 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -28,7 +28,6 @@
 #include "cpu.h"
 #include "exec-all.h"
 #include "gdbstub.h"
-#include "qemu-common.h"
 #include "host-utils.h"
 #if !defined(CONFIG_USER_ONLY)
 #include "hw/loader.h"
commit 8141905a4458400b094d60d835a98b26ab48a4af
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Feb 2 21:47:01 2012 +0100

    target-unicore32: Clean includes
    
    The change in cpu.h is needed when HOST_LONG_BITS is defined in qemu-common.h.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/target-unicore32/cpu.h b/target-unicore32/cpu.h
index b4e72cf..f725634 100644
--- a/target-unicore32/cpu.h
+++ b/target-unicore32/cpu.h
@@ -20,6 +20,8 @@
 
 #define CPUState                struct CPUState_UniCore32
 
+#include "config.h"
+#include "qemu-common.h"
 #include "cpu-defs.h"
 #include "softfloat.h"
 
diff --git a/target-unicore32/helper.c b/target-unicore32/helper.c
index b5b1cb7..ee7f82b 100644
--- a/target-unicore32/helper.c
+++ b/target-unicore32/helper.c
@@ -5,14 +5,10 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
 
 #include "cpu.h"
 #include "gdbstub.h"
 #include "helper.h"
-#include "qemu-common.h"
 #include "host-utils.h"
 
 static inline void set_feature(CPUState *env, int feature)
commit 2d0b9ac6d629bf9d32f101a319cebd9767bb3350
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Feb 2 21:44:38 2012 +0100

    target-sh4: Clean includes
    
    Remove some include statements which are not needed.
    
    Cc: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index aacf96d..dd0ee4b 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -16,11 +16,6 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
 
 #define DEBUG_DISAS
 #define SH4_DEBUG_DISAS
@@ -29,7 +24,6 @@
 #include "cpu.h"
 #include "disas.h"
 #include "tcg-op.h"
-#include "qemu-common.h"
 
 #include "helper.h"
 #define GEN_HELPER 1
commit 45133b74bacc67d2cc7c6b19315528325cc23c26
Author: Stefan Weil <sw at weilnetz.de>
Date:   Wed Feb 1 20:56:52 2012 +0100

    target-s390x: Clean includes
    
    The change in cpu.h is needed when HOST_LONG_BITS is defined in qemu-common.h.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index b8893b3..e892bec 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -19,6 +19,9 @@
 #ifndef CPU_S390X_H
 #define CPU_S390X_H
 
+#include "config.h"
+#include "qemu-common.h"
+
 #define TARGET_LONG_BITS 64
 
 #define ELF_MACHINE	EM_S390
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 10cc9dd..c0ec890 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -18,13 +18,8 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
 #include "cpu.h"
 #include "gdbstub.h"
-#include "qemu-common.h"
 #include "qemu-timer.h"
 #ifndef CONFIG_USER_ONLY
 #include "sysemu.h"
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index ee15672..71f9dcd 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -17,11 +17,6 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
 
 /* #define DEBUG_ILLEGAL_INSTRUCTIONS */
 /* #define DEBUG_INLINE_BRANCHES */
commit 550a82ec32c1afe6518bfbe8c811d34d85518cdc
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Feb 2 21:40:37 2012 +0100

    target-ppc: Clean includes
    
    Remove some include statements which are not needed.
    
    Acked-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 928fbcf..bb76a8b 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -16,15 +16,9 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
 
 #include "cpu.h"
 #include "helper_regs.h"
-#include "qemu-common.h"
 #include "kvm.h"
 #include "kvm_ppc.h"
 #include "cpus.h"
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index b2780db..8573e1f 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -17,16 +17,10 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
 
 #include "cpu.h"
 #include "disas.h"
 #include "tcg-op.h"
-#include "qemu-common.h"
 #include "host-utils.h"
 
 #include "helper.h"
commit 0056c093b683879535f99a0ab7ccccaa5d1fefc6
Author: Stefan Weil <sw at weilnetz.de>
Date:   Wed Feb 1 20:56:03 2012 +0100

    target-mips: Clean includes
    
    Remove some include statements which are not needed.
    
    Cc: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/target-mips/translate.c b/target-mips/translate.c
index d5b1c76..8361d88 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -20,16 +20,9 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
-
 #include "cpu.h"
 #include "disas.h"
 #include "tcg-op.h"
-#include "qemu-common.h"
 
 #include "helper.h"
 #define GEN_HELPER 1
commit 94598c1d9561e042ec80389c82e4fe3e15563584
Author: Stefan Weil <sw at weilnetz.de>
Date:   Wed Feb 1 20:55:39 2012 +0100

    target-microblaze: Clean includes
    
    The change in cpu.h is needed when HOST_LONG_BITS is defined in qemu-common.h.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index 3ecaeee..4092506 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -19,6 +19,9 @@
 #ifndef CPU_MICROBLAZE_H
 #define CPU_MICROBLAZE_H
 
+#include "config.h"
+#include "qemu-common.h"
+
 #define TARGET_LONG_BITS 32
 
 #define CPUState struct CPUMBState
diff --git a/target-microblaze/helper.c b/target-microblaze/helper.c
index 2cf2802..e1355ff 100644
--- a/target-microblaze/helper.c
+++ b/target-microblaze/helper.c
@@ -17,11 +17,6 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-
-#include "config.h"
 #include "cpu.h"
 #include "host-utils.h"
 
diff --git a/target-microblaze/mmu.c b/target-microblaze/mmu.c
index 281fc8d..7c34ac0 100644
--- a/target-microblaze/mmu.c
+++ b/target-microblaze/mmu.c
@@ -16,11 +16,7 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
 
-#include "config.h"
 #include "cpu.h"
 
 #define D(x)
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 96ce2ec..725c2dd 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -17,19 +17,11 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
-#include <assert.h>
-
 #include "cpu.h"
 #include "disas.h"
 #include "tcg-op.h"
 #include "helper.h"
 #include "microblaze-decode.h"
-#include "qemu-common.h"
 
 #define GEN_HELPER 1
 #include "helper.h"
commit 3aef481a6b043e6995d2edef49e89489b4f1e2cc
Author: Stefan Weil <sw at weilnetz.de>
Date:   Wed Feb 1 20:55:18 2012 +0100

    target-m68k: Clean includes
    
    config.h was missing in cpu.h.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index 0667f82..4cc3a35 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -24,6 +24,7 @@
 
 #define CPUState struct CPUM68KState
 
+#include "config.h"
 #include "qemu-common.h"
 #include "cpu-defs.h"
 
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 674c8e6..fa675bf 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -18,12 +18,7 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <stdio.h>
-#include <string.h>
-
-#include "config.h"
 #include "cpu.h"
-#include "qemu-common.h"
 #include "gdbstub.h"
 
 #include "helpers.h"
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 0e7f1fe..2bdd9dd 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -17,13 +17,7 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
 
-#include "config.h"
 #include "cpu.h"
 #include "disas.h"
 #include "tcg-op.h"
commit 60ed8d298e1e75b80a560dc5c3f25582aa1fc548
Author: Stefan Weil <sw at weilnetz.de>
Date:   Wed Feb 1 20:54:57 2012 +0100

    target-lm32: Clean includes
    
    config.h was missing in cpu.h.
    
    Acked-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index 037ef52..b6b6b4c 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -24,6 +24,7 @@
 
 #define CPUState struct CPULM32State
 
+#include "config.h"
 #include "qemu-common.h"
 #include "cpu-defs.h"
 struct CPULM32State;
diff --git a/target-lm32/helper.c b/target-lm32/helper.c
index fc0b444..2637c03 100644
--- a/target-lm32/helper.c
+++ b/target-lm32/helper.c
@@ -17,11 +17,6 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-
-#include "config.h"
 #include "cpu.h"
 #include "host-utils.h"
 
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index 0be105d..c80e48b 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -17,18 +17,10 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
-#include <assert.h>
-
 #include "cpu.h"
 #include "disas.h"
 #include "helper.h"
 #include "tcg-op.h"
-#include "qemu-common.h"
 
 #include "hw/lm32_pic.h"
 
commit 727d6bff27a176f12180149edffb3c52f07132c8
Author: Stefan Weil <sw at weilnetz.de>
Date:   Wed Feb 1 20:54:13 2012 +0100

    target-i386: Clean includes
    
    Remove some include statements which are not needed.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/target-i386/helper.c b/target-i386/helper.c
index 2586aff..87c6a8f 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -16,14 +16,8 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
 
 #include "cpu.h"
-#include "qemu-common.h"
 #include "kvm.h"
 #ifndef CONFIG_USER_ONLY
 #include "sysemu.h"
diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index 2aea71b..63a08d6 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -22,7 +22,6 @@
 #include "dyngen-exec.h"
 #include "host-utils.h"
 #include "ioport.h"
-#include "qemu-common.h"
 #include "qemu-log.h"
 #include "cpu-defs.h"
 #include "helper.h"
commit 7ad757b29b5096ae100d646c584036b4892c9be5
Author: Stefan Weil <sw at weilnetz.de>
Date:   Wed Feb 1 20:53:33 2012 +0100

    target-cris: Clean includes
    
    The change in cpu.h is needed when HOST_LONG_BITS is defined in qemu-common.h.
    
    Cc: Edgar E. Iglesias <edgar.iglesias at gmail.com>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index 453afbb..222a062 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -20,6 +20,9 @@
 #ifndef CPU_CRIS_H
 #define CPU_CRIS_H
 
+#include "config.h"
+#include "qemu-common.h"
+
 #define TARGET_LONG_BITS 32
 
 #define CPUState struct CPUCRISState
diff --git a/target-cris/helper.c b/target-cris/helper.c
index 5bc6d81..dd7f18e 100644
--- a/target-cris/helper.c
+++ b/target-cris/helper.c
@@ -18,10 +18,6 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <stdio.h>
-#include <string.h>
-
-#include "config.h"
 #include "cpu.h"
 #include "mmu.h"
 #include "host-utils.h"
diff --git a/target-cris/mmu.c b/target-cris/mmu.c
index d481e39..5cd8f27 100644
--- a/target-cris/mmu.c
+++ b/target-cris/mmu.c
@@ -20,11 +20,6 @@
 
 #ifndef CONFIG_USER_ONLY
 
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "config.h"
 #include "cpu.h"
 #include "mmu.h"
 
diff --git a/target-cris/translate.c b/target-cris/translate.c
index 70abf8a..cbdc72c 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -23,19 +23,12 @@
  * The condition code translation is in need of attention.
  */
 
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
-
 #include "cpu.h"
 #include "disas.h"
 #include "tcg-op.h"
 #include "helper.h"
 #include "mmu.h"
 #include "crisv32-decode.h"
-#include "qemu-common.h"
 
 #define GEN_HELPER 1
 #include "helper.h"
commit 853bfcc71afc5436830cfcb58bc31622024eaf7c
Author: Stefan Weil <sw at weilnetz.de>
Date:   Wed Feb 1 20:53:02 2012 +0100

    target-arm: Clean includes
    
    Remove some include statements which are not needed.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 4929372..abe1c30 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1,11 +1,6 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
 #include "cpu.h"
 #include "gdbstub.h"
 #include "helper.h"
-#include "qemu-common.h"
 #include "host-utils.h"
 #if !defined(CONFIG_USER_ONLY)
 #include "hw/loader.h"
commit 2c9762973cbee50de591cf63c05d0e79218be60c
Author: Stefan Weil <sw at weilnetz.de>
Date:   Wed Feb 1 20:51:52 2012 +0100

    target-alpha: Clean includes
    
    The change in cpu.h is needed when HOST_LONG_BITS is defined in qemu-common.h.
    
    Cc: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 9d61d45..5cd6fd8 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -21,6 +21,7 @@
 #define __CPU_ALPHA_H__
 
 #include "config.h"
+#include "qemu-common.h"
 
 #define TARGET_LONG_BITS 64
 
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index a961159..1d2142b 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -17,15 +17,10 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <stdint.h>
-#include <stdlib.h>
-#include <stdio.h>
-
 #include "cpu.h"
 #include "disas.h"
 #include "host-utils.h"
 #include "tcg-op.h"
-#include "qemu-common.h"
 
 #include "helper.h"
 #define GEN_HELPER 1
commit 9c6ecf3e76311ac04cf1779f0c9beef831c152b5
Author: Stefan Weil <sw at weilnetz.de>
Date:   Wed Feb 1 20:50:10 2012 +0100

    Remove macro HOST_LONG_SIZE
    
    HOST_LONG_SIZE is simply the size of a pointer value.
    There is no need for this macro.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/cpu-defs.h b/cpu-defs.h
index 57a709b..4527cbf 100644
--- a/cpu-defs.h
+++ b/cpu-defs.h
@@ -60,8 +60,6 @@ typedef uint64_t target_ulong __attribute__((aligned(TARGET_LONG_ALIGNMENT)));
 #error TARGET_LONG_SIZE undefined
 #endif
 
-#define HOST_LONG_SIZE (HOST_LONG_BITS / 8)
-
 #define EXCP_INTERRUPT 	0x10000 /* async interruption */
 #define EXCP_HLT        0x10001 /* hlt instruction reached */
 #define EXCP_DEBUG      0x10002 /* cpu stopped after a breakpoint or singlestep */
diff --git a/thunk.h b/thunk.h
index 109c541..9810743 100644
--- a/thunk.h
+++ b/thunk.h
@@ -99,7 +99,7 @@ static inline int thunk_type_size(const argtype *type_ptr, int is_host)
     case TYPE_PTRVOID:
     case TYPE_PTR:
         if (is_host) {
-            return HOST_LONG_SIZE;
+            return sizeof(void *);
         } else {
             return TARGET_ABI_BITS / 8;
         }
@@ -136,7 +136,7 @@ static inline int thunk_type_align(const argtype *type_ptr, int is_host)
     case TYPE_PTRVOID:
     case TYPE_PTR:
         if (is_host) {
-            return HOST_LONG_SIZE;
+            return sizeof(void *);
         } else {
             return TARGET_ABI_BITS / 8;
         }
commit e2efc0a3267811a2b9459116b2310325ef011f6e
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Feb 27 11:05:09 2012 +0100

    qxl: properly handle upright and non-shared surfaces
    
    Although qxl creates a shared displaysurface when the qxl surface is
    upright and doesn't need to be flipped there is no guarantee that the
    surface doesn't become unshared for some reason.  Rename qxl_flip to
    qxl_blit and fix it to handle both flip and non-flip cases.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index f323a4d..25857f6 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -21,25 +21,31 @@
 
 #include "qxl.h"
 
-static void qxl_flip(PCIQXLDevice *qxl, QXLRect *rect)
+static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect)
 {
     uint8_t *src;
     uint8_t *dst = qxl->vga.ds->surface->data;
     int len, i;
 
-    if (qxl->guest_primary.qxl_stride > 0) {
+    if (is_buffer_shared(qxl->vga.ds->surface)) {
         return;
     }
     if (!qxl->guest_primary.data) {
         dprint(qxl, 1, "%s: initializing guest_primary.data\n", __func__);
         qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram);
     }
-    dprint(qxl, 1, "%s: stride %d, [%d, %d, %d, %d]\n", __func__,
+    dprint(qxl, 2, "%s: stride %d, [%d, %d, %d, %d]\n", __func__,
             qxl->guest_primary.qxl_stride,
             rect->left, rect->right, rect->top, rect->bottom);
     src = qxl->guest_primary.data;
-    src += (qxl->guest_primary.surface.height - rect->top - 1) *
-        qxl->guest_primary.abs_stride;
+    if (qxl->guest_primary.qxl_stride < 0) {
+        /* qxl surface is upside down, walk src scanlines
+         * in reverse order to flip it */
+        src += (qxl->guest_primary.surface.height - rect->top - 1) *
+            qxl->guest_primary.abs_stride;
+    } else {
+        src += rect->top * qxl->guest_primary.abs_stride;
+    }
     dst += rect->top  * qxl->guest_primary.abs_stride;
     src += rect->left * qxl->guest_primary.bytes_pp;
     dst += rect->left * qxl->guest_primary.bytes_pp;
@@ -48,7 +54,7 @@ static void qxl_flip(PCIQXLDevice *qxl, QXLRect *rect)
     for (i = rect->top; i < rect->bottom; i++) {
         memcpy(dst, src, len);
         dst += qxl->guest_primary.abs_stride;
-        src -= qxl->guest_primary.abs_stride;
+        src += qxl->guest_primary.qxl_stride;
     }
 }
 
@@ -132,7 +138,7 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
         if (qemu_spice_rect_is_empty(qxl->dirty+i)) {
             break;
         }
-        qxl_flip(qxl, qxl->dirty+i);
+        qxl_blit(qxl, qxl->dirty+i);
         dpy_update(vga->ds,
                    qxl->dirty[i].left, qxl->dirty[i].top,
                    qxl->dirty[i].right - qxl->dirty[i].left,
commit 35c633291439185d3bbf84da23db1572498e0d5d
Author: Christophe Fergeau <cfergeau at redhat.com>
Date:   Fri Feb 24 18:28:32 2012 +0100

    Error out when tls-channel option is used without TLS
    
    It's currently possible to setup spice channels using TLS when
    no TLS port has been specified (ie TLS is disabled). This cannot
    work, so better to error out in such a situation.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/spice-core.c b/ui/spice-core.c
index e761813..c1091e1 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -511,6 +511,12 @@ static int add_channel(const char *name, const char *value, void *opaque)
     int rc;
 
     if (strcmp(name, "tls-channel") == 0) {
+        int *tls_port = opaque;
+        if (!*tls_port) {
+            error_report("spice: tried to setup tls-channel"
+                         " without specifying a TLS port");
+            exit(1);
+        }
         security = SPICE_CHANNEL_SECURITY_SSL;
     }
     if (strcmp(name, "plaintext-channel") == 0) {
@@ -680,7 +686,7 @@ void qemu_spice_init(void)
     spice_server_set_playback_compression
         (spice_server, qemu_opt_get_bool(opts, "playback-compression", 1));
 
-    qemu_opt_foreach(opts, add_channel, NULL, 0);
+    qemu_opt_foreach(opts, add_channel, &tls_port, 0);
 
     if (0 != spice_server_init(spice_server, &core_interface)) {
         error_report("failed to initialize spice server");
commit 339a475f50ae0df8d2e222e47f1264811d5f6bee
Author: Christophe Fergeau <cfergeau at redhat.com>
Date:   Fri Feb 24 18:13:12 2012 +0100

    spice: use error_report to report errors
    
    Error message reporting during spice startup wasn't consistent, it was done
    with fprintf(stderr, "") but sometimes the message didn't have a trailing
    \n. Using error_report make the intent of the message clearer and deal
    with the final \n for us.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/spice-core.c b/ui/spice-core.c
index 30d2c62..e761813 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -227,8 +227,8 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
         add_addr_info(server, (struct sockaddr *)&info->laddr_ext,
                       info->llen_ext);
     } else {
-        fprintf(stderr, "spice: %s, extended address is expected\n",
-                        __func__);
+        error_report("spice: %s, extended address is expected",
+                     __func__);
 #endif
         add_addr_info(client, &info->paddr, info->plen);
         add_addr_info(server, &info->laddr, info->llen);
@@ -333,7 +333,7 @@ static int parse_name(const char *string, const char *optname,
     if (value != -1) {
         return value;
     }
-    fprintf(stderr, "spice: invalid %s: %s\n", optname, string);
+    error_report("spice: invalid %s: %s", optname, string);
     exit(1);
 }
 
@@ -525,7 +525,7 @@ static int add_channel(const char *name, const char *value, void *opaque)
         rc = spice_server_set_channel_security(spice_server, value, security);
     }
     if (rc != 0) {
-        fprintf(stderr, "spice: failed to set channel security for %s\n", value);
+        error_report("spice: failed to set channel security for %s", value);
         exit(1);
     }
     return 0;
@@ -553,15 +553,15 @@ void qemu_spice_init(void)
     port = qemu_opt_get_number(opts, "port", 0);
     tls_port = qemu_opt_get_number(opts, "tls-port", 0);
     if (!port && !tls_port) {
-        fprintf(stderr, "neither port nor tls-port specified for spice.");
+        error_report("neither port nor tls-port specified for spice");
         exit(1);
     }
     if (port < 0 || port > 65535) {
-        fprintf(stderr, "spice port is out of range");
+        error_report("spice port is out of range");
         exit(1);
     }
     if (tls_port < 0 || tls_port > 65535) {
-        fprintf(stderr, "spice tls-port is out of range");
+        error_report("spice tls-port is out of range");
         exit(1);
     }
     password = qemu_opt_get(opts, "password");
@@ -631,11 +631,11 @@ void qemu_spice_init(void)
 #if SPICE_SERVER_VERSION >= 0x000900 /* 0.9.0 */
         if (spice_server_set_sasl_appname(spice_server, "qemu") == -1 ||
             spice_server_set_sasl(spice_server, 1) == -1) {
-            fprintf(stderr, "spice: failed to enable sasl\n");
+            error_report("spice: failed to enable sasl");
             exit(1);
         }
 #else
-        fprintf(stderr, "spice: sasl is not available (spice >= 0.9 required)\n");
+        error_report("spice: sasl is not available (spice >= 0.9 required)");
         exit(1);
 #endif
     }
@@ -683,7 +683,7 @@ void qemu_spice_init(void)
     qemu_opt_foreach(opts, add_channel, NULL, 0);
 
     if (0 != spice_server_init(spice_server, &core_interface)) {
-        fprintf(stderr, "failed to initialize spice server");
+        error_report("failed to initialize spice server");
         exit(1);
     };
     using_spice = 1;
@@ -708,7 +708,7 @@ int qemu_spice_add_interface(SpiceBaseInstance *sin)
 {
     if (!spice_server) {
         if (QTAILQ_FIRST(&qemu_spice_opts.head) != NULL) {
-            fprintf(stderr, "Oops: spice configured but not active\n");
+            error_report("Oops: spice configured but not active");
             exit(1);
         }
         /*
commit 6f2b175a090f367c3aab2226c4741b439671307a
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Oct 14 18:05:48 2011 +0200

    qxl: add optinal 64bit vram bar
    
    This patch adds an 64bit pci bar for vram.  It is turned off by default.
    It can be enabled by setting the size of the 64bit bar to be larger than
    the 32bit bar.  Both 32bit and 64bit bar refer to the same memory.  Only
    the first part of the memory is available via 32bit bar.
    
    The intention is to allow large vram sizes for 64bit guests, by allowing
    the vram bar being mapped above 4G, so we don't have to squeeze it into
    the pci I/O window below 4G.
    
    With vram_size_mb=16 and vram64_size_mb=256 it looks like this:
    
    00:02.0 VGA compatible controller: Red Hat, Inc. Device 0100 (rev 02) (prog-if 00 [VGA controller])
            Subsystem: Red Hat, Inc Device 1100
            Physical Slot: 2
            Flags: fast devsel, IRQ 10
            Memory at f8000000 (32-bit, non-prefetchable) [size=64M]
            Memory at fc000000 (32-bit, non-prefetchable) [size=16M]
            Memory at fd020000 (32-bit, non-prefetchable) [size=8K]
            I/O ports at c5a0 [size=32]
            Memory at ffe0000000 (64-bit, prefetchable) [size=256M]
            Expansion ROM at fd000000 [disabled] [size=64K]
    
    [ mapping above 4G needs patched seabios:
      http://www.kraxel.org/cgit/seabios/commit/?h=pci64 ]

diff --git a/hw/qxl.c b/hw/qxl.c
index d83d245..e17b0e3 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -976,6 +976,7 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
     static const int regions[] = {
         QXL_RAM_RANGE_INDEX,
         QXL_VRAM_RANGE_INDEX,
+        QXL_VRAM64_RANGE_INDEX,
     };
     uint64_t guest_start;
     uint64_t guest_end;
@@ -1022,6 +1023,7 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
         virt_start = (intptr_t)memory_region_get_ram_ptr(&d->vga.vram);
         break;
     case QXL_VRAM_RANGE_INDEX:
+    case 4 /* vram 64bit */:
         virt_start = (intptr_t)memory_region_get_ram_ptr(&d->vram_bar);
         break;
     default:
@@ -1622,18 +1624,28 @@ static void qxl_init_ramsize(PCIQXLDevice *qxl, uint32_t ram_min_mb)
         qxl->vga.vram_size = ram_min_mb * 1024 * 1024;
     }
 
-    /* vram (surfaces, bar 1) */
+    /* vram32 (surfaces, 32bit, bar 1) */
+    if (qxl->vram32_size_mb != -1) {
+        qxl->vram32_size = qxl->vram32_size_mb * 1024 * 1024;
+    }
+    if (qxl->vram32_size < 4096) {
+        qxl->vram32_size = 4096;
+    }
+
+    /* vram (surfaces, 64bit, bar 4+5) */
     if (qxl->vram_size_mb != -1) {
         qxl->vram_size = qxl->vram_size_mb * 1024 * 1024;
     }
-    if (qxl->vram_size < 4096) {
-        qxl->vram_size = 4096;
+    if (qxl->vram_size < qxl->vram32_size) {
+        qxl->vram_size = qxl->vram32_size;
     }
+
     if (qxl->revision == 1) {
+        qxl->vram32_size = 4096;
         qxl->vram_size = 4096;
     }
-
     qxl->vga.vram_size = msb_mask(qxl->vga.vram_size * 2 - 1);
+    qxl->vram32_size = msb_mask(qxl->vram32_size * 2 - 1);
     qxl->vram_size = msb_mask(qxl->vram_size * 2 - 1);
 }
 
@@ -1675,6 +1687,8 @@ static int qxl_init_common(PCIQXLDevice *qxl)
 
     memory_region_init_ram(&qxl->vram_bar, "qxl.vram", qxl->vram_size);
     vmstate_register_ram(&qxl->vram_bar, &qxl->pci.qdev);
+    memory_region_init_alias(&qxl->vram32_bar, "qxl.vram32", &qxl->vram_bar,
+                             0, qxl->vram32_size);
 
     io_size = msb_mask(QXL_IO_RANGE_SIZE * 2 - 1);
     if (qxl->revision == 1) {
@@ -1698,7 +1712,29 @@ static int qxl_init_common(PCIQXLDevice *qxl)
                      PCI_BASE_ADDRESS_SPACE_MEMORY, &qxl->vga.vram);
 
     pci_register_bar(&qxl->pci, QXL_VRAM_RANGE_INDEX,
-                     PCI_BASE_ADDRESS_SPACE_MEMORY, &qxl->vram_bar);
+                     PCI_BASE_ADDRESS_SPACE_MEMORY, &qxl->vram32_bar);
+
+    if (qxl->vram32_size < qxl->vram_size) {
+        /*
+         * Make the 64bit vram bar show up only in case it is
+         * configured to be larger than the 32bit vram bar.
+         */
+        pci_register_bar(&qxl->pci, QXL_VRAM64_RANGE_INDEX,
+                         PCI_BASE_ADDRESS_SPACE_MEMORY |
+                         PCI_BASE_ADDRESS_MEM_TYPE_64 |
+                         PCI_BASE_ADDRESS_MEM_PREFETCH,
+                         &qxl->vram_bar);
+    }
+
+    /* print pci bar details */
+    dprint(qxl, 1, "ram/%s: %d MB [region 0]\n",
+           qxl->id == 0 ? "pri" : "sec",
+           qxl->vga.vram_size / (1024*1024));
+    dprint(qxl, 1, "vram/32: %d MB [region 1]\n",
+           qxl->vram32_size / (1024*1024));
+    dprint(qxl, 1, "vram/64: %d MB %s\n",
+           qxl->vram_size / (1024*1024),
+           qxl->vram32_size < qxl->vram_size ? "[region 4]" : "[unmapped]");
 
     qxl->ssd.qxl.base.sif = &qxl_interface.base;
     qxl->ssd.qxl.id = qxl->id;
@@ -1917,7 +1953,7 @@ static VMStateDescription qxl_vmstate = {
 static Property qxl_properties[] = {
         DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size,
                            64 * 1024 * 1024),
-        DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size,
+        DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram32_size,
                            64 * 1024 * 1024),
         DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision,
                            QXL_DEFAULT_REVISION),
@@ -1925,7 +1961,8 @@ static Property qxl_properties[] = {
         DEFINE_PROP_UINT32("guestdebug", PCIQXLDevice, guestdebug, 0),
         DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0),
         DEFINE_PROP_UINT32("ram_size_mb",  PCIQXLDevice, ram_size_mb, -1),
-        DEFINE_PROP_UINT32("vram_size_mb", PCIQXLDevice, vram_size_mb, -1),
+        DEFINE_PROP_UINT32("vram_size_mb", PCIQXLDevice, vram32_size_mb, 0),
+        DEFINE_PROP_UINT32("vram64_size_mb", PCIQXLDevice, vram_size_mb, 0),
         DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/qxl.h b/hw/qxl.h
index 86e415b..11a0db3 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -16,6 +16,10 @@ enum qxl_mode {
     QXL_MODE_NATIVE,
 };
 
+#ifndef QXL_VRAM64_RANGE_INDEX
+#define QXL_VRAM64_RANGE_INDEX 4
+#endif
+
 #define QXL_UNDEFINED_IO UINT32_MAX
 
 #define QXL_NUM_DIRTY_RECTS 64
@@ -88,6 +92,8 @@ typedef struct PCIQXLDevice {
     /* vram pci bar */
     uint32_t           vram_size;
     MemoryRegion       vram_bar;
+    uint32_t           vram32_size;
+    MemoryRegion       vram32_bar;
 
     /* io bar */
     MemoryRegion       io_bar;
@@ -95,6 +101,7 @@ typedef struct PCIQXLDevice {
     /* user-friendly properties (in megabytes) */
     uint32_t          ram_size_mb;
     uint32_t          vram_size_mb;
+    uint32_t          vram32_size_mb;
 
     /* qxl_render_update state */
     int                render_update_cookie_num;
commit b55c952aea6de024bf1a06357b49367fba045443
Merge: 90d7416... 67d6fa5...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Feb 27 11:19:27 2012 -0600

    Merge remote-tracking branch 'aneesh/for-upstream' into staging
    
    * aneesh/for-upstream:
      hw/9pfs: Endian fixes for virtfs
      ./configure: add option for disabling VirtFS

commit 3741715cf2e54727fe3d9884ea6dcea68c7f7d4b
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Feb 27 15:18:47 2012 +0100

    usb: Resolve warnings about unassigned bus on usb device creation
    
    When creating an USB device the old way, there is no way to specify the
    target bus. Thus the warning issued by usb_create makes no sense and
    rather confuses our users.
    
    Resolve this by passing a bus reference to the usbdevice_init handler
    and letting those handlers forward it to usb_create.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-bt.c b/hw/usb-bt.c
index 649bdcf..23c39ec 100644
--- a/hw/usb-bt.c
+++ b/hw/usb-bt.c
@@ -498,14 +498,14 @@ static int usb_bt_initfn(USBDevice *dev)
     return 0;
 }
 
-USBDevice *usb_bt_init(HCIInfo *hci)
+USBDevice *usb_bt_init(USBBus *bus, HCIInfo *hci)
 {
     USBDevice *dev;
     struct USBBtState *s;
 
     if (!hci)
         return NULL;
-    dev = usb_create_simple(NULL /* FIXME */, "usb-bt-dongle");
+    dev = usb_create_simple(bus, "usb-bt-dongle");
     if (!dev) {
         return NULL;
     }
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index ae79a45..70b7ebc 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -203,13 +203,14 @@ typedef struct LegacyUSBFactory
 {
     const char *name;
     const char *usbdevice_name;
-    USBDevice *(*usbdevice_init)(const char *params);
+    USBDevice *(*usbdevice_init)(USBBus *bus, const char *params);
 } LegacyUSBFactory;
 
 static GSList *legacy_usb_factory;
 
 void usb_legacy_register(const char *typename, const char *usbdevice_name,
-                         USBDevice *(*usbdevice_init)(const char *params))
+                         USBDevice *(*usbdevice_init)(USBBus *bus,
+                                                      const char *params))
 {
     if (usbdevice_name) {
         LegacyUSBFactory *f = g_malloc0(sizeof(*f));
@@ -224,17 +225,6 @@ USBDevice *usb_create(USBBus *bus, const char *name)
 {
     DeviceState *dev;
 
-#if 1
-    /* temporary stopgap until all usb is properly qdev-ified */
-    if (!bus) {
-        bus = usb_bus_find(-1);
-        if (!bus)
-            return NULL;
-        error_report("%s: no bus specified, using \"%s\" for \"%s\"",
-                __FUNCTION__, bus->qbus.name, name);
-    }
-#endif
-
     dev = qdev_create(&bus->qbus, name);
     return USB_DEVICE(dev);
 }
@@ -565,7 +555,7 @@ USBDevice *usbdevice_create(const char *cmdline)
         }
         return usb_create_simple(bus, f->name);
     }
-    return f->usbdevice_init(params);
+    return f->usbdevice_init(bus, params);
 }
 
 static void usb_device_class_init(ObjectClass *klass, void *data)
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 5fbd2d0..c6f08a0 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -568,7 +568,7 @@ static int usb_msd_initfn(USBDevice *dev)
     return 0;
 }
 
-static USBDevice *usb_msd_init(const char *filename)
+static USBDevice *usb_msd_init(USBBus *bus, const char *filename)
 {
     static int nr=0;
     char id[8];
@@ -611,7 +611,7 @@ static USBDevice *usb_msd_init(const char *filename)
     }
 
     /* create guest device */
-    dev = usb_create(NULL /* FIXME */, "usb-storage");
+    dev = usb_create(bus, "usb-storage");
     if (!dev) {
         return NULL;
     }
diff --git a/hw/usb-net.c b/hw/usb-net.c
index 49d5d4d..22b8201 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -1353,7 +1353,7 @@ static int usb_net_initfn(USBDevice *dev)
     return 0;
 }
 
-static USBDevice *usb_net_init(const char *cmdline)
+static USBDevice *usb_net_init(USBBus *bus, const char *cmdline)
 {
     USBDevice *dev;
     QemuOpts *opts;
@@ -1371,7 +1371,7 @@ static USBDevice *usb_net_init(const char *cmdline)
         return NULL;
     }
 
-    dev = usb_create(NULL /* FIXME */, "usb-net");
+    dev = usb_create(bus, "usb-net");
     if (!dev) {
         return NULL;
     }
diff --git a/hw/usb-serial.c b/hw/usb-serial.c
index 52676e8..0aae379 100644
--- a/hw/usb-serial.c
+++ b/hw/usb-serial.c
@@ -492,7 +492,7 @@ static int usb_serial_initfn(USBDevice *dev)
     return 0;
 }
 
-static USBDevice *usb_serial_init(const char *filename)
+static USBDevice *usb_serial_init(USBBus *bus, const char *filename)
 {
     USBDevice *dev;
     CharDriverState *cdrv;
@@ -535,7 +535,7 @@ static USBDevice *usb_serial_init(const char *filename)
     if (!cdrv)
         return NULL;
 
-    dev = usb_create(NULL /* FIXME */, "usb-serial");
+    dev = usb_create(bus, "usb-serial");
     if (!dev) {
         return NULL;
     }
@@ -549,7 +549,7 @@ static USBDevice *usb_serial_init(const char *filename)
     return dev;
 }
 
-static USBDevice *usb_braille_init(const char *unused)
+static USBDevice *usb_braille_init(USBBus *bus, const char *unused)
 {
     USBDevice *dev;
     CharDriverState *cdrv;
@@ -558,7 +558,7 @@ static USBDevice *usb_braille_init(const char *unused)
     if (!cdrv)
         return NULL;
 
-    dev = usb_create(NULL /* FIXME */, "usb-braille");
+    dev = usb_create(bus, "usb-braille");
     qdev_prop_set_chr(&dev->qdev, "chardev", cdrv);
     qdev_init_nofail(&dev->qdev);
 
diff --git a/hw/usb.h b/hw/usb.h
index 4470ea8..8e83697 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -373,12 +373,12 @@ void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p);
 int set_usb_string(uint8_t *buf, const char *str);
 
 /* usb-linux.c */
-USBDevice *usb_host_device_open(const char *devname);
+USBDevice *usb_host_device_open(USBBus *bus, const char *devname);
 int usb_host_device_close(const char *devname);
 void usb_host_info(Monitor *mon);
 
 /* usb-bt.c */
-USBDevice *usb_bt_init(HCIInfo *hci);
+USBDevice *usb_bt_init(USBBus *bus, HCIInfo *hci);
 
 /* usb ports of the VM */
 
@@ -431,7 +431,8 @@ struct USBBusOps {
 void usb_bus_new(USBBus *bus, USBBusOps *ops, DeviceState *host);
 USBBus *usb_bus_find(int busnr);
 void usb_legacy_register(const char *typename, const char *usbdevice_name,
-                         USBDevice *(*usbdevice_init)(const char *params));
+                         USBDevice *(*usbdevice_init)(USBBus *bus,
+                                                      const char *params));
 USBDevice *usb_create(USBBus *bus, const char *name);
 USBDevice *usb_create_simple(USBBus *bus, const char *name);
 USBDevice *usbdevice_create(const char *cmdline);
diff --git a/usb-bsd.c b/usb-bsd.c
index 4fa4b42..ec26266 100644
--- a/usb-bsd.c
+++ b/usb-bsd.c
@@ -298,7 +298,7 @@ static int usb_host_initfn(USBDevice *dev)
     return 0;
 }
 
-USBDevice *usb_host_device_open(const char *devname)
+USBDevice *usb_host_device_open(USBBus *guest_bus, const char *devname)
 {
     struct usb_device_info bus_info, dev_info;
     USBDevice *d = NULL, *ret = NULL;
@@ -358,7 +358,7 @@ USBDevice *usb_host_device_open(const char *devname)
         goto fail_dfd;
     }
 
-    d = usb_create(NULL /* FIXME */, "usb-host");
+    d = usb_create(guest_bus, "usb-host");
     dev = DO_UPCAST(USBHostDevice, dev, d);
 
     if (dev_info.udi_speed == 1) {
diff --git a/usb-linux.c b/usb-linux.c
index 24700fc..47994f3 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -1443,13 +1443,13 @@ static void usb_host_register_types(void)
 
 type_init(usb_host_register_types)
 
-USBDevice *usb_host_device_open(const char *devname)
+USBDevice *usb_host_device_open(USBBus *bus, const char *devname)
 {
     struct USBAutoFilter filter;
     USBDevice *dev;
     char *p;
 
-    dev = usb_create(NULL /* FIXME */, "usb-host");
+    dev = usb_create(bus, "usb-host");
 
     if (strstr(devname, "auto:")) {
         if (parse_filter(devname, &filter) < 0) {
diff --git a/vl.c b/vl.c
index 1d4c350..4a77696 100644
--- a/vl.c
+++ b/vl.c
@@ -1052,12 +1052,13 @@ static int usb_device_add(const char *devname)
 #ifndef CONFIG_LINUX
     /* only the linux version is qdev-ified, usb-bsd still needs this */
     if (strstart(devname, "host:", &p)) {
-        dev = usb_host_device_open(p);
+        dev = usb_host_device_open(usb_bus_find(-1), p);
     } else
 #endif
     if (!strcmp(devname, "bt") || strstart(devname, "bt:", &p)) {
-        dev = usb_bt_init(devname[2] ? hci_init(p) :
-                        bt_new_hci(qemu_find_bt_vlan(0)));
+        dev = usb_bt_init(usb_bus_find(-1),
+                          devname[2] ? hci_init(p)
+                                     : bt_new_hci(qemu_find_bt_vlan(0)));
     } else {
         return -1;
     }
commit 90d7416ab13113ccd3891435eea8715c5f503460
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Feb 24 01:23:28 2012 +0100

    slirp: Fix assertion failure on rejected DHCP requests
    
    The guest network stack might DHCPREQUEST an address that the slirp built
    in dhcp server can't let it have - for example if the guest has an old
    leases file from another network configuration.  In this case the dhcp
    server should and does reject the request and prepares to send a DHCPNAK
    to the client.
    
    However, in this case the daddr variable in bootp_reply() is set to
    0.0.0.0.  Shortly afterwards, it unconditionally attempts to pre-insert the
    new client address into the ARP table.  This causes an assertion failure in
    arp_address_add() because of the 0.0.0.0 address.
    
    According to RFC2131, DHCPNAK messages for clients on the same subnet
    must be sent to the broadcast address (S3.2, subpoint 2).
    
    Cc: Jan Kiszka <jan.kiszka at siemens.com>
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>

diff --git a/slirp/bootp.c b/slirp/bootp.c
index efd1fe7..64eac7d 100644
--- a/slirp/bootp.c
+++ b/slirp/bootp.c
@@ -200,7 +200,8 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
             daddr.sin_addr = preq_addr;
             memcpy(bc->macaddr, client_ethaddr, ETH_ALEN);
         } else {
-            daddr.sin_addr.s_addr = 0;
+            /* DHCPNAKs should be sent to broadcast */
+            daddr.sin_addr.s_addr = 0xffffffff;
         }
     } else {
         bc = find_addr(slirp, &daddr.sin_addr, bp->bp_hwaddr);
commit b87ffa163185e339f9f9f1e6dbc561e0f990442d
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Feb 17 16:35:36 2012 +0100

    slirp: Refactor if_start
    
    Replace gotos with a while loop, fix coding style.
    
    CC: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com>
    CC: Fabien Chouteau <chouteau at adacore.com>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>

diff --git a/slirp/if.c b/slirp/if.c
index 710ec23..33f08e1 100644
--- a/slirp/if.c
+++ b/slirp/if.c
@@ -149,39 +149,36 @@ diddit:
  * from the second session, then one packet from the third, then back
  * to the first, etc. etc.
  */
-void
-if_start(Slirp *slirp)
+void if_start(Slirp *slirp)
 {
     uint64_t now = qemu_get_clock_ns(rt_clock);
     int requeued = 0;
     bool from_batchq = false;
-	struct mbuf *ifm, *ifqt;
-
-	DEBUG_CALL("if_start");
+    struct mbuf *ifm, *ifqt;
 
-	if (slirp->if_queued == 0)
-	   return; /* Nothing to do */
+    DEBUG_CALL("if_start");
 
- again:
+    while (slirp->if_queued) {
         /* check if we can really output */
         if (!slirp_can_output(slirp->opaque))
             return;
 
-	/*
-	 * See which queue to get next packet from
-	 * If there's something in the fastq, select it immediately
-	 */
-	if (slirp->if_fastq.ifq_next != &slirp->if_fastq) {
-		ifm = slirp->if_fastq.ifq_next;
-	} else {
-		/* Nothing on fastq, see if next_m is valid */
-		if (slirp->next_m != &slirp->if_batchq)
-		   ifm = slirp->next_m;
-		else
-		   ifm = slirp->if_batchq.ifq_next;
-
-                from_batchq = true;
-	}
+        /*
+         * See which queue to get next packet from
+         * If there's something in the fastq, select it immediately
+         */
+        if (slirp->if_fastq.ifq_next != &slirp->if_fastq) {
+            ifm = slirp->if_fastq.ifq_next;
+        } else {
+            /* Nothing on fastq, see if next_m is valid */
+            if (slirp->next_m != &slirp->if_batchq) {
+                ifm = slirp->next_m;
+            } else {
+                ifm = slirp->if_batchq.ifq_next;
+            }
+
+            from_batchq = true;
+        }
 
         slirp->if_queued--;
 
@@ -189,7 +186,7 @@ if_start(Slirp *slirp)
         if (ifm->expiration_date >= now && !if_encap(slirp, ifm)) {
             /* Packet is delayed due to pending ARP resolution */
             requeued++;
-            goto out;
+            continue;
         }
 
         if (from_batchq) {
@@ -197,28 +194,25 @@ if_start(Slirp *slirp)
             slirp->next_m = ifm->ifq_next;
         }
 
-	/* Remove it from the queue */
-	ifqt = ifm->ifq_prev;
-	remque(ifm);
+        /* Remove it from the queue */
+        ifqt = ifm->ifq_prev;
+        remque(ifm);
 
-	/* If there are more packets for this session, re-queue them */
-	if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) {
-		insque(ifm->ifs_next, ifqt);
-		ifs_remque(ifm);
-	}
+        /* If there are more packets for this session, re-queue them */
+        if (ifm->ifs_next != ifm) {
+            insque(ifm->ifs_next, ifqt);
+            ifs_remque(ifm);
+        }
 
-	/* Update so_queued */
-	if (ifm->ifq_so) {
-		if (--ifm->ifq_so->so_queued == 0)
-		   /* If there's no more queued, reset nqueued */
-		   ifm->ifq_so->so_nqueued = 0;
-	}
+        /* Update so_queued */
+        if (ifm->ifq_so && --ifm->ifq_so->so_queued == 0) {
+            /* If there's no more queued, reset nqueued */
+            ifm->ifq_so->so_nqueued = 0;
+        }
 
         m_free(ifm);
 
- out:
-	if (slirp->if_queued)
-	   goto again;
+    }
 
-        slirp->if_queued = requeued;
+    slirp->if_queued = requeued;
 }
commit b248ede2ef2792d364bd305e5e92e24921c924a8
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Feb 17 16:26:38 2012 +0100

    slirp: Fix requeuing of batchq packets in if_start
    
    In case we requeued a packet that was the head of a longer session
    queue, we failed to restore this ordering. Also, we did not properly
    deal with changes to Slirp::next_m.
    
    Instead of a cumbersome roll back, this fix simply avoids any changes
    until we know if the packet was actually sent. Both fixes crashes due
    to inconsistent queues and simplifies the logic.
    
    Thanks to Zhi Yong Wu who found the reason for these crashes.
    
    CC: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com>
    CC: Fabien Chouteau <chouteau at adacore.com>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>

diff --git a/slirp/if.c b/slirp/if.c
index 8e0cac2..710ec23 100644
--- a/slirp/if.c
+++ b/slirp/if.c
@@ -154,6 +154,7 @@ if_start(Slirp *slirp)
 {
     uint64_t now = qemu_get_clock_ns(rt_clock);
     int requeued = 0;
+    bool from_batchq = false;
 	struct mbuf *ifm, *ifqt;
 
 	DEBUG_CALL("if_start");
@@ -179,13 +180,26 @@ if_start(Slirp *slirp)
 		else
 		   ifm = slirp->if_batchq.ifq_next;
 
-		/* Set which packet to send on next iteration */
-		slirp->next_m = ifm->ifq_next;
+                from_batchq = true;
 	}
+
+        slirp->if_queued--;
+
+        /* Try to send packet unless it already expired */
+        if (ifm->expiration_date >= now && !if_encap(slirp, ifm)) {
+            /* Packet is delayed due to pending ARP resolution */
+            requeued++;
+            goto out;
+        }
+
+        if (from_batchq) {
+            /* Set which packet to send on next iteration */
+            slirp->next_m = ifm->ifq_next;
+        }
+
 	/* Remove it from the queue */
 	ifqt = ifm->ifq_prev;
 	remque(ifm);
-	slirp->if_queued--;
 
 	/* If there are more packets for this session, re-queue them */
 	if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) {
@@ -200,20 +214,9 @@ if_start(Slirp *slirp)
 		   ifm->ifq_so->so_nqueued = 0;
 	}
 
-        if (ifm->expiration_date < now) {
-            /* Expired */
-            m_free(ifm);
-        } else {
-            /* Encapsulate the packet for sending */
-            if (if_encap(slirp, ifm)) {
-                m_free(ifm);
-            } else {
-                /* re-queue */
-                insque(ifm, ifqt);
-                requeued++;
-            }
-        }
+        m_free(ifm);
 
+ out:
 	if (slirp->if_queued)
 	   goto again;
 
commit 79e7e937bd59ba8c4caaa08963712df2506adf8b
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Feb 17 14:39:30 2012 +0100

    slirp: Clean up ifs_init
    
    Remove duplicate ifs_init macros, reimplement the logic as static inline
    in mbuf.h.
    
    CC: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com>
    CC: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>

diff --git a/slirp/if.c b/slirp/if.c
index 2852396..8e0cac2 100644
--- a/slirp/if.c
+++ b/slirp/if.c
@@ -8,8 +8,6 @@
 #include <slirp.h>
 #include "qemu-timer.h"
 
-#define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))
-
 static void
 ifs_insque(struct mbuf *ifm, struct mbuf *ifmhead)
 {
diff --git a/slirp/if.h b/slirp/if.h
index 2dac1c7..3327023 100644
--- a/slirp/if.h
+++ b/slirp/if.h
@@ -20,6 +20,4 @@
 /* 2 for alignment, 14 for ethernet, 40 for TCP/IP */
 #define IF_MAXLINKHDR (2 + 14 + 40)
 
-#define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))
-
 #endif
diff --git a/slirp/mbuf.h b/slirp/mbuf.h
index 0708840..8d7951f 100644
--- a/slirp/mbuf.h
+++ b/slirp/mbuf.h
@@ -124,4 +124,9 @@ void m_adj(struct mbuf *, int);
 int m_copy(struct mbuf *, struct mbuf *, int, int);
 struct mbuf * dtom(Slirp *, void *);
 
+static inline void ifs_init(struct mbuf *ifm)
+{
+    ifm->ifs_next = ifm->ifs_prev = ifm;
+}
+
 #endif
commit e64722108c1342d499d408c386ce65794c44dd63
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sun Feb 26 16:14:47 2012 +0100

    usb-redir: Return USB_RET_NAK when we've no data for an interrupt endpoint
    
    We should return USB_RET_NAK, rather then a 0 sized packet, when we've no data
    for an interrupt IN endpoint.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/usb-redir.c b/usb-redir.c
index d905463..755492f 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -548,7 +548,10 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
             /* Check interrupt_error for stream errors */
             status = dev->endpoint[EP2I(ep)].interrupt_error;
             dev->endpoint[EP2I(ep)].interrupt_error = 0;
-            return usbredir_handle_status(dev, status, 0);
+            if (status) {
+                return usbredir_handle_status(dev, status, 0);
+            }
+            return USB_RET_NAK;
         }
         DPRINTF("interrupt-token-in ep %02X status %d len %d\n", ep,
                 intp->status, intp->len);
commit d86b8853e1f0c7ffb917a7a48f2e44bc3d8e9f8a
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sun Feb 26 16:14:46 2012 +0100

    usb-redir: Limit return values returned by iso packets
    
    The usbredir protocol uses a status of usb_redir_stall to indicate that
    an iso data stream has stopped (ie because the urbs failed on resubmit),
    but iso packets should never return a result of USB_RET_STALL, since iso
    endpoints cannot stall. So instead simply always return USB_RET_NAK on
    iso stream errors.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/usb-redir.c b/usb-redir.c
index 6c92fd9..d905463 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -431,7 +431,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
             /* Check iso_error for stream errors, otherwise its an underrun */
             status = dev->endpoint[EP2I(ep)].iso_error;
             dev->endpoint[EP2I(ep)].iso_error = 0;
-            return usbredir_handle_status(dev, status, 0);
+            return status ? USB_RET_NAK : 0;
         }
         DPRINTF2("iso-token-in ep %02X status %d len %d queue-size: %d\n", ep,
                  isop->status, isop->len, dev->endpoint[EP2I(ep)].bufpq_size);
@@ -439,7 +439,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
         status = isop->status;
         if (status != usb_redir_success) {
             bufp_free(dev, isop, ep);
-            return usbredir_handle_status(dev, status, 0);
+            return USB_RET_NAK;
         }
 
         len = isop->len;
commit 097a66ef5f6138c22bfdd1cc218eb2704e5eef9c
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sun Feb 26 16:14:45 2012 +0100

    usb-redir: Let the usb-host know about our device filtering
    
    libusbredirparser-0.3.4 adds 2 new packets which allows us to notify
    the usb-host:
    -about the usb device filter we have (if any), so that it knows not the even
     try to redirect certain devices
    -when we reject a device based on filtering (in case it tries anyways)
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/configure b/configure
index 87474e9..d64b2de 100755
--- a/configure
+++ b/configure
@@ -2592,7 +2592,7 @@ fi
 
 # check for usbredirparser for usb network redirection support
 if test "$usb_redir" != "no" ; then
-    if $pkg_config --atleast-version=0.3.3 libusbredirparser >/dev/null 2>&1 ; then
+    if $pkg_config --atleast-version=0.3.4 libusbredirparser >/dev/null 2>&1 ; then
         usb_redir="yes"
         usb_redir_cflags=$($pkg_config --cflags libusbredirparser 2>/dev/null)
         usb_redir_libs=$($pkg_config --libs libusbredirparser 2>/dev/null)
diff --git a/usb-redir.c b/usb-redir.c
index c98b14e..6c92fd9 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -106,6 +106,7 @@ struct AsyncURB {
     QTAILQ_ENTRY(AsyncURB)next;
 };
 
+static void usbredir_hello(void *priv, struct usb_redir_hello_header *h);
 static void usbredir_device_connect(void *priv,
     struct usb_redir_device_connect_header *device_connect);
 static void usbredir_device_disconnect(void *priv);
@@ -802,6 +803,7 @@ static void usbredir_open_close_bh(void *opaque)
         dev->parser->log_func = usbredir_log;
         dev->parser->read_func = usbredir_read;
         dev->parser->write_func = usbredir_write;
+        dev->parser->hello_func = usbredir_hello;
         dev->parser->device_connect_func = usbredir_device_connect;
         dev->parser->device_disconnect_func = usbredir_device_disconnect;
         dev->parser->interface_info_func = usbredir_interface_info;
@@ -820,6 +822,7 @@ static void usbredir_open_close_bh(void *opaque)
         dev->read_buf_size = 0;
 
         usbredirparser_caps_set_cap(caps, usb_redir_cap_connect_device_version);
+        usbredirparser_caps_set_cap(caps, usb_redir_cap_filter);
         usbredirparser_init(dev->parser, VERSION, caps, USB_REDIR_CAPS_SIZE, 0);
         usbredirparser_do_write(dev->parser);
     }
@@ -991,6 +994,10 @@ static int usbredir_check_filter(USBRedirDevice *dev)
 
 error:
     usbredir_device_disconnect(dev);
+    if (usbredirparser_peer_has_cap(dev->parser, usb_redir_cap_filter)) {
+        usbredirparser_send_filter_reject(dev->parser);
+        usbredirparser_do_write(dev->parser);
+    }
     return -1;
 }
 
@@ -1016,6 +1023,19 @@ static int usbredir_handle_status(USBRedirDevice *dev,
     }
 }
 
+static void usbredir_hello(void *priv, struct usb_redir_hello_header *h)
+{
+    USBRedirDevice *dev = priv;
+
+    /* Try to send the filter info now that we've the usb-host's caps */
+    if (usbredirparser_peer_has_cap(dev->parser, usb_redir_cap_filter) &&
+            dev->filter_rules) {
+        usbredirparser_send_filter_filter(dev->parser, dev->filter_rules,
+                                          dev->filter_rules_count);
+        usbredirparser_do_write(dev->parser);
+    }
+}
+
 static void usbredir_device_connect(void *priv,
     struct usb_redir_device_connect_header *device_connect)
 {
commit 5b3bd68244c87e161ea309ed380f216acf7cd754
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sun Feb 26 16:14:44 2012 +0100

    usb-redir: Always clear device state on filter reject
    
    Always call usbredir_device_disconnect() when usbredir_check_filter() fails
    to clean up all the device state (ie received endpoint info).
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/usb-redir.c b/usb-redir.c
index 18204be..c98b14e 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -958,7 +958,7 @@ static int usbredir_check_filter(USBRedirDevice *dev)
 {
     if (dev->interface_info.interface_count == 0) {
         ERROR("No interface info for device\n");
-        return -1;
+        goto error;
     }
 
     if (dev->filter_rules) {
@@ -966,7 +966,7 @@ static int usbredir_check_filter(USBRedirDevice *dev)
                                     usb_redir_cap_connect_device_version)) {
             ERROR("Device filter specified and peer does not have the "
                   "connect_device_version capability\n");
-            return -1;
+            goto error;
         }
 
         if (usbredirfilter_check(
@@ -983,11 +983,15 @@ static int usbredir_check_filter(USBRedirDevice *dev)
                 dev->device_info.product_id,
                 dev->device_info.device_version_bcd,
                 0) != 0) {
-            return -1;
+            goto error;
         }
     }
 
     return 0;
+
+error:
+    usbredir_device_disconnect(dev);
+    return -1;
 }
 
 /*
@@ -1113,7 +1117,6 @@ static void usbredir_interface_info(void *priv,
         if (usbredir_check_filter(dev)) {
             ERROR("Device no longer matches filter after interface info "
                   "change, disconnecting!\n");
-            usbredir_device_disconnect(dev);
         }
     }
 }
commit 52234bc00d5cf13cf96b3d632a4e0aa34cec08be
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sun Feb 26 16:14:43 2012 +0100

    usb-redir: Fix printing of device version
    
    The device version is in bcd format, which requires some special handling to
    print.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/usb-redir.c b/usb-redir.c
index a59b347..18204be 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -1049,8 +1049,10 @@ static void usbredir_device_connect(void *priv,
                                     usb_redir_cap_connect_device_version)) {
         INFO("attaching %s device %04x:%04x version %d.%d class %02x\n",
              speed, device_connect->vendor_id, device_connect->product_id,
-             device_connect->device_version_bcd >> 8,
-             device_connect->device_version_bcd & 0xff,
+             ((device_connect->device_version_bcd & 0xf000) >> 12) * 10 +
+             ((device_connect->device_version_bcd & 0x0f00) >>  8),
+             ((device_connect->device_version_bcd & 0x00f0) >>  4) * 10 +
+             ((device_connect->device_version_bcd & 0x000f) >>  0),
              device_connect->device_class);
     } else {
         INFO("attaching %s device %04x:%04x class %02x\n", speed,
commit 01cd4e98dc6eed96519f44f03de893364e0601ab
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Feb 27 13:08:25 2012 +0100

    ehci: drop old stuff
    
    Drop the "ehci under development" banner.
    Drop unused & inactive (#if 0) code.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index b95773f..afc8ccf 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1471,36 +1471,10 @@ static int ehci_process_itd(EHCIState *ehci,
             }
             qemu_sglist_destroy(&ehci->isgl);
 
-#if 0
-            /*  In isoch, there is no facility to indicate a NAK so let's
-             *  instead just complete a zero-byte transaction.  Setting
-             *  DBERR seems too draconian.
-             */
-
-            if (ret == USB_RET_NAK) {
-                if (ehci->isoch_pause > 0) {
-                    DPRINTF("ISOCH: received a NAK but paused so returning\n");
-                    ehci->isoch_pause--;
-                    return 0;
-                } else if (ehci->isoch_pause == -1) {
-                    DPRINTF("ISOCH: recv NAK & isoch pause inactive, setting\n");
-                    // Pause frindex for up to 50 msec waiting for data from
-                    // remote
-                    ehci->isoch_pause = 50;
-                    return 0;
-                } else {
-                    DPRINTF("ISOCH: isoch pause timeout! return 0\n");
-                    ret = 0;
-                }
-            } else {
-                DPRINTF("ISOCH: received ACK, clearing pause\n");
-                ehci->isoch_pause = -1;
-            }
-#else
             if (ret == USB_RET_NAK) {
+                /* no data for us, so do a zero-length transfer */
                 ret = 0;
             }
-#endif
 
             if (ret >= 0) {
                 if (!dir) {
@@ -2389,8 +2363,6 @@ static int usb_ehci_initfn(PCIDevice *dev)
     memory_region_init_io(&s->mem, &ehci_mem_ops, s, "ehci", MMIO_SIZE);
     pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem);
 
-    fprintf(stderr, "*** EHCI support is under development ***\n");
-
     return 0;
 }
 
commit df7871851eb327af0a612895738c0e1854fde00b
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sun Feb 26 16:14:48 2012 +0100

    usb-ehci: Handle ISO packets failing with an error other then NAK
    
    Before this patch the ehci code was not checking for any other errors other
    then USB_RET_NAK. This causes 2 problems:
    1) Other errors are not reported to the guest.
    2) When transactions with the ITD_XACT_IOC bit set completing with another
       error would not result in USBSTS_INT getting set.
    
    I hit this problem when unplugging devices while iso data was streaming from
    the device to the guest. When this happens it takes a while for the guest to
    process the unplugging and remove ISO transactions from the ehci schedule, in
    the mean time these transactions would complete with a result of USB_RET_NODEV,
    which was not handled. This lead to the Linux guest's usb subsystem "hanging",
    that is it would no longer see new usb devices getting plugged in and running
    for example lsusb would lead to a stuck (D state) lsusb process. This patch
    fixes this.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 048eb76..b95773f 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1510,11 +1510,27 @@ static int ehci_process_itd(EHCIState *ehci,
                     /* IN */
                     set_field(&itd->transact[i], ret, ITD_XACT_LENGTH);
                 }
-
-                if (itd->transact[i] & ITD_XACT_IOC) {
-                    ehci_record_interrupt(ehci, USBSTS_INT);
+            } else {
+                switch (ret) {
+                default:
+                    fprintf(stderr, "Unexpected iso usb result: %d\n", ret);
+                    /* Fall through */
+                case USB_RET_NODEV:
+                    /* 3.3.2: XACTERR is only allowed on IN transactions */
+                    if (dir) {
+                        itd->transact[i] |= ITD_XACT_XACTERR;
+                        ehci_record_interrupt(ehci, USBSTS_ERRINT);
+                    }
+                    break;
+                case USB_RET_BABBLE:
+                    itd->transact[i] |= ITD_XACT_BABBLE;
+                    ehci_record_interrupt(ehci, USBSTS_ERRINT);
+                    break;
                 }
             }
+            if (itd->transact[i] & ITD_XACT_IOC) {
+                ehci_record_interrupt(ehci, USBSTS_INT);
+            }
             itd->transact[i] &= ~ITD_XACT_ACTIVE;
         }
     }
commit 0082f4336e128a17d5f34e01de0fd29930e99b0d
Author: Alon Levy <alevy at redhat.com>
Date:   Sun Feb 26 17:09:24 2012 +0100

    libcacard: fix reported ATR length
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/libcacard/vcardt.h b/libcacard/vcardt.h
index 538bdde..d4d8e2e 100644
--- a/libcacard/vcardt.h
+++ b/libcacard/vcardt.h
@@ -26,8 +26,8 @@ typedef struct VCardEmulStruct VCardEmul;
 #define MAX_CHANNEL 4
 
 /* create an ATR with appropriate historical bytes */
-#define VCARD_ATR_PREFIX(size) 0x3b, 0x66+(size), 0x00, 0xff, \
-                               'V', 'C', 'A', 'R', 'D', '_'
+#define VCARD_ATR_PREFIX(size) (0x3b, 0x68+(size), 0x00, 0xff, \
+                               'V', 'C', 'A', 'R', 'D', '_')
 
 
 typedef enum {
commit cff17894e37feef5f0410c9557d38c2f00850657
Author: Alon Levy <alevy at redhat.com>
Date:   Sun Feb 26 17:09:23 2012 +0100

    usb-ccid: advertise SELF_POWERED
    
    Before commit ed5a83ddd8c1d8ec7b1015315530cf29949e7c48 each device
    provided it's own response to USB_REQ_GET_STATUS, but after it that
    response was based on bmAttributes, which was errounously set for
    usb-ccid as 0xa0 and not 0xe0.
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ccid.c b/hw/usb-ccid.c
index 0b2ac80..ce01e34 100644
--- a/hw/usb-ccid.c
+++ b/hw/usb-ccid.c
@@ -447,7 +447,7 @@ static const USBDescDevice desc_device = {
         {
             .bNumInterfaces        = 1,
             .bConfigurationValue   = 1,
-            .bmAttributes          = 0xa0,
+            .bmAttributes          = 0xe0,
             .bMaxPower             = 50,
             .nif = 1,
             .ifs = &desc_iface0,
commit 8c741c229f6402886412f142ca1252e8a6f258a5
Author: Alon Levy <alevy at redhat.com>
Date:   Sun Feb 26 17:09:22 2012 +0100

    libcacard: link with glib for g_strndup
    
    Without it the produced library for make libcacard.la has an unresolved
    symbol.
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/configure b/configure
index f9d5330..87474e9 100755
--- a/configure
+++ b/configure
@@ -2571,8 +2571,8 @@ if test "$smartcard" != "no" ; then
 int main(void) { PK11_FreeSlot(0); return 0; }
 EOF
         smartcard_cflags="-I\$(SRC_PATH)/libcacard"
-        libcacard_libs=$($pkg_config --libs nss 2>/dev/null)
-        libcacard_cflags=$($pkg_config --cflags nss 2>/dev/null)
+        libcacard_libs="$($pkg_config --libs nss 2>/dev/null) $glib_libs"
+        libcacard_cflags="$($pkg_config --cflags nss 2>/dev/null) $glib_cflags"
         if $pkg_config --atleast-version=3.12.8 nss >/dev/null 2>&1 && \
           compile_prog "$smartcard_cflags $libcacard_cflags" "$libcacard_libs"; then
             smartcard_nss="yes"
commit 8db36e9dddb1b6fab3554a8c00d92268b33a487b
Author: Alon Levy <alevy at redhat.com>
Date:   Sun Feb 26 17:09:21 2012 +0100

    usb-desc: fix user trigerrable segfaults (!config)
    
    Check for dev->config being NULL in two places:
     USB_REQ_GET_CONFIGURATION and USB_REQ_GET_STATUS.
    
    The behavior of USB_REQ_GET_STATUS is unspecified in the Default state,
    that corresponds to dev->config being NULL (it defaults to NULL and is
    reset whenever a SET_CONFIGURATION with value 0, or attachment). I
    implemented it to correspond with the state before
    ed5a83ddd8c1d8ec7b1015315530cf29949e7c48, the commit moving SET_STATUS
    to usb-desc; if dev->config is not set we return whatever is in the
    first configuration.
    
    The behavior of USB_REQ_GET_CONFIGURATION is also undefined before any
    SET_CONFIGURATION, but here we just return 0 (same as specified for the
    Address state).
    
    A win7 guest failed to initialize the device before this patch,
    segfaulting when GET_STATUS was called with dev->config == NULL. With
    this patch the passthrough device still doesn't work but the failure is
    unrelated.
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-desc.c b/hw/usb-desc.c
index 3c3ed6a..ccf85ad 100644
--- a/hw/usb-desc.c
+++ b/hw/usb-desc.c
@@ -536,7 +536,11 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
         break;
 
     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
-        data[0] = dev->config->bConfigurationValue;
+        /*
+         * 9.4.2: 0 should be returned if the device is unconfigured, otherwise
+         * the non zero value of bConfigurationValue.
+         */
+        data[0] = dev->config ? dev->config->bConfigurationValue : 0;
         ret = 1;
         break;
     case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
@@ -544,9 +548,18 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
         trace_usb_set_config(dev->addr, value, ret);
         break;
 
-    case DeviceRequest | USB_REQ_GET_STATUS:
+    case DeviceRequest | USB_REQ_GET_STATUS: {
+        const USBDescConfig *config = dev->config ?
+            dev->config : &dev->device->confs[0];
+
         data[0] = 0;
-        if (dev->config->bmAttributes & 0x40) {
+        /*
+         * Default state: Device behavior when this request is received while
+         *                the device is in the Default state is not specified.
+         * We return the same value that a configured device would return if
+         * it used the first configuration.
+         */
+        if (config->bmAttributes & 0x40) {
             data[0] |= 1 << USB_DEVICE_SELF_POWERED;
         }
         if (dev->remote_wakeup) {
@@ -555,6 +568,7 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
         data[1] = 0x00;
         ret = 2;
         break;
+    }
     case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
         if (value == USB_DEVICE_REMOTE_WAKEUP) {
             dev->remote_wakeup = 0;
commit aa0568ff2559d7717f4684af6a83d0bd1a125f56
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Feb 27 11:23:08 2012 +0100

    usb-ehci: sanity-check iso xfers
    
    This patch adds a sanity check to itd processing to make sure the
    endpoint addressed by the guest is actually an iso endpoint.  Also
    verify that usb drivers don't return USB_RET_ASYNC which is illegal for
    iso xfers.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index b9da26a..048eb76 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1459,12 +1459,16 @@ static int ehci_process_itd(EHCIState *ehci,
 
             dev = ehci_find_device(ehci, devaddr);
             ep = usb_ep_get(dev, pid, endp);
-            usb_packet_setup(&ehci->ipacket, pid, ep);
-            usb_packet_map(&ehci->ipacket, &ehci->isgl);
-
-            ret = usb_handle_packet(dev, &ehci->ipacket);
-
-            usb_packet_unmap(&ehci->ipacket);
+            if (ep->type == USB_ENDPOINT_XFER_ISOC) {
+                usb_packet_setup(&ehci->ipacket, pid, ep);
+                usb_packet_map(&ehci->ipacket, &ehci->isgl);
+                ret = usb_handle_packet(dev, &ehci->ipacket);
+                assert(ret != USB_RET_ASYNC);
+                usb_packet_unmap(&ehci->ipacket);
+            } else {
+                DPRINTF("ISOCH: attempt to addess non-iso endpoint\n");
+                ret = USB_RET_NAK;
+            }
             qemu_sglist_destroy(&ehci->isgl);
 
 #if 0
commit 808aeb98ffd9265da55a9ad3fceb86a7ac77107b
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Feb 24 11:03:27 2012 +0100

    usb: add tracepoint for usb packet state changes.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb.c b/hw/usb.c
index e5b8f33..57fc5e3 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -26,6 +26,7 @@
 #include "qemu-common.h"
 #include "usb.h"
 #include "iov.h"
+#include "trace.h"
 
 void usb_attach(USBPort *port)
 {
@@ -390,7 +391,6 @@ void usb_packet_init(USBPacket *p)
 
 void usb_packet_set_state(USBPacket *p, USBPacketState state)
 {
-#ifdef DEBUG
     static const char *name[] = {
         [USB_PACKET_UNDEFINED] = "undef",
         [USB_PACKET_SETUP]     = "setup",
@@ -399,28 +399,11 @@ void usb_packet_set_state(USBPacket *p, USBPacketState state)
         [USB_PACKET_COMPLETE]  = "complete",
         [USB_PACKET_CANCELED]  = "canceled",
     };
-    static const char *rets[] = {
-        [-USB_RET_NODEV]  = "NODEV",
-        [-USB_RET_NAK]    = "NAK",
-        [-USB_RET_STALL]  = "STALL",
-        [-USB_RET_BABBLE] = "BABBLE",
-        [-USB_RET_ASYNC]  = "ASYNC",
-    };
-    char add[16] = "";
+    USBDevice *dev = p->ep->dev;
+    USBBus *bus = usb_bus_from_device(dev);
 
-    if (state == USB_PACKET_COMPLETE) {
-        if (p->result < 0) {
-            snprintf(add, sizeof(add), " - %s", rets[-p->result]);
-        } else {
-            snprintf(add, sizeof(add), " - %d", p->result);
-        }
-    }
-    fprintf(stderr, "bus %s, port %s, dev %d, ep %d: packet %p: %s -> %s%s\n",
-            p->ep->dev->qdev.parent_bus->name,
-            p->ep->dev->port->path,
-            p->ep->dev->addr, p->ep->nr,
-            p, name[p->state], name[state], add);
-#endif
+    trace_usb_packet_state_change(bus->busnr, dev->port->path, p->ep->nr,
+                                  p, name[p->state], name[state]);
     p->state = state;
 }
 
diff --git a/trace-events b/trace-events
index e918ff6..c5d0f0f 100644
--- a/trace-events
+++ b/trace-events
@@ -227,6 +227,9 @@ sun4m_iommu_page_get_flags(uint64_t pa, uint64_t iopte, uint32_t ret) "get flags
 sun4m_iommu_translate_pa(uint64_t addr, uint64_t pa, uint32_t iopte) "xlate dva %"PRIx64" => pa %"PRIx64" iopte = %x"
 sun4m_iommu_bad_addr(uint64_t addr) "bad addr %"PRIx64
 
+# hw/usb.c
+usb_packet_state_change(int bus, const char *port, int ep, void *p, const char *o, const char *n) "bus %d, port %s, ep %d, packet %p, state %s -> %s"
+
 # hw/usb-bus.c
 usb_port_claim(int bus, const char *port) "bus %d, port %s"
 usb_port_attach(int bus, const char *port) "bus %d, port %s"
commit 7d1994f863c355f1906655f08d624582eeb30788
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Feb 24 10:44:05 2012 +0100

    usb-xhci: enable packet queuing
    
    qemu usb core has packet queues now, so flip lets the switch.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-xhci.c b/hw/usb-xhci.c
index 008b0b5..fc5b542 100644
--- a/hw/usb-xhci.c
+++ b/hw/usb-xhci.c
@@ -1769,12 +1769,6 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
             epctx->retry = xfer;
             break;
         }
-
-        /*
-         * Qemu usb can't handle multiple in-flight xfers.
-         * Stop here for now.
-         */
-        break;
     }
 }
 
commit 5a248289a8db9e5c872435757165e086d42bece1
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Jan 27 17:27:31 2012 +0100

    usb-uhci: implement packet queuing
    
    When a usb device is busy processing a packet (and returns
    USB_RET_ASYNC), continue walking the transfer descriptor list
    and process them to fill the request queue.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 13298aa..70e3881 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -942,6 +942,34 @@ static int qhdb_insert(QhDb *db, uint32_t addr)
     return 0;
 }
 
+static void uhci_fill_queue(UHCIState *s, UHCI_TD *td)
+{
+    uint32_t int_mask = 0;
+    uint32_t plink = td->link;
+    uint32_t token = uhci_queue_token(td);
+    UHCI_TD ptd;
+    int ret;
+
+    fprintf(stderr, "%s: -- %x\n", __func__, token);
+    while (is_valid(plink)) {
+        pci_dma_read(&s->dev, plink & ~0xf, &ptd, sizeof(ptd));
+        le32_to_cpus(&ptd.link);
+        le32_to_cpus(&ptd.ctrl);
+        le32_to_cpus(&ptd.token);
+        le32_to_cpus(&ptd.buffer);
+        if (!(ptd.ctrl & TD_CTRL_ACTIVE)) {
+            break;
+        }
+        if (uhci_queue_token(&ptd) != token) {
+            break;
+        }
+        ret = uhci_handle_td(s, plink, &ptd, &int_mask);
+        assert(ret == 2); /* got USB_RET_ASYNC */
+        assert(int_mask == 0);
+        plink = ptd.link;
+    }
+}
+
 static void uhci_process_frame(UHCIState *s)
 {
     uint32_t frame_addr, link, old_td_ctrl, val, int_mask;
@@ -1044,8 +1072,9 @@ static void uhci_process_frame(UHCIState *s)
             DPRINTF("uhci: TD 0x%x async. "
                     "link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n",
                     link, td.link, td.ctrl, td.token, curr_qh);
-            fprintf(stderr, "async td: link %x%s\n",
-                    td.link, is_valid(td.link) ? " valid" : "");
+            if (is_valid(td.link)) {
+                uhci_fill_queue(s, &td);
+            }
             link = curr_qh ? qh.link : td.link;
             continue;
 
commit 971a5a406ed3631797a6c83e47f6fc2e7d410f8f
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Jan 27 16:38:42 2012 +0100

    usb-uhci: process uhci_handle_td return code via switch.
    
    Restruct the uhci_handle_td return code processing to make the
    control flow more clear and the code more readable.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index b8b336f..13298aa 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1029,49 +1029,61 @@ static void uhci_process_frame(UHCIState *s)
             pci_dma_write(&s->dev, (link & ~0xf) + 4, &val, sizeof(val));
         }
 
-        if (ret < 0) {
-            /* interrupted frame */
-            break;
-        }
-
-        if (ret == 2 || ret == 1) {
-            DPRINTF("uhci: TD 0x%x %s. link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n",
-                    link, ret == 2 ? "pend" : "skip",
-                    td.link, td.ctrl, td.token, curr_qh);
+        switch (ret) {
+        case -1: /* interrupted frame */
+            goto out;
 
+        case 1: /* goto next queue */
+            DPRINTF("uhci: TD 0x%x skip. "
+                    "link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n",
+                    link, td.link, td.ctrl, td.token, curr_qh);
             link = curr_qh ? qh.link : td.link;
             continue;
-        }
 
-        /* completed TD */
+        case 2: /* got USB_RET_ASYNC */
+            DPRINTF("uhci: TD 0x%x async. "
+                    "link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n",
+                    link, td.link, td.ctrl, td.token, curr_qh);
+            fprintf(stderr, "async td: link %x%s\n",
+                    td.link, is_valid(td.link) ? " valid" : "");
+            link = curr_qh ? qh.link : td.link;
+            continue;
 
-        DPRINTF("uhci: TD 0x%x done. link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n", 
-                link, td.link, td.ctrl, td.token, curr_qh);
+        case 0: /* completed TD */
+            DPRINTF("uhci: TD 0x%x done. "
+                    "link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n",
+                    link, td.link, td.ctrl, td.token, curr_qh);
 
-        link = td.link;
-        td_count++;
-        bytes_count += (td.ctrl & 0x7ff) + 1;
+            link = td.link;
+            td_count++;
+            bytes_count += (td.ctrl & 0x7ff) + 1;
 
-        if (curr_qh) {
-	    /* update QH element link */
-            qh.el_link = link;
-            val = cpu_to_le32(qh.el_link);
-            pci_dma_write(&s->dev, (curr_qh & ~0xf) + 4, &val, sizeof(val));
+            if (curr_qh) {
+                /* update QH element link */
+                qh.el_link = link;
+                val = cpu_to_le32(qh.el_link);
+                pci_dma_write(&s->dev, (curr_qh & ~0xf) + 4, &val, sizeof(val));
 
-            if (!depth_first(link)) {
-               /* done with this QH */
+                if (!depth_first(link)) {
+                    /* done with this QH */
 
-               DPRINTF("uhci: QH 0x%x done. link 0x%x elink 0x%x\n",
-                       curr_qh, qh.link, qh.el_link);
+                    DPRINTF("uhci: QH 0x%x done. link 0x%x elink 0x%x\n",
+                            curr_qh, qh.link, qh.el_link);
 
-               curr_qh = 0;
-               link    = qh.link;
+                    curr_qh = 0;
+                    link    = qh.link;
+                }
             }
+            break;
+
+        default:
+            assert(!"unknown return code");
         }
 
         /* go to the next entry */
     }
 
+out:
     s->pending_int_mask |= int_mask;
 }
 
commit f8af1e889b7f314cd38a642d28bc3362c1790c97
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Jan 27 14:17:06 2012 +0100

    usb-uhci: add UHCIQueue
    
    UHCIAsync structs (in-flight requests) grouped in UHCIQueue now.
    Each (active) usb endpoint gets its own UHCIQueue.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index ca87290..b8b336f 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -95,23 +95,32 @@ static const char *pid2str(int pid)
 #endif
 
 typedef struct UHCIState UHCIState;
+typedef struct UHCIAsync UHCIAsync;
+typedef struct UHCIQueue UHCIQueue;
 
 /* 
  * Pending async transaction.
  * 'packet' must be the first field because completion
  * handler does "(UHCIAsync *) pkt" cast.
  */
-typedef struct UHCIAsync {
+
+struct UHCIAsync {
     USBPacket packet;
     QEMUSGList sgl;
-    UHCIState *uhci;
+    UHCIQueue *queue;
     QTAILQ_ENTRY(UHCIAsync) next;
     uint32_t  td;
-    uint32_t  token;
-    int8_t    valid;
     uint8_t   isoc;
     uint8_t   done;
-} UHCIAsync;
+};
+
+struct UHCIQueue {
+    uint32_t  token;
+    UHCIState *uhci;
+    QTAILQ_ENTRY(UHCIQueue) next;
+    QTAILQ_HEAD(, UHCIAsync) asyncs;
+    int8_t    valid;
+};
 
 typedef struct UHCIPort {
     USBPort port;
@@ -137,7 +146,7 @@ struct UHCIState {
     uint32_t pending_int_mask;
 
     /* Active packets */
-    QTAILQ_HEAD(,UHCIAsync) async_pending;
+    QTAILQ_HEAD(, UHCIQueue) queues;
     uint8_t num_ports_vmstate;
 
     /* Properties */
@@ -157,56 +166,90 @@ typedef struct UHCI_QH {
     uint32_t el_link;
 } UHCI_QH;
 
-static UHCIAsync *uhci_async_alloc(UHCIState *s)
+static inline int32_t uhci_queue_token(UHCI_TD *td)
+{
+    /* covers ep, dev, pid -> identifies the endpoint */
+    return td->token & 0x7ffff;
+}
+
+static UHCIQueue *uhci_queue_get(UHCIState *s, UHCI_TD *td)
+{
+    uint32_t token = uhci_queue_token(td);
+    UHCIQueue *queue;
+
+    QTAILQ_FOREACH(queue, &s->queues, next) {
+        if (queue->token == token) {
+            return queue;
+        }
+    }
+
+    queue = g_new0(UHCIQueue, 1);
+    queue->uhci = s;
+    queue->token = token;
+    QTAILQ_INIT(&queue->asyncs);
+    QTAILQ_INSERT_HEAD(&s->queues, queue, next);
+    return queue;
+}
+
+static void uhci_queue_free(UHCIQueue *queue)
+{
+    UHCIState *s = queue->uhci;
+
+    QTAILQ_REMOVE(&s->queues, queue, next);
+    g_free(queue);
+}
+
+static UHCIAsync *uhci_async_alloc(UHCIQueue *queue)
 {
     UHCIAsync *async = g_new0(UHCIAsync, 1);
 
-    async->uhci  = s;
+    async->queue = queue;
     usb_packet_init(&async->packet);
-    pci_dma_sglist_init(&async->sgl, &s->dev, 1);
+    pci_dma_sglist_init(&async->sgl, &queue->uhci->dev, 1);
 
     return async;
 }
 
-static void uhci_async_free(UHCIState *s, UHCIAsync *async)
+static void uhci_async_free(UHCIAsync *async)
 {
     usb_packet_cleanup(&async->packet);
     qemu_sglist_destroy(&async->sgl);
     g_free(async);
 }
 
-static void uhci_async_link(UHCIState *s, UHCIAsync *async)
+static void uhci_async_link(UHCIAsync *async)
 {
-    QTAILQ_INSERT_HEAD(&s->async_pending, async, next);
+    UHCIQueue *queue = async->queue;
+    QTAILQ_INSERT_TAIL(&queue->asyncs, async, next);
 }
 
-static void uhci_async_unlink(UHCIState *s, UHCIAsync *async)
+static void uhci_async_unlink(UHCIAsync *async)
 {
-    QTAILQ_REMOVE(&s->async_pending, async, next);
+    UHCIQueue *queue = async->queue;
+    QTAILQ_REMOVE(&queue->asyncs, async, next);
 }
 
-static void uhci_async_cancel(UHCIState *s, UHCIAsync *async)
+static void uhci_async_cancel(UHCIAsync *async)
 {
     DPRINTF("uhci: cancel td 0x%x token 0x%x done %u\n",
            async->td, async->token, async->done);
 
     if (!async->done)
         usb_cancel_packet(&async->packet);
-    uhci_async_free(s, async);
+    uhci_async_free(async);
 }
 
 /*
  * Mark all outstanding async packets as invalid.
  * This is used for canceling them when TDs are removed by the HCD.
  */
-static UHCIAsync *uhci_async_validate_begin(UHCIState *s)
+static void uhci_async_validate_begin(UHCIState *s)
 {
-    UHCIAsync *async;
+    UHCIQueue *queue;
 
-    QTAILQ_FOREACH(async, &s->async_pending, next) {
-        async->valid--;
+    QTAILQ_FOREACH(queue, &s->queues, next) {
+        queue->valid--;
     }
-    return NULL;
 }
 
 /*
@@ -214,77 +257,74 @@ static UHCIAsync *uhci_async_validate_begin(UHCIState *s)
  */
 static void uhci_async_validate_end(UHCIState *s)
 {
-    UHCIAsync *curr, *n;
+    UHCIQueue *queue, *n;
+    UHCIAsync *async;
 
-    QTAILQ_FOREACH_SAFE(curr, &s->async_pending, next, n) {
-        if (curr->valid > 0) {
+    QTAILQ_FOREACH_SAFE(queue, &s->queues, next, n) {
+        if (queue->valid > 0) {
             continue;
         }
-        uhci_async_unlink(s, curr);
-        uhci_async_cancel(s, curr);
+        while (!QTAILQ_EMPTY(&queue->asyncs)) {
+            async = QTAILQ_FIRST(&queue->asyncs);
+            uhci_async_unlink(async);
+            uhci_async_cancel(async);
+        }
+        uhci_queue_free(queue);
     }
 }
 
 static void uhci_async_cancel_device(UHCIState *s, USBDevice *dev)
 {
+    UHCIQueue *queue;
     UHCIAsync *curr, *n;
 
-    QTAILQ_FOREACH_SAFE(curr, &s->async_pending, next, n) {
-        if (!usb_packet_is_inflight(&curr->packet) ||
-            curr->packet.ep->dev != dev) {
-            continue;
+    QTAILQ_FOREACH(queue, &s->queues, next) {
+        QTAILQ_FOREACH_SAFE(curr, &queue->asyncs, next, n) {
+            if (!usb_packet_is_inflight(&curr->packet) ||
+                curr->packet.ep->dev != dev) {
+                continue;
+            }
+            uhci_async_unlink(curr);
+            uhci_async_cancel(curr);
         }
-        uhci_async_unlink(s, curr);
-        uhci_async_cancel(s, curr);
     }
 }
 
 static void uhci_async_cancel_all(UHCIState *s)
 {
+    UHCIQueue *queue;
     UHCIAsync *curr, *n;
 
-    QTAILQ_FOREACH_SAFE(curr, &s->async_pending, next, n) {
-        uhci_async_unlink(s, curr);
-        uhci_async_cancel(s, curr);
+    QTAILQ_FOREACH(queue, &s->queues, next) {
+        QTAILQ_FOREACH_SAFE(curr, &queue->asyncs, next, n) {
+            uhci_async_unlink(curr);
+            uhci_async_cancel(curr);
+        }
     }
 }
 
-static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t addr, uint32_t token)
+static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t addr, UHCI_TD *td)
 {
+    uint32_t token = uhci_queue_token(td);
+    UHCIQueue *queue;
     UHCIAsync *async;
-    UHCIAsync *match = NULL;
-    int count = 0;
-
-    /*
-     * We're looking for the best match here. ie both td addr and token.
-     * Otherwise we return last good match. ie just token.
-     * It's ok to match just token because it identifies the transaction
-     * rather well, token includes: device addr, endpoint, size, etc.
-     *
-     * Also since we queue async transactions in reverse order by returning
-     * last good match we restores the order.
-     *
-     * It's expected that we wont have a ton of outstanding transactions.
-     * If we ever do we'd want to optimize this algorithm.
-     */
-
-    QTAILQ_FOREACH(async, &s->async_pending, next) {
-        if (async->token == token) {
-            /* Good match */
-            match = async;
 
-            if (async->td == addr) {
-                /* Best match */
-                break;
-            }
+    QTAILQ_FOREACH(queue, &s->queues, next) {
+        if (queue->token == token) {
+            break;
         }
-        count++;
+    }
+    if (queue == NULL) {
+        return NULL;
     }
 
-    if (count > 64)
-	fprintf(stderr, "uhci: warning lots of async transactions\n");
+    QTAILQ_FOREACH(async, &queue->asyncs, next) {
+        if (async->td == addr) {
+            return async;
+        }
+    }
 
-    return match;
+    return NULL;
 }
 
 static void uhci_update_irq(UHCIState *s)
@@ -753,8 +793,7 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in
 {
     UHCIAsync *async;
     int len = 0, max_len;
-    uint8_t pid, isoc;
-    uint32_t token;
+    uint8_t pid;
     USBDevice *dev;
     USBEndpoint *ep;
 
@@ -762,41 +801,29 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in
     if (!(td->ctrl & TD_CTRL_ACTIVE))
         return 1;
 
-    /* token field is not unique for isochronous requests,
-     * so use the destination buffer 
-     */
-    if (td->ctrl & TD_CTRL_IOS) {
-        token = td->buffer;
-        isoc = 1;
-    } else {
-        token = td->token;
-        isoc = 0;
-    }
-
-    async = uhci_async_find_td(s, addr, token);
+    async = uhci_async_find_td(s, addr, td);
     if (async) {
         /* Already submitted */
-        async->valid = 32;
+        async->queue->valid = 32;
 
         if (!async->done)
             return 1;
 
-        uhci_async_unlink(s, async);
+        uhci_async_unlink(async);
         goto done;
     }
 
     /* Allocate new packet */
-    async = uhci_async_alloc(s);
+    async = uhci_async_alloc(uhci_queue_get(s, td));
     if (!async)
         return 1;
 
     /* valid needs to be large enough to handle 10 frame delay
      * for initial isochronous requests
      */
-    async->valid = 32;
+    async->queue->valid = 32;
     async->td    = addr;
-    async->token = token;
-    async->isoc  = isoc;
+    async->isoc  = td->ctrl & TD_CTRL_IOS;
 
     max_len = ((td->token >> 21) + 1) & 0x7ff;
     pid = td->token & 0xff;
@@ -821,14 +848,14 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in
 
     default:
         /* invalid pid : frame interrupted */
-        uhci_async_free(s, async);
+        uhci_async_free(async);
         s->status |= UHCI_STS_HCPERR;
         uhci_update_irq(s);
         return -1;
     }
  
     if (len == USB_RET_ASYNC) {
-        uhci_async_link(s, async);
+        uhci_async_link(async);
         return 2;
     }
 
@@ -837,14 +864,14 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in
 done:
     len = uhci_complete_td(s, td, async, int_mask);
     usb_packet_unmap(&async->packet);
-    uhci_async_free(s, async);
+    uhci_async_free(async);
     return len;
 }
 
 static void uhci_async_complete(USBPort *port, USBPacket *packet)
 {
     UHCIAsync *async = container_of(packet, UHCIAsync, packet);
-    UHCIState *s = async->uhci;
+    UHCIState *s = async->queue->uhci;
 
     DPRINTF("uhci: async complete. td 0x%x token 0x%x\n", async->td, async->token);
 
@@ -859,14 +886,14 @@ static void uhci_async_complete(USBPort *port, USBPacket *packet)
         le32_to_cpus(&td.token);
         le32_to_cpus(&td.buffer);
 
-        uhci_async_unlink(s, async);
+        uhci_async_unlink(async);
         uhci_complete_td(s, &td, async, &int_mask);
         s->pending_int_mask |= int_mask;
 
         /* update the status bits of the TD */
         val = cpu_to_le32(td.ctrl);
         pci_dma_write(&s->dev, (link & ~0xf) + 4, &val, sizeof(val));
-        uhci_async_free(s, async);
+        uhci_async_free(async);
     } else {
         async->done = 1;
         uhci_process_frame(s);
@@ -1142,7 +1169,7 @@ static int usb_uhci_common_initfn(PCIDevice *dev)
     }
     s->frame_timer = qemu_new_timer_ns(vm_clock, uhci_frame_timer, s);
     s->num_ports_vmstate = NB_PORTS;
-    QTAILQ_INIT(&s->async_pending);
+    QTAILQ_INIT(&s->queues);
 
     qemu_register_reset(uhci_reset, s);
 
commit 326700e35d2ac05ab83b91bf4857eedcdc049a30
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Jan 27 14:17:59 2012 +0100

    usb-uhci: cleanup UHCIAsync allocation & initialization.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 2280dc7..ca87290 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -159,15 +159,9 @@ typedef struct UHCI_QH {
 
 static UHCIAsync *uhci_async_alloc(UHCIState *s)
 {
-    UHCIAsync *async = g_malloc(sizeof(UHCIAsync));
+    UHCIAsync *async = g_new0(UHCIAsync, 1);
 
-    memset(&async->packet, 0, sizeof(async->packet));
     async->uhci  = s;
-    async->valid = 0;
-    async->td    = 0;
-    async->token = 0;
-    async->done  = 0;
-    async->isoc  = 0;
     usb_packet_init(&async->packet);
     pci_dma_sglist_init(&async->sgl, &s->dev, 1);
 
commit 81d37739dfded2ebd992f3bf8ae5d6cb1a0558cc
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 23 14:24:00 2012 +0100

    usb-ehci: fix reset
    
    Two reset fixes:
      * pick up s->usbcmd value after ehci_reset call to make sure it
        keeps the reset value and doesn't get rubbish filled in when
        val is written back to the mmio register array later on.
      * make sure the frame timer is zapped on reset.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index e699814..b9da26a 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -912,6 +912,7 @@ static void ehci_reset(void *opaque)
         }
     }
     ehci_queues_rip_all(s);
+    qemu_del_timer(s->frame_timer);
 }
 
 static uint32_t ehci_mem_readb(void *ptr, target_phys_addr_t addr)
@@ -1070,7 +1071,7 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
 
         if (val & USBCMD_HCRESET) {
             ehci_reset(s);
-            val &= ~USBCMD_HCRESET;
+            val = s->usbcmd;
         }
 
         /* not supporting dynamic frame list size at the moment */
commit 299aa1c6df1a308cc4d49666e7eb75655c0d40ce
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 23 15:24:24 2012 +0100

    usb-hid: fix tablet activation
    
    Activate usb hid pointer devices (mouse+tablet) unconditionally
    on polls, even if we NAK the poll due to lack of new events.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 7fc0bd8..37bca78 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -466,6 +466,9 @@ static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
     case USB_TOKEN_IN:
         if (p->ep->nr == 1) {
             int64_t curtime = qemu_get_clock_ns(vm_clock);
+            if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
+                hid_pointer_activate(hs);
+            }
             if (!hid_has_events(hs) &&
                 (!hs->idle || hs->next_idle_clock - curtime > 0)) {
                 return USB_RET_NAK;
commit 81fb6f1504fb9ef71f2382f44af34756668296e8
Author: Alon Levy <alevy at redhat.com>
Date:   Fri Feb 24 23:19:31 2012 +0200

    qxl: make qxl_render_update async
    
    RHBZ# 747011
    
    Removes the last user of QXL_SYNC when using update drivers that use the
    _ASYNC io ports.
    
    The last user is qxl_render_update, it is called both by qxl_hw_update
    which is the vga_hw_update_ptr passed to graphic_console_init, and by
    qxl_hw_screen_dump.
    
    At the same time the QXLRect area being passed to the red_worker thread
    is passed as a copy, as part of the QXLCookie.
    
    The implementation uses interface_update_area_complete with a bh to make
    sure dpy_update and qxl_flip are called from the io thread, otherwise
    the vga->ds->surface.data can change under our feet.
    
    With this patch sdl+spice works fine. But spice by itself doesn't
    produce the expected screendumps unless repeated a few times, due to
    ppm_save being called before update_area (rendering done in spice server
    thread) having a chance to complete. Fixed by next patch, but see commit
    message for problem introduced by it.
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index c45dc30..f323a4d 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -82,17 +82,25 @@ void qxl_render_resize(PCIQXLDevice *qxl)
     }
 }
 
-void qxl_render_update(PCIQXLDevice *qxl)
+static void qxl_set_rect_to_surface(PCIQXLDevice *qxl, QXLRect *area)
+{
+    area->left   = 0;
+    area->right  = qxl->guest_primary.surface.width;
+    area->top    = 0;
+    area->bottom = qxl->guest_primary.surface.height;
+}
+
+static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
 {
     VGACommonState *vga = &qxl->vga;
-    QXLRect dirty[32], update;
-    int i, redraw = 0;
+    int i;
     DisplaySurface *surface = vga->ds->surface;
 
     if (qxl->guest_primary.resized) {
         qxl->guest_primary.resized = 0;
-
         qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram);
+        qxl_set_rect_to_surface(qxl, &qxl->dirty[0]);
+        qxl->num_dirty_rects = 1;
         dprint(qxl, 1, "%s: %dx%d, stride %d, bpp %d, depth %d\n",
                __FUNCTION__,
                qxl->guest_primary.surface.width,
@@ -103,9 +111,9 @@ void qxl_render_update(PCIQXLDevice *qxl)
     }
     if (surface->width != qxl->guest_primary.surface.width ||
         surface->height != qxl->guest_primary.surface.height) {
-        dprint(qxl, 1, "%s: resizing displaysurface to guest_primary\n",
-               __func__);
         if (qxl->guest_primary.qxl_stride > 0) {
+            dprint(qxl, 1, "%s: using guest_primary for displaysurface\n",
+                   __func__);
             qemu_free_displaysurface(vga->ds);
             qemu_create_displaysurface_from(qxl->guest_primary.surface.width,
                                             qxl->guest_primary.surface.height,
@@ -113,36 +121,70 @@ void qxl_render_update(PCIQXLDevice *qxl)
                                             qxl->guest_primary.abs_stride,
                                             qxl->guest_primary.data);
         } else {
+            dprint(qxl, 1, "%s: resizing displaysurface to guest_primary\n",
+                   __func__);
             qemu_resize_displaysurface(vga->ds,
                     qxl->guest_primary.surface.width,
                     qxl->guest_primary.surface.height);
         }
     }
-    update.left   = 0;
-    update.right  = qxl->guest_primary.surface.width;
-    update.top    = 0;
-    update.bottom = qxl->guest_primary.surface.height;
-
-    memset(dirty, 0, sizeof(dirty));
-    if (runstate_is_running() && qxl->guest_primary.commands) {
-        qxl->guest_primary.commands = 0;
-        qxl_spice_update_area(qxl, 0, &update,
-                              dirty, ARRAY_SIZE(dirty), 1, QXL_SYNC, NULL);
-    }
-    if (redraw) {
-        memset(dirty, 0, sizeof(dirty));
-        dirty[0] = update;
-    }
-    for (i = 0; i < ARRAY_SIZE(dirty); i++) {
-        if (qemu_spice_rect_is_empty(dirty+i)) {
+    for (i = 0; i < qxl->num_dirty_rects; i++) {
+        if (qemu_spice_rect_is_empty(qxl->dirty+i)) {
             break;
         }
-        qxl_flip(qxl, dirty+i);
+        qxl_flip(qxl, qxl->dirty+i);
         dpy_update(vga->ds,
-                   dirty[i].left, dirty[i].top,
-                   dirty[i].right - dirty[i].left,
-                   dirty[i].bottom - dirty[i].top);
+                   qxl->dirty[i].left, qxl->dirty[i].top,
+                   qxl->dirty[i].right - qxl->dirty[i].left,
+                   qxl->dirty[i].bottom - qxl->dirty[i].top);
+    }
+    qxl->num_dirty_rects = 0;
+}
+
+/*
+ * use ssd.lock to protect render_update_cookie_num.
+ * qxl_render_update is called by io thread or vcpu thread, and the completion
+ * callbacks are called by spice_server thread, defering to bh called from the
+ * io thread.
+ */
+void qxl_render_update(PCIQXLDevice *qxl)
+{
+    QXLCookie *cookie;
+
+    qemu_mutex_lock(&qxl->ssd.lock);
+
+    if (!runstate_is_running() || !qxl->guest_primary.commands) {
+        qxl_render_update_area_unlocked(qxl);
+        qemu_mutex_unlock(&qxl->ssd.lock);
+        return;
     }
+
+    qxl->guest_primary.commands = 0;
+    qxl->render_update_cookie_num++;
+    qemu_mutex_unlock(&qxl->ssd.lock);
+    cookie = qxl_cookie_new(QXL_COOKIE_TYPE_RENDER_UPDATE_AREA,
+                            0);
+    qxl_set_rect_to_surface(qxl, &cookie->u.render.area);
+    qxl_spice_update_area(qxl, 0, &cookie->u.render.area, NULL,
+                          0, 1 /* clear_dirty_region */, QXL_ASYNC, cookie);
+}
+
+void qxl_render_update_area_bh(void *opaque)
+{
+    PCIQXLDevice *qxl = opaque;
+
+    qemu_mutex_lock(&qxl->ssd.lock);
+    qxl_render_update_area_unlocked(qxl);
+    qemu_mutex_unlock(&qxl->ssd.lock);
+}
+
+void qxl_render_update_area_done(PCIQXLDevice *qxl, QXLCookie *cookie)
+{
+    qemu_mutex_lock(&qxl->ssd.lock);
+    qemu_bh_schedule(qxl->update_area_bh);
+    qxl->render_update_cookie_num--;
+    qemu_mutex_unlock(&qxl->ssd.lock);
+    g_free(cookie);
 }
 
 static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor)
diff --git a/hw/qxl.c b/hw/qxl.c
index 3bc0e5c..d83d245 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -747,6 +747,11 @@ static void interface_async_complete_io(PCIQXLDevice *qxl, QXLCookie *cookie)
                 __func__, current_async, cookie->io);
     }
     switch (current_async) {
+    case QXL_IO_MEMSLOT_ADD_ASYNC:
+    case QXL_IO_DESTROY_PRIMARY_ASYNC:
+    case QXL_IO_UPDATE_AREA_ASYNC:
+    case QXL_IO_FLUSH_SURFACES_ASYNC:
+        break;
     case QXL_IO_CREATE_PRIMARY_ASYNC:
         qxl_create_guest_primary_complete(qxl);
         break;
@@ -756,11 +761,54 @@ static void interface_async_complete_io(PCIQXLDevice *qxl, QXLCookie *cookie)
     case QXL_IO_DESTROY_SURFACE_ASYNC:
         qxl_spice_destroy_surface_wait_complete(qxl, cookie->u.surface_id);
         break;
+    default:
+        fprintf(stderr, "qxl: %s: unexpected current_async %d\n", __func__,
+                current_async);
     }
     qxl_send_events(qxl, QXL_INTERRUPT_IO_CMD);
 }
 
 /* called from spice server thread context only */
+static void interface_update_area_complete(QXLInstance *sin,
+        uint32_t surface_id,
+        QXLRect *dirty, uint32_t num_updated_rects)
+{
+    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
+    int i;
+    int qxl_i;
+
+    qemu_mutex_lock(&qxl->ssd.lock);
+    if (surface_id != 0 || !qxl->render_update_cookie_num) {
+        qemu_mutex_unlock(&qxl->ssd.lock);
+        return;
+    }
+    if (qxl->num_dirty_rects + num_updated_rects > QXL_NUM_DIRTY_RECTS) {
+        /*
+         * overflow - treat this as a full update. Not expected to be common.
+         */
+        dprint(qxl, 1, "%s: overflow of dirty rects\n", __func__);
+        qxl->guest_primary.resized = 1;
+    }
+    if (qxl->guest_primary.resized) {
+        /*
+         * Don't bother copying or scheduling the bh since we will flip
+         * the whole area anyway on completion of the update_area async call
+         */
+        qemu_mutex_unlock(&qxl->ssd.lock);
+        return;
+    }
+    qxl_i = qxl->num_dirty_rects;
+    for (i = 0; i < num_updated_rects; i++) {
+        qxl->dirty[qxl_i++] = dirty[i];
+    }
+    qxl->num_dirty_rects += num_updated_rects;
+    dprint(qxl, 1, "%s: scheduling update_area_bh, #dirty %d\n",
+           __func__, qxl->num_dirty_rects);
+    qemu_bh_schedule(qxl->update_area_bh);
+    qemu_mutex_unlock(&qxl->ssd.lock);
+}
+
+/* called from spice server thread context only */
 static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token)
 {
     PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
@@ -769,12 +817,16 @@ static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token)
     switch (cookie->type) {
     case QXL_COOKIE_TYPE_IO:
         interface_async_complete_io(qxl, cookie);
+        g_free(cookie);
+        break;
+    case QXL_COOKIE_TYPE_RENDER_UPDATE_AREA:
+        qxl_render_update_area_done(qxl, cookie);
         break;
     default:
         fprintf(stderr, "qxl: %s: unexpected cookie type %d\n",
                 __func__, cookie->type);
+        g_free(cookie);
     }
-    g_free(cookie);
 }
 
 static const QXLInterface qxl_interface = {
@@ -797,6 +849,7 @@ static const QXLInterface qxl_interface = {
     .notify_update           = interface_notify_update,
     .flush_resources         = interface_flush_resources,
     .async_complete          = interface_async_complete,
+    .update_area_complete    = interface_update_area_complete,
 };
 
 static void qxl_enter_vga_mode(PCIQXLDevice *d)
@@ -1213,11 +1266,17 @@ async_common:
     switch (io_port) {
     case QXL_IO_UPDATE_AREA:
     {
+        QXLCookie *cookie = NULL;
         QXLRect update = d->ram->update_area;
+
+        if (async == QXL_ASYNC) {
+            cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+                                    QXL_IO_UPDATE_AREA_ASYNC);
+            cookie->u.area = update;
+        }
         qxl_spice_update_area(d, d->ram->update_surface,
-                              &update, NULL, 0, 0, async,
-                              qxl_cookie_new(QXL_COOKIE_TYPE_IO,
-                                             QXL_IO_UPDATE_AREA_ASYNC));
+                              cookie ? &cookie->u.area : &update,
+                              NULL, 0, 0, async, cookie);
         break;
     }
     case QXL_IO_NOTIFY_CMD:
@@ -1649,6 +1708,8 @@ static int qxl_init_common(PCIQXLDevice *qxl)
     init_pipe_signaling(qxl);
     qxl_reset_state(qxl);
 
+    qxl->update_area_bh = qemu_bh_new(qxl_render_update_area_bh, qxl);
+
     return 0;
 }
 
diff --git a/hw/qxl.h b/hw/qxl.h
index 1443925..86e415b 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -18,6 +18,8 @@ enum qxl_mode {
 
 #define QXL_UNDEFINED_IO UINT32_MAX
 
+#define QXL_NUM_DIRTY_RECTS 64
+
 typedef struct PCIQXLDevice {
     PCIDevice          pci;
     SimpleSpiceDisplay ssd;
@@ -93,6 +95,12 @@ typedef struct PCIQXLDevice {
     /* user-friendly properties (in megabytes) */
     uint32_t          ram_size_mb;
     uint32_t          vram_size_mb;
+
+    /* qxl_render_update state */
+    int                render_update_cookie_num;
+    int                num_dirty_rects;
+    QXLRect            dirty[QXL_NUM_DIRTY_RECTS];
+    QEMUBH            *update_area_bh;
 } PCIQXLDevice;
 
 #define PANIC_ON(x) if ((x)) {                         \
@@ -134,3 +142,5 @@ void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext);
 void qxl_render_resize(PCIQXLDevice *qxl);
 void qxl_render_update(PCIQXLDevice *qxl);
 void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext);
+void qxl_render_update_area_done(PCIQXLDevice *qxl, QXLCookie *cookie);
+void qxl_render_update_area_bh(void *opaque);
diff --git a/ui/spice-display.h b/ui/spice-display.h
index 8a010cb..12e50b6 100644
--- a/ui/spice-display.h
+++ b/ui/spice-display.h
@@ -50,6 +50,7 @@ typedef enum qxl_async_io {
 
 enum {
     QXL_COOKIE_TYPE_IO,
+    QXL_COOKIE_TYPE_RENDER_UPDATE_AREA,
 };
 
 typedef struct QXLCookie {
@@ -57,6 +58,11 @@ typedef struct QXLCookie {
     uint64_t io;
     union {
         uint32_t surface_id;
+        QXLRect area;
+        struct {
+            QXLRect area;
+            int redraw;
+        } render;
     } u;
 } QXLCookie;
 
commit 2e1a98c9c1b90ca093278c6b43244dc46604d7b7
Author: Alon Levy <alevy at redhat.com>
Date:   Fri Feb 24 23:19:30 2012 +0200

    qxl: introduce QXLCookie
    
    Will be used in the next patch.
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index c32d2fd..c45dc30 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -127,7 +127,7 @@ void qxl_render_update(PCIQXLDevice *qxl)
     if (runstate_is_running() && qxl->guest_primary.commands) {
         qxl->guest_primary.commands = 0;
         qxl_spice_update_area(qxl, 0, &update,
-                              dirty, ARRAY_SIZE(dirty), 1, QXL_SYNC);
+                              dirty, ARRAY_SIZE(dirty), 1, QXL_SYNC, NULL);
     }
     if (redraw) {
         memset(dirty, 0, sizeof(dirty));
diff --git a/hw/qxl.c b/hw/qxl.c
index 52df978..3bc0e5c 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -141,14 +141,15 @@ void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
                            struct QXLRect *area, struct QXLRect *dirty_rects,
                            uint32_t num_dirty_rects,
                            uint32_t clear_dirty_region,
-                           qxl_async_io async)
+                           qxl_async_io async, struct QXLCookie *cookie)
 {
     if (async == QXL_SYNC) {
         qxl->ssd.worker->update_area(qxl->ssd.worker, surface_id, area,
                         dirty_rects, num_dirty_rects, clear_dirty_region);
     } else {
+        assert(cookie != NULL);
         spice_qxl_update_area_async(&qxl->ssd.qxl, surface_id, area,
-                                    clear_dirty_region, 0);
+                                    clear_dirty_region, (uint64_t)cookie);
     }
 }
 
@@ -164,9 +165,13 @@ static void qxl_spice_destroy_surface_wait_complete(PCIQXLDevice *qxl,
 static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id,
                                            qxl_async_io async)
 {
+    QXLCookie *cookie;
+
     if (async) {
-        spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id,
-                                        (uint64_t)id);
+        cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+                                QXL_IO_DESTROY_SURFACE_ASYNC);
+        cookie->u.surface_id = id;
+        spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id, (uint64_t)cookie);
     } else {
         qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id);
         qxl_spice_destroy_surface_wait_complete(qxl, id);
@@ -175,7 +180,9 @@ static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id,
 
 static void qxl_spice_flush_surfaces_async(PCIQXLDevice *qxl)
 {
-    spice_qxl_flush_surfaces_async(&qxl->ssd.qxl, 0);
+    spice_qxl_flush_surfaces_async(&qxl->ssd.qxl,
+        (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+                                 QXL_IO_FLUSH_SURFACES_ASYNC));
 }
 
 void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext,
@@ -205,7 +212,9 @@ static void qxl_spice_destroy_surfaces_complete(PCIQXLDevice *qxl)
 static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async)
 {
     if (async) {
-        spice_qxl_destroy_surfaces_async(&qxl->ssd.qxl, 0);
+        spice_qxl_destroy_surfaces_async(&qxl->ssd.qxl,
+                (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+                                         QXL_IO_DESTROY_ALL_SURFACES_ASYNC));
     } else {
         qxl->ssd.worker->destroy_surfaces(qxl->ssd.worker);
         qxl_spice_destroy_surfaces_complete(qxl);
@@ -718,9 +727,8 @@ static int interface_flush_resources(QXLInstance *sin)
 static void qxl_create_guest_primary_complete(PCIQXLDevice *d);
 
 /* called from spice server thread context only */
-static void interface_async_complete(QXLInstance *sin, uint64_t cookie)
+static void interface_async_complete_io(PCIQXLDevice *qxl, QXLCookie *cookie)
 {
-    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
     uint32_t current_async;
 
     qemu_mutex_lock(&qxl->async_lock);
@@ -728,8 +736,16 @@ static void interface_async_complete(QXLInstance *sin, uint64_t cookie)
     qxl->current_async = QXL_UNDEFINED_IO;
     qemu_mutex_unlock(&qxl->async_lock);
 
-    dprint(qxl, 2, "async_complete: %d (%" PRId64 ") done\n",
-           current_async, cookie);
+    dprint(qxl, 2, "async_complete: %d (%p) done\n", current_async, cookie);
+    if (!cookie) {
+        fprintf(stderr, "qxl: %s: error, cookie is NULL\n", __func__);
+        return;
+    }
+    if (cookie && current_async != cookie->io) {
+        fprintf(stderr,
+                "qxl: %s: error: current_async = %d != %ld = cookie->io\n",
+                __func__, current_async, cookie->io);
+    }
     switch (current_async) {
     case QXL_IO_CREATE_PRIMARY_ASYNC:
         qxl_create_guest_primary_complete(qxl);
@@ -738,12 +754,29 @@ static void interface_async_complete(QXLInstance *sin, uint64_t cookie)
         qxl_spice_destroy_surfaces_complete(qxl);
         break;
     case QXL_IO_DESTROY_SURFACE_ASYNC:
-        qxl_spice_destroy_surface_wait_complete(qxl, (uint32_t)cookie);
+        qxl_spice_destroy_surface_wait_complete(qxl, cookie->u.surface_id);
         break;
     }
     qxl_send_events(qxl, QXL_INTERRUPT_IO_CMD);
 }
 
+/* called from spice server thread context only */
+static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token)
+{
+    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
+    QXLCookie *cookie = (QXLCookie *)cookie_token;
+
+    switch (cookie->type) {
+    case QXL_COOKIE_TYPE_IO:
+        interface_async_complete_io(qxl, cookie);
+        break;
+    default:
+        fprintf(stderr, "qxl: %s: unexpected cookie type %d\n",
+                __func__, cookie->type);
+    }
+    g_free(cookie);
+}
+
 static const QXLInterface qxl_interface = {
     .base.type               = SPICE_INTERFACE_QXL,
     .base.description        = "qxl gpu",
@@ -1054,9 +1087,7 @@ static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async)
     if (d->mode == QXL_MODE_UNDEFINED) {
         return 0;
     }
-
     dprint(d, 1, "%s\n", __FUNCTION__);
-
     d->mode = QXL_MODE_UNDEFINED;
     qemu_spice_destroy_primary_surface(&d->ssd, 0, async);
     qxl_spice_reset_cursor(d);
@@ -1184,7 +1215,9 @@ async_common:
     {
         QXLRect update = d->ram->update_area;
         qxl_spice_update_area(d, d->ram->update_surface,
-                              &update, NULL, 0, 0, async);
+                              &update, NULL, 0, 0, async,
+                              qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+                                             QXL_IO_UPDATE_AREA_ASYNC));
         break;
     }
     case QXL_IO_NOTIFY_CMD:
diff --git a/hw/qxl.h b/hw/qxl.h
index 53a3ace..1443925 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -118,7 +118,7 @@ void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
                            struct QXLRect *area, struct QXLRect *dirty_rects,
                            uint32_t num_dirty_rects,
                            uint32_t clear_dirty_region,
-                           qxl_async_io async);
+                           qxl_async_io async, QXLCookie *cookie);
 void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext,
                                uint32_t count);
 void qxl_spice_oom(PCIQXLDevice *qxl);
diff --git a/ui/spice-display.c b/ui/spice-display.c
index ad76bae..ab266ae 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -60,11 +60,23 @@ void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r)
     dest->right = MAX(dest->right, r->right);
 }
 
+QXLCookie *qxl_cookie_new(int type, uint64_t io)
+{
+    QXLCookie *cookie;
+
+    cookie = g_malloc0(sizeof(*cookie));
+    cookie->type = type;
+    cookie->io = io;
+    return cookie;
+}
+
 void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot,
                             qxl_async_io async)
 {
     if (async != QXL_SYNC) {
-        spice_qxl_add_memslot_async(&ssd->qxl, memslot, 0);
+        spice_qxl_add_memslot_async(&ssd->qxl, memslot,
+                (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+                                         QXL_IO_MEMSLOT_ADD_ASYNC));
     } else {
         ssd->worker->add_memslot(ssd->worker, memslot);
     }
@@ -80,7 +92,9 @@ void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id,
                                        qxl_async_io async)
 {
     if (async != QXL_SYNC) {
-        spice_qxl_create_primary_surface_async(&ssd->qxl, id, surface, 0);
+        spice_qxl_create_primary_surface_async(&ssd->qxl, id, surface,
+                (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+                                         QXL_IO_CREATE_PRIMARY_ASYNC));
     } else {
         ssd->worker->create_primary_surface(ssd->worker, id, surface);
     }
@@ -91,7 +105,9 @@ void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd,
                                         uint32_t id, qxl_async_io async)
 {
     if (async != QXL_SYNC) {
-        spice_qxl_destroy_primary_surface_async(&ssd->qxl, id, 0);
+        spice_qxl_destroy_primary_surface_async(&ssd->qxl, id,
+                (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+                                         QXL_IO_DESTROY_PRIMARY_ASYNC));
     } else {
         ssd->worker->destroy_primary_surface(ssd->worker, id);
     }
diff --git a/ui/spice-display.h b/ui/spice-display.h
index a23bfc8..8a010cb 100644
--- a/ui/spice-display.h
+++ b/ui/spice-display.h
@@ -48,6 +48,20 @@ typedef enum qxl_async_io {
     QXL_ASYNC,
 } qxl_async_io;
 
+enum {
+    QXL_COOKIE_TYPE_IO,
+};
+
+typedef struct QXLCookie {
+    int      type;
+    uint64_t io;
+    union {
+        uint32_t surface_id;
+    } u;
+} QXLCookie;
+
+QXLCookie *qxl_cookie_new(int type, uint64_t io);
+
 typedef struct SimpleSpiceDisplay SimpleSpiceDisplay;
 typedef struct SimpleSpiceUpdate SimpleSpiceUpdate;
 
commit 4c19ebb51dc0a59ff12d60844512816562a25047
Author: Alon Levy <alevy at redhat.com>
Date:   Fri Feb 24 23:19:29 2012 +0200

    qxl: remove flipped
    
    Tested on linux and windows guests. For negative stride, qxl_flip copies
    directly to vga->ds->surface->data, for positive it's reallocated to
    share qxl->guest_primary.data
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index 7084143..c32d2fd 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -23,10 +23,21 @@
 
 static void qxl_flip(PCIQXLDevice *qxl, QXLRect *rect)
 {
-    uint8_t *src = qxl->guest_primary.data;
-    uint8_t *dst = qxl->guest_primary.flipped;
+    uint8_t *src;
+    uint8_t *dst = qxl->vga.ds->surface->data;
     int len, i;
 
+    if (qxl->guest_primary.qxl_stride > 0) {
+        return;
+    }
+    if (!qxl->guest_primary.data) {
+        dprint(qxl, 1, "%s: initializing guest_primary.data\n", __func__);
+        qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram);
+    }
+    dprint(qxl, 1, "%s: stride %d, [%d, %d, %d, %d]\n", __func__,
+            qxl->guest_primary.qxl_stride,
+            rect->left, rect->right, rect->top, rect->bottom);
+    src = qxl->guest_primary.data;
     src += (qxl->guest_primary.surface.height - rect->top - 1) *
         qxl->guest_primary.abs_stride;
     dst += rect->top  * qxl->guest_primary.abs_stride;
@@ -75,52 +86,38 @@ void qxl_render_update(PCIQXLDevice *qxl)
 {
     VGACommonState *vga = &qxl->vga;
     QXLRect dirty[32], update;
-    void *ptr;
     int i, redraw = 0;
-
-    if (!is_buffer_shared(vga->ds->surface)) {
-        dprint(qxl, 1, "%s: restoring shared displaysurface\n", __func__);
-        qxl->guest_primary.resized++;
-        qxl->guest_primary.commands++;
-        redraw = 1;
-    }
+    DisplaySurface *surface = vga->ds->surface;
 
     if (qxl->guest_primary.resized) {
         qxl->guest_primary.resized = 0;
 
-        if (qxl->guest_primary.flipped) {
-            g_free(qxl->guest_primary.flipped);
-            qxl->guest_primary.flipped = NULL;
-        }
-        qemu_free_displaysurface(vga->ds);
-
         qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram);
-        if (qxl->guest_primary.qxl_stride < 0) {
-            /* spice surface is upside down -> need extra buffer to flip */
-            qxl->guest_primary.flipped =
-                g_malloc(qxl->guest_primary.surface.width *
-                         qxl->guest_primary.abs_stride);
-            ptr = qxl->guest_primary.flipped;
-        } else {
-            ptr = qxl->guest_primary.data;
-        }
-        dprint(qxl, 1, "%s: %dx%d, stride %d, bpp %d, depth %d, flip %s\n",
+        dprint(qxl, 1, "%s: %dx%d, stride %d, bpp %d, depth %d\n",
                __FUNCTION__,
                qxl->guest_primary.surface.width,
                qxl->guest_primary.surface.height,
                qxl->guest_primary.qxl_stride,
                qxl->guest_primary.bytes_pp,
-               qxl->guest_primary.bits_pp,
-               qxl->guest_primary.flipped ? "yes" : "no");
-        vga->ds->surface =
+               qxl->guest_primary.bits_pp);
+    }
+    if (surface->width != qxl->guest_primary.surface.width ||
+        surface->height != qxl->guest_primary.surface.height) {
+        dprint(qxl, 1, "%s: resizing displaysurface to guest_primary\n",
+               __func__);
+        if (qxl->guest_primary.qxl_stride > 0) {
+            qemu_free_displaysurface(vga->ds);
             qemu_create_displaysurface_from(qxl->guest_primary.surface.width,
                                             qxl->guest_primary.surface.height,
                                             qxl->guest_primary.bits_pp,
                                             qxl->guest_primary.abs_stride,
-                                            ptr);
-        dpy_resize(vga->ds);
+                                            qxl->guest_primary.data);
+        } else {
+            qemu_resize_displaysurface(vga->ds,
+                    qxl->guest_primary.surface.width,
+                    qxl->guest_primary.surface.height);
+        }
     }
-
     update.left   = 0;
     update.right  = qxl->guest_primary.surface.width;
     update.top    = 0;
@@ -136,14 +133,11 @@ void qxl_render_update(PCIQXLDevice *qxl)
         memset(dirty, 0, sizeof(dirty));
         dirty[0] = update;
     }
-
     for (i = 0; i < ARRAY_SIZE(dirty); i++) {
         if (qemu_spice_rect_is_empty(dirty+i)) {
             break;
         }
-        if (qxl->guest_primary.flipped) {
-            qxl_flip(qxl, dirty+i);
-        }
+        qxl_flip(qxl, dirty+i);
         dpy_update(vga->ds,
                    dirty[i].left, dirty[i].top,
                    dirty[i].right - dirty[i].left,
diff --git a/hw/qxl.h b/hw/qxl.h
index 9288e46..53a3ace 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -52,7 +52,7 @@ typedef struct PCIQXLDevice {
         uint32_t       abs_stride;
         uint32_t       bits_pp;
         uint32_t       bytes_pp;
-        uint8_t        *data, *flipped;
+        uint8_t        *data;
     } guest_primary;
 
     struct surfaces {
commit 4295e15aa730a95003a3639d6dad2eb1e65a59e2
Author: Alon Levy <alevy at redhat.com>
Date:   Fri Feb 24 23:19:28 2012 +0200

    qxl: require spice >= 0.8.2
    
    drop all ifdefs on SPICE_INTERFACE_QXL_MINOR >= 1 as a result,
    any check for SPICE_SERVER_VERSION that is now always satisfied,
    and SPICE_INTERFACE_CORE_MINOR >= 3 tests, because
    0.8.2 has SPICE_INTERFACE_QXL_MINOR == 1 and
    SPICE_INTERFACE_CORE_MINOR == 3.
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/configure b/configure
index f9d5330..9535f66 100755
--- a/configure
+++ b/configure
@@ -2547,7 +2547,7 @@ int main(void) { spice_server_new(); return 0; }
 EOF
   spice_cflags=$($pkg_config --cflags spice-protocol spice-server 2>/dev/null)
   spice_libs=$($pkg_config --libs spice-protocol spice-server 2>/dev/null)
-  if $pkg_config --atleast-version=0.6.0 spice-server >/dev/null 2>&1 && \
+  if $pkg_config --atleast-version=0.8.2 spice-server >/dev/null 2>&1 && \
      compile_prog "$spice_cflags" "$spice_libs" ; then
     spice="yes"
     libs_softmmu="$libs_softmmu $spice_libs"
diff --git a/hw/qxl.c b/hw/qxl.c
index 0bbf0e8..52df978 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -125,9 +125,7 @@ static void qxl_ring_set_dirty(PCIQXLDevice *qxl);
 
 void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg, ...)
 {
-#if SPICE_INTERFACE_QXL_MINOR >= 1
     qxl_send_events(qxl, QXL_INTERRUPT_ERROR);
-#endif
     if (qxl->guestdebug) {
         va_list ap;
         va_start(ap, msg);
@@ -149,12 +147,8 @@ void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
         qxl->ssd.worker->update_area(qxl->ssd.worker, surface_id, area,
                         dirty_rects, num_dirty_rects, clear_dirty_region);
     } else {
-#if SPICE_INTERFACE_QXL_MINOR >= 1
         spice_qxl_update_area_async(&qxl->ssd.qxl, surface_id, area,
                                     clear_dirty_region, 0);
-#else
-        abort();
-#endif
     }
 }
 
@@ -171,24 +165,18 @@ static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id,
                                            qxl_async_io async)
 {
     if (async) {
-#if SPICE_INTERFACE_QXL_MINOR < 1
-        abort();
-#else
         spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id,
                                         (uint64_t)id);
-#endif
     } else {
         qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id);
         qxl_spice_destroy_surface_wait_complete(qxl, id);
     }
 }
 
-#if SPICE_INTERFACE_QXL_MINOR >= 1
 static void qxl_spice_flush_surfaces_async(PCIQXLDevice *qxl)
 {
     spice_qxl_flush_surfaces_async(&qxl->ssd.qxl, 0);
 }
-#endif
 
 void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext,
                                uint32_t count)
@@ -217,11 +205,7 @@ static void qxl_spice_destroy_surfaces_complete(PCIQXLDevice *qxl)
 static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async)
 {
     if (async) {
-#if SPICE_INTERFACE_QXL_MINOR < 1
-        abort();
-#else
         spice_qxl_destroy_surfaces_async(&qxl->ssd.qxl, 0);
-#endif
     } else {
         qxl->ssd.worker->destroy_surfaces(qxl->ssd.worker);
         qxl_spice_destroy_surfaces_complete(qxl);
@@ -490,7 +474,6 @@ static const char *io_port_to_string(uint32_t io_port)
         [QXL_IO_DESTROY_PRIMARY]        = "QXL_IO_DESTROY_PRIMARY",
         [QXL_IO_DESTROY_SURFACE_WAIT]   = "QXL_IO_DESTROY_SURFACE_WAIT",
         [QXL_IO_DESTROY_ALL_SURFACES]   = "QXL_IO_DESTROY_ALL_SURFACES",
-#if SPICE_INTERFACE_QXL_MINOR >= 1
         [QXL_IO_UPDATE_AREA_ASYNC]      = "QXL_IO_UPDATE_AREA_ASYNC",
         [QXL_IO_MEMSLOT_ADD_ASYNC]      = "QXL_IO_MEMSLOT_ADD_ASYNC",
         [QXL_IO_CREATE_PRIMARY_ASYNC]   = "QXL_IO_CREATE_PRIMARY_ASYNC",
@@ -500,7 +483,6 @@ static const char *io_port_to_string(uint32_t io_port)
                                         = "QXL_IO_DESTROY_ALL_SURFACES_ASYNC",
         [QXL_IO_FLUSH_SURFACES_ASYNC]   = "QXL_IO_FLUSH_SURFACES_ASYNC",
         [QXL_IO_FLUSH_RELEASE]          = "QXL_IO_FLUSH_RELEASE",
-#endif
     };
     return io_port_to_string[io_port];
 }
@@ -735,8 +717,6 @@ static int interface_flush_resources(QXLInstance *sin)
 
 static void qxl_create_guest_primary_complete(PCIQXLDevice *d);
 
-#if SPICE_INTERFACE_QXL_MINOR >= 1
-
 /* called from spice server thread context only */
 static void interface_async_complete(QXLInstance *sin, uint64_t cookie)
 {
@@ -764,8 +744,6 @@ static void interface_async_complete(QXLInstance *sin, uint64_t cookie)
     qxl_send_events(qxl, QXL_INTERRUPT_IO_CMD);
 }
 
-#endif
-
 static const QXLInterface qxl_interface = {
     .base.type               = SPICE_INTERFACE_QXL,
     .base.description        = "qxl gpu",
@@ -785,9 +763,7 @@ static const QXLInterface qxl_interface = {
     .req_cursor_notification = interface_req_cursor_notification,
     .notify_update           = interface_notify_update,
     .flush_resources         = interface_flush_resources,
-#if SPICE_INTERFACE_QXL_MINOR >= 1
     .async_complete          = interface_async_complete,
-#endif
 };
 
 static void qxl_enter_vga_mode(PCIQXLDevice *d)
@@ -1137,9 +1113,7 @@ static void ioport_write(void *opaque, target_phys_addr_t addr,
     PCIQXLDevice *d = opaque;
     uint32_t io_port = addr;
     qxl_async_io async = QXL_SYNC;
-#if SPICE_INTERFACE_QXL_MINOR >= 1
     uint32_t orig_io_port = io_port;
-#endif
 
     switch (io_port) {
     case QXL_IO_RESET:
@@ -1149,10 +1123,8 @@ static void ioport_write(void *opaque, target_phys_addr_t addr,
     case QXL_IO_CREATE_PRIMARY:
     case QXL_IO_UPDATE_IRQ:
     case QXL_IO_LOG:
-#if SPICE_INTERFACE_QXL_MINOR >= 1
     case QXL_IO_MEMSLOT_ADD_ASYNC:
     case QXL_IO_CREATE_PRIMARY_ASYNC:
-#endif
         break;
     default:
         if (d->mode != QXL_MODE_VGA) {
@@ -1160,17 +1132,14 @@ static void ioport_write(void *opaque, target_phys_addr_t addr,
         }
         dprint(d, 1, "%s: unexpected port 0x%x (%s) in vga mode\n",
             __func__, io_port, io_port_to_string(io_port));
-#if SPICE_INTERFACE_QXL_MINOR >= 1
         /* be nice to buggy guest drivers */
         if (io_port >= QXL_IO_UPDATE_AREA_ASYNC &&
             io_port <= QXL_IO_DESTROY_ALL_SURFACES_ASYNC) {
             qxl_send_events(d, QXL_INTERRUPT_IO_CMD);
         }
-#endif
         return;
     }
 
-#if SPICE_INTERFACE_QXL_MINOR >= 1
     /* we change the io_port to avoid ifdeffery in the main switch */
     orig_io_port = io_port;
     switch (io_port) {
@@ -1209,7 +1178,6 @@ async_common:
     default:
         break;
     }
-#endif
 
     switch (io_port) {
     case QXL_IO_UPDATE_AREA:
@@ -1301,7 +1269,6 @@ async_common:
         }
         qxl_spice_destroy_surface_wait(d, val, async);
         break;
-#if SPICE_INTERFACE_QXL_MINOR >= 1
     case QXL_IO_FLUSH_RELEASE: {
         QXLReleaseRing *ring = &d->ram->release_ring;
         if (ring->prod - ring->cons + 1 == ring->num_items) {
@@ -1322,7 +1289,6 @@ async_common:
                d->num_free_res);
         qxl_spice_flush_surfaces_async(d);
         break;
-#endif
     case QXL_IO_DESTROY_ALL_SURFACES:
         d->mode = QXL_MODE_UNDEFINED;
         qxl_spice_destroy_surfaces(d, async);
@@ -1333,16 +1299,12 @@ async_common:
     }
     return;
 cancel_async:
-#if SPICE_INTERFACE_QXL_MINOR >= 1
     if (async) {
         qxl_send_events(d, QXL_INTERRUPT_IO_CMD);
         qemu_mutex_lock(&d->async_lock);
         d->current_async = QXL_UNDEFINED_IO;
         qemu_mutex_unlock(&d->async_lock);
     }
-#else
-    return;
-#endif
 }
 
 static uint64_t ioport_read(void *opaque, target_phys_addr_t addr,
@@ -1604,9 +1566,7 @@ static int qxl_init_common(PCIQXLDevice *qxl)
     case 2: /* spice 0.6 -- qxl-2 */
         pci_device_rev = QXL_REVISION_STABLE_V06;
         break;
-#if SPICE_INTERFACE_QXL_MINOR >= 1
     case 3: /* qxl-3 */
-#endif
     default:
         pci_device_rev = QXL_DEFAULT_REVISION;
         break;
diff --git a/hw/qxl.h b/hw/qxl.h
index a615eca..9288e46 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -108,11 +108,7 @@ typedef struct PCIQXLDevice {
         }                                                               \
     } while (0)
 
-#if SPICE_INTERFACE_QXL_MINOR >= 1
 #define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V10
-#else
-#define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V06
-#endif
 
 /* qxl.c */
 void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id);
diff --git a/ui/spice-core.c b/ui/spice-core.c
index 1308a3d..30d2c62 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -139,8 +139,6 @@ static void watch_remove(SpiceWatch *watch)
     g_free(watch);
 }
 
-#if SPICE_INTERFACE_CORE_MINOR >= 3
-
 typedef struct ChannelList ChannelList;
 struct ChannelList {
     SpiceChannelEventInfo *info;
@@ -257,15 +255,6 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
     }
 }
 
-#else /* SPICE_INTERFACE_CORE_MINOR >= 3 */
-
-static QList *channel_list_get(void)
-{
-    return NULL;
-}
-
-#endif /* SPICE_INTERFACE_CORE_MINOR >= 3 */
-
 static SpiceCoreInterface core_interface = {
     .base.type          = SPICE_INTERFACE_CORE,
     .base.description   = "qemu core services",
@@ -281,9 +270,7 @@ static SpiceCoreInterface core_interface = {
     .watch_update_mask  = watch_update_mask,
     .watch_remove       = watch_remove,
 
-#if SPICE_INTERFACE_CORE_MINOR >= 3
     .channel_event      = channel_event,
-#endif
 };
 
 #ifdef SPICE_INTERFACE_MIGRATION
@@ -490,7 +477,6 @@ static void migration_state_notifier(Notifier *notifier, void *data)
         spice_server_migrate_start(spice_server);
 #endif
     } else if (migration_has_finished(s)) {
-#if SPICE_SERVER_VERSION >= 0x000701 /* 0.7.1 */
 #ifndef SPICE_INTERFACE_MIGRATION
         spice_server_migrate_switch(spice_server);
 #else
@@ -498,7 +484,6 @@ static void migration_state_notifier(Notifier *notifier, void *data)
     } else if (migration_has_failed(s)) {
         spice_server_migrate_end(spice_server, false);
 #endif
-#endif
     }
 }
 
@@ -659,11 +644,9 @@ void qemu_spice_init(void)
         spice_server_set_noauth(spice_server);
     }
 
-#if SPICE_SERVER_VERSION >= 0x000801
     if (qemu_opt_get_bool(opts, "disable-copy-paste", 0)) {
         spice_server_set_agent_copypaste(spice_server, false);
     }
-#endif
 
     compression = SPICE_IMAGE_COMPRESS_AUTO_GLZ;
     str = qemu_opt_get(opts, "image-compression");
diff --git a/ui/spice-display.c b/ui/spice-display.c
index c6e61d8..ad76bae 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -64,11 +64,7 @@ void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot,
                             qxl_async_io async)
 {
     if (async != QXL_SYNC) {
-#if SPICE_INTERFACE_QXL_MINOR >= 1
         spice_qxl_add_memslot_async(&ssd->qxl, memslot, 0);
-#else
-        abort();
-#endif
     } else {
         ssd->worker->add_memslot(ssd->worker, memslot);
     }
@@ -84,11 +80,7 @@ void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id,
                                        qxl_async_io async)
 {
     if (async != QXL_SYNC) {
-#if SPICE_INTERFACE_QXL_MINOR >= 1
         spice_qxl_create_primary_surface_async(&ssd->qxl, id, surface, 0);
-#else
-        abort();
-#endif
     } else {
         ssd->worker->create_primary_surface(ssd->worker, id, surface);
     }
@@ -99,11 +91,7 @@ void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd,
                                         uint32_t id, qxl_async_io async)
 {
     if (async != QXL_SYNC) {
-#if SPICE_INTERFACE_QXL_MINOR >= 1
         spice_qxl_destroy_primary_surface_async(&ssd->qxl, id, 0);
-#else
-        abort();
-#endif
     } else {
         ssd->worker->destroy_primary_surface(ssd->worker, id);
     }
commit 45a4b48528aa20b602eb8c764d511fb1c4d6cab7
Author: Alon Levy <alevy at redhat.com>
Date:   Fri Feb 24 23:19:27 2012 +0200

    qxl: drop qxl_spice_update_area_async definition
    
    It was never used. Introduced in
    5ff4e36c804157bd84af43c139f8cd3a59722db9
    qxl: async io support using new spice api
    
    But not used even then.
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.h b/hw/qxl.h
index d062991..a615eca 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -138,9 +138,3 @@ void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext);
 void qxl_render_resize(PCIQXLDevice *qxl);
 void qxl_render_update(PCIQXLDevice *qxl);
 void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext);
-#if SPICE_INTERFACE_QXL_MINOR >= 1
-void qxl_spice_update_area_async(PCIQXLDevice *qxl, uint32_t surface_id,
-                                 struct QXLRect *area,
-                                 uint32_t clear_dirty_region,
-                                 int is_vga);
-#endif
commit 63ea491d4efc1e02cda3d335db3a46c81adf14ee
Author: Alon Levy <alevy at redhat.com>
Date:   Fri Feb 24 23:19:26 2012 +0200

    sdl: remove NULL check, g_malloc0 can't fail
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/sdl.c b/ui/sdl.c
index 6f8091c..f6f711c 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -167,10 +167,6 @@ static PixelFormat sdl_to_qemu_pixelformat(SDL_PixelFormat *sdl_pf)
 static DisplaySurface* sdl_create_displaysurface(int width, int height)
 {
     DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface));
-    if (surface == NULL) {
-        fprintf(stderr, "sdl_create_displaysurface: malloc failed\n");
-        exit(1);
-    }
 
     surface->width = width;
     surface->height = height;
commit bb5a8cd5b0aec0286c5e749803083de22c2b0be6
Author: Alon Levy <alevy at redhat.com>
Date:   Fri Feb 24 23:19:25 2012 +0200

    qxl: fix spice+sdl no cursor regression
    
    regression introduced by 075360945860ad9bdd491921954b383bf762b0e5,
    
    v2: lock around qemu_spice_cursor_refresh_unlocked
    
    Reported-by: Fabiano Fidêncio <fabiano at fidencio.org>
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index f643667..0bbf0e8 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1545,6 +1545,10 @@ static void display_refresh(struct DisplayState *ds)
 {
     if (qxl0->mode == QXL_MODE_VGA) {
         qemu_spice_display_refresh(&qxl0->ssd);
+    } else {
+        qemu_mutex_lock(&qxl0->ssd.lock);
+        qemu_spice_cursor_refresh_unlocked(&qxl0->ssd);
+        qemu_mutex_unlock(&qxl0->ssd.lock);
     }
 }
 
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 6c302a3..c6e61d8 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -317,16 +317,8 @@ void qemu_spice_display_resize(SimpleSpiceDisplay *ssd)
     ssd->notify++;
 }
 
-void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd)
+void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd)
 {
-    dprint(3, "%s:\n", __FUNCTION__);
-    vga_hw_update();
-
-    qemu_mutex_lock(&ssd->lock);
-    if (ssd->update == NULL) {
-        ssd->update = qemu_spice_create_update(ssd);
-        ssd->notify++;
-    }
     if (ssd->cursor) {
         ssd->ds->cursor_define(ssd->cursor);
         cursor_put(ssd->cursor);
@@ -337,6 +329,19 @@ void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd)
         ssd->mouse_x = -1;
         ssd->mouse_y = -1;
     }
+}
+
+void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd)
+{
+    dprint(3, "%s:\n", __func__);
+    vga_hw_update();
+
+    qemu_mutex_lock(&ssd->lock);
+    if (ssd->update == NULL) {
+        ssd->update = qemu_spice_create_update(ssd);
+        ssd->notify++;
+    }
+    qemu_spice_cursor_refresh_unlocked(ssd);
     qemu_mutex_unlock(&ssd->lock);
 
     if (ssd->notify) {
diff --git a/ui/spice-display.h b/ui/spice-display.h
index 5e52df9..a23bfc8 100644
--- a/ui/spice-display.h
+++ b/ui/spice-display.h
@@ -97,6 +97,7 @@ void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
                                int x, int y, int w, int h);
 void qemu_spice_display_resize(SimpleSpiceDisplay *ssd);
 void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd);
+void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd);
 
 void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot,
                             qxl_async_io async);
commit 67d6fa53629f1eb3401974d740310c10e03fa1c9
Author: Benjamin Herrenschmidt <benh at kernel.crashing.org>
Date:   Fri Feb 24 11:23:30 2012 +1100

    hw/9pfs: Endian fixes for virtfs
    
    This patch fixes several endian bugs in virtfs.
    
    Cc: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    
    Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>

diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index a72ffc3..c633fb9 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -1349,7 +1349,9 @@ static void v9fs_open(void *opaque)
     if (s->proto_version == V9FS_PROTO_2000L) {
         err = pdu_unmarshal(pdu, offset, "dd", &fid, &mode);
     } else {
-        err = pdu_unmarshal(pdu, offset, "db", &fid, &mode);
+        uint8_t modebyte;
+        err = pdu_unmarshal(pdu, offset, "db", &fid, &modebyte);
+        mode = modebyte;
     }
     if (err < 0) {
         goto out_nofid;
@@ -3260,9 +3262,9 @@ void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
 
         ptr = pdu->elem.out_sg[0].iov_base;
 
-        memcpy(&pdu->size, ptr, 4);
+        pdu->size = le32_to_cpu(*(uint32_t *)ptr);
         pdu->id = ptr[4];
-        memcpy(&pdu->tag, ptr + 5, 2);
+        pdu->tag = le16_to_cpu(*(uint16_t *)(ptr + 5));
         qemu_co_queue_init(&pdu->complete);
         submit_pdu(s, pdu);
     }
commit 983eef5ad77fc4202e53ae32d79a1d2992302377
Author: Meador Inge <meadori at codesourcery.com>
Date:   Fri Feb 24 14:00:42 2012 +0530

    ./configure: add option for disabling VirtFS
    
    Signed-off-by: Meador Inge <meadori at codesourcery.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>

diff --git a/Makefile b/Makefile
index c67493e..ac82afe 100644
--- a/Makefile
+++ b/Makefile
@@ -40,7 +40,9 @@ HELPERS-$(CONFIG_LINUX) = qemu-bridge-helper$(EXESUF)
 
 ifdef BUILD_DOCS
 DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 qemu-nbd.8 QMP/qmp-commands.txt
+ifdef CONFIG_VIRTFS
 DOCS+=fsdev/virtfs-proxy-helper.1
+endif
 else
 DOCS=
 endif
diff --git a/configure b/configure
index 037f7f7..05a778d 100755
--- a/configure
+++ b/configure
@@ -121,6 +121,7 @@ docs=""
 fdt=""
 nptl=""
 sdl=""
+virtfs=""
 vnc="yes"
 sparse="no"
 uuid=""
@@ -586,6 +587,10 @@ for opt do
   ;;
   --enable-sdl) sdl="yes"
   ;;
+  --disable-virtfs) virtfs="no"
+  ;;
+  --enable-virtfs) virtfs="yes"
+  ;;
   --disable-vnc) vnc="no"
   ;;
   --enable-vnc) vnc="yes"
@@ -993,6 +998,8 @@ echo "  --disable-strip          disable stripping binaries"
 echo "  --disable-werror         disable compilation abort on warning"
 echo "  --disable-sdl            disable SDL"
 echo "  --enable-sdl             enable SDL"
+echo "  --disable-virtfs         disable VirtFS"
+echo "  --enable-virtfs          enable VirtFS"
 echo "  --disable-vnc            disable VNC"
 echo "  --enable-vnc             enable VNC"
 echo "  --enable-cocoa           enable COCOA (Mac OS X only)"
@@ -2805,8 +2812,15 @@ confdir=$sysconfdir$confsuffix
 tools=
 if test "$softmmu" = yes ; then
   tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools"
-  if [ "$cap" = "yes" -a "$linux" = "yes" ] ; then
-      tools="$tools fsdev/virtfs-proxy-helper\$(EXESUF)"
+  if test "$virtfs" != no ; then
+      if test "$cap" = yes && test "$linux" = yes && test "$attr" = yes ; then
+	  virtfs=yes
+	  tools="$tools fsdev/virtfs-proxy-helper\$(EXESUF)"
+      else
+	  if test "$virtfs" = yes; then
+	      feature_not_found "virtfs"
+	  fi
+      fi
   fi
   if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
       tools="qemu-nbd\$(EXESUF) $tools"
@@ -2871,6 +2885,7 @@ echo "Audio drivers     $audio_drv_list"
 echo "Extra audio cards $audio_card_list"
 echo "Block whitelist   $block_drv_whitelist"
 echo "Mixer emulation   $mixemu"
+echo "VirtFS support    $virtfs"
 echo "VNC support       $vnc"
 if test "$vnc" = "yes" ; then
     echo "VNC TLS support   $vnc_tls"
@@ -3160,10 +3175,8 @@ fi
 if test "$libattr" = "yes" ; then
   echo "CONFIG_LIBATTR=y" >> $config_host_mak
 fi
-if test "$linux" = "yes" ; then
-  if test "$attr" = "yes" ; then
-    echo "CONFIG_VIRTFS=y" >> $config_host_mak
-  fi
+if test "$virtfs" = "yes" ; then
+  echo "CONFIG_VIRTFS=y" >> $config_host_mak
 fi
 if test "$blobs" = "yes" ; then
   echo "INSTALL_BLOBS=yes" >> $config_host_mak
commit e7dfa64def10e76a33e48a425d18055939c5a60e
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Fri Jan 13 09:22:07 2012 +0400

    target-xtensa: add breakpoint tests
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/tests/tcg/xtensa/Makefile b/tests/tcg/xtensa/Makefile
index 8713af1..7e1e619 100644
--- a/tests/tcg/xtensa/Makefile
+++ b/tests/tcg/xtensa/Makefile
@@ -23,6 +23,7 @@ CRT        = crt.o vectors.o
 TESTCASES += test_b.tst
 TESTCASES += test_bi.tst
 #TESTCASES += test_boolean.tst
+TESTCASES += test_break.tst
 TESTCASES += test_bz.tst
 TESTCASES += test_clamps.tst
 TESTCASES += test_fail.tst
diff --git a/tests/tcg/xtensa/test_break.S b/tests/tcg/xtensa/test_break.S
new file mode 100644
index 0000000..8a8db80
--- /dev/null
+++ b/tests/tcg/xtensa/test_break.S
@@ -0,0 +1,223 @@
+.include "macros.inc"
+
+#define debug_level 6
+#define debug_vector level6
+
+test_suite break
+
+test break
+    set_vector debug_vector, 0
+    rsil    a2, debug_level
+    _break  0, 0
+
+    set_vector debug_vector, 2f
+    rsil    a2, debug_level - 1
+1:
+    _break  0, 0
+    test_fail
+2:
+    rsr     a2, ps
+    movi    a3, 0x1f
+    and     a2, a2, a3
+    movi    a3, 0x10 | debug_level
+    assert  eq, a2, a3
+    rsr     a2, epc6
+    movi    a3, 1b
+    assert  eq, a2, a3
+    rsr     a2, debugcause
+    movi    a3, 0x8
+    assert  eq, a2, a3
+test_end
+
+test breakn
+    set_vector debug_vector, 0
+    rsil    a2, debug_level
+    _break.n  0
+
+    set_vector debug_vector, 2f
+    rsil    a2, debug_level - 1
+1:
+    _break.n  0
+    test_fail
+2:
+    rsr     a2, ps
+    movi    a3, 0x1f
+    and     a2, a2, a3
+    movi    a3, 0x10 | debug_level
+    assert  eq, a2, a3
+    rsr     a2, epc6
+    movi    a3, 1b
+    assert  eq, a2, a3
+    rsr     a2, debugcause
+    movi    a3, 0x10
+    assert  eq, a2, a3
+test_end
+
+test ibreak
+    set_vector debug_vector, 0
+    rsil    a2, debug_level
+    movi    a2, 1f
+    wsr     a2, ibreaka0
+    movi    a2, 1
+    wsr     a2, ibreakenable
+    isync
+1:
+    rsil    a2, debug_level - 1
+    movi    a2, 1f
+    wsr     a2, ibreaka0
+    movi    a2, 0
+    wsr     a2, ibreakenable
+    isync
+1:
+    set_vector debug_vector, 2f
+    movi    a2, 1f
+    wsr     a2, ibreaka0
+    movi    a2, 1
+    wsr     a2, ibreakenable
+    isync
+1:
+    test_fail
+2:
+    rsr     a2, ps
+    movi    a3, 0x1f
+    and     a2, a2, a3
+    movi    a3, 0x10 | debug_level
+    assert  eq, a2, a3
+    rsr     a2, epc6
+    movi    a3, 1b
+    assert  eq, a2, a3
+    rsr     a2, debugcause
+    movi    a3, 0x2
+    assert  eq, a2, a3
+test_end
+
+test ibreak_priority
+    set_vector debug_vector, 2f
+    rsil    a2, debug_level - 1
+    movi    a2, 1f
+    wsr     a2, ibreaka0
+    movi    a2, 1
+    wsr     a2, ibreakenable
+    isync
+1:
+    break   0, 0
+    test_fail
+2:
+    rsr     a2, debugcause
+    movi    a3, 0x2
+    assert  eq, a2, a3
+test_end
+
+test icount
+    set_vector debug_vector, 2f
+    rsil    a2, debug_level - 1
+    movi    a2, -2
+    wsr     a2, icount
+    movi    a2, 1
+    wsr     a2, icountlevel
+    isync
+    rsil    a2, 0
+    nop
+1:
+    break   0, 0
+    test_fail
+2:
+    movi    a2, 0
+    wsr     a2, icountlevel
+    rsr     a2, epc6
+    movi    a3, 1b
+    assert  eq, a2, a3
+    rsr     a2, debugcause
+    movi    a3, 0x1
+    assert  eq, a2, a3
+test_end
+
+.macro check_dbreak dr
+    rsr     a2, epc6
+    movi    a3, 1b
+    assert  eq, a2, a3
+    rsr     a2, debugcause
+    movi    a3, 0x4 | (\dr << 8)
+    assert  eq, a2, a3
+    movi    a2, 0
+    wsr     a2, dbreakc\dr
+.endm
+
+.macro dbreak_test dr, ctl, break, access, op
+    set_vector debug_vector, 2f
+    rsil    a2, debug_level - 1
+    movi    a2, \ctl
+    wsr     a2, dbreakc\dr
+    movi    a2, \break
+    wsr     a2, dbreaka\dr
+    movi    a2, \access
+    isync
+1:
+    \op     a3, a2, 0
+    test_fail
+2:
+    check_dbreak \dr
+    reset_ps
+.endm
+
+test dbreak_exact
+    dbreak_test 0, 0x4000003f, 0xd000007f, 0xd000007f, l8ui
+    dbreak_test 1, 0x4000003e, 0xd000007e, 0xd000007e, l16ui
+    dbreak_test 0, 0x4000003c, 0xd000007c, 0xd000007c, l32i
+
+    dbreak_test 1, 0x8000003f, 0xd000007f, 0xd000007f, s8i
+    dbreak_test 0, 0x8000003e, 0xd000007e, 0xd000007e, s16i
+    dbreak_test 1, 0x8000003c, 0xd000007c, 0xd000007c, s32i
+test_end
+
+test dbreak_overlap
+    dbreak_test 0, 0x4000003f, 0xd000007d, 0xd000007c, l16ui
+    dbreak_test 1, 0x4000003f, 0xd000007d, 0xd000007c, l32i
+
+    dbreak_test 0, 0x4000003e, 0xd000007e, 0xd000007f, l8ui
+    dbreak_test 1, 0x4000003e, 0xd000007e, 0xd000007c, l32i
+
+    dbreak_test 0, 0x4000003c, 0xd000007c, 0xd000007d, l8ui
+    dbreak_test 1, 0x4000003c, 0xd000007c, 0xd000007c, l16ui
+
+    dbreak_test 0, 0x40000038, 0xd0000078, 0xd000007b, l8ui
+    dbreak_test 1, 0x40000038, 0xd0000078, 0xd000007a, l16ui
+    dbreak_test 0, 0x40000038, 0xd0000078, 0xd000007c, l32i
+
+    dbreak_test 1, 0x40000030, 0xd0000070, 0xd0000075, l8ui
+    dbreak_test 0, 0x40000030, 0xd0000070, 0xd0000076, l16ui
+    dbreak_test 1, 0x40000030, 0xd0000070, 0xd0000078, l32i
+
+    dbreak_test 0, 0x40000020, 0xd0000060, 0xd000006f, l8ui
+    dbreak_test 1, 0x40000020, 0xd0000060, 0xd0000070, l16ui
+    dbreak_test 0, 0x40000020, 0xd0000060, 0xd0000074, l32i
+
+
+    dbreak_test 0, 0x8000003f, 0xd000007d, 0xd000007c, s16i
+    dbreak_test 1, 0x8000003f, 0xd000007d, 0xd000007c, s32i
+
+    dbreak_test 0, 0x8000003e, 0xd000007e, 0xd000007f, s8i
+    dbreak_test 1, 0x8000003e, 0xd000007e, 0xd000007c, s32i
+
+    dbreak_test 0, 0x8000003c, 0xd000007c, 0xd000007d, s8i
+    dbreak_test 1, 0x8000003c, 0xd000007c, 0xd000007c, s16i
+
+    dbreak_test 0, 0x80000038, 0xd0000078, 0xd000007b, s8i
+    dbreak_test 1, 0x80000038, 0xd0000078, 0xd000007a, s16i
+    dbreak_test 0, 0x80000038, 0xd0000078, 0xd000007c, s32i
+
+    dbreak_test 1, 0x80000030, 0xd0000070, 0xd0000075, s8i
+    dbreak_test 0, 0x80000030, 0xd0000070, 0xd0000076, s16i
+    dbreak_test 1, 0x80000030, 0xd0000070, 0xd0000078, s32i
+
+    dbreak_test 0, 0x80000020, 0xd0000060, 0xd000006f, s8i
+    dbreak_test 1, 0x80000020, 0xd0000060, 0xd0000070, s16i
+    dbreak_test 0, 0x80000020, 0xd0000060, 0xd0000074, s32i
+test_end
+
+test dbreak_invalid
+    dbreak_test 0, 0x40000030, 0xd0000071, 0xd0000070, l16ui
+    dbreak_test 1, 0x40000035, 0xd0000072, 0xd0000070, l32i
+test_end
+
+test_suite_end
commit 18da9326412874983c06f8d1689543c45e693873
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Fri Jan 13 10:10:49 2012 +0400

    target-xtensa: add DEBUG_SECTION to overlay tool
    
    Fill debug configuration from overlay definitions in the DEBUG_SECTION.
    Add DEBUG_SECTION to DC232B and FSF cores.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/target-xtensa/core-dc232b.c b/target-xtensa/core-dc232b.c
index 4d9bd55..b723c4c 100644
--- a/target-xtensa/core-dc232b.c
+++ b/target-xtensa/core-dc232b.c
@@ -22,6 +22,7 @@ static const XtensaConfig dc232b = {
     EXCEPTIONS_SECTION,
     INTERRUPTS_SECTION,
     TLB_SECTION,
+    DEBUG_SECTION,
     .clock_freq_khz = 10000,
 };
 
diff --git a/target-xtensa/core-fsf.c b/target-xtensa/core-fsf.c
index 7650462..88de4dd 100644
--- a/target-xtensa/core-fsf.c
+++ b/target-xtensa/core-fsf.c
@@ -16,6 +16,7 @@ static const XtensaConfig fsf = {
     EXCEPTIONS_SECTION,
     INTERRUPTS_SECTION,
     TLB_SECTION,
+    DEBUG_SECTION,
     .clock_freq_khz = 10000,
 };
 
diff --git a/target-xtensa/overlay_tool.h b/target-xtensa/overlay_tool.h
index e7c4c3a..a3a5650 100644
--- a/target-xtensa/overlay_tool.h
+++ b/target-xtensa/overlay_tool.h
@@ -114,6 +114,7 @@
         [EXC_KERNEL] = XCHAL_KERNEL_VECTOR_VADDR, \
         [EXC_USER] = XCHAL_USER_VECTOR_VADDR, \
         [EXC_DOUBLE] = XCHAL_DOUBLEEXC_VECTOR_VADDR, \
+        [EXC_DEBUG] = XCHAL_DEBUG_VECTOR_VADDR, \
     }
 
 #define INTERRUPT_VECTORS { \
@@ -302,6 +303,10 @@
 #define REGISTER_CORE(core)
 #endif
 
+#define DEBUG_SECTION \
+    .debug_level = XCHAL_DEBUGLEVEL, \
+    .nibreak = XCHAL_NUM_IBREAK, \
+    .ndbreak = XCHAL_NUM_DBREAK
 
 #if XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI + 1 <= 2
 #define XCHAL_INTLEVEL2_VECTOR_VADDR 0
commit f14c4b5fb1e2509ad738afe491c099a84ca80749
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun Jan 29 05:28:21 2012 +0400

    target-xtensa: add DBREAK data breakpoints
    
    Add DBREAKA/DBREAKC SRs and implement DBREAK breakpoints as debug
    watchpoints.
    
    This implementation is not fully compliant to ISA: when a breakpoint is
    set to an unmapped/inaccessible memory address it generates TLB/memory
    protection exception instead of debug exception.
    
    See ISA, 4.7.7.3, 4.7.7.6 for more details.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 92441e3..fb8a727 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -128,6 +128,8 @@ enum {
     DTLBCFG = 92,
     IBREAKENABLE = 96,
     IBREAKA = 128,
+    DBREAKA = 144,
+    DBREAKC = 160,
     EPC1 = 177,
     DEPC = 192,
     EPS2 = 194,
@@ -175,12 +177,18 @@ enum {
 #define DEBUGCAUSE_DBNUM 0xf00
 #define DEBUGCAUSE_DBNUM_SHIFT 8
 
+#define DBREAKC_SB 0x80000000
+#define DBREAKC_LB 0x40000000
+#define DBREAKC_SB_LB (DBREAKC_SB | DBREAKC_LB)
+#define DBREAKC_MASK 0x3f
+
 #define MAX_NAREG 64
 #define MAX_NINTERRUPT 32
 #define MAX_NLEVEL 6
 #define MAX_NNMI 1
 #define MAX_NCCOMPARE 3
 #define MAX_TLB_WAY_SIZE 8
+#define MAX_NDBREAK 2
 
 #define REGION_PAGE_MASK 0xe0000000
 
@@ -330,6 +338,9 @@ typedef struct CPUXtensaState {
 
     int exception_taken;
 
+    /* Watchpoints for DBREAK registers */
+    CPUWatchpoint *cpu_watchpoint[MAX_NDBREAK];
+
     CPU_COMMON
 } CPUXtensaState;
 
@@ -365,6 +376,7 @@ int xtensa_get_physical_addr(CPUState *env,
         uint32_t vaddr, int is_write, int mmu_idx,
         uint32_t *paddr, uint32_t *page_size, unsigned *access);
 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env);
+void debug_exception_env(CPUState *new_env, uint32_t cause);
 
 
 #define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index 0a26f8d..2ef50d6 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -58,9 +58,44 @@ void xtensa_register_core(XtensaConfigList *node)
     xtensa_cores = node;
 }
 
+static uint32_t check_hw_breakpoints(CPUState *env)
+{
+    unsigned i;
+
+    for (i = 0; i < env->config->ndbreak; ++i) {
+        if (env->cpu_watchpoint[i] &&
+                env->cpu_watchpoint[i]->flags & BP_WATCHPOINT_HIT) {
+            return DEBUGCAUSE_DB | (i << DEBUGCAUSE_DBNUM_SHIFT);
+        }
+    }
+    return 0;
+}
+
+static CPUDebugExcpHandler *prev_debug_excp_handler;
+
+static void breakpoint_handler(CPUState *env)
+{
+    if (env->watchpoint_hit) {
+        if (env->watchpoint_hit->flags & BP_CPU) {
+            uint32_t cause;
+
+            env->watchpoint_hit = NULL;
+            cause = check_hw_breakpoints(env);
+            if (cause) {
+                debug_exception_env(env, cause);
+            }
+            cpu_resume_from_signal(env, NULL);
+        }
+    }
+    if (prev_debug_excp_handler) {
+        prev_debug_excp_handler(env);
+    }
+}
+
 CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
 {
     static int tcg_inited;
+    static int debug_handler_inited;
     CPUXtensaState *env;
     const XtensaConfig *config = NULL;
     XtensaConfigList *core = xtensa_cores;
@@ -84,6 +119,12 @@ CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
         xtensa_translate_init();
     }
 
+    if (!debug_handler_inited && tcg_enabled()) {
+        debug_handler_inited = 1;
+        prev_debug_excp_handler =
+            cpu_set_debug_excp_handler(breakpoint_handler);
+    }
+
     xtensa_irq_init(env);
     qemu_init_vcpu(env);
     return env;
diff --git a/target-xtensa/helpers.h b/target-xtensa/helpers.h
index afe39d4..48a741e 100644
--- a/target-xtensa/helpers.h
+++ b/target-xtensa/helpers.h
@@ -33,5 +33,7 @@ DEF_HELPER_3(wtlb, void, i32, i32, i32)
 
 DEF_HELPER_1(wsr_ibreakenable, void, i32)
 DEF_HELPER_2(wsr_ibreaka, void, i32, i32)
+DEF_HELPER_2(wsr_dbreaka, void, i32, i32)
+DEF_HELPER_2(wsr_dbreakc, void, i32, i32)
 
 #include "def-helper.h"
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index 1feaaee..e184cf6 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -134,6 +134,14 @@ void HELPER(exception_cause_vaddr)(uint32_t pc, uint32_t cause, uint32_t vaddr)
     HELPER(exception_cause)(pc, cause);
 }
 
+void debug_exception_env(CPUState *new_env, uint32_t cause)
+{
+    if (xtensa_get_cintlevel(new_env) < new_env->config->debug_level) {
+        env = new_env;
+        HELPER(debug_exception)(env->pc, cause);
+    }
+}
+
 void HELPER(debug_exception)(uint32_t pc, uint32_t cause)
 {
     unsigned level = env->config->debug_level;
@@ -700,3 +708,57 @@ 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)
+{
+    int flags = BP_CPU | BP_STOP_BEFORE_ACCESS;
+    uint32_t mask = dbreakc | ~DBREAKC_MASK;
+
+    if (env->cpu_watchpoint[i]) {
+        cpu_watchpoint_remove_by_ref(env, env->cpu_watchpoint[i]);
+    }
+    if (dbreakc & DBREAKC_SB) {
+        flags |= BP_MEM_WRITE;
+    }
+    if (dbreakc & DBREAKC_LB) {
+        flags |= BP_MEM_READ;
+    }
+    /* contiguous mask after inversion is one less than some power of 2 */
+    if ((~mask + 1) & ~mask) {
+        qemu_log("DBREAKC mask is not contiguous: 0x%08x\n", dbreakc);
+        /* cut mask after the first zero bit */
+        mask = 0xffffffff << (32 - clo32(mask));
+    }
+    if (cpu_watchpoint_insert(env, dbreaka & mask, ~mask + 1,
+            flags, &env->cpu_watchpoint[i])) {
+        env->cpu_watchpoint[i] = NULL;
+        qemu_log("Failed to set data breakpoint at 0x%08x/%d\n",
+                dbreaka & mask, ~mask + 1);
+    }
+}
+
+void HELPER(wsr_dbreaka)(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);
+    }
+    env->sregs[DBREAKA + i] = v;
+}
+
+void HELPER(wsr_dbreakc)(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);
+        } else {
+            if (env->cpu_watchpoint[i]) {
+                cpu_watchpoint_remove_by_ref(env, env->cpu_watchpoint[i]);
+                env->cpu_watchpoint[i] = NULL;
+            }
+        }
+    }
+    env->sregs[DBREAKC + i] = v;
+}
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 3bf880f..9e8e20a 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -98,6 +98,10 @@ static const char * const sregnames[256] = {
     [IBREAKENABLE] = "IBREAKENABLE",
     [IBREAKA] = "IBREAKA0",
     [IBREAKA + 1] = "IBREAKA1",
+    [DBREAKA] = "DBREAKA0",
+    [DBREAKA + 1] = "DBREAKA1",
+    [DBREAKC] = "DBREAKC0",
+    [DBREAKC + 1] = "DBREAKC1",
     [EPC1] = "EPC1",
     [EPC1 + 1] = "EPC2",
     [EPC1 + 2] = "EPC3",
@@ -536,6 +540,28 @@ static void gen_wsr_ibreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v)
     }
 }
 
+static void gen_wsr_dbreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    unsigned id = sr - DBREAKA;
+
+    if (id < dc->config->ndbreak) {
+        TCGv_i32 tmp = tcg_const_i32(id);
+        gen_helper_wsr_dbreaka(tmp, v);
+        tcg_temp_free(tmp);
+    }
+}
+
+static void gen_wsr_dbreakc(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    unsigned id = sr - DBREAKC;
+
+    if (id < dc->config->ndbreak) {
+        TCGv_i32 tmp = tcg_const_i32(id);
+        gen_helper_wsr_dbreakc(tmp, v);
+        tcg_temp_free(tmp);
+    }
+}
+
 static void gen_wsr_intset(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
     tcg_gen_andi_i32(cpu_SR[sr], v,
@@ -634,6 +660,10 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
         [IBREAKENABLE] = gen_wsr_ibreakenable,
         [IBREAKA] = gen_wsr_ibreaka,
         [IBREAKA + 1] = gen_wsr_ibreaka,
+        [DBREAKA] = gen_wsr_dbreaka,
+        [DBREAKA + 1] = gen_wsr_dbreaka,
+        [DBREAKC] = gen_wsr_dbreakc,
+        [DBREAKC + 1] = gen_wsr_dbreakc,
         [INTSET] = gen_wsr_intset,
         [INTCLEAR] = gen_wsr_intclear,
         [INTENABLE] = gen_wsr_intenable,
commit 0dc23828f1487a3e587f42a0630dd6879ab8f2bb
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun Jan 29 03:15:23 2012 +0400

    exec: let cpu_watchpoint_insert accept larger watchpoints
    
    Make cpu_watchpoint_insert accept watchpoints of any power-of-two size
    up to the target page size.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/exec.c b/exec.c
index ed091f3..80560fa 100644
--- a/exec.c
+++ b/exec.c
@@ -1443,7 +1443,8 @@ int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len,
     CPUWatchpoint *wp;
 
     /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
-    if ((len != 1 && len != 2 && len != 4 && len != 8) || (addr & ~len_mask)) {
+    if ((len & (len - 1)) || (addr & ~len_mask) ||
+            len == 0 || len > TARGET_PAGE_SIZE) {
         fprintf(stderr, "qemu: tried to set invalid watchpoint at "
                 TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len);
         return -EINVAL;
commit 488d65772ce94aa439f26d7136db384aec460bcb
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun Jan 29 02:24:39 2012 +0400

    exec: fix check_watchpoint exiting cpu_loop
    
    In case of BP_STOP_BEFORE_ACCESS watchpoint check_watchpoint intends to
    signal EXCP_DEBUG exception on exit from cpu loop, but later overwrites
    exception code by the cpu_resume_from_signal call.
    
    Use cpu_loop_exit with BP_STOP_BEFORE_ACCESS watchpoints.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/exec.c b/exec.c
index f105b43..ed091f3 100644
--- a/exec.c
+++ b/exec.c
@@ -3257,11 +3257,12 @@ static void check_watchpoint(int offset, int len_mask, int flags)
                 tb_phys_invalidate(tb, -1);
                 if (wp->flags & BP_STOP_BEFORE_ACCESS) {
                     env->exception_index = EXCP_DEBUG;
+                    cpu_loop_exit(env);
                 } else {
                     cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
                     tb_gen_code(env, pc, cs_base, cpu_flags, 1);
+                    cpu_resume_from_signal(env, NULL);
                 }
-                cpu_resume_from_signal(env, NULL);
             }
         } else {
             wp->flags &= ~BP_WATCHPOINT_HIT;
commit 673641504780300be2f0553b76bee34e3d643e57
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun Jan 29 00:01:40 2012 +0400

    exec: add missing breaks to the watch_mem_write
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Meador Inge <meadori at codesourcery.com>

diff --git a/exec.c b/exec.c
index b81677a..f105b43 100644
--- a/exec.c
+++ b/exec.c
@@ -3289,9 +3289,15 @@ static void watch_mem_write(void *opaque, target_phys_addr_t addr,
 {
     check_watchpoint(addr & ~TARGET_PAGE_MASK, ~(size - 1), BP_MEM_WRITE);
     switch (size) {
-    case 1: stb_phys(addr, val);
-    case 2: stw_phys(addr, val);
-    case 4: stl_phys(addr, val);
+    case 1:
+        stb_phys(addr, val);
+        break;
+    case 2:
+        stw_phys(addr, val);
+        break;
+    case 4:
+        stl_phys(addr, val);
+        break;
     default: abort();
     }
 }
commit 35b5c0442798c1754f1d56452528dce5fee003c2
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun Jan 15 05:40:50 2012 +0400

    target-xtensa: add ICOUNT SR and debug exception
    
    ICOUNT SR gets incremented on every instruction completion provided that
    CINTLEVEL at the beginning of the instruction execution is lower than
    ICOUNTLEVEL.
    
    When ICOUNT would increment to 0 a debug exception is raised if
    CINTLEVEL is lower than DEBUGLEVEL.
    
    See ISA, 4.7.7.5 for more details.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index a18072b..92441e3 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -142,6 +142,8 @@ enum {
     DEBUGCAUSE = 233,
     CCOUNT = 234,
     PRID = 235,
+    ICOUNT = 236,
+    ICOUNTLEVEL = 237,
     EXCVADDR = 238,
     CCOMPARE = 240,
 };
@@ -429,6 +431,7 @@ static inline int cpu_mmu_index(CPUState *env)
 #define XTENSA_TBFLAG_EXCM 0x4
 #define XTENSA_TBFLAG_LITBASE 0x8
 #define XTENSA_TBFLAG_DEBUG 0x10
+#define XTENSA_TBFLAG_ICOUNT 0x20
 
 static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
         target_ulong *cs_base, int *flags)
@@ -448,6 +451,9 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
         if (xtensa_get_cintlevel(env) < env->config->debug_level) {
             *flags |= XTENSA_TBFLAG_DEBUG;
         }
+        if (xtensa_get_cintlevel(env) < env->sregs[ICOUNTLEVEL]) {
+            *flags |= XTENSA_TBFLAG_ICOUNT;
+        }
     }
 }
 
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index a438474..3bf880f 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -63,6 +63,8 @@ typedef struct DisasContext {
     unsigned used_window;
 
     bool debug;
+    bool icount;
+    TCGv_i32 next_icount;
 } DisasContext;
 
 static TCGv_ptr cpu_env;
@@ -127,6 +129,8 @@ static const char * const sregnames[256] = {
     [DEBUGCAUSE] = "DEBUGCAUSE",
     [CCOUNT] = "CCOUNT",
     [PRID] = "PRID",
+    [ICOUNT] = "ICOUNT",
+    [ICOUNTLEVEL] = "ICOUNTLEVEL",
     [EXCVADDR] = "EXCVADDR",
     [CCOMPARE] = "CCOMPARE0",
     [CCOMPARE + 1] = "CCOMPARE1",
@@ -313,10 +317,13 @@ static void gen_check_privilege(DisasContext *dc)
 static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot)
 {
     tcg_gen_mov_i32(cpu_pc, dest);
+    gen_advance_ccount(dc);
+    if (dc->icount) {
+        tcg_gen_mov_i32(cpu_SR[ICOUNT], dc->next_icount);
+    }
     if (dc->singlestep_enabled) {
         gen_exception(dc, EXCP_DEBUG);
     } else {
-        gen_advance_ccount(dc);
         if (slot >= 0) {
             tcg_gen_goto_tb(slot);
             tcg_gen_exit_tb((tcg_target_long)dc->tb + slot);
@@ -580,6 +587,22 @@ static void gen_wsr_prid(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
 }
 
+static void gen_wsr_icount(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    if (dc->icount) {
+        tcg_gen_mov_i32(dc->next_icount, v);
+    } else {
+        tcg_gen_mov_i32(cpu_SR[sr], v);
+    }
+}
+
+static void gen_wsr_icountlevel(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    tcg_gen_andi_i32(cpu_SR[sr], v, 0xf);
+    /* This can change tb->flags, so exit tb */
+    gen_jumpi_check_loop_end(dc, -1);
+}
+
 static void gen_wsr_ccompare(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
     uint32_t id = sr - CCOMPARE;
@@ -617,6 +640,8 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
         [PS] = gen_wsr_ps,
         [DEBUGCAUSE] = gen_wsr_debugcause,
         [PRID] = gen_wsr_prid,
+        [ICOUNT] = gen_wsr_icount,
+        [ICOUNTLEVEL] = gen_wsr_icountlevel,
         [CCOMPARE] = gen_wsr_ccompare,
         [CCOMPARE + 1] = gen_wsr_ccompare,
         [CCOMPARE + 2] = gen_wsr_ccompare,
@@ -2493,10 +2518,14 @@ static void gen_intermediate_code_internal(
     dc.is_jmp = DISAS_NEXT;
     dc.ccount_delta = 0;
     dc.debug = tb->flags & XTENSA_TBFLAG_DEBUG;
+    dc.icount = tb->flags & XTENSA_TBFLAG_ICOUNT;
 
     init_litbase(&dc);
     init_sar_tracker(&dc);
     reset_used_window(&dc);
+    if (dc.icount) {
+        dc.next_icount = tcg_temp_local_new_i32();
+    }
 
     gen_icount_start();
 
@@ -2532,12 +2561,27 @@ static void gen_intermediate_code_internal(
             gen_io_start();
         }
 
+        if (dc.icount) {
+            int label = gen_new_label();
+
+            tcg_gen_addi_i32(dc.next_icount, cpu_SR[ICOUNT], 1);
+            tcg_gen_brcondi_i32(TCG_COND_NE, dc.next_icount, 0, label);
+            tcg_gen_mov_i32(dc.next_icount, cpu_SR[ICOUNT]);
+            if (dc.debug) {
+                gen_debug_exception(&dc, DEBUGCAUSE_IC);
+            }
+            gen_set_label(label);
+        }
+
         if (dc.debug) {
             gen_ibreak_check(env, &dc);
         }
 
         disas_xtensa_insn(&dc);
         ++insn_count;
+        if (dc.icount) {
+            tcg_gen_mov_i32(cpu_SR[ICOUNT], dc.next_icount);
+        }
         if (env->singlestep_enabled) {
             tcg_gen_movi_i32(cpu_pc, dc.pc);
             gen_exception(&dc, EXCP_DEBUG);
@@ -2550,6 +2594,9 @@ static void gen_intermediate_code_internal(
 
     reset_litbase(&dc);
     reset_sar_tracker(&dc);
+    if (dc.icount) {
+        tcg_temp_free(dc.next_icount);
+    }
 
     if (tb->cflags & CF_LAST_IO) {
         gen_io_end();
commit e61dc8f72c096e084106d5e97101d9d88f642d0e
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Fri Jan 13 09:21:32 2012 +0400

    target-xtensa: implement instruction breakpoints
    
    Add IBREAKA/IBREAKENABLE SRs and implement debug exception, BREAK and
    BREAK.N instructions and IBREAK breakpoints.
    
    IBREAK breakpoint address is considered constant for TB lifetime.
    On IBREAKA/IBREAKENABLE change corresponding TBs are invalidated.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index c77fe13..a18072b 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -126,6 +126,8 @@ enum {
     RASID = 90,
     ITLBCFG = 91,
     DTLBCFG = 92,
+    IBREAKENABLE = 96,
+    IBREAKA = 128,
     EPC1 = 177,
     DEPC = 192,
     EPS2 = 194,
@@ -196,6 +198,7 @@ enum {
     EXC_KERNEL,
     EXC_USER,
     EXC_DOUBLE,
+    EXC_DEBUG,
     EXC_MAX
 };
 
@@ -425,6 +428,7 @@ static inline int cpu_mmu_index(CPUState *env)
 #define XTENSA_TBFLAG_RING_MASK 0x3
 #define XTENSA_TBFLAG_EXCM 0x4
 #define XTENSA_TBFLAG_LITBASE 0x8
+#define XTENSA_TBFLAG_DEBUG 0x10
 
 static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
         target_ulong *cs_base, int *flags)
@@ -440,6 +444,11 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
             (env->sregs[LITBASE] & 1)) {
         *flags |= XTENSA_TBFLAG_LITBASE;
     }
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_DEBUG)) {
+        if (xtensa_get_cintlevel(env) < env->config->debug_level) {
+            *flags |= XTENSA_TBFLAG_DEBUG;
+        }
+    }
 }
 
 #include "cpu-all.h"
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index 973c268..0a26f8d 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -44,6 +44,7 @@ void cpu_reset(CPUXtensaState *env)
     env->sregs[PS] = xtensa_option_enabled(env->config,
             XTENSA_OPTION_INTERRUPT) ? 0x1f : 0x10;
     env->sregs[VECBASE] = env->config->vecbase;
+    env->sregs[IBREAKENABLE] = 0;
 
     env->pending_irq_level = 0;
     reset_mmu(env);
@@ -193,6 +194,7 @@ void do_interrupt(CPUState *env)
     case EXC_KERNEL:
     case EXC_USER:
     case EXC_DOUBLE:
+    case EXC_DEBUG:
         qemu_log_mask(CPU_LOG_INT, "%s(%d) "
                 "pc = %08x, a0 = %08x, ps = %08x, ccount = %08x\n",
                 __func__, env->exception_index,
diff --git a/target-xtensa/helpers.h b/target-xtensa/helpers.h
index 09ab332..afe39d4 100644
--- a/target-xtensa/helpers.h
+++ b/target-xtensa/helpers.h
@@ -3,6 +3,8 @@
 DEF_HELPER_1(exception, void, i32)
 DEF_HELPER_2(exception_cause, void, i32, i32)
 DEF_HELPER_3(exception_cause_vaddr, void, i32, i32, i32)
+DEF_HELPER_2(debug_exception, void, i32, i32)
+
 DEF_HELPER_1(nsa, i32, i32)
 DEF_HELPER_1(nsau, i32, i32)
 DEF_HELPER_1(wsr_windowbase, void, i32)
@@ -29,4 +31,7 @@ DEF_HELPER_2(itlb, void, i32, i32)
 DEF_HELPER_2(ptlb, i32, i32, i32)
 DEF_HELPER_3(wtlb, void, i32, i32, i32)
 
+DEF_HELPER_1(wsr_ibreakenable, void, i32)
+DEF_HELPER_2(wsr_ibreaka, void, i32, i32)
+
 #include "def-helper.h"
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index 0605611..1feaaee 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -134,6 +134,19 @@ void HELPER(exception_cause_vaddr)(uint32_t pc, uint32_t cause, uint32_t vaddr)
     HELPER(exception_cause)(pc, cause);
 }
 
+void HELPER(debug_exception)(uint32_t pc, uint32_t cause)
+{
+    unsigned level = env->config->debug_level;
+
+    env->pc = pc;
+    env->sregs[DEBUGCAUSE] = cause;
+    env->sregs[EPC1 + level - 1] = pc;
+    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);
+}
+
 uint32_t HELPER(nsa)(uint32_t v)
 {
     if (v & 0x80000000) {
@@ -662,3 +675,28 @@ void HELPER(wtlb)(uint32_t p, uint32_t v, uint32_t dtlb)
     split_tlb_entry_spec(v, dtlb, &vpn, &wi, &ei);
     xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, p);
 }
+
+
+void HELPER(wsr_ibreakenable)(uint32_t v)
+{
+    uint32_t change = v ^ env->sregs[IBREAKENABLE];
+    unsigned i;
+
+    for (i = 0; i < env->config->nibreak; ++i) {
+        if (change & (1 << i)) {
+            tb_invalidate_phys_page_range(
+                    env->sregs[IBREAKA + i], env->sregs[IBREAKA + i] + 1, 0);
+        }
+    }
+    env->sregs[IBREAKENABLE] = v & ((1 << env->config->nibreak) - 1);
+}
+
+void HELPER(wsr_ibreaka)(uint32_t i, uint32_t v)
+{
+    if (env->sregs[IBREAKENABLE] & (1 << i) && env->sregs[IBREAKA + i] != v) {
+        tb_invalidate_phys_page_range(
+                env->sregs[IBREAKA + i], env->sregs[IBREAKA + i] + 1, 0);
+        tb_invalidate_phys_page_range(v, v + 1, 0);
+    }
+    env->sregs[IBREAKA + i] = v;
+}
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index da5fdb5..a438474 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -61,6 +61,8 @@ typedef struct DisasContext {
 
     uint32_t ccount_delta;
     unsigned used_window;
+
+    bool debug;
 } DisasContext;
 
 static TCGv_ptr cpu_env;
@@ -91,6 +93,9 @@ static const char * const sregnames[256] = {
     [RASID] = "RASID",
     [ITLBCFG] = "ITLBCFG",
     [DTLBCFG] = "DTLBCFG",
+    [IBREAKENABLE] = "IBREAKENABLE",
+    [IBREAKA] = "IBREAKA0",
+    [IBREAKA + 1] = "IBREAKA1",
     [EPC1] = "EPC1",
     [EPC1 + 1] = "EPC2",
     [EPC1 + 2] = "EPC3",
@@ -284,6 +289,19 @@ static void gen_exception_cause_vaddr(DisasContext *dc, uint32_t cause,
     tcg_temp_free(tcause);
 }
 
+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);
+    tcg_temp_free(tpc);
+    tcg_temp_free(tcause);
+    if (cause & (DEBUGCAUSE_IB | DEBUGCAUSE_BI | DEBUGCAUSE_BN)) {
+        dc->is_jmp = DISAS_UPDATE;
+    }
+}
+
 static void gen_check_privilege(DisasContext *dc)
 {
     if (dc->cring) {
@@ -493,6 +511,24 @@ static void gen_wsr_tlbcfg(DisasContext *dc, uint32_t sr, TCGv_i32 v)
     tcg_gen_andi_i32(cpu_SR[sr], v, 0x01130000);
 }
 
+static void gen_wsr_ibreakenable(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    gen_helper_wsr_ibreakenable(v);
+    gen_jumpi_check_loop_end(dc, 0);
+}
+
+static void gen_wsr_ibreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    unsigned id = sr - IBREAKA;
+
+    if (id < dc->config->nibreak) {
+        TCGv_i32 tmp = tcg_const_i32(id);
+        gen_helper_wsr_ibreaka(tmp, v);
+        tcg_temp_free(tmp);
+        gen_jumpi_check_loop_end(dc, 0);
+    }
+}
+
 static void gen_wsr_intset(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
     tcg_gen_andi_i32(cpu_SR[sr], v,
@@ -572,6 +608,9 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
         [RASID] = gen_wsr_rasid,
         [ITLBCFG] = gen_wsr_tlbcfg,
         [DTLBCFG] = gen_wsr_tlbcfg,
+        [IBREAKENABLE] = gen_wsr_ibreakenable,
+        [IBREAKA] = gen_wsr_ibreaka,
+        [IBREAKA + 1] = gen_wsr_ibreaka,
         [INTSET] = gen_wsr_intset,
         [INTCLEAR] = gen_wsr_intclear,
         [INTENABLE] = gen_wsr_intenable,
@@ -975,8 +1014,10 @@ static void disas_xtensa_insn(DisasContext *dc)
                     break;
 
                 case 4: /*BREAKx*/
-                    HAS_OPTION(XTENSA_OPTION_EXCEPTION);
-                    TBD();
+                    HAS_OPTION(XTENSA_OPTION_DEBUG);
+                    if (dc->debug) {
+                        gen_debug_exception(dc, DEBUGCAUSE_BI);
+                    }
                     break;
 
                 case 5: /*SYSCALLx*/
@@ -2356,7 +2397,10 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 2: /*BREAK.Nn*/
-                TBD();
+                HAS_OPTION(XTENSA_OPTION_DEBUG);
+                if (dc->debug) {
+                    gen_debug_exception(dc, DEBUGCAUSE_BN);
+                }
                 break;
 
             case 3: /*NOP.Nn*/
@@ -2409,6 +2453,19 @@ static void check_breakpoint(CPUState *env, DisasContext *dc)
     }
 }
 
+static void gen_ibreak_check(CPUState *env, DisasContext *dc)
+{
+    unsigned i;
+
+    for (i = 0; i < dc->config->nibreak; ++i) {
+        if ((env->sregs[IBREAKENABLE] & (1 << i)) &&
+                env->sregs[IBREAKA + i] == dc->pc) {
+            gen_debug_exception(dc, DEBUGCAUSE_IB);
+            break;
+        }
+    }
+}
+
 static void gen_intermediate_code_internal(
         CPUState *env, TranslationBlock *tb, int search_pc)
 {
@@ -2435,6 +2492,7 @@ static void gen_intermediate_code_internal(
     dc.lend = env->sregs[LEND];
     dc.is_jmp = DISAS_NEXT;
     dc.ccount_delta = 0;
+    dc.debug = tb->flags & XTENSA_TBFLAG_DEBUG;
 
     init_litbase(&dc);
     init_sar_tracker(&dc);
@@ -2474,6 +2532,10 @@ static void gen_intermediate_code_internal(
             gen_io_start();
         }
 
+        if (dc.debug) {
+            gen_ibreak_check(env, &dc);
+        }
+
         disas_xtensa_insn(&dc);
         ++insn_count;
         if (env->singlestep_enabled) {
commit ab58c5b4fd07fbe94950ff459ef51d43cfb5b8c8
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Wed Dec 14 02:13:40 2011 +0400

    target-xtensa: add DEBUGCAUSE SR and configuration
    
    DEBUGCAUSE SR holds information about the most recent debug exception.
    See ISA, 4.7.7 for more details.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index c32bf35..c77fe13 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -137,6 +137,7 @@ enum {
     PS = 230,
     VECBASE = 231,
     EXCCAUSE = 232,
+    DEBUGCAUSE = 233,
     CCOUNT = 234,
     PRID = 235,
     EXCVADDR = 238,
@@ -161,6 +162,15 @@ enum {
 
 #define PS_WOE 0x40000
 
+#define DEBUGCAUSE_IC 0x1
+#define DEBUGCAUSE_IB 0x2
+#define DEBUGCAUSE_DB 0x4
+#define DEBUGCAUSE_BI 0x8
+#define DEBUGCAUSE_BN 0x10
+#define DEBUGCAUSE_DI 0x20
+#define DEBUGCAUSE_DBNUM 0xf00
+#define DEBUGCAUSE_DBNUM_SHIFT 8
+
 #define MAX_NAREG 64
 #define MAX_NINTERRUPT 32
 #define MAX_NLEVEL 6
@@ -279,6 +289,11 @@ typedef struct XtensaConfig {
     uint32_t timerint[MAX_NCCOMPARE];
     unsigned nextint;
     unsigned extint[MAX_NINTERRUPT];
+
+    unsigned debug_level;
+    unsigned nibreak;
+    unsigned ndbreak;
+
     uint32_t clock_freq_khz;
 
     xtensa_tlb itlb;
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 6a0177f..da5fdb5 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -119,6 +119,7 @@ static const char * const sregnames[256] = {
     [PS] = "PS",
     [VECBASE] = "VECBASE",
     [EXCCAUSE] = "EXCCAUSE",
+    [DEBUGCAUSE] = "DEBUGCAUSE",
     [CCOUNT] = "CCOUNT",
     [PRID] = "PRID",
     [EXCVADDR] = "EXCVADDR",
@@ -535,6 +536,10 @@ static void gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v)
     gen_jumpi_check_loop_end(dc, -1);
 }
 
+static void gen_wsr_debugcause(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+}
+
 static void gen_wsr_prid(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
 }
@@ -571,6 +576,7 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
         [INTCLEAR] = gen_wsr_intclear,
         [INTENABLE] = gen_wsr_intenable,
         [PS] = gen_wsr_ps,
+        [DEBUGCAUSE] = gen_wsr_debugcause,
         [PRID] = gen_wsr_prid,
         [CCOMPARE] = gen_wsr_ccompare,
         [CCOMPARE + 1] = gen_wsr_ccompare,
commit 501981126d0aaaa72f720edeee892b830cbe3e55
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Feb 17 18:31:22 2012 +0100

    kvmvapic: Use optionrom helpers
    
    Use OPTION_ROM_START/END from the common header file, add comment to
    init code.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/pc-bios/optionrom/kvmvapic.S b/pc-bios/optionrom/kvmvapic.S
index 856c1e5..aa17a40 100644
--- a/pc-bios/optionrom/kvmvapic.S
+++ b/pc-bios/optionrom/kvmvapic.S
@@ -9,12 +9,10 @@
 # option) any later version.  See the COPYING file in the top-level directory.
 #
 
-	.text 0
-	.code16
-.global _start
-_start:
-	.short 0xaa55
-	.byte (_end - _start) / 512
+#include "optionrom.h"
+
+OPTION_ROM_START
+
 	# clear vapic area: firmware load using rep insb may cause
 	# stale tpr/isr/irr data to corrupt the vapic area.
 	push %es
@@ -26,8 +24,11 @@ _start:
 	cld
 	rep stosw
 	pop %es
+
+	# announce presence to the hypervisor
 	mov $vapic_base, %ax
 	out %ax, $0x7e
+
 	lret
 
 	.code32
@@ -331,7 +332,4 @@ up_set_tpr_poll_irq:
 vapic:
 . = . + vapic_size
 
-.byte 0  # reserve space for signature
-.align 512, 0
-
-_end:
+OPTION_ROM_END
commit 209ca750b9e1854fa8f63fae16aef15becb1cdea
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Feb 17 18:31:21 2012 +0100

    optionsrom: Reserve space for checksum
    
    Always add a byte before the final 512-bytes alignment to reserve the
    space for the ROM checksum.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/pc-bios/optionrom/optionrom.h b/pc-bios/optionrom/optionrom.h
index aa783de..3daf7da 100644
--- a/pc-bios/optionrom/optionrom.h
+++ b/pc-bios/optionrom/optionrom.h
@@ -124,7 +124,8 @@
 	movw		%ax, %ds;
 
 #define OPTION_ROM_END					\
-    .align 512, 0;					\
+	.byte		0;				\
+	.align		512, 0;				\
     _end:
 
 #define BOOT_ROM_END					\
commit 1189aa519ca9d088e3cc6fb621c2690a20077495
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Feb 17 18:31:20 2012 +0100

    kvmvapic: Simplify mp/up_set_tpr
    
    The CH registers is only written, never read. So we can remove these
    operations and, in case of up_set_tpr, also the ECX push/pop.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/pc-bios/optionrom/kvmvapic.S b/pc-bios/optionrom/kvmvapic.S
index e1d8f18..856c1e5 100644
--- a/pc-bios/optionrom/kvmvapic.S
+++ b/pc-bios/optionrom/kvmvapic.S
@@ -202,7 +202,6 @@ mp_isr_is_bigger:
 	mov %bh, %bl
 mp_tpr_is_bigger:
 	/* %bl = ppr */
-	mov %bl, %ch   /* ch = ppr */
 	rol $8, %ebx
 	/* now: %bl = irr, %bh = ppr */
 	cmp %bh, %bl
@@ -276,7 +275,6 @@ up_set_tpr_eax:
 up_set_tpr:
 	pushf
 	push %eax
-	push %ecx
 	push %ebx
 	reenable_vtpr
 
@@ -284,7 +282,7 @@ up_set_tpr_failed:
 	mov vapic, %eax	; fixup
 
 	mov %eax, %ebx
-	mov 20(%esp), %bl
+	mov 16(%esp), %bl
 
 	/* %ebx = new vapic (%bl = tpr, %bh = isr, %b3 = irr) */
 
@@ -298,7 +296,6 @@ up_isr_is_bigger:
 	mov %bh, %bl
 up_tpr_is_bigger:
 	/* %bl = ppr */
-	mov %bl, %ch   /* ch = ppr */
 	rol $8, %ebx
 	/* now: %bl = irr, %bh = ppr */
 	cmp %bh, %bl
@@ -306,7 +303,6 @@ up_tpr_is_bigger:
 
 up_set_tpr_out:
 	pop %ebx
-	pop %ecx
 	pop %eax
 	popf
 	ret $4
commit e5ad936b0fd7dfd7fd7908be6f9f1ca88f63b96b
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Feb 17 18:31:19 2012 +0100

    kvmvapic: Introduce TPR access optimization for Windows guests
    
    This enables acceleration for MMIO-based TPR registers accesses of
    32-bit Windows guest systems. It is mostly useful with KVM enabled,
    either on older Intel CPUs (without flexpriority feature, can also be
    manually disabled for testing) or any current AMD processor.
    
    The approach introduced here is derived from the original version of
    qemu-kvm. It was refactored, documented, and extended by support for
    user space APIC emulation, both with and without KVM acceleration. The
    VMState format was kept compatible, so was the ABI to the option ROM
    that implements the guest-side para-virtualized driver service. This
    enables seamless migration from qemu-kvm to upstream or, one day,
    between KVM and TCG mode.
    
    The basic concept goes like this:
     - VAPIC PV interface consisting of I/O port 0x7e and (for KVM in-kernel
       irqchip) a vmcall hypercall is registered
     - VAPIC option ROM is loaded into guest
     - option ROM activates TPR MMIO access reporting via port 0x7e
     - TPR accesses are trapped and patched in the guest to call into option
       ROM instead, VAPIC support is enabled
     - option ROM TPR helpers track state in memory and invoke hypercall to
       poll for pending IRQs if required
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/Makefile.target b/Makefile.target
index 29fde6e..4b460fd 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -236,7 +236,8 @@ obj-y += device-hotplug.o
 
 # Hardware support
 obj-i386-y += mc146818rtc.o pc.o
-obj-i386-y += sga.o apic_common.o apic.o ioapic_common.o ioapic.o piix_pci.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
diff --git a/hw/apic.c b/hw/apic.c
index ff9d24e..4eeaf88 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -35,6 +35,10 @@
 #define MSI_ADDR_DEST_ID_SHIFT		12
 #define	MSI_ADDR_DEST_ID_MASK		0x00ffff0
 
+#define SYNC_FROM_VAPIC                 0x1
+#define SYNC_TO_VAPIC                   0x2
+#define SYNC_ISR_IRR_TO_VAPIC           0x4
+
 static APICCommonState *local_apics[MAX_APICS + 1];
 
 static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode);
@@ -78,6 +82,70 @@ static inline int get_bit(uint32_t *tab, int index)
     return !!(tab[i] & mask);
 }
 
+/* return -1 if no bit is set */
+static int get_highest_priority_int(uint32_t *tab)
+{
+    int i;
+    for (i = 7; i >= 0; i--) {
+        if (tab[i] != 0) {
+            return i * 32 + fls_bit(tab[i]);
+        }
+    }
+    return -1;
+}
+
+static void apic_sync_vapic(APICCommonState *s, int sync_type)
+{
+    VAPICState vapic_state;
+    size_t length;
+    off_t start;
+    int vector;
+
+    if (!s->vapic_paddr) {
+        return;
+    }
+    if (sync_type & SYNC_FROM_VAPIC) {
+        cpu_physical_memory_rw(s->vapic_paddr, (void *)&vapic_state,
+                               sizeof(vapic_state), 0);
+        s->tpr = vapic_state.tpr;
+    }
+    if (sync_type & (SYNC_TO_VAPIC | SYNC_ISR_IRR_TO_VAPIC)) {
+        start = offsetof(VAPICState, isr);
+        length = offsetof(VAPICState, enabled) - offsetof(VAPICState, isr);
+
+        if (sync_type & SYNC_TO_VAPIC) {
+            assert(qemu_cpu_is_self(s->cpu_env));
+
+            vapic_state.tpr = s->tpr;
+            vapic_state.enabled = 1;
+            start = 0;
+            length = sizeof(VAPICState);
+        }
+
+        vector = get_highest_priority_int(s->isr);
+        if (vector < 0) {
+            vector = 0;
+        }
+        vapic_state.isr = vector & 0xf0;
+
+        vapic_state.zero = 0;
+
+        vector = get_highest_priority_int(s->irr);
+        if (vector < 0) {
+            vector = 0;
+        }
+        vapic_state.irr = vector & 0xff;
+
+        cpu_physical_memory_write_rom(s->vapic_paddr + start,
+                                      ((void *)&vapic_state) + start, length);
+    }
+}
+
+static void apic_vapic_base_update(APICCommonState *s)
+{
+    apic_sync_vapic(s, SYNC_TO_VAPIC);
+}
+
 static void apic_local_deliver(APICCommonState *s, int vector)
 {
     uint32_t lvt = s->lvt[vector];
@@ -239,20 +307,17 @@ static void apic_set_base(APICCommonState *s, uint64_t val)
 
 static void apic_set_tpr(APICCommonState *s, uint8_t val)
 {
-    s->tpr = (val & 0x0f) << 4;
-    apic_update_irq(s);
+    /* Updates from cr8 are ignored while the VAPIC is active */
+    if (!s->vapic_paddr) {
+        s->tpr = val << 4;
+        apic_update_irq(s);
+    }
 }
 
-/* return -1 if no bit is set */
-static int get_highest_priority_int(uint32_t *tab)
+static uint8_t apic_get_tpr(APICCommonState *s)
 {
-    int i;
-    for(i = 7; i >= 0; i--) {
-        if (tab[i] != 0) {
-            return i * 32 + fls_bit(tab[i]);
-        }
-    }
-    return -1;
+    apic_sync_vapic(s, SYNC_FROM_VAPIC);
+    return s->tpr >> 4;
 }
 
 static int apic_get_ppr(APICCommonState *s)
@@ -312,6 +377,14 @@ static void apic_update_irq(APICCommonState *s)
     }
 }
 
+void apic_poll_irq(DeviceState *d)
+{
+    APICCommonState *s = APIC_COMMON(d);
+
+    apic_sync_vapic(s, SYNC_FROM_VAPIC);
+    apic_update_irq(s);
+}
+
 static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode)
 {
     apic_report_irq_delivered(!get_bit(s->irr, vector_num));
@@ -321,6 +394,16 @@ static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode)
         set_bit(s->tmr, vector_num);
     else
         reset_bit(s->tmr, vector_num);
+    if (s->vapic_paddr) {
+        apic_sync_vapic(s, SYNC_ISR_IRR_TO_VAPIC);
+        /*
+         * The vcpu thread needs to see the new IRR before we pull its current
+         * TPR value. That way, if we miss a lowering of the TRP, the guest
+         * has the chance to notice the new IRR and poll for IRQs on its own.
+         */
+        smp_wmb();
+        apic_sync_vapic(s, SYNC_FROM_VAPIC);
+    }
     apic_update_irq(s);
 }
 
@@ -334,6 +417,7 @@ static void apic_eoi(APICCommonState *s)
     if (!(s->spurious_vec & APIC_SV_DIRECTED_IO) && get_bit(s->tmr, isrv)) {
         ioapic_eoi_broadcast(isrv);
     }
+    apic_sync_vapic(s, SYNC_FROM_VAPIC | SYNC_TO_VAPIC);
     apic_update_irq(s);
 }
 
@@ -471,15 +555,19 @@ int apic_get_interrupt(DeviceState *d)
     if (!(s->spurious_vec & APIC_SV_ENABLE))
         return -1;
 
+    apic_sync_vapic(s, SYNC_FROM_VAPIC);
     intno = apic_irq_pending(s);
 
     if (intno == 0) {
+        apic_sync_vapic(s, SYNC_TO_VAPIC);
         return -1;
     } else if (intno < 0) {
+        apic_sync_vapic(s, SYNC_TO_VAPIC);
         return s->spurious_vec & 0xff;
     }
     reset_bit(s->irr, intno);
     set_bit(s->isr, intno);
+    apic_sync_vapic(s, SYNC_TO_VAPIC);
     apic_update_irq(s);
     return intno;
 }
@@ -576,6 +664,10 @@ static uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr)
         val = 0x11 | ((APIC_LVT_NB - 1) << 16); /* version 0x11 */
         break;
     case 0x08:
+        apic_sync_vapic(s, SYNC_FROM_VAPIC);
+        if (apic_report_tpr_access) {
+            cpu_report_tpr_access(s->cpu_env, TPR_ACCESS_READ);
+        }
         val = s->tpr;
         break;
     case 0x09:
@@ -675,7 +767,11 @@ static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
     case 0x03:
         break;
     case 0x08:
+        if (apic_report_tpr_access) {
+            cpu_report_tpr_access(s->cpu_env, TPR_ACCESS_WRITE);
+        }
         s->tpr = val;
+        apic_sync_vapic(s, SYNC_TO_VAPIC);
         apic_update_irq(s);
         break;
     case 0x09:
@@ -737,6 +833,11 @@ static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
     }
 }
 
+static void apic_pre_save(APICCommonState *s)
+{
+    apic_sync_vapic(s, SYNC_FROM_VAPIC);
+}
+
 static void apic_post_load(APICCommonState *s)
 {
     if (s->timer_expiry != -1) {
@@ -770,7 +871,10 @@ static void apic_class_init(ObjectClass *klass, void *data)
     k->init = apic_init;
     k->set_base = apic_set_base;
     k->set_tpr = apic_set_tpr;
+    k->get_tpr = apic_get_tpr;
+    k->vapic_base_update = apic_vapic_base_update;
     k->external_nmi = apic_external_nmi;
+    k->pre_save = apic_pre_save;
     k->post_load = apic_post_load;
 }
 
diff --git a/hw/apic_common.c b/hw/apic_common.c
index 340d793..60b8259 100644
--- a/hw/apic_common.c
+++ b/hw/apic_common.c
@@ -20,8 +20,10 @@
 #include "apic.h"
 #include "apic_internal.h"
 #include "trace.h"
+#include "kvm.h"
 
 static int apic_irq_delivered;
+bool apic_report_tpr_access;
 
 void cpu_set_apic_base(DeviceState *d, uint64_t val)
 {
@@ -63,14 +65,45 @@ void cpu_set_apic_tpr(DeviceState *d, uint8_t val)
 
 uint8_t cpu_get_apic_tpr(DeviceState *d)
 {
+    APICCommonState *s;
+    APICCommonClass *info;
+
+    if (!d) {
+        return 0;
+    }
+
+    s = APIC_COMMON(d);
+    info = APIC_COMMON_GET_CLASS(s);
+
+    return info->get_tpr(s);
+}
+
+void apic_enable_tpr_access_reporting(DeviceState *d, bool enable)
+{
+    APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
+    APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
+
+    apic_report_tpr_access = enable;
+    if (info->enable_tpr_reporting) {
+        info->enable_tpr_reporting(s, enable);
+    }
+}
+
+void apic_enable_vapic(DeviceState *d, target_phys_addr_t paddr)
+{
     APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
+    APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
 
-    return s ? s->tpr >> 4 : 0;
+    s->vapic_paddr = paddr;
+    info->vapic_base_update(s);
 }
 
 void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip,
                                    TPRAccess access)
 {
+    APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
+
+    vapic_report_tpr_access(s->vapic, s->cpu_env, ip, access);
 }
 
 void apic_report_irq_delivered(int delivered)
@@ -171,12 +204,16 @@ void apic_init_reset(DeviceState *d)
 static void apic_reset_common(DeviceState *d)
 {
     APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
+    APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
     bool bsp;
 
     bsp = cpu_is_bsp(s->cpu_env);
     s->apicbase = 0xfee00000 |
         (bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE;
 
+    s->vapic_paddr = 0;
+    info->vapic_base_update(s);
+
     apic_init_reset(d);
 
     if (bsp) {
@@ -239,6 +276,7 @@ static int apic_init_common(SysBusDevice *dev)
 {
     APICCommonState *s = APIC_COMMON(dev);
     APICCommonClass *info;
+    static DeviceState *vapic;
     static int apic_no;
 
     if (apic_no >= MAX_APICS) {
@@ -249,10 +287,29 @@ static int apic_init_common(SysBusDevice *dev)
     info = APIC_COMMON_GET_CLASS(s);
     info->init(s);
 
-    sysbus_init_mmio(&s->busdev, &s->io_memory);
+    sysbus_init_mmio(dev, &s->io_memory);
+
+    if (!vapic && s->vapic_control & VAPIC_ENABLE_MASK) {
+        vapic = sysbus_create_simple("kvmvapic", -1, NULL);
+    }
+    s->vapic = vapic;
+    if (apic_report_tpr_access && info->enable_tpr_reporting) {
+        info->enable_tpr_reporting(s, true);
+    }
+
     return 0;
 }
 
+static void apic_dispatch_pre_save(void *opaque)
+{
+    APICCommonState *s = APIC_COMMON(opaque);
+    APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
+
+    if (info->pre_save) {
+        info->pre_save(s);
+    }
+}
+
 static int apic_dispatch_post_load(void *opaque, int version_id)
 {
     APICCommonState *s = APIC_COMMON(opaque);
@@ -270,6 +327,7 @@ static const VMStateDescription vmstate_apic_common = {
     .minimum_version_id = 3,
     .minimum_version_id_old = 1,
     .load_state_old = apic_load_old,
+    .pre_save = apic_dispatch_pre_save,
     .post_load = apic_dispatch_post_load,
     .fields = (VMStateField[]) {
         VMSTATE_UINT32(apicbase, APICCommonState),
@@ -299,6 +357,8 @@ static const VMStateDescription vmstate_apic_common = {
 static Property apic_properties_common[] = {
     DEFINE_PROP_UINT8("id", APICCommonState, id, -1),
     DEFINE_PROP_PTR("cpu_env", APICCommonState, cpu_env),
+    DEFINE_PROP_BIT("vapic", APICCommonState, vapic_control, VAPIC_ENABLE_BIT,
+                    true),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/apic_internal.h b/hw/apic_internal.h
index 0cab010..60a6a8b 100644
--- a/hw/apic_internal.h
+++ b/hw/apic_internal.h
@@ -61,6 +61,9 @@
 #define APIC_SV_DIRECTED_IO             (1<<12)
 #define APIC_SV_ENABLE                  (1<<8)
 
+#define VAPIC_ENABLE_BIT                0
+#define VAPIC_ENABLE_MASK               (1 << VAPIC_ENABLE_BIT)
+
 #define MAX_APICS 255
 
 #define MSI_SPACE_SIZE                  0x100000
@@ -82,7 +85,11 @@ typedef struct APICCommonClass
     void (*init)(APICCommonState *s);
     void (*set_base)(APICCommonState *s, uint64_t val);
     void (*set_tpr)(APICCommonState *s, uint8_t val);
+    uint8_t (*get_tpr)(APICCommonState *s);
+    void (*enable_tpr_reporting)(APICCommonState *s, bool enable);
+    void (*vapic_base_update)(APICCommonState *s);
     void (*external_nmi)(APICCommonState *s);
+    void (*pre_save)(APICCommonState *s);
     void (*post_load)(APICCommonState *s);
 } APICCommonClass;
 
@@ -114,9 +121,29 @@ struct APICCommonState {
     int64_t timer_expiry;
     int sipi_vector;
     int wait_for_sipi;
+
+    uint32_t vapic_control;
+    DeviceState *vapic;
+    target_phys_addr_t vapic_paddr; /* note: persistence via kvmvapic */
 };
 
+typedef struct VAPICState {
+    uint8_t tpr;
+    uint8_t isr;
+    uint8_t zero;
+    uint8_t irr;
+    uint8_t enabled;
+} QEMU_PACKED VAPICState;
+
+extern bool apic_report_tpr_access;
+
 void apic_report_irq_delivered(int delivered);
 bool apic_next_timer(APICCommonState *s, int64_t current_time);
+void apic_enable_tpr_access_reporting(DeviceState *d, bool enable);
+void apic_enable_vapic(DeviceState *d, target_phys_addr_t paddr);
+void apic_poll_irq(DeviceState *d);
+
+void vapic_report_tpr_access(DeviceState *dev, void *cpu, target_ulong ip,
+                             TPRAccess access);
 
 #endif /* !QEMU_APIC_INTERNAL_H */
diff --git a/hw/kvm/apic.c b/hw/kvm/apic.c
index 5bb0a4b..9ca68f8 100644
--- a/hw/kvm/apic.c
+++ b/hw/kvm/apic.c
@@ -92,6 +92,35 @@ static void kvm_apic_set_tpr(APICCommonState *s, uint8_t val)
     s->tpr = (val & 0x0f) << 4;
 }
 
+static uint8_t kvm_apic_get_tpr(APICCommonState *s)
+{
+    return s->tpr >> 4;
+}
+
+static void kvm_apic_enable_tpr_reporting(APICCommonState *s, bool enable)
+{
+    struct kvm_tpr_access_ctl ctl = {
+        .enabled = enable
+    };
+
+    kvm_vcpu_ioctl(s->cpu_env, KVM_TPR_ACCESS_REPORTING, &ctl);
+}
+
+static void kvm_apic_vapic_base_update(APICCommonState *s)
+{
+    struct kvm_vapic_addr vapid_addr = {
+        .vapic_addr = s->vapic_paddr,
+    };
+    int ret;
+
+    ret = kvm_vcpu_ioctl(s->cpu_env, KVM_SET_VAPIC_ADDR, &vapid_addr);
+    if (ret < 0) {
+        fprintf(stderr, "KVM: setting VAPIC address failed (%s)\n",
+                strerror(-ret));
+        abort();
+    }
+}
+
 static void do_inject_external_nmi(void *data)
 {
     APICCommonState *s = data;
@@ -129,6 +158,9 @@ static void kvm_apic_class_init(ObjectClass *klass, void *data)
     k->init = kvm_apic_init;
     k->set_base = kvm_apic_set_base;
     k->set_tpr = kvm_apic_set_tpr;
+    k->get_tpr = kvm_apic_get_tpr;
+    k->enable_tpr_reporting = kvm_apic_enable_tpr_reporting;
+    k->vapic_base_update = kvm_apic_vapic_base_update;
     k->external_nmi = kvm_apic_external_nmi;
 }
 
diff --git a/hw/kvmvapic.c b/hw/kvmvapic.c
new file mode 100644
index 0000000..36ccfbc
--- /dev/null
+++ b/hw/kvmvapic.c
@@ -0,0 +1,805 @@
+/*
+ * TPR optimization for 32-bit Windows guests (XP and Server 2003)
+ *
+ * Copyright (C) 2007-2008 Qumranet Technologies
+ * Copyright (C) 2012      Jan Kiszka, Siemens AG
+ *
+ * This work is licensed under the terms of the GNU GPL version 2, or
+ * (at your option) any later version. See the COPYING file in the
+ * top-level directory.
+ */
+#include "sysemu.h"
+#include "cpus.h"
+#include "kvm.h"
+#include "apic_internal.h"
+
+#define APIC_DEFAULT_ADDRESS    0xfee00000
+
+#define VAPIC_IO_PORT           0x7e
+
+#define VAPIC_CPU_SHIFT         7
+
+#define ROM_BLOCK_SIZE          512
+#define ROM_BLOCK_MASK          (~(ROM_BLOCK_SIZE - 1))
+
+typedef enum VAPICMode {
+    VAPIC_INACTIVE = 0,
+    VAPIC_ACTIVE   = 1,
+    VAPIC_STANDBY  = 2,
+} VAPICMode;
+
+typedef struct VAPICHandlers {
+    uint32_t set_tpr;
+    uint32_t set_tpr_eax;
+    uint32_t get_tpr[8];
+    uint32_t get_tpr_stack;
+} QEMU_PACKED VAPICHandlers;
+
+typedef struct GuestROMState {
+    char signature[8];
+    uint32_t vaddr;
+    uint32_t fixup_start;
+    uint32_t fixup_end;
+    uint32_t vapic_vaddr;
+    uint32_t vapic_size;
+    uint32_t vcpu_shift;
+    uint32_t real_tpr_addr;
+    VAPICHandlers up;
+    VAPICHandlers mp;
+} QEMU_PACKED GuestROMState;
+
+typedef struct VAPICROMState {
+    SysBusDevice busdev;
+    MemoryRegion io;
+    MemoryRegion rom;
+    uint32_t state;
+    uint32_t rom_state_paddr;
+    uint32_t rom_state_vaddr;
+    uint32_t vapic_paddr;
+    uint32_t real_tpr_addr;
+    GuestROMState rom_state;
+    size_t rom_size;
+    bool rom_mapped_writable;
+} VAPICROMState;
+
+#define TPR_INSTR_ABS_MODRM             0x1
+#define TPR_INSTR_MATCH_MODRM_REG       0x2
+
+typedef struct TPRInstruction {
+    uint8_t opcode;
+    uint8_t modrm_reg;
+    unsigned int flags;
+    TPRAccess access;
+    size_t length;
+    off_t addr_offset;
+} TPRInstruction;
+
+/* must be sorted by length, shortest first */
+static const TPRInstruction tpr_instr[] = {
+    { /* mov abs to eax */
+        .opcode = 0xa1,
+        .access = TPR_ACCESS_READ,
+        .length = 5,
+        .addr_offset = 1,
+    },
+    { /* mov eax to abs */
+        .opcode = 0xa3,
+        .access = TPR_ACCESS_WRITE,
+        .length = 5,
+        .addr_offset = 1,
+    },
+    { /* mov r32 to r/m32 */
+        .opcode = 0x89,
+        .flags = TPR_INSTR_ABS_MODRM,
+        .access = TPR_ACCESS_WRITE,
+        .length = 6,
+        .addr_offset = 2,
+    },
+    { /* mov r/m32 to r32 */
+        .opcode = 0x8b,
+        .flags = TPR_INSTR_ABS_MODRM,
+        .access = TPR_ACCESS_READ,
+        .length = 6,
+        .addr_offset = 2,
+    },
+    { /* push r/m32 */
+        .opcode = 0xff,
+        .modrm_reg = 6,
+        .flags = TPR_INSTR_ABS_MODRM | TPR_INSTR_MATCH_MODRM_REG,
+        .access = TPR_ACCESS_READ,
+        .length = 6,
+        .addr_offset = 2,
+    },
+    { /* mov imm32, r/m32 (c7/0) */
+        .opcode = 0xc7,
+        .modrm_reg = 0,
+        .flags = TPR_INSTR_ABS_MODRM | TPR_INSTR_MATCH_MODRM_REG,
+        .access = TPR_ACCESS_WRITE,
+        .length = 10,
+        .addr_offset = 2,
+    },
+};
+
+static void read_guest_rom_state(VAPICROMState *s)
+{
+    cpu_physical_memory_rw(s->rom_state_paddr, (void *)&s->rom_state,
+                           sizeof(GuestROMState), 0);
+}
+
+static void write_guest_rom_state(VAPICROMState *s)
+{
+    cpu_physical_memory_rw(s->rom_state_paddr, (void *)&s->rom_state,
+                           sizeof(GuestROMState), 1);
+}
+
+static void update_guest_rom_state(VAPICROMState *s)
+{
+    read_guest_rom_state(s);
+
+    s->rom_state.real_tpr_addr = cpu_to_le32(s->real_tpr_addr);
+    s->rom_state.vcpu_shift = cpu_to_le32(VAPIC_CPU_SHIFT);
+
+    write_guest_rom_state(s);
+}
+
+static int find_real_tpr_addr(VAPICROMState *s, CPUState *env)
+{
+    target_phys_addr_t paddr;
+    target_ulong addr;
+
+    if (s->state == VAPIC_ACTIVE) {
+        return 0;
+    }
+    /*
+     * If there is no prior TPR access instruction we could analyze (which is
+     * the case after resume from hibernation), we need to scan the possible
+     * virtual address space for the APIC mapping.
+     */
+    for (addr = 0xfffff000; addr >= 0x80000000; addr -= TARGET_PAGE_SIZE) {
+        paddr = cpu_get_phys_page_debug(env, addr);
+        if (paddr != APIC_DEFAULT_ADDRESS) {
+            continue;
+        }
+        s->real_tpr_addr = addr + 0x80;
+        update_guest_rom_state(s);
+        return 0;
+    }
+    return -1;
+}
+
+static uint8_t modrm_reg(uint8_t modrm)
+{
+    return (modrm >> 3) & 7;
+}
+
+static bool is_abs_modrm(uint8_t modrm)
+{
+    return (modrm & 0xc7) == 0x05;
+}
+
+static bool opcode_matches(uint8_t *opcode, const TPRInstruction *instr)
+{
+    return opcode[0] == instr->opcode &&
+        (!(instr->flags & TPR_INSTR_ABS_MODRM) || is_abs_modrm(opcode[1])) &&
+        (!(instr->flags & TPR_INSTR_MATCH_MODRM_REG) ||
+         modrm_reg(opcode[1]) == instr->modrm_reg);
+}
+
+static int evaluate_tpr_instruction(VAPICROMState *s, CPUState *env,
+                                    target_ulong *pip, TPRAccess access)
+{
+    const TPRInstruction *instr;
+    target_ulong ip = *pip;
+    uint8_t opcode[2];
+    uint32_t real_tpr_addr;
+    int i;
+
+    if ((ip & 0xf0000000ULL) != 0x80000000ULL &&
+        (ip & 0xf0000000ULL) != 0xe0000000ULL) {
+        return -1;
+    }
+
+    /*
+     * Early Windows 2003 SMP initialization contains a
+     *
+     *   mov imm32, r/m32
+     *
+     * instruction that is patched by TPR optimization. The problem is that
+     * RSP, used by the patched instruction, is zero, so the guest gets a
+     * double fault and dies.
+     */
+    if (env->regs[R_ESP] == 0) {
+        return -1;
+    }
+
+    if (kvm_enabled() && !kvm_irqchip_in_kernel()) {
+        /*
+         * KVM without kernel-based TPR access reporting will pass an IP that
+         * points after the accessing instruction. So we need to look backward
+         * to find the reason.
+         */
+        for (i = 0; i < ARRAY_SIZE(tpr_instr); i++) {
+            instr = &tpr_instr[i];
+            if (instr->access != access) {
+                continue;
+            }
+            if (cpu_memory_rw_debug(env, ip - instr->length, opcode,
+                                    sizeof(opcode), 0) < 0) {
+                return -1;
+            }
+            if (opcode_matches(opcode, instr)) {
+                ip -= instr->length;
+                goto instruction_ok;
+            }
+        }
+        return -1;
+    } else {
+        if (cpu_memory_rw_debug(env, ip, opcode, sizeof(opcode), 0) < 0) {
+            return -1;
+        }
+        for (i = 0; i < ARRAY_SIZE(tpr_instr); i++) {
+            instr = &tpr_instr[i];
+            if (opcode_matches(opcode, instr)) {
+                goto instruction_ok;
+            }
+        }
+        return -1;
+    }
+
+instruction_ok:
+    /*
+     * Grab the virtual TPR address from the instruction
+     * and update the cached values.
+     */
+    if (cpu_memory_rw_debug(env, ip + instr->addr_offset,
+                            (void *)&real_tpr_addr,
+                            sizeof(real_tpr_addr), 0) < 0) {
+        return -1;
+    }
+    real_tpr_addr = le32_to_cpu(real_tpr_addr);
+    if ((real_tpr_addr & 0xfff) != 0x80) {
+        return -1;
+    }
+    s->real_tpr_addr = real_tpr_addr;
+    update_guest_rom_state(s);
+
+    *pip = ip;
+    return 0;
+}
+
+static int update_rom_mapping(VAPICROMState *s, CPUState *env, target_ulong ip)
+{
+    target_phys_addr_t paddr;
+    uint32_t rom_state_vaddr;
+    uint32_t pos, patch, offset;
+
+    /* nothing to do if already activated */
+    if (s->state == VAPIC_ACTIVE) {
+        return 0;
+    }
+
+    /* bail out if ROM init code was not executed (missing ROM?) */
+    if (s->state == VAPIC_INACTIVE) {
+        return -1;
+    }
+
+    /* find out virtual address of the ROM */
+    rom_state_vaddr = s->rom_state_paddr + (ip & 0xf0000000);
+    paddr = cpu_get_phys_page_debug(env, rom_state_vaddr);
+    if (paddr == -1) {
+        return -1;
+    }
+    paddr += rom_state_vaddr & ~TARGET_PAGE_MASK;
+    if (paddr != s->rom_state_paddr) {
+        return -1;
+    }
+    read_guest_rom_state(s);
+    if (memcmp(s->rom_state.signature, "kvm aPiC", 8) != 0) {
+        return -1;
+    }
+    s->rom_state_vaddr = rom_state_vaddr;
+
+    /* fixup addresses in ROM if needed */
+    if (rom_state_vaddr == le32_to_cpu(s->rom_state.vaddr)) {
+        return 0;
+    }
+    for (pos = le32_to_cpu(s->rom_state.fixup_start);
+         pos < le32_to_cpu(s->rom_state.fixup_end);
+         pos += 4) {
+        cpu_physical_memory_rw(paddr + pos - s->rom_state.vaddr,
+                               (void *)&offset, sizeof(offset), 0);
+        offset = le32_to_cpu(offset);
+        cpu_physical_memory_rw(paddr + offset, (void *)&patch,
+                               sizeof(patch), 0);
+        patch = le32_to_cpu(patch);
+        patch += rom_state_vaddr - le32_to_cpu(s->rom_state.vaddr);
+        patch = cpu_to_le32(patch);
+        cpu_physical_memory_rw(paddr + offset, (void *)&patch,
+                               sizeof(patch), 1);
+    }
+    read_guest_rom_state(s);
+    s->vapic_paddr = paddr + le32_to_cpu(s->rom_state.vapic_vaddr) -
+        le32_to_cpu(s->rom_state.vaddr);
+
+    return 0;
+}
+
+/*
+ * Tries to read the unique processor number from the Kernel Processor Control
+ * Region (KPCR) of 32-bit Windows XP and Server 2003. Returns -1 if the KPCR
+ * cannot be accessed or is considered invalid. This also ensures that we are
+ * not patching the wrong guest.
+ */
+static int get_kpcr_number(CPUState *env)
+{
+    struct kpcr {
+        uint8_t  fill1[0x1c];
+        uint32_t self;
+        uint8_t  fill2[0x31];
+        uint8_t  number;
+    } QEMU_PACKED kpcr;
+
+    if (cpu_memory_rw_debug(env, env->segs[R_FS].base,
+                            (void *)&kpcr, sizeof(kpcr), 0) < 0 ||
+        kpcr.self != env->segs[R_FS].base) {
+        return -1;
+    }
+    return kpcr.number;
+}
+
+static int vapic_enable(VAPICROMState *s, CPUState *env)
+{
+    int cpu_number = get_kpcr_number(env);
+    target_phys_addr_t vapic_paddr;
+    static const uint8_t enabled = 1;
+
+    if (cpu_number < 0) {
+        return -1;
+    }
+    vapic_paddr = s->vapic_paddr +
+        (((target_phys_addr_t)cpu_number) << VAPIC_CPU_SHIFT);
+    cpu_physical_memory_rw(vapic_paddr + offsetof(VAPICState, enabled),
+                           (void *)&enabled, sizeof(enabled), 1);
+    apic_enable_vapic(env->apic_state, vapic_paddr);
+
+    s->state = VAPIC_ACTIVE;
+
+    return 0;
+}
+
+static void patch_byte(CPUState *env, target_ulong addr, uint8_t byte)
+{
+    cpu_memory_rw_debug(env, addr, &byte, 1, 1);
+}
+
+static void patch_call(VAPICROMState *s, CPUState *env, target_ulong ip,
+                       uint32_t target)
+{
+    uint32_t offset;
+
+    offset = cpu_to_le32(target - ip - 5);
+    patch_byte(env, ip, 0xe8); /* call near */
+    cpu_memory_rw_debug(env, ip + 1, (void *)&offset, sizeof(offset), 1);
+}
+
+static void patch_instruction(VAPICROMState *s, CPUState *env, target_ulong ip)
+{
+    target_phys_addr_t paddr;
+    VAPICHandlers *handlers;
+    uint8_t opcode[2];
+    uint32_t imm32;
+
+    if (smp_cpus == 1) {
+        handlers = &s->rom_state.up;
+    } else {
+        handlers = &s->rom_state.mp;
+    }
+
+    pause_all_vcpus();
+
+    cpu_memory_rw_debug(env, ip, opcode, sizeof(opcode), 0);
+
+    switch (opcode[0]) {
+    case 0x89: /* mov r32 to r/m32 */
+        patch_byte(env, ip, 0x50 + modrm_reg(opcode[1]));  /* push reg */
+        patch_call(s, env, ip + 1, handlers->set_tpr);
+        break;
+    case 0x8b: /* mov r/m32 to r32 */
+        patch_byte(env, ip, 0x90);
+        patch_call(s, env, ip + 1, handlers->get_tpr[modrm_reg(opcode[1])]);
+        break;
+    case 0xa1: /* mov abs to eax */
+        patch_call(s, env, ip, handlers->get_tpr[0]);
+        break;
+    case 0xa3: /* mov eax to abs */
+        patch_call(s, env, ip, handlers->set_tpr_eax);
+        break;
+    case 0xc7: /* mov imm32, r/m32 (c7/0) */
+        patch_byte(env, ip, 0x68);  /* push imm32 */
+        cpu_memory_rw_debug(env, ip + 6, (void *)&imm32, sizeof(imm32), 0);
+        cpu_memory_rw_debug(env, ip + 1, (void *)&imm32, sizeof(imm32), 1);
+        patch_call(s, env, ip + 5, handlers->set_tpr);
+        break;
+    case 0xff: /* push r/m32 */
+        patch_byte(env, ip, 0x50); /* push eax */
+        patch_call(s, env, ip + 1, handlers->get_tpr_stack);
+        break;
+    default:
+        abort();
+    }
+
+    resume_all_vcpus();
+
+    paddr = cpu_get_phys_page_debug(env, ip);
+    paddr += ip & ~TARGET_PAGE_MASK;
+    tb_invalidate_phys_page_range(paddr, paddr + 1, 1);
+}
+
+void vapic_report_tpr_access(DeviceState *dev, void *cpu, target_ulong ip,
+                             TPRAccess access)
+{
+    VAPICROMState *s = DO_UPCAST(VAPICROMState, busdev.qdev, dev);
+    CPUState *env = cpu;
+
+    cpu_synchronize_state(env);
+
+    if (evaluate_tpr_instruction(s, env, &ip, access) < 0) {
+        if (s->state == VAPIC_ACTIVE) {
+            vapic_enable(s, env);
+        }
+        return;
+    }
+    if (update_rom_mapping(s, env, ip) < 0) {
+        return;
+    }
+    if (vapic_enable(s, env) < 0) {
+        return;
+    }
+    patch_instruction(s, env, ip);
+}
+
+typedef struct VAPICEnableTPRReporting {
+    DeviceState *apic;
+    bool enable;
+} VAPICEnableTPRReporting;
+
+static void vapic_do_enable_tpr_reporting(void *data)
+{
+    VAPICEnableTPRReporting *info = data;
+
+    apic_enable_tpr_access_reporting(info->apic, info->enable);
+}
+
+static void vapic_enable_tpr_reporting(bool enable)
+{
+    VAPICEnableTPRReporting info = {
+        .enable = enable,
+    };
+    CPUState *env;
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        info.apic = env->apic_state;
+        run_on_cpu(env, vapic_do_enable_tpr_reporting, &info);
+    }
+}
+
+static void vapic_reset(DeviceState *dev)
+{
+    VAPICROMState *s = DO_UPCAST(VAPICROMState, busdev.qdev, dev);
+
+    if (s->state == VAPIC_ACTIVE) {
+        s->state = VAPIC_STANDBY;
+    }
+    vapic_enable_tpr_reporting(false);
+}
+
+/*
+ * Set the IRQ polling hypercalls to the supported variant:
+ *  - vmcall if using KVM in-kernel irqchip
+ *  - 32-bit VAPIC port write otherwise
+ */
+static int patch_hypercalls(VAPICROMState *s)
+{
+    target_phys_addr_t rom_paddr = s->rom_state_paddr & ROM_BLOCK_MASK;
+    static const uint8_t vmcall_pattern[] = { /* vmcall */
+        0xb8, 0x1, 0, 0, 0, 0xf, 0x1, 0xc1
+    };
+    static const uint8_t outl_pattern[] = { /* nop; outl %eax,0x7e */
+        0xb8, 0x1, 0, 0, 0, 0x90, 0xe7, 0x7e
+    };
+    uint8_t alternates[2];
+    const uint8_t *pattern;
+    const uint8_t *patch;
+    int patches = 0;
+    off_t pos;
+    uint8_t *rom;
+
+    rom = g_malloc(s->rom_size);
+    cpu_physical_memory_rw(rom_paddr, rom, s->rom_size, 0);
+
+    for (pos = 0; pos < s->rom_size - sizeof(vmcall_pattern); pos++) {
+        if (kvm_irqchip_in_kernel()) {
+            pattern = outl_pattern;
+            alternates[0] = outl_pattern[7];
+            alternates[1] = outl_pattern[7];
+            patch = &vmcall_pattern[5];
+        } else {
+            pattern = vmcall_pattern;
+            alternates[0] = vmcall_pattern[7];
+            alternates[1] = 0xd9; /* AMD's VMMCALL */
+            patch = &outl_pattern[5];
+        }
+        if (memcmp(rom + pos, pattern, 7) == 0 &&
+            (rom[pos + 7] == alternates[0] || rom[pos + 7] == alternates[1])) {
+            cpu_physical_memory_rw(rom_paddr + pos + 5, (uint8_t *)patch,
+                                   3, 1);
+            /*
+             * Don't flush the tb here. Under ordinary conditions, the patched
+             * calls are miles away from the current IP. Under malicious
+             * conditions, the guest could trick us to crash.
+             */
+        }
+    }
+
+    g_free(rom);
+
+    if (patches != 0 && patches != 2) {
+        return -1;
+    }
+
+    return 0;
+}
+
+/*
+ * For TCG mode or the time KVM honors read-only memory regions, we need to
+ * enable write access to the option ROM so that variables can be updated by
+ * the guest.
+ */
+static void vapic_map_rom_writable(VAPICROMState *s)
+{
+    target_phys_addr_t rom_paddr = s->rom_state_paddr & ROM_BLOCK_MASK;
+    MemoryRegionSection section;
+    MemoryRegion *as;
+    size_t rom_size;
+    uint8_t *ram;
+
+    as = sysbus_address_space(&s->busdev);
+
+    if (s->rom_mapped_writable) {
+        memory_region_del_subregion(as, &s->rom);
+        memory_region_destroy(&s->rom);
+    }
+
+    /* grab RAM memory region (region @rom_paddr may still be pc.rom) */
+    section = memory_region_find(as, 0, 1);
+
+    /* read ROM size from RAM region */
+    ram = memory_region_get_ram_ptr(section.mr);
+    rom_size = ram[rom_paddr + 2] * ROM_BLOCK_SIZE;
+    s->rom_size = rom_size;
+
+    /* We need to round up to avoid creating subpages
+     * from which we cannot run code. */
+    rom_size = TARGET_PAGE_ALIGN(rom_size);
+
+    memory_region_init_alias(&s->rom, "kvmvapic-rom", section.mr, rom_paddr,
+                             rom_size);
+    memory_region_add_subregion_overlap(as, rom_paddr, &s->rom, 1000);
+    s->rom_mapped_writable = true;
+}
+
+static int vapic_prepare(VAPICROMState *s)
+{
+    vapic_map_rom_writable(s);
+
+    if (patch_hypercalls(s) < 0) {
+        return -1;
+    }
+
+    vapic_enable_tpr_reporting(true);
+
+    return 0;
+}
+
+static void vapic_write(void *opaque, target_phys_addr_t addr, uint64_t data,
+                        unsigned int size)
+{
+    CPUState *env = cpu_single_env;
+    target_phys_addr_t rom_paddr;
+    VAPICROMState *s = opaque;
+
+    cpu_synchronize_state(env);
+
+    /*
+     * The VAPIC supports two PIO-based hypercalls, both via port 0x7E.
+     *  o 16-bit write access:
+     *    Reports the option ROM initialization to the hypervisor. Written
+     *    value is the offset of the state structure in the ROM.
+     *  o 8-bit write access:
+     *    Reactivates the VAPIC after a guest hibernation, i.e. after the
+     *    option ROM content has been re-initialized by a guest power cycle.
+     *  o 32-bit write access:
+     *    Poll for pending IRQs, considering the current VAPIC state.
+     */
+    switch (size) {
+    case 2:
+        if (s->state == VAPIC_INACTIVE) {
+            rom_paddr = (env->segs[R_CS].base + env->eip) & ROM_BLOCK_MASK;
+            s->rom_state_paddr = rom_paddr + data;
+
+            s->state = VAPIC_STANDBY;
+        }
+        if (vapic_prepare(s) < 0) {
+            s->state = VAPIC_INACTIVE;
+            break;
+        }
+        break;
+    case 1:
+        if (kvm_enabled()) {
+            /*
+             * Disable triggering instruction in ROM by writing a NOP.
+             *
+             * We cannot do this in TCG mode as the reported IP is not
+             * accurate.
+             */
+            pause_all_vcpus();
+            patch_byte(env, env->eip - 2, 0x66);
+            patch_byte(env, env->eip - 1, 0x90);
+            resume_all_vcpus();
+        }
+
+        if (s->state == VAPIC_ACTIVE) {
+            break;
+        }
+        if (update_rom_mapping(s, env, env->eip) < 0) {
+            break;
+        }
+        if (find_real_tpr_addr(s, env) < 0) {
+            break;
+        }
+        vapic_enable(s, env);
+        break;
+    default:
+    case 4:
+        if (!kvm_irqchip_in_kernel()) {
+            apic_poll_irq(env->apic_state);
+        }
+        break;
+    }
+}
+
+static const MemoryRegionOps vapic_ops = {
+    .write = vapic_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int vapic_init(SysBusDevice *dev)
+{
+    VAPICROMState *s = FROM_SYSBUS(VAPICROMState, dev);
+
+    memory_region_init_io(&s->io, &vapic_ops, s, "kvmvapic", 2);
+    sysbus_add_io(dev, VAPIC_IO_PORT, &s->io);
+    sysbus_init_ioports(dev, VAPIC_IO_PORT, 2);
+
+    option_rom[nb_option_roms].name = "kvmvapic.bin";
+    option_rom[nb_option_roms].bootindex = -1;
+    nb_option_roms++;
+
+    return 0;
+}
+
+static void do_vapic_enable(void *data)
+{
+    VAPICROMState *s = data;
+
+    vapic_enable(s, first_cpu);
+}
+
+static int vapic_post_load(void *opaque, int version_id)
+{
+    VAPICROMState *s = opaque;
+    uint8_t *zero;
+
+    /*
+     * The old implementation of qemu-kvm did not provide the state
+     * VAPIC_STANDBY. Reconstruct it.
+     */
+    if (s->state == VAPIC_INACTIVE && s->rom_state_paddr != 0) {
+        s->state = VAPIC_STANDBY;
+    }
+
+    if (s->state != VAPIC_INACTIVE) {
+        if (vapic_prepare(s) < 0) {
+            return -1;
+        }
+    }
+    if (s->state == VAPIC_ACTIVE) {
+        if (smp_cpus == 1) {
+            run_on_cpu(first_cpu, do_vapic_enable, s);
+        } else {
+            zero = g_malloc0(s->rom_state.vapic_size);
+            cpu_physical_memory_rw(s->vapic_paddr, zero,
+                                   s->rom_state.vapic_size, 1);
+            g_free(zero);
+        }
+    }
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_handlers = {
+    .name = "kvmvapic-handlers",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(set_tpr, VAPICHandlers),
+        VMSTATE_UINT32(set_tpr_eax, VAPICHandlers),
+        VMSTATE_UINT32_ARRAY(get_tpr, VAPICHandlers, 8),
+        VMSTATE_UINT32(get_tpr_stack, VAPICHandlers),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_guest_rom = {
+    .name = "kvmvapic-guest-rom",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UNUSED(8),     /* signature */
+        VMSTATE_UINT32(vaddr, GuestROMState),
+        VMSTATE_UINT32(fixup_start, GuestROMState),
+        VMSTATE_UINT32(fixup_end, GuestROMState),
+        VMSTATE_UINT32(vapic_vaddr, GuestROMState),
+        VMSTATE_UINT32(vapic_size, GuestROMState),
+        VMSTATE_UINT32(vcpu_shift, GuestROMState),
+        VMSTATE_UINT32(real_tpr_addr, GuestROMState),
+        VMSTATE_STRUCT(up, GuestROMState, 0, vmstate_handlers, VAPICHandlers),
+        VMSTATE_STRUCT(mp, GuestROMState, 0, vmstate_handlers, VAPICHandlers),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_vapic = {
+    .name = "kvm-tpr-opt",      /* compatible with qemu-kvm VAPIC */
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .post_load = vapic_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_STRUCT(rom_state, VAPICROMState, 0, vmstate_guest_rom,
+                       GuestROMState),
+        VMSTATE_UINT32(state, VAPICROMState),
+        VMSTATE_UINT32(real_tpr_addr, VAPICROMState),
+        VMSTATE_UINT32(rom_state_vaddr, VAPICROMState),
+        VMSTATE_UINT32(vapic_paddr, VAPICROMState),
+        VMSTATE_UINT32(rom_state_paddr, VAPICROMState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void vapic_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->no_user = 1;
+    dc->reset   = vapic_reset;
+    dc->vmsd    = &vmstate_vapic;
+    sc->init    = vapic_init;
+}
+
+static TypeInfo vapic_type = {
+    .name          = "kvmvapic",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(VAPICROMState),
+    .class_init    = vapic_class_init,
+};
+
+static void vapic_register(void)
+{
+    type_register_static(&vapic_type);
+}
+
+type_init(vapic_register);
commit 2a2af967b0bc601c9b450c72b95104e67222e5b2
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Feb 17 18:31:18 2012 +0100

    kvmvapic: Add option ROM
    
    This imports and builds the original VAPIC option ROM of qemu-kvm.
    Its interaction with QEMU is described in the commit that introduces the
    corresponding device model.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/.gitignore b/.gitignore
index f5aab2c..d3b78c3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -75,6 +75,7 @@ pc-bios/vgabios-pq/status
 pc-bios/optionrom/linuxboot.bin
 pc-bios/optionrom/multiboot.bin
 pc-bios/optionrom/multiboot.raw
+pc-bios/optionrom/kvmvapic.bin
 .stgit-*
 cscope.*
 tags
diff --git a/Makefile b/Makefile
index e66e885..e2f357d 100644
--- a/Makefile
+++ b/Makefile
@@ -253,7 +253,7 @@ pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \
 pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \
 bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
 mpc8544ds.dtb \
-multiboot.bin linuxboot.bin \
+multiboot.bin linuxboot.bin kvmvapic.bin \
 s390-zipl.rom \
 spapr-rtas.bin slof.bin \
 palcode-clipper
diff --git a/pc-bios/optionrom/Makefile b/pc-bios/optionrom/Makefile
index 2caf7e6..f6b4027 100644
--- a/pc-bios/optionrom/Makefile
+++ b/pc-bios/optionrom/Makefile
@@ -14,7 +14,7 @@ CFLAGS += -I$(SRC_PATH)
 CFLAGS += $(call cc-option, $(CFLAGS), -fno-stack-protector)
 QEMU_CFLAGS = $(CFLAGS)
 
-build-all: multiboot.bin linuxboot.bin
+build-all: multiboot.bin linuxboot.bin kvmvapic.bin
 
 # suppress auto-removal of intermediate files
 .SECONDARY:
diff --git a/pc-bios/optionrom/kvmvapic.S b/pc-bios/optionrom/kvmvapic.S
new file mode 100644
index 0000000..e1d8f18
--- /dev/null
+++ b/pc-bios/optionrom/kvmvapic.S
@@ -0,0 +1,341 @@
+#
+# Local APIC acceleration for Windows XP and related guests
+#
+# Copyright 2011 Red Hat, Inc. and/or its affiliates
+#
+# Author: Avi Kivity <avi at redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2, or (at your
+# option) any later version.  See the COPYING file in the top-level directory.
+#
+
+	.text 0
+	.code16
+.global _start
+_start:
+	.short 0xaa55
+	.byte (_end - _start) / 512
+	# clear vapic area: firmware load using rep insb may cause
+	# stale tpr/isr/irr data to corrupt the vapic area.
+	push %es
+	push %cs
+	pop %es
+	xor %ax, %ax
+	mov $vapic_size/2, %cx
+	lea vapic, %di
+	cld
+	rep stosw
+	pop %es
+	mov $vapic_base, %ax
+	out %ax, $0x7e
+	lret
+
+	.code32
+vapic_size = 2*4096
+
+.macro fixup delta=-4
+777:
+	.text 1
+	.long 777b + \delta  - vapic_base
+	.text 0
+.endm
+
+.macro reenable_vtpr
+	out %al, $0x7e
+.endm
+
+.text 1
+	fixup_start = .
+.text 0
+
+.align 16
+
+vapic_base:
+	.ascii "kvm aPiC"
+
+	/* relocation data */
+	.long vapic_base	; fixup
+	.long fixup_start	; fixup
+	.long fixup_end		; fixup
+
+	.long vapic		; fixup
+	.long vapic_size
+vcpu_shift:
+	.long 0
+real_tpr:
+	.long 0
+	.long up_set_tpr	; fixup
+	.long up_set_tpr_eax	; fixup
+	.long up_get_tpr_eax	; fixup
+	.long up_get_tpr_ecx	; fixup
+	.long up_get_tpr_edx	; fixup
+	.long up_get_tpr_ebx	; fixup
+	.long 0 /* esp. won't work. */
+	.long up_get_tpr_ebp	; fixup
+	.long up_get_tpr_esi	; fixup
+	.long up_get_tpr_edi	; fixup
+	.long up_get_tpr_stack  ; fixup
+	.long mp_set_tpr	; fixup
+	.long mp_set_tpr_eax	; fixup
+	.long mp_get_tpr_eax	; fixup
+	.long mp_get_tpr_ecx	; fixup
+	.long mp_get_tpr_edx	; fixup
+	.long mp_get_tpr_ebx	; fixup
+	.long 0 /* esp. won't work. */
+	.long mp_get_tpr_ebp	; fixup
+	.long mp_get_tpr_esi	; fixup
+	.long mp_get_tpr_edi	; fixup
+	.long mp_get_tpr_stack  ; fixup
+
+.macro kvm_hypercall
+	.byte 0x0f, 0x01, 0xc1
+.endm
+
+kvm_hypercall_vapic_poll_irq = 1
+
+pcr_cpu = 0x51
+
+.align 64
+
+mp_get_tpr_eax:
+	pushf
+	cli
+	reenable_vtpr
+	push %ecx
+
+	fs/movzbl pcr_cpu, %eax
+
+	mov vcpu_shift, %ecx	; fixup
+	shl %cl, %eax
+	testb $1, vapic+4(%eax)	; fixup delta=-5
+	jz mp_get_tpr_bad
+	movzbl vapic(%eax), %eax ; fixup
+
+mp_get_tpr_out:
+	pop %ecx
+	popf
+	ret
+
+mp_get_tpr_bad:
+	mov real_tpr, %eax	; fixup
+	mov (%eax), %eax
+	jmp mp_get_tpr_out
+
+mp_get_tpr_ebx:
+	mov %eax, %ebx
+	call mp_get_tpr_eax
+	xchg %eax, %ebx
+	ret
+
+mp_get_tpr_ecx:
+	mov %eax, %ecx
+	call mp_get_tpr_eax
+	xchg %eax, %ecx
+	ret
+
+mp_get_tpr_edx:
+	mov %eax, %edx
+	call mp_get_tpr_eax
+	xchg %eax, %edx
+	ret
+
+mp_get_tpr_esi:
+	mov %eax, %esi
+	call mp_get_tpr_eax
+	xchg %eax, %esi
+	ret
+
+mp_get_tpr_edi:
+	mov %eax, %edi
+	call mp_get_tpr_edi
+	xchg %eax, %edi
+	ret
+
+mp_get_tpr_ebp:
+	mov %eax, %ebp
+	call mp_get_tpr_eax
+	xchg %eax, %ebp
+	ret
+
+mp_get_tpr_stack:
+	call mp_get_tpr_eax
+	xchg %eax, 4(%esp)
+	ret
+
+mp_set_tpr_eax:
+	push %eax
+	call mp_set_tpr
+	ret
+
+mp_set_tpr:
+	pushf
+	push %eax
+	push %ecx
+	push %edx
+	push %ebx
+	cli
+	reenable_vtpr
+
+mp_set_tpr_failed:
+	fs/movzbl pcr_cpu, %edx
+
+	mov vcpu_shift, %ecx	; fixup
+	shl %cl, %edx
+
+	testb $1, vapic+4(%edx)	; fixup delta=-5
+	jz mp_set_tpr_bad
+
+	mov vapic(%edx), %eax	; fixup
+
+	mov %eax, %ebx
+	mov 24(%esp), %bl
+
+	/* %ebx = new vapic (%bl = tpr, %bh = isr, %b3 = irr) */
+
+	lock cmpxchg %ebx, vapic(%edx) ; fixup
+	jnz mp_set_tpr_failed
+
+	/* compute ppr */
+	cmp %bh, %bl
+	jae mp_tpr_is_bigger
+mp_isr_is_bigger:
+	mov %bh, %bl
+mp_tpr_is_bigger:
+	/* %bl = ppr */
+	mov %bl, %ch   /* ch = ppr */
+	rol $8, %ebx
+	/* now: %bl = irr, %bh = ppr */
+	cmp %bh, %bl
+	ja mp_set_tpr_poll_irq
+
+mp_set_tpr_out:
+	pop %ebx
+	pop %edx
+	pop %ecx
+	pop %eax
+	popf
+	ret $4
+
+mp_set_tpr_poll_irq:
+	mov $kvm_hypercall_vapic_poll_irq, %eax
+	kvm_hypercall
+	jmp mp_set_tpr_out
+
+mp_set_tpr_bad:
+	mov 24(%esp), %ecx
+	mov real_tpr, %eax	; fixup
+	mov %ecx, (%eax)
+	jmp mp_set_tpr_out
+
+up_get_tpr_eax:
+	reenable_vtpr
+	movzbl vapic, %eax ; fixup
+	ret
+
+up_get_tpr_ebx:
+	reenable_vtpr
+	movzbl vapic, %ebx ; fixup
+	ret
+
+up_get_tpr_ecx:
+	reenable_vtpr
+	movzbl vapic, %ecx ; fixup
+	ret
+
+up_get_tpr_edx:
+	reenable_vtpr
+	movzbl vapic, %edx ; fixup
+	ret
+
+up_get_tpr_esi:
+	reenable_vtpr
+	movzbl vapic, %esi ; fixup
+	ret
+
+up_get_tpr_edi:
+	reenable_vtpr
+	movzbl vapic, %edi ; fixup
+	ret
+
+up_get_tpr_ebp:
+	reenable_vtpr
+	movzbl vapic, %ebp ; fixup
+	ret
+
+up_get_tpr_stack:
+	reenable_vtpr
+	movzbl vapic, %eax ; fixup
+	xchg %eax, 4(%esp)
+	ret
+
+up_set_tpr_eax:
+	push %eax
+	call up_set_tpr
+	ret
+
+up_set_tpr:
+	pushf
+	push %eax
+	push %ecx
+	push %ebx
+	reenable_vtpr
+
+up_set_tpr_failed:
+	mov vapic, %eax	; fixup
+
+	mov %eax, %ebx
+	mov 20(%esp), %bl
+
+	/* %ebx = new vapic (%bl = tpr, %bh = isr, %b3 = irr) */
+
+	lock cmpxchg %ebx, vapic ; fixup
+	jnz up_set_tpr_failed
+
+	/* compute ppr */
+	cmp %bh, %bl
+	jae up_tpr_is_bigger
+up_isr_is_bigger:
+	mov %bh, %bl
+up_tpr_is_bigger:
+	/* %bl = ppr */
+	mov %bl, %ch   /* ch = ppr */
+	rol $8, %ebx
+	/* now: %bl = irr, %bh = ppr */
+	cmp %bh, %bl
+	ja up_set_tpr_poll_irq
+
+up_set_tpr_out:
+	pop %ebx
+	pop %ecx
+	pop %eax
+	popf
+	ret $4
+
+up_set_tpr_poll_irq:
+	mov $kvm_hypercall_vapic_poll_irq, %eax
+	kvm_hypercall
+	jmp up_set_tpr_out
+
+.text 1
+	fixup_end = .
+.text 0
+
+/*
+ * vapic format:
+ *  per-vcpu records of size 2^vcpu shift.
+ *     byte 0: tpr (r/w)
+ *     byte 1: highest in-service interrupt (isr) (r/o); bits 3:0 are zero
+ *     byte 2: zero (r/o)
+ *     byte 3: highest pending interrupt (irr) (r/o)
+ */
+.text 2
+
+.align 128
+
+vapic:
+. = . + vapic_size
+
+.byte 0  # reserve space for signature
+.align 512, 0
+
+_end:
commit d362e757d35727c915052974086f8687d3557431
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Feb 17 18:31:17 2012 +0100

    target-i386: Add infrastructure for reporting TPR MMIO accesses
    
    This will allow the APIC core to file a TPR access report. Depending on
    the accelerator and kernel irqchip mode, it will either be delivered
    right away or queued for later reporting.
    
    In TCG mode, we can restart the triggering instruction and can therefore
    forward the event directly. KVM does not allows us to restart, so we
    postpone the delivery of events recording in the user space APIC until
    the current instruction is completed.
    
    Note that KVM without in-kernel irqchip will report the address after
    the instruction that triggered the access.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/cpu-all.h b/cpu-all.h
index e2c3c49..80e6d42 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -375,8 +375,9 @@ DECLARE_TLS(CPUState *,cpu_single_env);
 #define CPU_INTERRUPT_TGT_INT_0   0x0100
 #define CPU_INTERRUPT_TGT_INT_1   0x0400
 #define CPU_INTERRUPT_TGT_INT_2   0x0800
+#define CPU_INTERRUPT_TGT_INT_3   0x2000
 
-/* First unused bit: 0x2000.  */
+/* First unused bit: 0x4000.  */
 
 /* The set of all bits that should be masked when single-stepping.  */
 #define CPU_INTERRUPT_SSTEP_MASK \
diff --git a/hw/apic.h b/hw/apic.h
index a62d83b..d6d6d44 100644
--- a/hw/apic.h
+++ b/hw/apic.h
@@ -18,6 +18,8 @@ void cpu_set_apic_tpr(DeviceState *s, uint8_t val);
 uint8_t cpu_get_apic_tpr(DeviceState *s);
 void apic_init_reset(DeviceState *s);
 void apic_sipi(DeviceState *s);
+void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip,
+                                   TPRAccess access);
 
 /* pc.c */
 int cpu_is_bsp(CPUState *env);
diff --git a/hw/apic_common.c b/hw/apic_common.c
index c91f7d5..340d793 100644
--- a/hw/apic_common.c
+++ b/hw/apic_common.c
@@ -68,6 +68,11 @@ uint8_t cpu_get_apic_tpr(DeviceState *d)
     return s ? s->tpr >> 4 : 0;
 }
 
+void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip,
+                                   TPRAccess access)
+{
+}
+
 void apic_report_irq_delivered(int delivered)
 {
     apic_irq_delivered += delivered;
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 6c1ad38..5671840 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -25,10 +25,13 @@
 #include "qemu-timer.h"
 #include "sysemu.h"
 #include "pc.h"
-#include "apic.h"
 #include "isa.h"
 #include "mc146818rtc.h"
 
+#ifdef TARGET_I386
+#include "apic.h"
+#endif
+
 //#define DEBUG_CMOS
 //#define DEBUG_COALESCED
 
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 37dde79..196b0c5 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -482,6 +482,7 @@
 #define CPU_INTERRUPT_VIRQ      CPU_INTERRUPT_TGT_INT_0
 #define CPU_INTERRUPT_INIT      CPU_INTERRUPT_TGT_INT_1
 #define CPU_INTERRUPT_SIPI      CPU_INTERRUPT_TGT_INT_2
+#define CPU_INTERRUPT_TPR       CPU_INTERRUPT_TGT_INT_3
 
 
 enum {
@@ -613,6 +614,11 @@ typedef struct {
 
 #define NB_MMU_MODES 2
 
+typedef enum TPRAccess {
+    TPR_ACCESS_READ,
+    TPR_ACCESS_WRITE,
+} TPRAccess;
+
 typedef struct CPUX86State {
     /* standard registers */
     target_ulong regs[CPU_NB_REGS];
@@ -772,6 +778,8 @@ typedef struct CPUX86State {
     XMMReg ymmh_regs[CPU_NB_REGS];
 
     uint64_t xcr0;
+
+    TPRAccess tpr_access_type;
 } CPUX86State;
 
 CPUX86State *cpu_x86_init(const char *cpu_model);
@@ -1064,4 +1072,6 @@ void svm_check_intercept(CPUState *env1, uint32_t type);
 
 uint32_t cpu_cc_compute_all(CPUState *env1, int op);
 
+void cpu_report_tpr_access(CPUState *env, TPRAccess access);
+
 #endif /* CPU_I386_H */
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 2586aff..d12c962 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1189,6 +1189,22 @@ void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,
         }
     }
 }
+
+void cpu_report_tpr_access(CPUState *env, TPRAccess access)
+{
+    TranslationBlock *tb;
+
+    if (kvm_enabled()) {
+        env->tpr_access_type = access;
+
+        cpu_interrupt(env, CPU_INTERRUPT_TPR);
+    } else {
+        tb = tb_find_pc(env->mem_io_pc);
+        cpu_restore_state(tb, env, env->mem_io_pc);
+
+        apic_handle_tpr_access_report(env->apic_state, env->eip, access);
+    }
+}
 #endif /* !CONFIG_USER_ONLY */
 
 static void mce_init(CPUX86State *cenv)
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 0e0b63b..9a73207 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1635,8 +1635,10 @@ void kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
     }
 
     if (!kvm_irqchip_in_kernel()) {
-        /* Force the VCPU out of its inner loop to process the INIT request */
-        if (env->interrupt_request & CPU_INTERRUPT_INIT) {
+        /* Force the VCPU out of its inner loop to process any INIT requests
+         * or pending TPR access reports. */
+        if (env->interrupt_request &
+            (CPU_INTERRUPT_INIT | CPU_INTERRUPT_TPR)) {
             env->exit_request = 1;
         }
 
@@ -1730,6 +1732,12 @@ int kvm_arch_process_async_events(CPUState *env)
         kvm_cpu_synchronize_state(env);
         do_cpu_sipi(env);
     }
+    if (env->interrupt_request & CPU_INTERRUPT_TPR) {
+        env->interrupt_request &= ~CPU_INTERRUPT_TPR;
+        kvm_cpu_synchronize_state(env);
+        apic_handle_tpr_access_report(env->apic_state, env->eip,
+                                      env->tpr_access_type);
+    }
 
     return env->halted;
 }
@@ -1746,6 +1754,16 @@ static int kvm_handle_halt(CPUState *env)
     return 0;
 }
 
+static int kvm_handle_tpr_access(CPUState *env)
+{
+    struct kvm_run *run = env->kvm_run;
+
+    apic_handle_tpr_access_report(env->apic_state, run->tpr_access.rip,
+                                  run->tpr_access.is_write ? TPR_ACCESS_WRITE
+                                                           : TPR_ACCESS_READ);
+    return 1;
+}
+
 int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
 {
     static const uint8_t int3 = 0xcc;
@@ -1950,6 +1968,9 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
     case KVM_EXIT_SET_TPR:
         ret = 0;
         break;
+    case KVM_EXIT_TPR_ACCESS:
+        ret = kvm_handle_tpr_access(env);
+        break;
     case KVM_EXIT_FAIL_ENTRY:
         code = run->fail_entry.hardware_entry_failure_reason;
         fprintf(stderr, "KVM: entry failed, hardware error 0x%" PRIx64 "\n",
commit d798e97456658ea7605303b7c69b04ec7df95c10
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Feb 17 18:31:16 2012 +0100

    Allow to use pause_all_vcpus from VCPU context
    
    In order to perform critical manipulations on the VM state in the
    context of a VCPU, specifically code patching, stopping and resuming of
    all VCPUs may be necessary. resume_all_vcpus is already compatible, now
    enable pause_all_vcpus for this use case by stopping the calling context
    before starting to wait for the whole gang.
    
    CC: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/cpus.c b/cpus.c
index 4a10775..17b055f 100644
--- a/cpus.c
+++ b/cpus.c
@@ -875,6 +875,18 @@ void pause_all_vcpus(void)
         penv = penv->next_cpu;
     }
 
+    if (!qemu_thread_is_self(&io_thread)) {
+        cpu_stop_current();
+        if (!kvm_enabled()) {
+            while (penv) {
+                penv->stop = 0;
+                penv->stopped = 1;
+                penv = penv->next_cpu;
+            }
+            return;
+        }
+    }
+
     while (!all_vcpus_paused()) {
         qemu_cond_wait(&qemu_pause_cond, &qemu_global_mutex);
         penv = first_cpu;
commit 8e564b4ebf472095b7ca5692302c8a3883d99d91
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Feb 17 18:31:15 2012 +0100

    Process pending work while waiting for initial kick-off in TCG mode
    
    When the TCG thread is started but not yet the machine, we wait in
    qemu_tcg_cpu_thread_fn on tcg_halt_cond. To allow run_on_cpu already at
    this time, we need to process pending request in that loop.
    
    CC: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/cpus.c b/cpus.c
index 4e65894..4a10775 100644
--- a/cpus.c
+++ b/cpus.c
@@ -761,6 +761,11 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
     /* wait for initial kick-off after machine start */
     while (first_cpu->stopped) {
         qemu_cond_wait(tcg_halt_cond, &qemu_global_mutex);
+
+        /* process any pending work */
+        for (env = first_cpu; env != NULL; env = env->next_cpu) {
+            qemu_wait_io_event_common(env);
+        }
     }
 
     while (1) {
commit 5207a5e0c33ce836341ff760e64ea4880bf1bc29
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Feb 17 18:31:14 2012 +0100

    Remove useless casts from cpu iterators
    
    CPUState::next_cpu is already CPUState *.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/cpus.c b/cpus.c
index d0c8340..4e65894 100644
--- a/cpus.c
+++ b/cpus.c
@@ -853,7 +853,7 @@ static int all_vcpus_paused(void)
         if (!penv->stopped) {
             return 0;
         }
-        penv = (CPUState *)penv->next_cpu;
+        penv = penv->next_cpu;
     }
 
     return 1;
@@ -867,7 +867,7 @@ void pause_all_vcpus(void)
     while (penv) {
         penv->stop = 1;
         qemu_cpu_kick(penv);
-        penv = (CPUState *)penv->next_cpu;
+        penv = penv->next_cpu;
     }
 
     while (!all_vcpus_paused()) {
@@ -875,7 +875,7 @@ void pause_all_vcpus(void)
         penv = first_cpu;
         while (penv) {
             qemu_cpu_kick(penv);
-            penv = (CPUState *)penv->next_cpu;
+            penv = penv->next_cpu;
         }
     }
 }
@@ -889,7 +889,7 @@ void resume_all_vcpus(void)
         penv->stop = 0;
         penv->stopped = 0;
         qemu_cpu_kick(penv);
-        penv = (CPUState *)penv->next_cpu;
+        penv = penv->next_cpu;
     }
 }
 
commit e479c207d7616e3b6ea42d14d1c6a7fef1f32fc4
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Feb 17 18:31:13 2012 +0100

    kvm: Set cpu_single_env only once
    
    As we have thread-local cpu_single_env now and KVM uses exactly one
    thread per VCPU, we can drop the cpu_single_env updates from the loop
    and initialize this variable only once during setup.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/cpus.c b/cpus.c
index f45a438..d0c8340 100644
--- a/cpus.c
+++ b/cpus.c
@@ -714,6 +714,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
     qemu_mutex_lock(&qemu_global_mutex);
     qemu_thread_get_self(env->thread);
     env->thread_id = qemu_get_thread_id();
+    cpu_single_env = env;
 
     r = kvm_init_vcpu(env);
     if (r < 0) {
diff --git a/kvm-all.c b/kvm-all.c
index c4babda..e2cbc03 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1118,8 +1118,6 @@ int kvm_cpu_exec(CPUState *env)
         return EXCP_HLT;
     }
 
-    cpu_single_env = env;
-
     do {
         if (env->kvm_vcpu_dirty) {
             kvm_arch_put_registers(env, KVM_PUT_RUNTIME_STATE);
@@ -1136,13 +1134,11 @@ int kvm_cpu_exec(CPUState *env)
              */
             qemu_cpu_kick_self();
         }
-        cpu_single_env = NULL;
         qemu_mutex_unlock_iothread();
 
         run_ret = kvm_vcpu_ioctl(env, KVM_RUN, 0);
 
         qemu_mutex_lock_iothread();
-        cpu_single_env = env;
         kvm_arch_post_run(env, run);
 
         kvm_flush_coalesced_mmio_buffer();
@@ -1206,7 +1202,6 @@ int kvm_cpu_exec(CPUState *env)
     }
 
     env->exit_request = 0;
-    cpu_single_env = NULL;
     return ret;
 }
 
commit a044ec2a066a6002f83aba5ee937db17e7493fa8
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sat Jan 14 13:29:29 2012 +0400

    target-xtensa: fetch 3rd opcode byte only when needed
    
    According to ISA, 3.5.4, third opcode byte should not be fetched for
    2-byte instructions.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index c81450d..6a0177f 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -749,7 +749,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
     uint8_t b0 = ldub_code(dc->pc);
     uint8_t b1 = ldub_code(dc->pc + 1);
-    uint8_t b2 = ldub_code(dc->pc + 2);
+    uint8_t b2 = 0;
 
     static const uint32_t B4CONST[] = {
         0xffffffff, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256
@@ -764,6 +764,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);
     }
 
     switch (OP0) {
commit 692f737cc252b811f0b00ab3c77008dd64680965
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sat Jan 7 20:02:40 2012 +0400

    target-xtensa: implement info tlb monitor command
    
    Command dumps valid ITLB and DTLB entries.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 573b823..454d619 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1341,7 +1341,7 @@ show i8259 (PIC) state
 @item info pci
 show emulated PCI device info
 @item info tlb
-show virtual to physical memory mappings (i386, SH4, SPARC, and PPC only)
+show virtual to physical memory mappings (i386, SH4, SPARC, PPC, and Xtensa only)
 @item info mem
 show the active virtual memory mappings (i386 only)
 @item info jit
diff --git a/monitor.c b/monitor.c
index aadbdcb..2ac1965 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1935,7 +1935,7 @@ static void tlb_info(Monitor *mon)
 
 #endif
 
-#if defined(TARGET_SPARC) || defined(TARGET_PPC)
+#if defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_XTENSA)
 static void tlb_info(Monitor *mon)
 {
     CPUState *env1 = mon_get_cpu();
@@ -2382,7 +2382,7 @@ static mon_cmd_t info_cmds[] = {
         .mhandler.info = hmp_info_pci,
     },
 #if defined(TARGET_I386) || defined(TARGET_SH4) || defined(TARGET_SPARC) || \
-    defined(TARGET_PPC)
+    defined(TARGET_PPC) || defined(TARGET_XTENSA)
     {
         .name       = "tlb",
         .args_type  = "",
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 0db83a6..c32bf35 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -344,6 +344,7 @@ void xtensa_tlb_set_entry(CPUState *env, bool dtlb,
 int xtensa_get_physical_addr(CPUState *env,
         uint32_t vaddr, int is_write, int mmu_idx,
         uint32_t *paddr, uint32_t *page_size, unsigned *access);
+void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env);
 
 
 #define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index 2a0cb1a..973c268 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -540,3 +540,70 @@ int xtensa_get_physical_addr(CPUState *env,
         return 0;
     }
 }
+
+static void dump_tlb(FILE *f, fprintf_function cpu_fprintf,
+        CPUState *env, bool dtlb)
+{
+    unsigned wi, ei;
+    const xtensa_tlb *conf =
+        dtlb ? &env->config->dtlb : &env->config->itlb;
+    unsigned (*attr_to_access)(uint32_t) =
+        xtensa_option_enabled(env->config, XTENSA_OPTION_MMU) ?
+        mmu_attr_to_access : region_attr_to_access;
+
+    for (wi = 0; wi < conf->nways; ++wi) {
+        uint32_t sz = ~xtensa_tlb_get_addr_mask(env, dtlb, wi) + 1;
+        const char *sz_text;
+        bool print_header = true;
+
+        if (sz >= 0x100000) {
+            sz >>= 20;
+            sz_text = "MB";
+        } else {
+            sz >>= 10;
+            sz_text = "KB";
+        }
+
+        for (ei = 0; ei < conf->way_size[wi]; ++ei) {
+            const xtensa_tlb_entry *entry =
+                xtensa_tlb_get_entry(env, dtlb, wi, ei);
+
+            if (entry->asid) {
+                unsigned access = attr_to_access(entry->attr);
+
+                if (print_header) {
+                    print_header = false;
+                    cpu_fprintf(f, "Way %u (%d %s)\n", wi, sz, sz_text);
+                    cpu_fprintf(f,
+                            "\tVaddr       Paddr       ASID  Attr RWX\n"
+                            "\t----------  ----------  ----  ---- ---\n");
+                }
+                cpu_fprintf(f,
+                        "\t0x%08x  0x%08x  0x%02x  0x%02x %c%c%c\n",
+                        entry->vaddr,
+                        entry->paddr,
+                        entry->asid,
+                        entry->attr,
+                        (access & PAGE_READ) ? 'R' : '-',
+                        (access & PAGE_WRITE) ? 'W' : '-',
+                        (access & PAGE_EXEC) ? 'X' : '-');
+            }
+        }
+    }
+}
+
+void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
+{
+    if (xtensa_option_bits_enabled(env->config,
+                XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_PROTECTION) |
+                XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_TRANSLATION) |
+                XTENSA_OPTION_BIT(XTENSA_OPTION_MMU))) {
+
+        cpu_fprintf(f, "ITLB:\n");
+        dump_tlb(f, cpu_fprintf, env, false);
+        cpu_fprintf(f, "\nDTLB:\n");
+        dump_tlb(f, cpu_fprintf, env, true);
+    } else {
+        cpu_fprintf(f, "No TLB for this CPU core\n");
+    }
+}
commit b96ac3e4cccf0ed92ffad4803d8558ebb6cdbad5
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Mon Jan 9 06:42:11 2012 +0400

    target-xtensa: define TLB_TEMPLATE for MMU-less cores
    
    TLB_TEMPLATE macro specifies TLB geometry in the core configuration.
    Make TLB_TEMPLATE available for region protection core variants,
    defining 1 way ITLB and DTLB with 8 entries each.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>

diff --git a/target-xtensa/overlay_tool.h b/target-xtensa/overlay_tool.h
index df19cc9..e7c4c3a 100644
--- a/target-xtensa/overlay_tool.h
+++ b/target-xtensa/overlay_tool.h
@@ -251,6 +251,8 @@
     .nextint = XCHAL_NUM_EXTINTERRUPTS, \
     .extint = EXTINTS
 
+#if XCHAL_HAVE_PTP_MMU
+
 #define TLB_TEMPLATE(ways, refill_way_size, way56) { \
         .nways = ways, \
         .way_size = { \
@@ -268,11 +270,23 @@
 #define DTLB(varway56) \
     TLB_TEMPLATE(10, 1 << XCHAL_DTLB_ARF_ENTRIES_LOG2, varway56)
 
-#if XCHAL_HAVE_PTP_MMU
 #define TLB_SECTION \
     .itlb = ITLB(XCHAL_HAVE_SPANNING_WAY), \
     .dtlb = DTLB(XCHAL_HAVE_SPANNING_WAY)
-#else
+
+#elif XCHAL_HAVE_XLT_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR
+
+#define TLB_TEMPLATE { \
+        .nways = 1, \
+        .way_size = { \
+            8, \
+        } \
+    }
+
+#define TLB_SECTION \
+    .itlb = TLB_TEMPLATE, \
+    .dtlb = TLB_TEMPLATE
+
 #endif
 
 #if (defined(TARGET_WORDS_BIGENDIAN) != 0) == (XCHAL_HAVE_BE != 0)
commit d1f866366070d09ff5c467efb0a64ac582e3aa5d
Author: Gleb Natapov <gleb at redhat.com>
Date:   Thu Feb 16 11:12:51 2012 +0200

    kvm: Synchronize cpu state in kvm_arch_stop_on_emulation_error()
    
    Call to kvm_cpu_synchronize_state() is missing.
    kvm_arch_stop_on_emulation_error may look at outdated registers here.
    
    Signed-off-by: Gleb Natapov <gleb at redhat.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Reviewed-by: Jan Kiszka <jan.kiszka at siemens.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 981192d..0e0b63b 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1987,6 +1987,7 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
 
 bool kvm_arch_stop_on_emulation_error(CPUState *env)
 {
+    kvm_cpu_synchronize_state(env);
     return !(env->cr[0] & CR0_PE_MASK) ||
            ((env->segs[R_CS].selector  & 3) != 3);
 }


More information about the Spice-commits mailing list